From: "Michael S. Tsirkin" <mst@redhat.com>
To: Jason Baron <jbaron@redhat.com>
Cc: agraf@suse.de, aliguori@us.ibm.com, juzhang@redhat.com,
jan.kiszka@siemens.com, qemu-devel@nongnu.org, armbru@redhat.com,
blauwirbel@gmail.com, yamahata@valinux.co.jp,
alex.williamson@redhat.com, kevin@koconnor.net, avi@redhat.com,
mkletzan@redhat.com, pbonzini@redhat.com, lcapitulino@redhat.com,
afaerber@suse.de, kraxel@redhat.com
Subject: Re: [Qemu-devel] [PATCH v2 21/21] q35: add acpi-based pci hotplug.
Date: Thu, 11 Oct 2012 12:57:06 +0200 [thread overview]
Message-ID: <20121011105705.GE5552@redhat.com> (raw)
In-Reply-To: <d7a7e7fccdb3d81ae1ee7c021e1ebbcf36aaa6e3.1349749915.git.jbaron@redhat.com>
On Mon, Oct 08, 2012 at 11:30:39PM -0400, Jason Baron wrote:
> From: Jason Baron <jbaron@redhat.com>
>
> Add piix style acpi hotplug to q35.
>
> Signed-off-by: Jason Baron <jbaron@redhat.com>
Something I don't understand here: this only handles hotplug
of devices behind the root, no?
Don't we need support for hotplug/hot remove of devices behind
bridges?
> ---
> hw/acpi_ich9.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> hw/acpi_ich9.h | 10 +++
> 2 files changed, 181 insertions(+), 1 deletions(-)
>
> diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
> index 1412ad3..412c9c1 100644
> --- a/hw/acpi_ich9.c
> +++ b/hw/acpi_ich9.c
> @@ -41,6 +41,13 @@ do { printf("%s "fmt, __func__, ## __VA_ARGS__); } while (0)
> #define ICH9_DEBUG(fmt, ...) do { } while (0)
> #endif
>
> +#define PCI_UP_BASE 0xae00
> +#define PCI_DOWN_BASE 0xae04
> +#define PCI_EJ_BASE 0xae08
> +#define PCI_RMV_BASE 0xae0c
> +#define ICH9_PCI_HOTPLUG_STATUS 2
> +
> +
> static void pm_ioport_write_fallback(void *opaque, uint32_t addr, int len,
> uint32_t val);
> static uint32_t pm_ioport_read_fallback(void *opaque, uint32_t addr, int len);
> @@ -55,7 +62,10 @@ static void pm_update_sci(ICH9LPCPMRegs *pm)
> (ACPI_BITMASK_RT_CLOCK_ENABLE |
> ACPI_BITMASK_POWER_BUTTON_ENABLE |
> ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
> - ACPI_BITMASK_TIMER_ENABLE)) != 0);
> + ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
> + (((pm->acpi_regs.gpe.sts[0] & pm->acpi_regs.gpe.en[0])
> + & ICH9_PCI_HOTPLUG_STATUS) != 0);
> +
> qemu_set_irq(pm->irq, sci_level);
>
> /* schedule a timer interruption if needed */
> @@ -77,6 +87,7 @@ static void pm_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
> switch (addr & ICH9_PMIO_MASK) {
> case ICH9_PMIO_GPE0_STS ... (ICH9_PMIO_GPE0_STS + ICH9_PMIO_GPE0_LEN - 1):
> acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
> + pm_update_sci(pm);
> break;
> default:
> break;
> @@ -283,6 +294,65 @@ const VMStateDescription vmstate_ich9_pm = {
> }
> };
>
> +static void acpi_ich9_eject_slot(ICH9LPCPMRegs *opaque, unsigned slots)
> +{
> + BusChild *kid, *next;
> + ICH9LPCPMRegs *pm = opaque;
> + ICH9LPCState *lpc = container_of(pm, ICH9LPCState, pm);
> + PCIDevice *s = PCI_DEVICE(lpc);
> + BusState *bus = qdev_get_parent_bus(&s->qdev);
> + int slot = ffs(slots) - 1;
> + bool slot_free = true;
> +
> + /* Mark request as complete */
> + pm->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) {
> + pm->pci0_slot_device_present &= ~(1U << slot);
> + }
> +}
> +
> +static void acpi_ich9_update_hotplug(ICH9LPCPMRegs *pm)
> +{
> + ICH9LPCState *lpc = container_of(pm, ICH9LPCState, pm);
> + PCIDevice *dev = PCI_DEVICE(lpc);
> + BusState *bus = qdev_get_parent_bus(&dev->qdev);
> + BusChild *kid, *next;
> +
> + /* Execute any pending removes during reset */
> + while (pm->pci0_status.down) {
> + acpi_ich9_eject_slot(pm, pm->pci0_status.down);
> + }
> +
> + pm->pci0_hotplug_enable = ~0;
> + pm->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) {
> + pm->pci0_hotplug_enable &= ~(1U << slot);
> + }
> +
> + pm->pci0_slot_device_present |= (1U << slot);
> + }
> +}
> +
> static void pm_reset(void *opaque)
> {
> ICH9LPCPMRegs *pm = opaque;
> @@ -300,6 +370,7 @@ static void pm_reset(void *opaque)
> }
>
> pm_update_sci(pm);
> + acpi_ich9_update_hotplug(pm);
> }
>
> static void pm_powerdown_req(Notifier *n, void *opaque)
> @@ -309,6 +380,104 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
> acpi_pm1_evt_power_down(&pm->acpi_regs);
> }
>
> +static uint32_t pci_up_read(void *opaque, uint32_t addr)
> +{
> + ICH9LPCPMRegs *pm = 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 = pm->pci0_slot_device_present & pm->pci0_hotplug_enable;
> +
> + ICH9_DEBUG("pci_up_read %x\n", val);
> + return val;
> +}
> +
> +static uint32_t pci_down_read(void *opaque, uint32_t addr)
> +{
> + ICH9LPCPMRegs *pm = opaque;
> + uint32_t val = pm->pci0_status.down;
> +
> + ICH9_DEBUG("pci_down_read %x\n", val);
> + return val;
> +}
> +
> +static uint32_t pci_features_read(void *opaque, uint32_t addr)
> +{
> + /* No feature defined yet */
> + ICH9_DEBUG("pci_features_read %x\n", 0);
> + return 0;
> +}
> +
> +static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
> +{
> + acpi_ich9_eject_slot(opaque, val);
> +
> + ICH9_DEBUG("pciej write %x <== %d\n", addr, val);
> +}
> +
> +static uint32_t pcirmv_read(void *opaque, uint32_t addr)
> +{
> + ICH9LPCPMRegs *pm = opaque;
> +
> + return pm->pci0_hotplug_enable;
> +}
> +
> +static void enable_device(ICH9LPCPMRegs *pm, int slot)
> +{
> + pm->acpi_regs.gpe.sts[0] |= ICH9_PCI_HOTPLUG_STATUS;
> + pm->pci0_slot_device_present |= (1U << slot);
> +}
> +
> +static void disable_device(ICH9LPCPMRegs *pm, int slot)
> +{
> + pm->acpi_regs.gpe.sts[0] |= ICH9_PCI_HOTPLUG_STATUS;
> + pm->pci0_status.down |= (1U << slot);
> +}
> +
> +static int ich9_device_hotplug(DeviceState *qdev, PCIDevice *dev,
> + PCIHotplugState state)
> +{
> + int slot = PCI_SLOT(dev->devfn);
> + ICH9LPCState *lpc = DO_UPCAST(ICH9LPCState, d,
> + PCI_DEVICE(qdev));
> + ICH9LPCPMRegs *pm = &lpc->pm;
> +
> + /* 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) {
> + pm->pci0_slot_device_present |= (1U << slot);
> + return 0;
> + }
> +
> + if (state == PCI_HOTPLUG_ENABLED) {
> + enable_device(pm, slot);
> + } else {
> + disable_device(pm, slot);
> + }
> +
> + pm_update_sci(pm);
> +
> + return 0;
> +}
> +
> +static void ich9_acpi_system_hot_add_init(ICH9LPCPMRegs *s)
> +{
> + ICH9LPCState *lpc = container_of(s, ICH9LPCState, pm);
> + PCIDevice *pdev = PCI_DEVICE(lpc);
> +
> + register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s);
> + register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s);
> +
> + register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, s);
> + register_ioport_read(PCI_EJ_BASE, 4, 4, pci_features_read, s);
> +
> + register_ioport_read(PCI_RMV_BASE, 4, 4, pcirmv_read, s);
> +
> + pci_bus_hotplug(pdev->bus, ich9_device_hotplug, &pdev->qdev);
> +}
> +
> void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
> {
> acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn);
> @@ -319,4 +488,5 @@ void ich9_pm_init(ICH9LPCPMRegs *pm, qemu_irq sci_irq, qemu_irq cmos_s3)
> qemu_register_reset(pm_reset, pm);
> pm->powerdown_notifier.notify = pm_powerdown_req;
> qemu_register_powerdown_notifier(&pm->powerdown_notifier);
> + ich9_acpi_system_hot_add_init(pm);
> }
> diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
> index 180c406..b4e2aff 100644
> --- a/hw/acpi_ich9.h
> +++ b/hw/acpi_ich9.h
> @@ -23,6 +23,11 @@
>
> #include "acpi.h"
>
> +struct pci_status {
> + uint32_t up; /* deprecated, maintained for migration compatibility */
> + uint32_t down;
> +};
> +
> typedef struct ICH9LPCPMRegs {
> /*
> * In ich9 spec says that pm1_cnt register is 32bit width and
> @@ -37,6 +42,11 @@ typedef struct ICH9LPCPMRegs {
>
> uint32_t pm_io_base;
> Notifier powerdown_notifier;
> +
> + /* for pci hotplug */
> + struct pci_status pci0_status;
> + uint32_t pci0_hotplug_enable;
> + uint32_t pci0_slot_device_present;
> } ICH9LPCPMRegs;
>
> void ich9_pm_init(ICH9LPCPMRegs *pm,
> --
> 1.7.1
next prev parent reply other threads:[~2012-10-11 10:55 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-09 3:30 [Qemu-devel] [PATCH v2 00/21] q35 qemu support Jason Baron
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 01/21] blockdev: Introduce a default machine blockdev interface field, QEMUMachine->mach_if Jason Baron
2012-10-09 7:34 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 03/21] pci: pci capability must be in PCI space Jason Baron
2012-10-09 7:36 ` Paolo Bonzini
2012-10-13 8:29 ` Blue Swirl
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 02/21] blockdev: Introduce IF_AHCI Jason Baron
2012-10-09 7:36 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 04/21] pci: introduce pci_swizzle_map_irq_fn() for standardized interrupt pin swizzle Jason Baron
2012-10-09 7:39 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 05/21] pc, pc_piix: split out pc nic initialization Jason Baron
2012-10-09 7:39 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 06/21] pc: Move ioapic_init() from pc_piix.c to pc.c Jason Baron
2012-10-09 7:44 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 07/21] pc/piix_pci: factor out smram/pam logic Jason Baron
2012-10-09 7:47 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 08/21] pci_ids: add intel 82801BA pci-to-pci bridge id and PCI_CLASS_SERIAL_SMBUS Jason Baron
2012-10-09 7:48 ` Paolo Bonzini
2012-10-13 8:31 ` Blue Swirl
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 09/21] pci: Add class 0xc05 as 'SMBus' Jason Baron
2012-10-09 7:49 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 10/21] pcie: pass pcie window size to pcie_host_mmcfg_update() Jason Baron
2012-10-09 7:52 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 12/21] q35: Introduce q35 pc based chipset emulator Jason Baron
2012-10-11 14:47 ` Michael S. Tsirkin
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 11/21] pcie: Convert PCIExpressHost to use the QOM Jason Baron
2012-10-09 7:52 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 13/21] q35: Re-base q35 Jason Baron
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 14/21] q35: Suppress SMM BIOS initialization under KVM Jason Baron
2012-10-09 7:53 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 15/21] q35: Fix non-PCI IRQ processing in ich9_lpc_update_apic Jason Baron
2012-10-09 7:53 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 16/21] q35: smbus: Remove PCI_STATUS_SIG_SYSTEM_ERROR and PCI_STATUS_DETECTED_PARITY from w1cmask Jason Baron
2012-10-09 7:54 ` Paolo Bonzini
2012-10-11 14:53 ` Michael S. Tsirkin
2012-10-19 15:13 ` Jason Baron
2012-10-19 16:17 ` Isaku Yamahata
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 17/21] q35: Add kvmclock support Jason Baron
2012-10-09 7:54 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 18/21] q35: Fix irr initialization for slots 25..31 Jason Baron
2012-10-09 7:58 ` Paolo Bonzini
2012-10-11 14:49 ` Michael S. Tsirkin
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 19/21] Add a fallback bios file search, if -L fails Jason Baron
2012-10-09 7:59 ` Paolo Bonzini
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 20/21] q35: automatically load the q35 dsdt table Jason Baron
2012-10-09 8:02 ` Paolo Bonzini
2012-10-09 8:29 ` Paolo Bonzini
2012-10-09 20:06 ` Jason Baron
2012-10-13 8:33 ` Blue Swirl
2012-10-09 3:30 ` [Qemu-devel] [PATCH v2 21/21] q35: add acpi-based pci hotplug Jason Baron
2012-10-09 8:04 ` Paolo Bonzini
2012-10-11 10:57 ` Michael S. Tsirkin [this message]
2012-10-11 14:21 ` Jason Baron
2012-10-11 14:46 ` Michael S. Tsirkin
2012-10-11 14:54 ` Paolo Bonzini
2012-10-11 15:40 ` Jason Baron
2012-10-11 15:34 ` Jason Baron
2012-10-11 20:40 ` Michael S. Tsirkin
2012-10-12 15:27 ` Jason Baron
2012-10-13 23:03 ` Michael S. Tsirkin
2012-10-12 7:27 ` Gerd Hoffmann
2012-10-12 9:39 ` Michael S. Tsirkin
2012-10-12 10:06 ` Gerd Hoffmann
2012-10-12 10:39 ` Michael S. Tsirkin
2012-10-12 15:00 ` Jason Baron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20121011105705.GE5552@redhat.com \
--to=mst@redhat.com \
--cc=afaerber@suse.de \
--cc=agraf@suse.de \
--cc=alex.williamson@redhat.com \
--cc=aliguori@us.ibm.com \
--cc=armbru@redhat.com \
--cc=avi@redhat.com \
--cc=blauwirbel@gmail.com \
--cc=jan.kiszka@siemens.com \
--cc=jbaron@redhat.com \
--cc=juzhang@redhat.com \
--cc=kevin@koconnor.net \
--cc=kraxel@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=mkletzan@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=yamahata@valinux.co.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).