From 5a2223ca26b1a34e131b5b9a63599d9426d2c25c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 26 Jan 2014 12:31:27 +0200 Subject: pcihp: reduce number of device check events PIIX created a made-up value for the UP register since it was read by guest 32 times for each interrupt. There's no reason to do this for the new PCIHP: register is only read once for each interrupt, so clean up code by making read act as an interrupt acknowledgement: the new UP register clear on read. In this way we cut down the number of bus rescans by a factor of 32, and drop a bunch of code that's now unused. Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/pcihp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/hw') diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index 6230e60..aa297c2 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -32,7 +32,7 @@ #include "hw/pci/pci.h" /* for PCIHotplugState */ typedef struct AcpiPciHpPciStatus { - uint32_t up; /* deprecated, maintained for migration compatibility */ + uint32_t up; uint32_t down; uint32_t hotplug_enable; uint32_t device_present; -- cgit v1.1 From 99d09dd32820f5702031e3c08c81f8c209dc2220 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 3 Feb 2014 11:44:59 +0100 Subject: pcihp: make pci_read() mmio calback compatible with legacy ACPI hotplug due to recent change introduced by: "pcihp: reduce number of device check events" 'up' field is cleared right after it's read. This is incompatible with legacy BIOS ACPI code where PCNF ACPI method reads this field 32 times. To make pci_read mmio callback compatible with legacy 'up' behavior, pcihp code will need to know in which mode it runs add 'legacy_piix' field to AcpiPciHpState structure and alter register behavior accordingly. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/pcihp.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/hw') diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index aa297c2..02d3ce3 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -46,10 +46,11 @@ typedef struct AcpiPciHpState { uint32_t hotplug_select; PCIBus *root; MemoryRegion io; + bool legacy_piix; } AcpiPciHpState; void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root, - MemoryRegion *address_space_io); + MemoryRegion *address_space_io, bool bridges_enabled); /* Invoke on device hotplug */ int acpi_pcihp_device_hotplug(AcpiPciHpState *, PCIDevice *, -- cgit v1.1 From a1b4d9eff9e8dec8b827bd744c7d670d3cdf2fb8 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 3 Feb 2014 11:45:00 +0100 Subject: pcihp: remove unused AcpiPciHpPciStatus.device_present field Remove now unused 'device_present' field wich was obsoleted by patch "pcihp: reduce number of device check events" Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/pcihp.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/hw') diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index 02d3ce3..1fd90e1 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -35,7 +35,6 @@ typedef struct AcpiPciHpPciStatus { uint32_t up; uint32_t down; uint32_t hotplug_enable; - uint32_t device_present; } AcpiPciHpPciStatus; #define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel" -- cgit v1.1 From e358edc8e90d580443b824e4ef799e137377ad86 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 3 Feb 2014 11:45:01 +0100 Subject: hw:piix4:acpi: reuse pcihp code for legacy PCI hotplug reduces acpi PCI hotplug code duplication by ~200LOC Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/pcihp.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/hw') diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index 1fd90e1..0a90e4a 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -39,6 +39,7 @@ typedef struct AcpiPciHpPciStatus { #define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel" #define ACPI_PCIHP_MAX_HOTPLUG_BUS 256 +#define ACPI_PCIHP_BSEL_DEFAULT 0x0 typedef struct AcpiPciHpState { AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS]; -- cgit v1.1 From a1483f88b6e21dd3ea481a021e5d4f7f273204c6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 5 Feb 2014 21:57:55 +0200 Subject: loader: document that errno is set Document that get_image_size sets errno on failure. Suggested-by: Peter Maydell Reviewed-by: Eric Blake Signed-off-by: Michael S. Tsirkin --- include/hw/loader.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/hw') diff --git a/include/hw/loader.h b/include/hw/loader.h index 7a23d6b..91b0122 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -4,6 +4,13 @@ #include "hw/nvram/fw_cfg.h" /* loader.c */ +/** + * get_image_size: retrieve size of an image file + * @filename: Path to the image file + * + * Returns the size of the image file on success, -1 otherwise. + * On error, errno is also set as appropriate. + */ int get_image_size(const char *filename); int load_image(const char *filename, uint8_t *addr); /* deprecated */ int load_image_targphys(const char *filename, hwaddr, -- cgit v1.1 From 9f117d41841e13ca29cc2a10ac03258339ea1f8b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Feb 2014 16:36:44 +0100 Subject: define hotplug interface Provide a generic hotplug interface for hotplug handlers. Intended for replacing hotplug mechanism used by PCI/PCIE/SHPC code and will be used for memory hotplug. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/hotplug.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 include/hw/hotplug.h (limited to 'include/hw') diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h new file mode 100644 index 0000000..a6533cb --- /dev/null +++ b/include/hw/hotplug.h @@ -0,0 +1,78 @@ +/* + * Hotplug handler interface. + * + * Copyright (c) 2014 Red Hat Inc. + * + * Authors: + * Igor Mammedov , + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef HOTPLUG_H +#define HOTPLUG_H + +#include "qom/object.h" +#include "qemu/typedefs.h" + +#define TYPE_HOTPLUG_HANDLER "hotplug-handler" + +#define HOTPLUG_HANDLER_CLASS(klass) \ + OBJECT_CLASS_CHECK(HotplugHandlerClass, (klass), TYPE_HOTPLUG_HANDLER) +#define HOTPLUG_HANDLER_GET_CLASS(obj) \ + OBJECT_GET_CLASS(HotplugHandlerClass, (obj), TYPE_HOTPLUG_HANDLER) +#define HOTPLUG_HANDLER(obj) \ + INTERFACE_CHECK(HotplugHandler, (obj), TYPE_HOTPLUG_HANDLER) + + +typedef struct HotplugHandler { + /* */ + Object Parent; +} HotplugHandler; + +/** + * hotplug_fn: + * @plug_handler: a device performing plug/uplug action + * @plugged_dev: a device that has been (un)plugged + * @errp: returns an error if this function fails + */ +typedef void (*hotplug_fn)(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp); + +/** + * HotplugDeviceClass: + * + * Interface to be implemented by a device performing + * hardware (un)plug functions. + * + * @parent: Opaque parent interface. + * @plug: plug callback. + * @unplug: unplug callback. + */ +typedef struct HotplugHandlerClass { + /* */ + InterfaceClass parent; + + /* */ + hotplug_fn plug; + hotplug_fn unplug; +} HotplugHandlerClass; + +/** + * hotplug_handler_plug: + * + * Call #HotplugHandlerClass.plug callback of @plug_handler. + */ +void hotplug_handler_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp); + +/** + * hotplug_handler_unplug: + * + * Call #HotplugHandlerClass.unplug callback of @plug_handler. + */ +void hotplug_handler_unplug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp); +#endif -- cgit v1.1 From 0ee4de6ce1d403b3d8017b340cec772c3c5c106f Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Feb 2014 16:36:45 +0100 Subject: qdev: add to BusState "hotplug-handler" link It will allow to reuse field with different BUSes, reducing code duplication. Field is intended for replacing 'hotplug_qdev' field in PCIBus and also will allow to avoid adding equivalent field to DimmBus with possiblitity to refactor other BUSes to use it instead of custom field. In addition once all users of allow_hotplug field are converted to new API, link could replace allow_hotplug field in qdev hotplug code. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/qdev-core.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include/hw') diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 2c4f140..41ec533 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -8,6 +8,7 @@ #include "qom/object.h" #include "hw/irq.h" #include "qapi/error.h" +#include "hw/hotplug.h" enum { DEV_NVECTORS_UNSPECIFIED = -1, @@ -180,14 +181,18 @@ typedef struct BusChild { QTAILQ_ENTRY(BusChild) sibling; } BusChild; +#define QDEV_HOTPLUG_HANDLER_PROPERTY "hotplug-handler" + /** * BusState: + * @hotplug_device: link to a hotplug device associated with bus. */ struct BusState { Object obj; DeviceState *parent; const char *name; int allow_hotplug; + HotplugHandler *hotplug_handler; int max_index; QTAILQ_HEAD(ChildrenHead, BusChild) children; QLIST_ENTRY(BusState) sibling; @@ -321,4 +326,11 @@ extern int qdev_hotplug; char *qdev_get_dev_path(DeviceState *dev); +static inline void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, + Error **errp) +{ + object_property_set_link(OBJECT(bus), OBJECT(handler), + QDEV_HOTPLUG_HANDLER_PROPERTY, errp); + bus->allow_hotplug = 1; +} #endif -- cgit v1.1 From 1a37eca107cece3ed454bae29eef0bd1fac4a244 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Feb 2014 16:36:46 +0100 Subject: qdev: add "hotpluggable" property to Device Currently it's possible to make PCIDevice not hotpluggable by using no_hotplug field of PCIDeviceClass. However it limits this only to PCI devices and prevents from generalizing hotplug code. So add similar field to DeviceClass so it could be reused with other Devices and would allow to replace PCI specific hotplug callbacks with generic implementation. Following patches will replace PCIDeviceClass.no_hotplug with this new property. In addition expose field as "hotpluggable" readonly property, to make it possible to read its value via QOM interface. Make DeviceClass hotpluggable by default as it was assumed before. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/qdev-core.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/hw') diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 41ec533..08d329d 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -50,6 +50,8 @@ struct VMStateDescription; * is changed to %true. Deprecated, new types inheriting directly from * TYPE_DEVICE should use @realize instead, new leaf types should consult * their respective parent type. + * @hotpluggable: indicates if #DeviceClass is hotpluggable, available + * as readonly "hotpluggable" property of #DeviceState instance * * # Realization # * Devices are constructed in two stages, @@ -110,6 +112,7 @@ typedef struct DeviceClass { * TODO remove once we're there */ bool cannot_instantiate_with_device_add_yet; + bool hotpluggable; /* callbacks */ void (*reset)(DeviceState *dev); -- cgit v1.1 From 2897ae026758eac78284ba6c3bd7732f3a1d9987 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Feb 2014 16:36:48 +0100 Subject: qdev:pci: refactor PCIDevice to use generic "hotpluggable" property Get rid of PCIDevice specific PCIDeviceClass.no_hotplug and use generic DeviceClass.hotpluggable field instead. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pci.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/hw') diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 5252346..c173b6a 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -201,9 +201,6 @@ typedef struct PCIDeviceClass { /* pcie stuff */ int is_express; /* is this device pci express? */ - /* device isn't hot-pluggable */ - int no_hotplug; - /* rom bar */ const char *romfile; } PCIDeviceClass; -- cgit v1.1 From c24d5e0b91d138f8cc95f5694d4964de36a739d3 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Feb 2014 16:36:49 +0100 Subject: acpi/piix4pm: convert ACPI PCI hotplug to use hotplug-handler API Split piix4_device_hotplug() into hotplug/unplug callbacks and register them as "hotplug-handler" interface implementation of PIIX4_PM device. Replace pci_bus_hotplug() wiring with setting link on PCI BUS "hotplug-handler" property to PIIX4_PM device. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/acpi.h | 1 + include/hw/acpi/pcihp.h | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'include/hw') diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h index 3e53297..a9fae9d 100644 --- a/include/hw/acpi/acpi.h +++ b/include/hw/acpi/acpi.h @@ -24,6 +24,7 @@ #include "qemu/notify.h" #include "qemu/option.h" #include "exec/memory.h" +#include "hw/irq.h" /* from linux include/acpi/actype.h */ /* Default ACPI register widths */ diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h index 0a90e4a..9323838 100644 --- a/include/hw/acpi/pcihp.h +++ b/include/hw/acpi/pcihp.h @@ -29,7 +29,8 @@ #include #include -#include "hw/pci/pci.h" /* for PCIHotplugState */ +#include "hw/acpi/acpi.h" +#include "migration/vmstate.h" typedef struct AcpiPciHpPciStatus { uint32_t up; @@ -52,9 +53,10 @@ typedef struct AcpiPciHpState { void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root, MemoryRegion *address_space_io, bool bridges_enabled); -/* Invoke on device hotplug */ -int acpi_pcihp_device_hotplug(AcpiPciHpState *, PCIDevice *, - PCIHotplugState state); +void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, + DeviceState *dev, Error **errp); +void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s, + DeviceState *dev, Error **errp); /* Called on reset */ void acpi_pcihp_reset(AcpiPciHpState *s); -- cgit v1.1 From 5d268704d7c2bc58c38b87d7d94804639ef100ec Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Feb 2014 16:36:50 +0100 Subject: pci/shpc: convert SHPC hotplug to use hotplug-handler API Split shpc_device_hotplug() into hotplug/unplug callbacks and register them as "hotplug-handler" interface implementation of PCI_BRIDGE_DEV device. Replace pci_bus_hotplug() wiring with setting link on PCI BUS "hotplug-handler" property to PCI_BRIDGE_DEV device. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/shpc.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/hw') diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h index 467911a..eef1a1a 100644 --- a/include/hw/pci/shpc.h +++ b/include/hw/pci/shpc.h @@ -4,6 +4,8 @@ #include "qemu-common.h" #include "exec/memory.h" #include "migration/vmstate.h" +#include "qapi/error.h" +#include "hw/hotplug.h" struct SHPCDevice { /* Capability offset in device's config space */ @@ -41,6 +43,12 @@ int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off); void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar); void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len); + +void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); +void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); + extern VMStateInfo shpc_vmstate_info; #define SHPC_VMSTATE(_field, _type) \ VMSTATE_BUFFER_UNSAFE_INFO(_field, _type, 0, shpc_vmstate_info, 0) -- cgit v1.1 From a66e657e18cd9b70e9f57ae5512c07faf2bc508f Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Feb 2014 16:36:51 +0100 Subject: pci/pcie: convert PCIE hotplug to use hotplug-handler API Split pcie_cap_slot_hotplug() into hotplug/unplug callbacks and register them as "hotplug-handler" interface implementation of PCIE_SLOT device. Replace pci_bus_hotplug() wiring with setting link on PCI BUS "hotplug-handler" property to PCI_BRIDGE_DEV device. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pcie.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/hw') diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 1966169..b0bf7e3 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -25,6 +25,7 @@ #include "hw/pci/pci_regs.h" #include "hw/pci/pcie_regs.h" #include "hw/pci/pcie_aer.h" +#include "hw/hotplug.h" typedef enum { /* for attention and power indicator */ @@ -122,4 +123,8 @@ extern const VMStateDescription vmstate_pcie_device; .offset = vmstate_offset_value(_state, _field, PCIDevice), \ } +void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); +void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp); #endif /* QEMU_PCIE_H */ -- cgit v1.1 From 5e95494380ecf83c97d28f72134ab45e0cace8f9 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Wed, 5 Feb 2014 16:36:52 +0100 Subject: hw/pci: switch to a generic hotplug handling for PCIDevice make qdev_unplug()/device_set_realized() to call hotplug handler's plug/unplug methods if available and remove not needed anymore hot(un)plug handling from PCIDevice. In case if hotplug handler is not available, revert to the legacy hotplug method for compatibility with not yet converted buses. Signed-off-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pci.h | 10 ---------- include/hw/pci/pci_bus.h | 2 -- 2 files changed, 12 deletions(-) (limited to 'include/hw') diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index c173b6a..693dd6b 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -327,15 +327,6 @@ typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); -typedef enum { - PCI_HOTPLUG_DISABLED, - PCI_HOTPLUG_ENABLED, - PCI_COLDPLUG_ENABLED, -} PCIHotplugState; - -typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev, - PCIHotplugState state); - #define TYPE_PCI_BUS "PCI" #define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS) #define TYPE_PCIE_BUS "PCIE" @@ -354,7 +345,6 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int nirq); int pci_bus_get_irq_level(PCIBus *bus, int irq_num); -void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); /* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */ int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin); PCIBus *pci_register_bus(DeviceState *parent, const char *name, diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h index 9df1788..fabaeee 100644 --- a/include/hw/pci/pci_bus.h +++ b/include/hw/pci/pci_bus.h @@ -16,8 +16,6 @@ struct PCIBus { pci_set_irq_fn set_irq; pci_map_irq_fn map_irq; pci_route_irq_fn route_intx_to_irq; - pci_hotplug_fn hotplug; - DeviceState *hotplug_qdev; void *irq_opaque; PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX]; PCIDevice *parent_dev; -- cgit v1.1