[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [RFC PATCH 15/15] spapr: add hotplug hooks for PHB hotplug
From: |
Michael Roth |
Subject: |
[Qemu-ppc] [RFC PATCH 15/15] spapr: add hotplug hooks for PHB hotplug |
Date: |
Wed, 29 Apr 2015 14:20:24 -0500 |
Hotplugging PHBs is a machine-level operation, but PHBs reside on the
main system bus, so we register spapr machine as the handler for the
main system bus. The entry point for plug/unplug is shared by all
such machine-level hotplug operations (memory, CPU, PHB, etc), and
from there we branch off to specific hotplug callbacks based on the
object type.
Signed-off-by: Michael Roth <address@hidden>
---
hw/ppc/spapr.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ecf40e4..25c46bb 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -62,6 +62,7 @@
#include "hw/compat.h"
#include <libfdt.h>
+#include "sysemu/device_tree.h"
/* SLOF memory layout:
*
@@ -1711,6 +1712,11 @@ static void ppc_spapr_init(MachineState *machine)
/* used by RTAS */
QTAILQ_INIT(&spapr->ccs_list);
qemu_register_reset(spapr_ccs_reset_hook, spapr);
+
+ if (spapr->dr_phb_enabled) {
+ qbus_set_hotplug_handler_generic(sysbus_get_default(), OBJECT(machine),
+ NULL);
+ }
}
static int spapr_kvm_type(const char *vm_type)
@@ -1829,14 +1835,104 @@ static void spapr_nmi(NMIState *n, int cpu_index,
Error **errp)
}
}
+static void spapr_machine_phb_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ sPAPRPHBState *sphb;
+ void *fdt = NULL;
+ int fdt_start_offset = 0;
+ int fdt_size = 0;
+ Error *local_err = NULL;
+ sPAPRDRConnector *drc;
+ sPAPRDRConnectorClass *drck;
+
+ sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+ drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_PHB, sphb->index);
+ /* hotplug hooks should check it's enabled before getting this far */
+ g_assert(drc);
+ drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+
+ /* boot-time devices get their device tree node created by SLOF, but for
+ * hotplugged devices we need QEMU to generate it so the guest can fetch
+ * it via RTAS
+ */
+ if (dev->hotplugged) {
+ int ret;
+ fdt = create_device_tree(&fdt_size);
+ ret = spapr_populate_pci_dt(sphb, PHANDLE_XICP, fdt,
&fdt_start_offset);
+ if (ret < 0) {
+ error_setg(&local_err, "unable to create FDT for hotplugged PHB");
+ goto out;
+ }
+
+ /* generally SLOF creates these, for hotplug it's up to QEMU */
+ _FDT(fdt_setprop_string(fdt, fdt_start_offset, "name", "pci"));
+ }
+
+ /* boot-time devices still get associated with a DRC to allow for unplug,
+ * but since we use SLOF-generated DT here we don't need to re-generate it
+ */
+ drck->attach(drc, DEVICE(dev),
+ fdt, fdt_start_offset, !dev->hotplugged, &local_err);
+out:
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(fdt);
+ return;
+ }
+
+ if (dev->hotplugged) {
+ spapr_hotplug_req_add_event(drc);
+ }
+}
+
+static void spapr_machine_phb_remove_cb(DeviceState *dev, void *opaque)
+{
+ object_unparent(OBJECT(dev));
+}
+
+static void spapr_machine_phb_unplug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ sPAPRPHBState *sphb;
+ sPAPRDRConnector *drc;
+ sPAPRDRConnectorClass *drck;
+ Error *local_err = NULL;
+
+ sphb = SPAPR_PCI_HOST_BRIDGE(dev);
+ drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_PHB, sphb->index);
+ g_assert(drc);
+ drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+
+ if (!drck->release_pending(drc)) {
+ drck->detach(drc, DEVICE(dev), spapr_machine_phb_remove_cb, NULL,
+ &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ spapr_hotplug_req_remove_event(drc);
+ }
+}
+
static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
+ if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ if (spapr->dr_phb_enabled) {
+ spapr_machine_phb_plug(hotplug_dev, dev, errp);
+ }
+ }
}
static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
+ if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
+ if (spapr->dr_phb_enabled) {
+ spapr_machine_phb_unplug(hotplug_dev, dev, errp);
+ }
+ }
}
static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine,
--
1.9.1
- [Qemu-ppc] [RFC PATCH 00/15] spapr: add support for PHB hotplug, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 09/15] spapr: populate PHB DRC entries for root DT node, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 10/15] spapr_events: add support for phb hotplug events, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 11/15] qdev: add qbus_set_hotplug_handler_generic(), Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 14/15] spapr_pci: add ibm, my-drc-index property for PHB hotplug, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 12/15] spapr: stub implementation of machine-level HotplugHandler interface, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 13/15] spapr_pci: provide node start offset via spapr_populate_pci_dt(), Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 01/15] pci: allow cleanup/unregistration of PCI buses, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 15/15] spapr: add hotplug hooks for PHB hotplug,
Michael Roth <=
- [Qemu-ppc] [RFC PATCH 02/15] qdev: store DeviceState's canonical path to use when unparenting, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 05/15] spapr_pci: add PHB unrealize, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 03/15] spapr_drc: pass object ownership to parent/owner, Michael Roth, 2015/04/29
- [Qemu-ppc] [RFC PATCH 04/15] spapr_iommu: pass object ownership to parent/owner, Michael Roth, 2015/04/29