* [Qemu-devel] [RfC PATCH 0/3] q35: acpi hotplug
@ 2013-01-09 15:41 Gerd Hoffmann
2013-01-09 15:41 ` [Qemu-devel] [PATCH 1/3] split acpi pci hotplug code into separate file Gerd Hoffmann
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2013-01-09 15:41 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hi,
Experimental and untested patch series to implement acpi-based pci
hotplug on q35. I'm only looking for comments on the approach taken,
especially on patch #3.
The actual hotplug protocol is identical to piix, the difference is
how the io ports are mapped. piix has magic io ports at a fixed
address. For ich9 I don't want to do the same and create a pci device
instead, so the io ports show up as usual in the guests ressource
management and we can be sure we don't get conflicts.
No seabios bits yet. Should be largely identical to the piix ones,
except that we create the OperationalRegion using PciBarTarget instead
of SystemIO.
cheers,
Gerd
Gerd Hoffmann (3):
split acpi pci hotplug code into separate file
fix off-byone in hw/acpi_pci_hotplug.h
q35: add & windup ich9-pci-hotplug device
hw/Makefile.objs | 2 +-
hw/acpi_ich9.c | 89 ++++++++++++++++++++
hw/acpi_ich9.h | 1 +
hw/acpi_pci_hotplug.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/acpi_pci_hotplug.h | 26 ++++++
hw/acpi_piix4.c | 202 ++--------------------------------------------
hw/lpc_ich9.c | 5 +-
7 files changed, 344 insertions(+), 195 deletions(-)
create mode 100644 hw/acpi_pci_hotplug.c
create mode 100644 hw/acpi_pci_hotplug.h
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 1/3] split acpi pci hotplug code into separate file
2013-01-09 15:41 [Qemu-devel] [RfC PATCH 0/3] q35: acpi hotplug Gerd Hoffmann
@ 2013-01-09 15:41 ` Gerd Hoffmann
2013-01-09 21:13 ` Blue Swirl
2013-01-09 15:41 ` [Qemu-devel] [PATCH 2/3] fix off-byone in hw/acpi_pci_hotplug.h Gerd Hoffmann
2013-01-09 15:41 ` [Qemu-devel] [PATCH 3/3] q35: add & windup ich9-pci-hotplug device Gerd Hoffmann
2 siblings, 1 reply; 5+ messages in thread
From: Gerd Hoffmann @ 2013-01-09 15:41 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Also some minor code restructions along the way:
* create a new struct for acpi pci hotplug state
* rename functions so they no longer carry piix in the name
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/Makefile.objs | 2 +-
hw/acpi_pci_hotplug.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/acpi_pci_hotplug.h | 26 ++++++
hw/acpi_piix4.c | 202 ++--------------------------------------------
4 files changed, 250 insertions(+), 194 deletions(-)
create mode 100644 hw/acpi_pci_hotplug.c
create mode 100644 hw/acpi_pci_hotplug.h
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 6b8a68c..dc1479f 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -31,7 +31,7 @@ common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
common-obj-$(CONFIG_PCSPK) += pcspk.o
common-obj-$(CONFIG_PCKBD) += pckbd.o
common-obj-$(CONFIG_FDC) += fdc.o
-common-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o acpi_ich9.o smbus_ich9.o
+common-obj-$(CONFIG_ACPI) += acpi.o acpi_pci_hotplug.o acpi_piix4.o acpi_ich9.o smbus_ich9.o
common-obj-$(CONFIG_APM) += pm_smbus.o apm.o
common-obj-$(CONFIG_DMA) += dma.o
common-obj-$(CONFIG_I82374) += i82374.o
diff --git a/hw/acpi_pci_hotplug.c b/hw/acpi_pci_hotplug.c
new file mode 100644
index 0000000..cff21bd
--- /dev/null
+++ b/hw/acpi_pci_hotplug.c
@@ -0,0 +1,214 @@
+/*
+ * ACPI implementation
+ *
+ * Copyright (c) 2006 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw.h"
+#include "pci/pci.h"
+
+#include "acpi_pci_hotplug.h"
+
+//#define DEBUG
+
+#ifdef DEBUG
+# define DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define DPRINTF(format, ...) do { } while (0)
+#endif
+
+static void acpi_pci_hotplug_eject_slot(ACPIPCI *s, unsigned slots)
+{
+ BusChild *kid, *next;
+ BusState *bus = s->bus;
+ int slot = ffs(slots) - 1;
+ bool slot_free = true;
+
+ /* Mark request as complete */
+ s->pci0_status.down &= ~(1U << slot);
+
+ QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
+ DeviceState *qdev = kid->child;
+ PCIDevice *dev = PCI_DEVICE(qdev);
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+ if (PCI_SLOT(dev->devfn) == slot) {
+ if (pc->no_hotplug) {
+ slot_free = false;
+ } else {
+ qdev_free(qdev);
+ }
+ }
+ }
+ if (slot_free) {
+ s->pci0_slot_device_present &= ~(1U << slot);
+ }
+}
+
+static uint32_t pci_up_read(void *opaque, uint32_t addr)
+{
+ ACPIPCI *s = opaque;
+ uint32_t val;
+
+ /* Manufacture an "up" value to cause a device check on any hotplug
+ * slot with a device. Extra device checks are harmless. */
+ val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
+
+ DPRINTF("pci_up_read %x\n", val);
+ return val;
+}
+
+static uint32_t pci_down_read(void *opaque, uint32_t addr)
+{
+ ACPIPCI *s = opaque;
+ uint32_t val = s->pci0_status.down;
+
+ DPRINTF("pci_down_read %x\n", val);
+ return val;
+}
+
+static uint32_t pci_features_read(void *opaque, uint32_t addr)
+{
+ /* No feature defined yet */
+ DPRINTF("pci_features_read %x\n", 0);
+ return 0;
+}
+
+static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ acpi_pci_hotplug_eject_slot(opaque, val);
+
+ DPRINTF("pciej write %x <== %d\n", addr, val);
+}
+
+static uint32_t pcirmv_read(void *opaque, uint32_t addr)
+{
+ ACPIPCI *s = opaque;
+
+ return s->pci0_hotplug_enable;
+}
+
+static const MemoryRegionOps piix4_pci_ops = {
+ .old_portio = (MemoryRegionPortio[]) {
+ {
+ .offset = PCI_UP_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+ .read = pci_up_read,
+ },{
+ .offset = PCI_DOWN_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+ .read = pci_down_read,
+ },{
+ .offset = PCI_EJ_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+ .read = pci_features_read,
+ .write = pciej_write,
+ },{
+ .offset = PCI_RMV_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
+ .read = pcirmv_read,
+ },
+ PORTIO_END_OF_LIST()
+ },
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vmstate_pci_status_pre_save(void *opaque)
+{
+ struct pci_status *pci0_status = opaque;
+ ACPIPCI *s = container_of(pci0_status, ACPIPCI, pci0_status);
+
+ /* We no longer track up, so build a safe value for migrating
+ * to a version that still does... of course these might get lost
+ * by an old buggy implementation, but we try. */
+ pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable;
+}
+
+const VMStateDescription vmstate_pci_status = {
+ .name = "pci_status",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .pre_save = vmstate_pci_status_pre_save,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(up, struct pci_status),
+ VMSTATE_UINT32(down, struct pci_status),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+void acpi_pci_hotplug_update(ACPIPCI *s)
+{
+ BusState *bus = s->bus;
+ BusChild *kid, *next;
+
+ /* Execute any pending removes during reset */
+ while (s->pci0_status.down) {
+ acpi_pci_hotplug_eject_slot(s, s->pci0_status.down);
+ }
+
+ s->pci0_hotplug_enable = ~0;
+ s->pci0_slot_device_present = 0;
+
+ QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
+ DeviceState *qdev = kid->child;
+ PCIDevice *pdev = PCI_DEVICE(qdev);
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
+ int slot = PCI_SLOT(pdev->devfn);
+
+ if (pc->no_hotplug) {
+ s->pci0_hotplug_enable &= ~(1U << slot);
+ }
+
+ s->pci0_slot_device_present |= (1U << slot);
+ }
+}
+
+void acpi_pci_hotplug_init(ACPIPCI *s, DeviceState *qdev)
+{
+ s->bus = qdev_get_parent_bus(qdev);
+ memory_region_init_io(&s->io, &piix4_pci_ops, s, "apci-pci-hotplug",
+ PCI_HOTPLUG_SIZE);
+}
+
+
+static void enable_device(ACPIPCI *s, int slot)
+{
+ s->pci0_slot_device_present |= (1U << slot);
+}
+
+static void disable_device(ACPIPCI *s, int slot)
+{
+ s->pci0_status.down |= (1U << slot);
+}
+
+int acpi_pci_hotplug_device(ACPIPCI *s, PCIDevice *dev,
+ PCIHotplugState state)
+{
+ int slot = PCI_SLOT(dev->devfn);
+
+ /* Don't send event when device is enabled during qemu machine creation:
+ * it is present on boot, no hotplug event is necessary. We do send an
+ * event when the device is disabled later. */
+ if (state == PCI_COLDPLUG_ENABLED) {
+ s->pci0_slot_device_present |= (1U << slot);
+ return 0;
+ }
+
+ if (state == PCI_HOTPLUG_ENABLED) {
+ enable_device(s, slot);
+ } else {
+ disable_device(s, slot);
+ }
+ return 1;
+}
diff --git a/hw/acpi_pci_hotplug.h b/hw/acpi_pci_hotplug.h
new file mode 100644
index 0000000..b97403d
--- /dev/null
+++ b/hw/acpi_pci_hotplug.h
@@ -0,0 +1,26 @@
+#define PCI_HOTPLUG_ADDR 0xae00
+#define PCI_HOTPLUG_SIZE 0x000f
+#define PCI_UP_BASE 0xae00
+#define PCI_DOWN_BASE 0xae04
+#define PCI_EJ_BASE 0xae08
+#define PCI_RMV_BASE 0xae0c
+
+struct pci_status {
+ uint32_t up; /* deprecated, maintained for migration compatibility */
+ uint32_t down;
+};
+
+typedef struct ACPIPCI {
+ MemoryRegion io;
+ BusState *bus;
+ struct pci_status pci0_status;
+ uint32_t pci0_hotplug_enable;
+ uint32_t pci0_slot_device_present;
+} ACPIPCI;
+
+extern const VMStateDescription vmstate_pci_status;
+
+void acpi_pci_hotplug_update(ACPIPCI *s);
+void acpi_pci_hotplug_init(ACPIPCI *s, DeviceState *qdev);
+int acpi_pci_hotplug_device(ACPIPCI *s, PCIDevice *dev,
+ PCIHotplugState state);
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 06a8aca..1374116 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -29,6 +29,7 @@
#include "exec/ioport.h"
#include "fw_cfg.h"
#include "exec/address-spaces.h"
+#include "acpi_pci_hotplug.h"
//#define DEBUG
@@ -41,27 +42,15 @@
#define GPE_BASE 0xafe0
#define GPE_LEN 4
-#define PCI_HOTPLUG_ADDR 0xae00
-#define PCI_HOTPLUG_SIZE 0x000f
-#define PCI_UP_BASE 0xae00
-#define PCI_DOWN_BASE 0xae04
-#define PCI_EJ_BASE 0xae08
-#define PCI_RMV_BASE 0xae0c
-
#define PIIX4_PCI_HOTPLUG_STATUS 2
-struct pci_status {
- uint32_t up; /* deprecated, maintained for migration compatibility */
- uint32_t down;
-};
-
typedef struct PIIX4PMState {
PCIDevice dev;
MemoryRegion io;
MemoryRegion io_gpe;
- MemoryRegion io_pci;
ACPIREGS ar;
+ ACPIPCI pci;
APMState apm;
@@ -74,11 +63,6 @@ typedef struct PIIX4PMState {
Notifier machine_ready;
Notifier powerdown_notifier;
- /* for pci hotplug */
- struct pci_status pci0_status;
- uint32_t pci0_hotplug_enable;
- uint32_t pci0_slot_device_present;
-
uint8_t disable_s3;
uint8_t disable_s4;
uint8_t s4_val;
@@ -167,17 +151,6 @@ static void pm_write_config(PCIDevice *d,
}
}
-static void vmstate_pci_status_pre_save(void *opaque)
-{
- struct pci_status *pci0_status = opaque;
- PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status);
-
- /* We no longer track up, so build a safe value for migrating
- * to a version that still does... of course these might get lost
- * by an old buggy implementation, but we try. */
- pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable;
-}
-
static int vmstate_acpi_post_load(void *opaque, int version_id)
{
PIIX4PMState *s = opaque;
@@ -208,19 +181,6 @@ static const VMStateDescription vmstate_gpe = {
}
};
-static const VMStateDescription vmstate_pci_status = {
- .name = "pci_status",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .pre_save = vmstate_pci_status_pre_save,
- .fields = (VMStateField []) {
- VMSTATE_UINT32(up, struct pci_status),
- VMSTATE_UINT32(down, struct pci_status),
- VMSTATE_END_OF_LIST()
- }
-};
-
static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
{
PIIX4PMState *s = opaque;
@@ -279,67 +239,12 @@ static const VMStateDescription vmstate_acpi = {
VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
- VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
+ VMSTATE_STRUCT(pci.pci0_status, PIIX4PMState, 2, vmstate_pci_status,
struct pci_status),
VMSTATE_END_OF_LIST()
}
};
-static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
-{
- BusChild *kid, *next;
- BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
- int slot = ffs(slots) - 1;
- bool slot_free = true;
-
- /* Mark request as complete */
- s->pci0_status.down &= ~(1U << slot);
-
- QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
- DeviceState *qdev = kid->child;
- PCIDevice *dev = PCI_DEVICE(qdev);
- PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
- if (PCI_SLOT(dev->devfn) == slot) {
- if (pc->no_hotplug) {
- slot_free = false;
- } else {
- qdev_free(qdev);
- }
- }
- }
- if (slot_free) {
- s->pci0_slot_device_present &= ~(1U << slot);
- }
-}
-
-static void piix4_update_hotplug(PIIX4PMState *s)
-{
- PCIDevice *dev = &s->dev;
- BusState *bus = qdev_get_parent_bus(&dev->qdev);
- BusChild *kid, *next;
-
- /* Execute any pending removes during reset */
- while (s->pci0_status.down) {
- acpi_piix_eject_slot(s, s->pci0_status.down);
- }
-
- s->pci0_hotplug_enable = ~0;
- s->pci0_slot_device_present = 0;
-
- QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
- DeviceState *qdev = kid->child;
- PCIDevice *pdev = PCI_DEVICE(qdev);
- PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
- int slot = PCI_SLOT(pdev->devfn);
-
- if (pc->no_hotplug) {
- s->pci0_hotplug_enable &= ~(1U << slot);
- }
-
- s->pci0_slot_device_present |= (1U << slot);
- }
-}
-
static void piix4_reset(void *opaque)
{
PIIX4PMState *s = opaque;
@@ -357,7 +262,7 @@ static void piix4_reset(void *opaque)
/* Mark SMM as already inited (until KVM supports SMM). */
pci_conf[0x5B] = 0x02;
}
- piix4_update_hotplug(s);
+ acpi_pci_hotplug_update(&s->pci);
}
static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
@@ -531,70 +436,6 @@ static const MemoryRegionOps piix4_gpe_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static uint32_t pci_up_read(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val;
-
- /* Manufacture an "up" value to cause a device check on any hotplug
- * slot with a device. Extra device checks are harmless. */
- val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
-
- PIIX4_DPRINTF("pci_up_read %x\n", val);
- return val;
-}
-
-static uint32_t pci_down_read(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val = s->pci0_status.down;
-
- PIIX4_DPRINTF("pci_down_read %x\n", val);
- return val;
-}
-
-static uint32_t pci_features_read(void *opaque, uint32_t addr)
-{
- /* No feature defined yet */
- PIIX4_DPRINTF("pci_features_read %x\n", 0);
- return 0;
-}
-
-static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
-{
- acpi_piix_eject_slot(opaque, val);
-
- PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
-}
-
-static uint32_t pcirmv_read(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
-
- return s->pci0_hotplug_enable;
-}
-
-static const MemoryRegionOps piix4_pci_ops = {
- .old_portio = (MemoryRegionPortio[]) {
- {
- .offset = PCI_UP_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
- .read = pci_up_read,
- },{
- .offset = PCI_DOWN_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
- .read = pci_down_read,
- },{
- .offset = PCI_EJ_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
- .read = pci_features_read,
- .write = pciej_write,
- },{
- .offset = PCI_RMV_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
- .read = pcirmv_read,
- },
- PORTIO_END_OF_LIST()
- },
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
PCIHotplugState state);
@@ -605,47 +446,22 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
GPE_LEN);
memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
- memory_region_init_io(&s->io_pci, &piix4_pci_ops, s, "apci-pci-hotplug",
- PCI_HOTPLUG_SIZE);
+ acpi_pci_hotplug_init(&s->pci, &s->dev.qdev);
memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
- &s->io_pci);
+ &s->pci.io);
pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
}
-static void enable_device(PIIX4PMState *s, int slot)
-{
- s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
- s->pci0_slot_device_present |= (1U << slot);
-}
-
-static void disable_device(PIIX4PMState *s, int slot)
-{
- s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
- s->pci0_status.down |= (1U << slot);
-}
-
static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
PCIHotplugState state)
{
- int slot = PCI_SLOT(dev->devfn);
PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
PCI_DEVICE(qdev));
- /* Don't send event when device is enabled during qemu machine creation:
- * it is present on boot, no hotplug event is necessary. We do send an
- * event when the device is disabled later. */
- if (state == PCI_COLDPLUG_ENABLED) {
- s->pci0_slot_device_present |= (1U << slot);
- return 0;
+ if (acpi_pci_hotplug_device(&s->pci, dev, state)) {
+ s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
+ pm_update_sci(s);
}
- if (state == PCI_HOTPLUG_ENABLED) {
- enable_device(s, slot);
- } else {
- disable_device(s, slot);
- }
-
- pm_update_sci(s);
-
return 0;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 2/3] fix off-byone in hw/acpi_pci_hotplug.h
2013-01-09 15:41 [Qemu-devel] [RfC PATCH 0/3] q35: acpi hotplug Gerd Hoffmann
2013-01-09 15:41 ` [Qemu-devel] [PATCH 1/3] split acpi pci hotplug code into separate file Gerd Hoffmann
@ 2013-01-09 15:41 ` Gerd Hoffmann
2013-01-09 15:41 ` [Qemu-devel] [PATCH 3/3] q35: add & windup ich9-pci-hotplug device Gerd Hoffmann
2 siblings, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2013-01-09 15:41 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/acpi_pci_hotplug.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/hw/acpi_pci_hotplug.h b/hw/acpi_pci_hotplug.h
index b97403d..220fca8 100644
--- a/hw/acpi_pci_hotplug.h
+++ b/hw/acpi_pci_hotplug.h
@@ -1,5 +1,5 @@
#define PCI_HOTPLUG_ADDR 0xae00
-#define PCI_HOTPLUG_SIZE 0x000f
+#define PCI_HOTPLUG_SIZE 0x0010
#define PCI_UP_BASE 0xae00
#define PCI_DOWN_BASE 0xae04
#define PCI_EJ_BASE 0xae08
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 3/3] q35: add & windup ich9-pci-hotplug device
2013-01-09 15:41 [Qemu-devel] [RfC PATCH 0/3] q35: acpi hotplug Gerd Hoffmann
2013-01-09 15:41 ` [Qemu-devel] [PATCH 1/3] split acpi pci hotplug code into separate file Gerd Hoffmann
2013-01-09 15:41 ` [Qemu-devel] [PATCH 2/3] fix off-byone in hw/acpi_pci_hotplug.h Gerd Hoffmann
@ 2013-01-09 15:41 ` Gerd Hoffmann
2 siblings, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2013-01-09 15:41 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/acpi_ich9.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/acpi_ich9.h | 1 +
hw/lpc_ich9.c | 5 ++-
3 files changed, 94 insertions(+), 1 deletions(-)
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index d2f9808..5977d4b 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -33,6 +33,7 @@
#include "exec/address-spaces.h"
#include "ich9.h"
+#include "acpi_pci_hotplug.h"
//#define DEBUG
@@ -202,9 +203,97 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
acpi_pm1_evt_power_down(&pm->acpi_regs);
}
+/* ------------------------------------------------------------------ */
+
+#define TYPE_ICH9_PCI_HOTPLUG_DEVICE "ich9-pci-hotplug"
+#define ICH9_PCI_HOTPLUG_DEVICE(obj) \
+ OBJECT_CHECK(ICH9PCIHotplugState, (obj), TYPE_ICH9_PCI_HOTPLUG_DEVICE)
+
+#define ICH9_PCI_HOTPLUG_STATUS 2
+
+typedef struct ICH9PCIHotplugState {
+ PCIDevice parent_obj;
+
+ ICH9LPCPMRegs *pm;
+ ACPIPCI pci;
+} ICH9PCIHotplugState;
+
+static const VMStateDescription vmstate_ich9_pci_hotplug = {
+ .name = TYPE_ICH9_PCI_HOTPLUG_DEVICE,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(pci.pci0_status, ICH9PCIHotplugState, 2,
+ vmstate_pci_status, struct pci_status),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static int ich9_device_hotplug(DeviceState *qdev, PCIDevice *dev,
+ PCIHotplugState state)
+{
+ ICH9PCIHotplugState *s = ICH9_PCI_HOTPLUG_DEVICE(qdev);
+
+ if (acpi_pci_hotplug_device(&s->pci, dev, state)) {
+ s->pm->acpi_regs.gpe.sts[0] |= ICH9_PCI_HOTPLUG_STATUS;
+ pm_update_sci(s->pm);
+ }
+
+ return 0;
+}
+
+static int ich9_pci_hotplug_initfn(PCIDevice *d)
+{
+ ICH9PCIHotplugState *s = ICH9_PCI_HOTPLUG_DEVICE(d);
+
+ acpi_pci_hotplug_init(&s->pci, &d->qdev);
+ pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_IO,
+ &s->pci.io);
+ pci_bus_hotplug(d->bus, ich9_device_hotplug, &d->qdev);
+ return 0;
+}
+
+static void ich9_pci_hotplug_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->vendor_id = 0x1b36; /* Red Hat */
+ k->device_id = 0x0005;
+ k->class_id = PCI_CLASS_BRIDGE_OTHER;
+ k->revision = 1;
+ dc->no_user = 1;
+ dc->vmsd = &vmstate_ich9_pci_hotplug;
+ dc->desc = "ICH9 PCI Hotplug Device";
+ k->init = ich9_pci_hotplug_initfn;
+}
+
+static const TypeInfo ich9_pci_hotplug_info = {
+ .name = TYPE_ICH9_PCI_HOTPLUG_DEVICE,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(ICH9PCIHotplugState),
+ .class_init = ich9_pci_hotplug_class_init,
+};
+
+static void ich9_pci_hotplug_register(void)
+{
+ type_register_static(&ich9_pci_hotplug_info);
+}
+
+type_init(ich9_pci_hotplug_register);
+
+/* ------------------------------------------------------------------ */
+
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
+ PCIDevice *hotplug_pci,
qemu_irq sci_irq, qemu_irq cmos_s3)
{
+ if (hotplug_pci) {
+ ICH9PCIHotplugState *s = ICH9_PCI_HOTPLUG_DEVICE(hotplug_pci);
+ s->pm = pm;
+ }
+
memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE);
memory_region_set_enabled(&pm->io, false);
memory_region_add_subregion(pci_address_space_io(lpc_pci),
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
index ecb82ab..2594eab 100644
--- a/hw/acpi_ich9.h
+++ b/hw/acpi_ich9.h
@@ -45,6 +45,7 @@ typedef struct ICH9LPCPMRegs {
} ICH9LPCPMRegs;
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
+ PCIDevice *hotplug_pci,
qemu_irq sci_irq, qemu_irq cmos_s3_resume);
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
extern const VMStateDescription vmstate_ich9_pm;
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index 16843d7..0ba0303 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -333,10 +333,13 @@ static void ich9_set_sci(void *opaque, int irq_num, int level)
void ich9_lpc_pm_init(PCIDevice *lpc_pci, qemu_irq cmos_s3)
{
ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci);
+ PCIDevice *hp;
qemu_irq *sci_irq;
+ hp = pci_create_simple_multifunction(lpc_pci->bus, PCI_DEVFN(0x1f, 7),
+ true, "ich9-pci-hotplug");
sci_irq = qemu_allocate_irqs(ich9_set_sci, lpc, 1);
- ich9_pm_init(lpc_pci, &lpc->pm, sci_irq[0], cmos_s3);
+ ich9_pm_init(lpc_pci, &lpc->pm, hp, sci_irq[0], cmos_s3);
ich9_lpc_reset(&lpc->d.qdev);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] split acpi pci hotplug code into separate file
2013-01-09 15:41 ` [Qemu-devel] [PATCH 1/3] split acpi pci hotplug code into separate file Gerd Hoffmann
@ 2013-01-09 21:13 ` Blue Swirl
0 siblings, 0 replies; 5+ messages in thread
From: Blue Swirl @ 2013-01-09 21:13 UTC (permalink / raw)
To: Gerd Hoffmann; +Cc: qemu-devel
On Wed, Jan 9, 2013 at 3:41 PM, Gerd Hoffmann <kraxel@redhat.com> wrote:
> Also some minor code restructions along the way:
>
> * create a new struct for acpi pci hotplug state
> * rename functions so they no longer carry piix in the name
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
> hw/Makefile.objs | 2 +-
> hw/acpi_pci_hotplug.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++
> hw/acpi_pci_hotplug.h | 26 ++++++
> hw/acpi_piix4.c | 202 ++--------------------------------------------
> 4 files changed, 250 insertions(+), 194 deletions(-)
> create mode 100644 hw/acpi_pci_hotplug.c
> create mode 100644 hw/acpi_pci_hotplug.h
>
> diff --git a/hw/Makefile.objs b/hw/Makefile.objs
> index 6b8a68c..dc1479f 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -31,7 +31,7 @@ common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
> common-obj-$(CONFIG_PCSPK) += pcspk.o
> common-obj-$(CONFIG_PCKBD) += pckbd.o
> common-obj-$(CONFIG_FDC) += fdc.o
> -common-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o acpi_ich9.o smbus_ich9.o
> +common-obj-$(CONFIG_ACPI) += acpi.o acpi_pci_hotplug.o acpi_piix4.o acpi_ich9.o smbus_ich9.o
> common-obj-$(CONFIG_APM) += pm_smbus.o apm.o
> common-obj-$(CONFIG_DMA) += dma.o
> common-obj-$(CONFIG_I82374) += i82374.o
> diff --git a/hw/acpi_pci_hotplug.c b/hw/acpi_pci_hotplug.c
> new file mode 100644
> index 0000000..cff21bd
> --- /dev/null
> +++ b/hw/acpi_pci_hotplug.c
> @@ -0,0 +1,214 @@
> +/*
> + * ACPI implementation
> + *
> + * Copyright (c) 2006 Fabrice Bellard
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License version 2 as published by the Free Software Foundation.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>
> + *
> + * Contributions after 2012-01-13 are licensed under the terms of the
> + * GNU GPL, version 2 or (at your option) any later version.
> + */
> +
> +#include "hw.h"
> +#include "pci/pci.h"
> +
> +#include "acpi_pci_hotplug.h"
> +
> +//#define DEBUG
> +
> +#ifdef DEBUG
> +# define DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
> +#else
> +# define DPRINTF(format, ...) do { } while (0)
> +#endif
> +
> +static void acpi_pci_hotplug_eject_slot(ACPIPCI *s, unsigned slots)
> +{
> + BusChild *kid, *next;
> + BusState *bus = s->bus;
> + int slot = ffs(slots) - 1;
> + bool slot_free = true;
> +
> + /* Mark request as complete */
> + s->pci0_status.down &= ~(1U << slot);
> +
> + QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
> + DeviceState *qdev = kid->child;
> + PCIDevice *dev = PCI_DEVICE(qdev);
> + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
> + if (PCI_SLOT(dev->devfn) == slot) {
> + if (pc->no_hotplug) {
> + slot_free = false;
> + } else {
> + qdev_free(qdev);
> + }
> + }
> + }
> + if (slot_free) {
> + s->pci0_slot_device_present &= ~(1U << slot);
> + }
> +}
> +
> +static uint32_t pci_up_read(void *opaque, uint32_t addr)
> +{
> + ACPIPCI *s = opaque;
> + uint32_t val;
> +
> + /* Manufacture an "up" value to cause a device check on any hotplug
> + * slot with a device. Extra device checks are harmless. */
> + val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
> +
> + DPRINTF("pci_up_read %x\n", val);
> + return val;
> +}
> +
> +static uint32_t pci_down_read(void *opaque, uint32_t addr)
> +{
> + ACPIPCI *s = opaque;
> + uint32_t val = s->pci0_status.down;
> +
> + DPRINTF("pci_down_read %x\n", val);
> + return val;
> +}
> +
> +static uint32_t pci_features_read(void *opaque, uint32_t addr)
> +{
> + /* No feature defined yet */
> + DPRINTF("pci_features_read %x\n", 0);
> + return 0;
> +}
> +
> +static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
> +{
> + acpi_pci_hotplug_eject_slot(opaque, val);
> +
> + DPRINTF("pciej write %x <== %d\n", addr, val);
> +}
> +
> +static uint32_t pcirmv_read(void *opaque, uint32_t addr)
> +{
> + ACPIPCI *s = opaque;
> +
> + return s->pci0_hotplug_enable;
> +}
> +
> +static const MemoryRegionOps piix4_pci_ops = {
> + .old_portio = (MemoryRegionPortio[]) {
> + {
> + .offset = PCI_UP_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
> + .read = pci_up_read,
> + },{
> + .offset = PCI_DOWN_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
> + .read = pci_down_read,
> + },{
> + .offset = PCI_EJ_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
> + .read = pci_features_read,
> + .write = pciej_write,
> + },{
> + .offset = PCI_RMV_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
> + .read = pcirmv_read,
> + },
> + PORTIO_END_OF_LIST()
> + },
> + .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static void vmstate_pci_status_pre_save(void *opaque)
> +{
> + struct pci_status *pci0_status = opaque;
> + ACPIPCI *s = container_of(pci0_status, ACPIPCI, pci0_status);
> +
> + /* We no longer track up, so build a safe value for migrating
> + * to a version that still does... of course these might get lost
> + * by an old buggy implementation, but we try. */
> + pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable;
> +}
> +
> +const VMStateDescription vmstate_pci_status = {
> + .name = "pci_status",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .minimum_version_id_old = 1,
> + .pre_save = vmstate_pci_status_pre_save,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT32(up, struct pci_status),
> + VMSTATE_UINT32(down, struct pci_status),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> +void acpi_pci_hotplug_update(ACPIPCI *s)
> +{
> + BusState *bus = s->bus;
> + BusChild *kid, *next;
> +
> + /* Execute any pending removes during reset */
> + while (s->pci0_status.down) {
> + acpi_pci_hotplug_eject_slot(s, s->pci0_status.down);
> + }
> +
> + s->pci0_hotplug_enable = ~0;
> + s->pci0_slot_device_present = 0;
> +
> + QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
> + DeviceState *qdev = kid->child;
> + PCIDevice *pdev = PCI_DEVICE(qdev);
> + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
> + int slot = PCI_SLOT(pdev->devfn);
> +
> + if (pc->no_hotplug) {
> + s->pci0_hotplug_enable &= ~(1U << slot);
> + }
> +
> + s->pci0_slot_device_present |= (1U << slot);
> + }
> +}
> +
> +void acpi_pci_hotplug_init(ACPIPCI *s, DeviceState *qdev)
> +{
> + s->bus = qdev_get_parent_bus(qdev);
> + memory_region_init_io(&s->io, &piix4_pci_ops, s, "apci-pci-hotplug",
> + PCI_HOTPLUG_SIZE);
> +}
> +
> +
> +static void enable_device(ACPIPCI *s, int slot)
> +{
> + s->pci0_slot_device_present |= (1U << slot);
> +}
> +
> +static void disable_device(ACPIPCI *s, int slot)
> +{
> + s->pci0_status.down |= (1U << slot);
> +}
> +
> +int acpi_pci_hotplug_device(ACPIPCI *s, PCIDevice *dev,
> + PCIHotplugState state)
> +{
> + int slot = PCI_SLOT(dev->devfn);
> +
> + /* Don't send event when device is enabled during qemu machine creation:
> + * it is present on boot, no hotplug event is necessary. We do send an
> + * event when the device is disabled later. */
> + if (state == PCI_COLDPLUG_ENABLED) {
> + s->pci0_slot_device_present |= (1U << slot);
> + return 0;
> + }
> +
> + if (state == PCI_HOTPLUG_ENABLED) {
> + enable_device(s, slot);
> + } else {
> + disable_device(s, slot);
> + }
> + return 1;
> +}
> diff --git a/hw/acpi_pci_hotplug.h b/hw/acpi_pci_hotplug.h
> new file mode 100644
> index 0000000..b97403d
> --- /dev/null
> +++ b/hw/acpi_pci_hotplug.h
> @@ -0,0 +1,26 @@
> +#define PCI_HOTPLUG_ADDR 0xae00
> +#define PCI_HOTPLUG_SIZE 0x000f
> +#define PCI_UP_BASE 0xae00
> +#define PCI_DOWN_BASE 0xae04
> +#define PCI_EJ_BASE 0xae08
> +#define PCI_RMV_BASE 0xae0c
> +
> +struct pci_status {
This should be renamed to PCIStatus and the typedef added. Perhaps
with a separate patch.
> + uint32_t up; /* deprecated, maintained for migration compatibility */
> + uint32_t down;
> +};
> +
> +typedef struct ACPIPCI {
> + MemoryRegion io;
> + BusState *bus;
> + struct pci_status pci0_status;
> + uint32_t pci0_hotplug_enable;
> + uint32_t pci0_slot_device_present;
> +} ACPIPCI;
> +
> +extern const VMStateDescription vmstate_pci_status;
> +
> +void acpi_pci_hotplug_update(ACPIPCI *s);
> +void acpi_pci_hotplug_init(ACPIPCI *s, DeviceState *qdev);
> +int acpi_pci_hotplug_device(ACPIPCI *s, PCIDevice *dev,
> + PCIHotplugState state);
> diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
> index 06a8aca..1374116 100644
> --- a/hw/acpi_piix4.c
> +++ b/hw/acpi_piix4.c
> @@ -29,6 +29,7 @@
> #include "exec/ioport.h"
> #include "fw_cfg.h"
> #include "exec/address-spaces.h"
> +#include "acpi_pci_hotplug.h"
>
> //#define DEBUG
>
> @@ -41,27 +42,15 @@
> #define GPE_BASE 0xafe0
> #define GPE_LEN 4
>
> -#define PCI_HOTPLUG_ADDR 0xae00
> -#define PCI_HOTPLUG_SIZE 0x000f
> -#define PCI_UP_BASE 0xae00
> -#define PCI_DOWN_BASE 0xae04
> -#define PCI_EJ_BASE 0xae08
> -#define PCI_RMV_BASE 0xae0c
> -
> #define PIIX4_PCI_HOTPLUG_STATUS 2
>
> -struct pci_status {
> - uint32_t up; /* deprecated, maintained for migration compatibility */
> - uint32_t down;
> -};
> -
> typedef struct PIIX4PMState {
> PCIDevice dev;
>
> MemoryRegion io;
> MemoryRegion io_gpe;
> - MemoryRegion io_pci;
> ACPIREGS ar;
> + ACPIPCI pci;
>
> APMState apm;
>
> @@ -74,11 +63,6 @@ typedef struct PIIX4PMState {
> Notifier machine_ready;
> Notifier powerdown_notifier;
>
> - /* for pci hotplug */
> - struct pci_status pci0_status;
> - uint32_t pci0_hotplug_enable;
> - uint32_t pci0_slot_device_present;
> -
> uint8_t disable_s3;
> uint8_t disable_s4;
> uint8_t s4_val;
> @@ -167,17 +151,6 @@ static void pm_write_config(PCIDevice *d,
> }
> }
>
> -static void vmstate_pci_status_pre_save(void *opaque)
> -{
> - struct pci_status *pci0_status = opaque;
> - PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status);
> -
> - /* We no longer track up, so build a safe value for migrating
> - * to a version that still does... of course these might get lost
> - * by an old buggy implementation, but we try. */
> - pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable;
> -}
> -
> static int vmstate_acpi_post_load(void *opaque, int version_id)
> {
> PIIX4PMState *s = opaque;
> @@ -208,19 +181,6 @@ static const VMStateDescription vmstate_gpe = {
> }
> };
>
> -static const VMStateDescription vmstate_pci_status = {
> - .name = "pci_status",
> - .version_id = 1,
> - .minimum_version_id = 1,
> - .minimum_version_id_old = 1,
> - .pre_save = vmstate_pci_status_pre_save,
> - .fields = (VMStateField []) {
> - VMSTATE_UINT32(up, struct pci_status),
> - VMSTATE_UINT32(down, struct pci_status),
> - VMSTATE_END_OF_LIST()
> - }
> -};
> -
> static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
> {
> PIIX4PMState *s = opaque;
> @@ -279,67 +239,12 @@ static const VMStateDescription vmstate_acpi = {
> VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
> VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
> VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
> - VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
> + VMSTATE_STRUCT(pci.pci0_status, PIIX4PMState, 2, vmstate_pci_status,
> struct pci_status),
> VMSTATE_END_OF_LIST()
> }
> };
>
> -static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
> -{
> - BusChild *kid, *next;
> - BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
> - int slot = ffs(slots) - 1;
> - bool slot_free = true;
> -
> - /* Mark request as complete */
> - s->pci0_status.down &= ~(1U << slot);
> -
> - QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
> - DeviceState *qdev = kid->child;
> - PCIDevice *dev = PCI_DEVICE(qdev);
> - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
> - if (PCI_SLOT(dev->devfn) == slot) {
> - if (pc->no_hotplug) {
> - slot_free = false;
> - } else {
> - qdev_free(qdev);
> - }
> - }
> - }
> - if (slot_free) {
> - s->pci0_slot_device_present &= ~(1U << slot);
> - }
> -}
> -
> -static void piix4_update_hotplug(PIIX4PMState *s)
> -{
> - PCIDevice *dev = &s->dev;
> - BusState *bus = qdev_get_parent_bus(&dev->qdev);
> - BusChild *kid, *next;
> -
> - /* Execute any pending removes during reset */
> - while (s->pci0_status.down) {
> - acpi_piix_eject_slot(s, s->pci0_status.down);
> - }
> -
> - s->pci0_hotplug_enable = ~0;
> - s->pci0_slot_device_present = 0;
> -
> - QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
> - DeviceState *qdev = kid->child;
> - PCIDevice *pdev = PCI_DEVICE(qdev);
> - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
> - int slot = PCI_SLOT(pdev->devfn);
> -
> - if (pc->no_hotplug) {
> - s->pci0_hotplug_enable &= ~(1U << slot);
> - }
> -
> - s->pci0_slot_device_present |= (1U << slot);
> - }
> -}
> -
> static void piix4_reset(void *opaque)
> {
> PIIX4PMState *s = opaque;
> @@ -357,7 +262,7 @@ static void piix4_reset(void *opaque)
> /* Mark SMM as already inited (until KVM supports SMM). */
> pci_conf[0x5B] = 0x02;
> }
> - piix4_update_hotplug(s);
> + acpi_pci_hotplug_update(&s->pci);
> }
>
> static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
> @@ -531,70 +436,6 @@ static const MemoryRegionOps piix4_gpe_ops = {
> .endianness = DEVICE_LITTLE_ENDIAN,
> };
>
> -static uint32_t pci_up_read(void *opaque, uint32_t addr)
> -{
> - PIIX4PMState *s = opaque;
> - uint32_t val;
> -
> - /* Manufacture an "up" value to cause a device check on any hotplug
> - * slot with a device. Extra device checks are harmless. */
> - val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
> -
> - PIIX4_DPRINTF("pci_up_read %x\n", val);
> - return val;
> -}
> -
> -static uint32_t pci_down_read(void *opaque, uint32_t addr)
> -{
> - PIIX4PMState *s = opaque;
> - uint32_t val = s->pci0_status.down;
> -
> - PIIX4_DPRINTF("pci_down_read %x\n", val);
> - return val;
> -}
> -
> -static uint32_t pci_features_read(void *opaque, uint32_t addr)
> -{
> - /* No feature defined yet */
> - PIIX4_DPRINTF("pci_features_read %x\n", 0);
> - return 0;
> -}
> -
> -static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
> -{
> - acpi_piix_eject_slot(opaque, val);
> -
> - PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
> -}
> -
> -static uint32_t pcirmv_read(void *opaque, uint32_t addr)
> -{
> - PIIX4PMState *s = opaque;
> -
> - return s->pci0_hotplug_enable;
> -}
> -
> -static const MemoryRegionOps piix4_pci_ops = {
> - .old_portio = (MemoryRegionPortio[]) {
> - {
> - .offset = PCI_UP_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
> - .read = pci_up_read,
> - },{
> - .offset = PCI_DOWN_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
> - .read = pci_down_read,
> - },{
> - .offset = PCI_EJ_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
> - .read = pci_features_read,
> - .write = pciej_write,
> - },{
> - .offset = PCI_RMV_BASE - PCI_HOTPLUG_ADDR, .len = 4, .size = 4,
> - .read = pcirmv_read,
> - },
> - PORTIO_END_OF_LIST()
> - },
> - .endianness = DEVICE_LITTLE_ENDIAN,
> -};
> -
> static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
> PCIHotplugState state);
>
> @@ -605,47 +446,22 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
> GPE_LEN);
> memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
>
> - memory_region_init_io(&s->io_pci, &piix4_pci_ops, s, "apci-pci-hotplug",
> - PCI_HOTPLUG_SIZE);
> + acpi_pci_hotplug_init(&s->pci, &s->dev.qdev);
> memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
> - &s->io_pci);
> + &s->pci.io);
> pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
> }
>
> -static void enable_device(PIIX4PMState *s, int slot)
> -{
> - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
> - s->pci0_slot_device_present |= (1U << slot);
> -}
> -
> -static void disable_device(PIIX4PMState *s, int slot)
> -{
> - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
> - s->pci0_status.down |= (1U << slot);
> -}
> -
> static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
> PCIHotplugState state)
> {
> - int slot = PCI_SLOT(dev->devfn);
> PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev,
> PCI_DEVICE(qdev));
>
> - /* Don't send event when device is enabled during qemu machine creation:
> - * it is present on boot, no hotplug event is necessary. We do send an
> - * event when the device is disabled later. */
> - if (state == PCI_COLDPLUG_ENABLED) {
> - s->pci0_slot_device_present |= (1U << slot);
> - return 0;
> + if (acpi_pci_hotplug_device(&s->pci, dev, state)) {
> + s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
> + pm_update_sci(s);
> }
>
> - if (state == PCI_HOTPLUG_ENABLED) {
> - enable_device(s, slot);
> - } else {
> - disable_device(s, slot);
> - }
> -
> - pm_update_sci(s);
> -
> return 0;
> }
> --
> 1.7.1
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-01-09 21:14 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-09 15:41 [Qemu-devel] [RfC PATCH 0/3] q35: acpi hotplug Gerd Hoffmann
2013-01-09 15:41 ` [Qemu-devel] [PATCH 1/3] split acpi pci hotplug code into separate file Gerd Hoffmann
2013-01-09 21:13 ` Blue Swirl
2013-01-09 15:41 ` [Qemu-devel] [PATCH 2/3] fix off-byone in hw/acpi_pci_hotplug.h Gerd Hoffmann
2013-01-09 15:41 ` [Qemu-devel] [PATCH 3/3] q35: add & windup ich9-pci-hotplug device Gerd Hoffmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).