diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index ed39241..b43b2b4 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -75,12 +75,14 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
     case 0x14: /* pack and return is_* fields */
         val |= mdev->is_enabled   ? 1 : 0;
         val |= mdev->is_inserting ? 2 : 0;
+        val |= mdev->is_removing ? 4 : 0;
         trace_mhp_acpi_read_flags(mem_st->selector, val);
         break;
     default:
         val = ~0;
         break;
     }
+
     return val;
 }
 
@@ -126,17 +128,57 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
         info = acpi_memory_device_status(mem_st->selector, mdev);
         qapi_event_send_acpi_device_ost(info, &error_abort);
         qapi_free_ACPIOSTInfo(info);
+        switch (mdev->ost_event) {
+        case 0x03: /* EJECT */
+            switch (mdev->ost_status) {
+            case 0x0: /* SUCCESS */
+                object_unparent(OBJECT(mdev->dimm));
+                mdev->is_removing = false;
+                mdev->dimm = NULL;
+                break;
+            case 0x1: /* FAILURE */
+            case 0x2: /* UNRECOGNIZED NOTIFY */
+            case 0x80: /* EJECT NOT SUPPORTED */
+            case 0x81: /* DEVICE IN USE */
+            case 0x82: /* DEVICE BUSY */
+            case 0x83: /* EJECT_DEPENDENCY_BUSY */
+                mdev->is_removing = false;
+                mdev->is_enabled = true;
+                break;
+            case 0x84: /* EJECTION IN PROGRESS */
+                break;
+            default:
+                break;
+            }
+            break;
+        case 0x103: /* OSPM EJECT */
+            switch (mdev->ost_status) {
+            case 0x0: /* SUCCESS */
+                object_unparent(OBJECT(mdev->dimm));
+                mdev->is_removing = false;
+                mdev->dimm = NULL;
+                break;
+            case 0x84: /* EJECTION IN PROGRESS */
+                mdev->is_enabled = false;
+                mdev->is_removing = true;
+                break;
+            default:
+                break;
+            }
+        }
         break;
     case 0x14:
         mdev = &mem_st->devs[mem_st->selector];
         if (data & 2) { /* clear insert event */
             mdev->is_inserting  = false;
             trace_mhp_acpi_clear_insert_evt(mem_st->selector);
+        } else if (data & 4) { /* MRMV */
+            mdev->is_enabled = false;
         }
         break;
     }
-
 }
+
 static const MemoryRegionOps acpi_memory_hotplug_ops = {
     .read = acpi_memory_hotplug_read,
     .write = acpi_memory_hotplug_write,
@@ -195,6 +237,36 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
     return;
 }
 
+void acpi_memory_unplug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
+                           DeviceState *dev, Error **errp)
+{
+    MemStatus *mdev;
+    Error *local_err = NULL;
+    int slot = object_property_get_int(OBJECT(dev), "slot", &local_err);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (slot >= mem_st->dev_count) {
+        char *dev_path = object_get_canonical_path(OBJECT(dev));
+        error_setg(errp, "acpi_memory_plug_cb: "
+                   "device [%s] returned invalid memory slot[%d]",
+                    dev_path, slot);
+        g_free(dev_path);
+        return;
+    }
+
+    mdev = &mem_st->devs[slot];
+    mdev->is_removing = true;
+
+    /* do ACPI magic */
+    ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS;
+    acpi_update_sci(ar, irq);
+    return;
+}
+
 static const VMStateDescription vmstate_memhp_sts = {
     .name = "memory hotplug device state",
     .version_id = 1,
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index b72b34e..37d593a 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -362,6 +362,8 @@ static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
     if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
         acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
                                     errp);
+    } else if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        acpi_memory_unplug_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, dev, errp);
     } else {
         error_setg(errp, "acpi: device unplug request for not supported device"
                    " type: %s", object_get_typename(OBJECT(dev)));
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index da1ba48..7990edf 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -228,6 +228,15 @@ void qdev_unplug(DeviceState *dev, Error **errp)
 
     if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
         hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp);
