Patchwork [RFC,v4,24/30] acpi_piix4: add hot-remove capability

login
register
mail settings
Submitter Vasilis Liaskovitis
Date Dec. 18, 2012, 12:41 p.m.
Message ID <1355834518-17989-25-git-send-email-vasilis.liaskovitis@profitbricks.com>
Download mbox | patch
Permalink /patch/207140/
State New
Headers show

Comments

Vasilis Liaskovitis - Dec. 18, 2012, 12:41 p.m.
---
 docs/specs/acpi_hotplug.txt |    8 ++++++++
 hw/acpi_piix4.c             |   29 ++++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletions(-)

Patch

diff --git a/docs/specs/acpi_hotplug.txt b/docs/specs/acpi_hotplug.txt
index 8391713..cf86242 100644
--- a/docs/specs/acpi_hotplug.txt
+++ b/docs/specs/acpi_hotplug.txt
@@ -12,3 +12,11 @@  Dimm hot-plug notification pending. One bit per slot.
 
 Read by ACPI BIOS GPE.3 handler to notify OS of memory hot-add or hot-remove
 events.  Read-only.
+
+Memory Dimm ejection success notification (IO port 0xafa0, 1-byte access):
+---------------------------------------------------------------
+Dimm hot-remove _EJ0 notification. Byte value indicates Dimm slot that was
+ejected.
+
+Written by ACPI memory device _EJ0 method to notify qemu of successfull
+hot-removal.  Write-only.
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 879d8a0..6e4718e 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -50,6 +50,7 @@ 
 #define PCI_EJ_BASE 0xae08
 #define PCI_RMV_BASE 0xae0c
 #define MEM_BASE 0xaf80
+#define MEM_EJ_BASE 0xafa0
 
 #define PIIX4_MEM_HOTPLUG_STATUS 8
 #define PIIX4_PCI_HOTPLUG_STATUS 2
@@ -544,12 +545,29 @@  static uint32_t memhp_readb(void *opaque, uint32_t addr)
     return val;
 }
 
+static void memhp_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    switch (addr) {
+    case MEM_EJ_BASE - MEM_BASE:
+        dimm_notify(val, DIMM_REMOVE_SUCCESS);
+        break;
+    default:
+        PIIX4_DPRINTF("memhp write invalid %x <== %d\n", addr, val);
+    }
+    PIIX4_DPRINTF("memhp write %x <== %d\n", addr, val);
+}
+
 static const MemoryRegionOps piix4_memhp_ops = {
     .old_portio = (MemoryRegionPortio[]) {
         {
             .offset = 0,   .len = DIMM_BITMAP_BYTES, .size = 1,
             .read = memhp_readb,
         },
+        {
+            .offset = MEM_EJ_BASE - MEM_BASE, .len = 1,
+            .size = 1,
+            .write = memhp_writeb,
+        },
         PORTIO_END_OF_LIST()
     },
     .endianness = DEVICE_LITTLE_ENDIAN,
@@ -635,7 +653,7 @@  static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
     memory_region_add_subregion(get_system_io(), PCI_HOTPLUG_ADDR,
                                 &s->io_pci);
     memory_region_init_io(&s->io_memhp, &piix4_memhp_ops, s, "apci-memhp0",
-                          DIMM_BITMAP_BYTES);
+                          DIMM_BITMAP_BYTES + 1);
     memory_region_add_subregion(get_system_io(), MEM_BASE, &s->io_memhp);
 
     for (i = 0; i < DIMM_BITMAP_BYTES; i++) {
@@ -665,6 +683,13 @@  static void enable_mem_device(PIIX4PMState *s, int memdevice)
     g->mems_sts[memdevice/8] |= (1 << (memdevice%8));
 }
 
+static void disable_mem_device(PIIX4PMState *s, int memdevice)
+{
+    struct gpe_regs *g = &s->gperegs;
+    s->ar.gpe.sts[0] |= PIIX4_MEM_HOTPLUG_STATUS;
+    g->mems_sts[memdevice/8] &= ~(1 << (memdevice%8));
+}
+
 static int piix4_dimm_hotplug(DeviceState *qdev, DimmDevice *dev, int
         add)
 {
@@ -674,6 +699,8 @@  static int piix4_dimm_hotplug(DeviceState *qdev, DimmDevice *dev, int
 
     if (add) {
         enable_mem_device(s, slot->idx);
+    } else {
+        disable_mem_device(s, slot->idx);
     }
     pm_update_sci(s);
     return 0;