This will allow us to update dimm state on OSPM-initiated eject operations e.g.
with "echo 1 > /sys/bus/acpi/devices/PNP0C80\:00/eject"
v3->v4: Add support for ich9
---
docs/specs/acpi_hotplug.txt | 7 +++++++
hw/acpi_ich9.c | 7 +++++--
hw/acpi_ich9.h | 1 +
hw/acpi_piix4.c | 9 ++++++---
hw/dimm.c | 4 ++++
hw/dimm.h | 3 ++-
6 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/docs/specs/acpi_hotplug.txt b/docs/specs/acpi_hotplug.txt
index 536da16..69868fe 100644
--- a/docs/specs/acpi_hotplug.txt
+++ b/docs/specs/acpi_hotplug.txt
@@ -45,3 +45,10 @@ insertion failed.
Written by ACPI memory device _OST method to notify qemu of failed
hot-add. Write-only.
+Memory Dimm _PS3 power-off initiated by OSPM (IO port 0xafa4, 1-byte access):
+---------------------------------------------------------------
+Dimm hot-add _PS3 initiated by OSPM. Byte value indicates Dimm slot which
+entered D3 state.
+
+Written by ACPI memory device _PS3 method to notify qemu of power-off state for
+the dimm. Write-only.
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 2705230..5e7fca6 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -120,6 +120,9 @@ static void memhp_writeb(void *opaque, uint32_t addr, uint32_t val)
case ICH9_MEM_OST_ADD_FAIL - ICH9_MEM_BASE:
dimm_notify(val, DIMM_ADD_FAIL);
break;
+ case ICH9_MEM_PS3 - ICH9_MEM_BASE:
+ dimm_notify(val, DIMM_OSPM_POWEROFF);
+ break;
default:
ICH9_DEBUG("memhp write invalid %x <== %d\n", addr, val);
}
@@ -134,7 +137,7 @@ static const MemoryRegionOps ich9_memhp_ops = {
},
{
.offset = ICH9_MEM_EJ_BASE - ICH9_MEM_BASE,
- .len = 4, .size = 1,
+ .len = 5, .size = 1,
.write = memhp_writeb,
},
PORTIO_END_OF_LIST()
@@ -321,7 +324,7 @@ void ich9_pm_init(void *device, qemu_irq sci_irq, qemu_irq cmos_s3)
memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
memory_region_init_io(&pm->io_memhp, &ich9_memhp_ops, pm, "apci-memhp0",
- DIMM_BITMAP_BYTES + 4);
+ DIMM_BITMAP_BYTES + 5);
memory_region_add_subregion(get_system_io(), ICH9_MEM_BASE, &pm->io_memhp);
dimm_bus_hotplug(ich9_dimm_hotplug, ich9_dimm_revert, &lpc->d.qdev);
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
index 8f57cd8..816d453 100644
--- a/hw/acpi_ich9.h
+++ b/hw/acpi_ich9.h
@@ -29,6 +29,7 @@
#define ICH9_MEM_OST_REMOVE_FAIL 0xafa1
#define ICH9_MEM_OST_ADD_SUCCESS 0xafa2
#define ICH9_MEM_OST_ADD_FAIL 0xafa3
+#define ICH9_MEM_PS3 0xafa4
typedef struct ICH9LPCPMRegs {
/*
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 70aa480..6c953c2 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -54,6 +54,7 @@
#define MEM_OST_REMOVE_FAIL 0xafa1
#define MEM_OST_ADD_SUCCESS 0xafa2
#define MEM_OST_ADD_FAIL 0xafa3
+#define MEM_PS3 0xafa4
#define PIIX4_MEM_HOTPLUG_STATUS 8
#define PIIX4_PCI_HOTPLUG_STATUS 2
@@ -564,6 +565,9 @@ static void memhp_writeb(void *opaque, uint32_t addr, uint32_t val)
case MEM_OST_ADD_FAIL - MEM_BASE:
dimm_notify(val, DIMM_ADD_FAIL);
break;
+ case MEM_PS3 - MEM_BASE:
+ dimm_notify(val, DIMM_OSPM_POWEROFF);
+ break;
default:
PIIX4_DPRINTF("memhp write invalid %x <== %d\n", addr, val);
}
@@ -577,7 +581,7 @@ static const MemoryRegionOps piix4_memhp_ops = {
.read = memhp_readb,
},
{
- .offset = MEM_EJ_BASE - MEM_BASE, .len = 4,
+ .offset = MEM_EJ_BASE - MEM_BASE, .len = 5,
.size = 1,
.write = memhp_writeb,
},
@@ -666,7 +670,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 + 4);
+ DIMM_BITMAP_BYTES + 5);
memory_region_add_subregion(get_system_io(), MEM_BASE, &s->io_memhp);
for (i = 0; i < DIMM_BITMAP_BYTES; i++) {
@@ -726,7 +730,6 @@ static int piix4_dimm_revert(DeviceState *qdev, DimmDevice *dev, int add)
struct gpe_regs *g = &s->gperegs;
DimmDevice *slot = DIMM(dev);
int idx = slot->idx;
-
if (add) {
g->mems_sts[idx/8] &= ~(1 << (idx%8));
} else {
diff --git a/hw/dimm.c b/hw/dimm.c
index 69b97b6..2454e38 100644
--- a/hw/dimm.c
+++ b/hw/dimm.c
@@ -407,6 +407,10 @@ void dimm_notify(uint32_t idx, uint32_t event)
qdev_unplug_complete((DeviceState *)slot, NULL);
QTAILQ_REMOVE(&bus->dimmlist, slot, nextdimm);
QTAILQ_INSERT_TAIL(&bus->dimm_hp_result_queue, result, next);
+ case DIMM_OSPM_POWEROFF:
+ if (bus->dimm_revert) {
+ bus->dimm_revert(bus->dimm_hotplug_qdev, slot, 1);
+ }
default:
g_free(result);
break;
diff --git a/hw/dimm.h b/hw/dimm.h
index f43f745..081f2db 100644
--- a/hw/dimm.h
+++ b/hw/dimm.h
@@ -15,7 +15,8 @@ typedef enum {
DIMM_REMOVE_SUCCESS = 0,
DIMM_REMOVE_FAIL = 1,
DIMM_ADD_SUCCESS = 2,
- DIMM_ADD_FAIL = 3
+ DIMM_ADD_FAIL = 3,
+ DIMM_OSPM_POWEROFF = 4
} dimm_hp_result_code;
typedef enum {
--
1.7.9