+    } else if (*errp == NULL) {
+            HotplugHandler *hotplug_ctrl;
+            MachineState *machine = MACHINE(qdev_get_machine());
+            MachineClass *mc = MACHINE_GET_CLASS(machine);
+
+            hotplug_ctrl = mc->get_hotplug_handler(machine ,dev);
+            if (hotplug_ctrl) {
+                hotplug_handler_unplug(hotplug_ctrl, dev, errp);
+            }
     } else {
         assert(dc->unplug != NULL);
         if (dc->unplug(dev) < 0) { /* legacy handler */
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2cf22b1..3537601 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -61,6 +61,8 @@
 #include "hw/mem/pc-dimm.h"
 #include "trace.h"
 #include "qapi/visitor.h"
+#include "hw/acpi/piix4.h"
+#include "hw/i386/ich9.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -1612,6 +1614,26 @@ out:
     error_propagate(errp, local_err);
 }
 
+static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
+                           DeviceState *dev, Error **errp)
+{
+    Object *acpi_dev;
+    HotplugHandlerClass *hhc;
+    Error *local_err = NULL;
+
+    acpi_dev = (acpi_dev = piix4_pm_find()) ? acpi_dev : ich9_lpc_find();
+    if (!acpi_dev) {
+        error_setg(&local_err,
+                   "memory hotplug is not enabled: missing acpi device");
+        return;
+    }
+
+    hhc = HOTPLUG_HANDLER_GET_CLASS(acpi_dev);
+    hhc->unplug(HOTPLUG_HANDLER(acpi_dev), dev, &local_err);
+
+    error_propagate(errp, local_err);
+}
+
 static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
                                       DeviceState *dev, Error **errp)
 {
@@ -1620,6 +1642,14 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
     }
 }
 
+static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
+                                        DeviceState *dev, Error **errp)
+{
+    if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+        pc_dimm_unplug(hotplug_dev, dev, errp);
+    }
+}
+
 static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
                                              DeviceState *dev)
 {
@@ -1706,6 +1736,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     pcmc->get_hotplug_handler = mc->get_hotplug_handler;
     mc->get_hotplug_handler = pc_get_hotpug_handler;
     hc->plug = pc_machine_device_plug_cb;
+    hc->unplug = pc_machine_device_unplug_cb;
 }
 
 static const TypeInfo pc_machine_info = {
diff --git a/hw/i386/ssdt-mem.dsl b/hw/i386/ssdt-mem.dsl
index 8e17bd1..bf20ee4 100644
--- a/hw/i386/ssdt-mem.dsl
+++ b/hw/i386/ssdt-mem.dsl
@@ -43,6 +43,11 @@ DefinitionBlock ("ssdt-mem.aml", "SSDT", 0x02, "BXPC", "CSSDT", 0x1)
     External(\_SB.PCI0.MEMORY_HOPTLUG_DEVICE.MEMORY_SLOT_STATUS_METHOD, MethodObj)
     External(\_SB.PCI0.MEMORY_HOPTLUG_DEVICE.MEMORY_SLOT_OST_METHOD, MethodObj)
     External(\_SB.PCI0.MEMORY_HOPTLUG_DEVICE.MEMORY_SLOT_PROXIMITY_METHOD, MethodObj)
+    External(\_SB.MHPD.MCRS, MethodObj)
+    External(\_SB.MHPD.MRST, MethodObj)
+    External(\_SB.MHPD.MOST, MethodObj)
+    External(\_SB.MHPD.MPXM, MethodObj)
+    External(\_SB.MHPD.MDEJ, MethodObj)
 
     Scope(\_SB) {
 /*  v------------------ DO NOT EDIT ------------------v */
@@ -72,6 +77,9 @@ DefinitionBlock ("ssdt-mem.aml", "SSDT", 0x02, "BXPC", "CSSDT", 0x1)
             Method(_OST, 3) {
                 \_SB.PCI0.MEMORY_HOPTLUG_DEVICE.MEMORY_SLOT_OST_METHOD(_UID, Arg0, Arg1, Arg2)
             }
+            Method(_EJ0, 1) {
+                \_SB.MHPD.MDEJ(_UID, Arg0)
+            }
         }
     }
 }
diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
index d329b8b..38e9bed 100644
--- a/hw/i386/ssdt-misc.dsl
+++ b/hw/i386/ssdt-misc.dsl
@@ -156,6 +156,9 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
                 Offset(20),
                 MEMORY_SLOT_ENABLED,  1, // 1 if enabled, read only
                 MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event
+                //MES,  1, // 1 if DIMM enabled used by _STA, read only
+                //MINS, 1, // (read) 1 if DIMM has a insert event. (write) 1 after MTFY() to clear event
+                MRMV, 1, // 1 if DIMM has a remove request, read only
             }
 
             Mutex (MEMORY_SLOT_LOCK, 0)
@@ -178,7 +181,9 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
                         MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
                         Store(1, MEMORY_SLOT_INSERT_EVENT)
                     }
-                    // TODO: handle memory eject request
+                    If (LEqual(MRMV, One)) { // Ejection request
+                        MTFY(Local0, 3)
+                    }
                     Add(Local0, One, Local0) // goto next DIMM
                 }
                 Release(MEMORY_SLOT_LOCK)
@@ -278,6 +283,12 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
                 Store(Arg2, MEMORY_SLOT_OST_STATUS)
                 Release(MEMORY_SLOT_LOCK)
             }
+            Method(MDEJ, 2) {
+                Acquire(MLCK, 0xFFFF)
+                Store(ToInteger(Arg0), MSEL) // select DIMM
+                Store(One, MRMV)
+                Release(MLCK)
+            }
         } // Device()
     } // Scope()
 }
diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h
index 7bbf8a0..fe41268 100644
--- a/include/hw/acpi/memory_hotplug.h
+++ b/include/hw/acpi/memory_hotplug.h
@@ -11,6 +11,7 @@ typedef struct MemStatus {
     DeviceState *dimm;
     bool is_enabled;
     bool is_inserting;
+    bool is_removing;
     uint32_t ost_event;
     uint32_t ost_status;
 } MemStatus;
@@ -28,6 +29,8 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
 
 void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
                          DeviceState *dev, Error **errp);
+void acpi_memory_unplug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
+                           DeviceState *dev, Error **errp);
 
 extern const VMStateDescription vmstate_memory_hotplug;
 #define VMSTATE_MEMORY_HOTPLUG(memhp, state) \
diff --git a/include/qom/object.h b/include/qom/object.h
index 8a05a81..a352beb 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1300,5 +1300,6 @@ int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
  */
 Object *container_get(Object *root, const char *path);
 
+bool object_property_is_child(ObjectProperty *prop);
 
 #endif
diff --git a/qdev-monitor.c b/qdev-monitor.c
index f87f3d8..168806f 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -24,6 +24,7 @@
 #include "qmp-commands.h"
 #include "sysemu/arch_init.h"
 #include "qemu/config-file.h"
+#include "qom/object.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
@@ -689,12 +690,34 @@ int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
+static DeviceState *find_peripheral_device(const char *id)
+{
+    Object *peripheral = qdev_get_peripheral();
+    DeviceState *dev = NULL;
+    ObjectProperty *prop;
+
+
+    QTAILQ_FOREACH(prop, &peripheral->properties, node) {
+        if (object_property_is_child(prop)) {
+            dev = DEVICE(prop->opaque);
+            if (!strcmp(dev->id, id)) {
+                return dev;
+            }
+        }
+    }
+
+    return dev;
+}
+
 void qmp_device_del(const char *id, Error **errp)
 {
     DeviceState *dev;
 
     dev = qdev_find_recursive(sysbus_get_default(), id);
-    if (NULL == dev) {
+    if (dev == NULL) {
+        dev = find_peripheral_device(id);
+    }
+    if (dev == NULL) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, id);
         return;
     }
diff --git a/qom/object.c b/qom/object.c
index 0e8267b..1183e5d 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -351,7 +351,7 @@ void object_initialize(void *data, size_t size, const char *typename)
     object_initialize_with_type(data, size, type);
 }
 
-static inline bool object_property_is_child(ObjectProperty *prop)
+bool object_property_is_child(ObjectProperty *prop)
 {
     return strstart(prop->type, "child<", NULL);
 }
