diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-06-13 11:56:00 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-06-13 11:56:00 +0100 |
commit | 9746211baa6ff1275e9c726c6f3a3bcfe4b1f8bd (patch) | |
tree | a53b570a5344370b8d6991ae1c84691024330a80 /hw | |
parent | 8e3cf49c47064da19f4bfb1c5bf16e6e613f1bfa (diff) | |
parent | 593080936a06a04eacc589350e3a7ebc02f2ed8e (diff) | |
download | qemu-9746211baa6ff1275e9c726c6f3a3bcfe4b1f8bd.zip qemu-9746211baa6ff1275e9c726c6f3a3bcfe4b1f8bd.tar.gz qemu-9746211baa6ff1275e9c726c6f3a3bcfe4b1f8bd.tar.bz2 |
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.10-20170609' into staging
ppc patch queue 2017-06-09
This batch contains more patches to rework the pseries machine hotplug
infrastructure, plus an assorted batch of bugfixes.
It contains a start on fixes to restore migration from older machine
types on older versions which was broken by some xics changes. There
are still a few missing pieces here, though.
# gpg: Signature made Fri 09 Jun 2017 06:26:03 BST
# gpg: using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* remotes/dgibson/tags/ppc-for-2.10-20170609:
Revert "spapr: fix memory hot-unplugging"
xics: drop ICPStateClass::cpu_setup() handler
xics: setup cpu at realize time
xics: pass appropriate types to realize() handlers.
xics: introduce macros for ICP/ICS link properties
hw/cpu: core.c can be compiled as common object
hw/ppc/spapr: Adjust firmware name for PCI bridges
xics: add reset() handler to ICPStateClass
pnv_core: drop reference on ICPState object during CPU realization
spapr: Rework DRC name handling
spapr: Fold spapr_phb_{add,remove}_pci_device() into their only callers
spapr: Change DRC attach & detach methods to functions
spapr: Clean up handling of DR-indicator
spapr: Clean up RTAS set-indicator
spapr: Don't misuse DR-indicator in spapr_recover_pending_dimm_state()
spapr: Clean up DR entity sense handling
pseries: Correct panic behaviour for pseries machine type
spapr: fix memory leak in spapr_memory_pre_plug()
target/ppc: fix memory leak in kvmppc_is_mem_backend_page_size_ok()
target/ppc: pass const string to kvmppc_is_mem_backend_page_size_ok()
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/cpu/Makefile.objs | 3 | ||||
-rw-r--r-- | hw/intc/xics.c | 95 | ||||
-rw-r--r-- | hw/intc/xics_kvm.c | 45 | ||||
-rw-r--r-- | hw/intc/xics_pnv.c | 6 | ||||
-rw-r--r-- | hw/ppc/pnv_core.c | 16 | ||||
-rw-r--r-- | hw/ppc/pnv_psi.c | 3 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 44 | ||||
-rw-r--r-- | hw/ppc/spapr_cpu_core.c | 22 | ||||
-rw-r--r-- | hw/ppc/spapr_drc.c | 289 | ||||
-rw-r--r-- | hw/ppc/spapr_pci.c | 72 | ||||
-rw-r--r-- | hw/ppc/spapr_rtas.c | 7 | ||||
-rw-r--r-- | hw/ppc/trace-events | 5 |
12 files changed, 248 insertions, 359 deletions
diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs index 942a4bb..cd52d20 100644 --- a/hw/cpu/Makefile.objs +++ b/hw/cpu/Makefile.objs @@ -2,5 +2,4 @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o obj-$(CONFIG_REALVIEW) += realview_mpcore.o obj-$(CONFIG_A9MPCORE) += a9mpcore.o obj-$(CONFIG_A15MPCORE) += a15mpcore.o -obj-y += core.o - +common-obj-y += core.o diff --git a/hw/intc/xics.c b/hw/intc/xics.c index ea35167..7ccfb53 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -38,50 +38,6 @@ #include "monitor/monitor.h" #include "hw/intc/intc.h" -void xics_cpu_destroy(XICSFabric *xi, PowerPCCPU *cpu) -{ - CPUState *cs = CPU(cpu); - ICPState *icp = ICP(cpu->intc); - - assert(icp); - assert(cs == icp->cs); - - icp->output = NULL; - icp->cs = NULL; -} - -void xics_cpu_setup(XICSFabric *xi, PowerPCCPU *cpu, ICPState *icp) -{ - CPUState *cs = CPU(cpu); - CPUPPCState *env = &cpu->env; - ICPStateClass *icpc; - - assert(icp); - - cpu->intc = OBJECT(icp); - icp->cs = cs; - - icpc = ICP_GET_CLASS(icp); - if (icpc->cpu_setup) { - icpc->cpu_setup(icp, cpu); - } - - switch (PPC_INPUT(env)) { - case PPC_FLAGS_INPUT_POWER7: - icp->output = env->irq_inputs[POWER7_INPUT_INT]; - break; - - case PPC_FLAGS_INPUT_970: - icp->output = env->irq_inputs[PPC970_INPUT_INT]; - break; - - default: - error_report("XICS interrupt controller does not support this CPU " - "bus model"); - abort(); - } -} - void icp_pic_print_info(ICPState *icp, Monitor *mon) { int cpu_index = icp->cs ? icp->cs->cpu_index : -1; @@ -325,6 +281,7 @@ static const VMStateDescription vmstate_icp_server = { static void icp_reset(void *dev) { ICPState *icp = ICP(dev); + ICPStateClass *icpc = ICP_GET_CLASS(icp); icp->xirr = 0; icp->pending_priority = 0xff; @@ -332,26 +289,58 @@ static void icp_reset(void *dev) /* Make all outputs are deasserted */ qemu_set_irq(icp->output, 0); + + if (icpc->reset) { + icpc->reset(icp); + } } static void icp_realize(DeviceState *dev, Error **errp) { ICPState *icp = ICP(dev); ICPStateClass *icpc = ICP_GET_CLASS(dev); + PowerPCCPU *cpu; + CPUPPCState *env; Object *obj; Error *err = NULL; - obj = object_property_get_link(OBJECT(dev), "xics", &err); + obj = object_property_get_link(OBJECT(dev), ICP_PROP_XICS, &err); if (!obj) { - error_setg(errp, "%s: required link 'xics' not found: %s", + error_setg(errp, "%s: required link '" ICP_PROP_XICS "' not found: %s", __func__, error_get_pretty(err)); return; } icp->xics = XICS_FABRIC(obj); + obj = object_property_get_link(OBJECT(dev), ICP_PROP_CPU, &err); + if (!obj) { + error_setg(errp, "%s: required link '" ICP_PROP_CPU "' not found: %s", + __func__, error_get_pretty(err)); + return; + } + + cpu = POWERPC_CPU(obj); + cpu->intc = OBJECT(icp); + icp->cs = CPU(obj); + + env = &cpu->env; + switch (PPC_INPUT(env)) { + case PPC_FLAGS_INPUT_POWER7: + icp->output = env->irq_inputs[POWER7_INPUT_INT]; + break; + + case PPC_FLAGS_INPUT_970: + icp->output = env->irq_inputs[PPC970_INPUT_INT]; + break; + + default: + error_setg(errp, "XICS interrupt controller does not support this CPU bus model"); + return; + } + if (icpc->realize) { - icpc->realize(dev, errp); + icpc->realize(icp, errp); } qemu_register_reset(icp_reset, dev); @@ -601,10 +590,8 @@ static void ics_simple_initfn(Object *obj) ics->offset = XICS_IRQ_BASE; } -static void ics_simple_realize(DeviceState *dev, Error **errp) +static void ics_simple_realize(ICSState *ics, Error **errp) { - ICSState *ics = ICS_SIMPLE(dev); - if (!ics->nr_irqs) { error_setg(errp, "Number of interrupts needs to be greater 0"); return; @@ -612,7 +599,7 @@ static void ics_simple_realize(DeviceState *dev, Error **errp) ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs); - qemu_register_reset(ics_simple_reset, dev); + qemu_register_reset(ics_simple_reset, ics); } static Property ics_simple_properties[] = { @@ -649,9 +636,9 @@ static void ics_base_realize(DeviceState *dev, Error **errp) Object *obj; Error *err = NULL; - obj = object_property_get_link(OBJECT(dev), "xics", &err); + obj = object_property_get_link(OBJECT(dev), ICS_PROP_XICS, &err); if (!obj) { - error_setg(errp, "%s: required link 'xics' not found: %s", + error_setg(errp, "%s: required link '" ICS_PROP_XICS "' not found: %s", __func__, error_get_pretty(err)); return; } @@ -659,7 +646,7 @@ static void ics_base_realize(DeviceState *dev, Error **errp) if (icsc->realize) { - icsc->realize(dev, errp); + icsc->realize(ics, errp); } } diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 14b8f6f..3091ad3 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -110,25 +110,14 @@ static int icp_set_kvm_state(ICPState *icp, int version_id) return 0; } -static void icp_kvm_reset(void *dev) +static void icp_kvm_reset(ICPState *icp) { - ICPState *icp = ICP(dev); - - icp->xirr = 0; - icp->pending_priority = 0xff; - icp->mfrr = 0xff; - - /* Make all outputs as deasserted only if the CPU thread is in use */ - if (icp->output) { - qemu_set_irq(icp->output, 0); - } - icp_set_kvm_state(icp, 1); } -static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU *cpu) +static void icp_kvm_realize(ICPState *icp, Error **errp) { - CPUState *cs = CPU(cpu); + CPUState *cs = icp->cs; KVMEnabledICP *enabled_icp; unsigned long vcpu_id = kvm_arch_vcpu_id(cs); int ret; @@ -150,35 +139,23 @@ static void icp_kvm_cpu_setup(ICPState *icp, PowerPCCPU *cpu) ret = kvm_vcpu_enable_cap(cs, KVM_CAP_IRQ_XICS, 0, kernel_xics_fd, vcpu_id); if (ret < 0) { - error_report("Unable to connect CPU%ld to kernel XICS: %s", vcpu_id, - strerror(errno)); - exit(1); + error_setg(errp, "Unable to connect CPU%ld to kernel XICS: %s", vcpu_id, + strerror(errno)); + return; } enabled_icp = g_malloc(sizeof(*enabled_icp)); enabled_icp->vcpu_id = vcpu_id; QLIST_INSERT_HEAD(&kvm_enabled_icps, enabled_icp, node); } -static void icp_kvm_realize(DeviceState *dev, Error **errp) -{ - qemu_register_reset(icp_kvm_reset, dev); -} - -static void icp_kvm_unrealize(DeviceState *dev, Error **errp) -{ - qemu_unregister_reset(icp_kvm_reset, dev); -} - static void icp_kvm_class_init(ObjectClass *klass, void *data) { - DeviceClass *dc = DEVICE_CLASS(klass); ICPStateClass *icpc = ICP_CLASS(klass); - dc->realize = icp_kvm_realize; - dc->unrealize = icp_kvm_unrealize; icpc->pre_save = icp_get_kvm_state; icpc->post_load = icp_set_kvm_state; - icpc->cpu_setup = icp_kvm_cpu_setup; + icpc->realize = icp_kvm_realize; + icpc->reset = icp_kvm_reset; } static const TypeInfo icp_kvm_info = { @@ -351,10 +328,8 @@ static void ics_kvm_reset(void *dev) ics_set_kvm_state(ics, 1); } -static void ics_kvm_realize(DeviceState *dev, Error **errp) +static void ics_kvm_realize(ICSState *ics, Error **errp) { - ICSState *ics = ICS_SIMPLE(dev); - if (!ics->nr_irqs) { error_setg(errp, "Number of interrupts needs to be greater 0"); return; @@ -362,7 +337,7 @@ static void ics_kvm_realize(DeviceState *dev, Error **errp) ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState)); ics->qirqs = qemu_allocate_irqs(ics_kvm_set_irq, ics, ics->nr_irqs); - qemu_register_reset(ics_kvm_reset, dev); + qemu_register_reset(ics_kvm_reset, ics); } static void ics_kvm_class_init(ObjectClass *klass, void *data) diff --git a/hw/intc/xics_pnv.c b/hw/intc/xics_pnv.c index 12ae605..2a955a8 100644 --- a/hw/intc/xics_pnv.c +++ b/hw/intc/xics_pnv.c @@ -159,11 +159,11 @@ static const MemoryRegionOps pnv_icp_ops = { }, }; -static void pnv_icp_realize(DeviceState *dev, Error **errp) +static void pnv_icp_realize(ICPState *icp, Error **errp) { - PnvICPState *icp = PNV_ICP(dev); + PnvICPState *pnv_icp = PNV_ICP(icp); - memory_region_init_io(&icp->mmio, OBJECT(dev), &pnv_icp_ops, + memory_region_init_io(&pnv_icp->mmio, OBJECT(icp), &pnv_icp_ops, icp, "icp-thread", 0x1000); } diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 1b7ec70..c7b00b6 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -118,18 +118,20 @@ static void pnv_core_realize_child(Object *child, XICSFabric *xi, Error **errp) PowerPCCPU *cpu = POWERPC_CPU(cs); Object *obj; - obj = object_new(TYPE_PNV_ICP); - object_property_add_child(OBJECT(cpu), "icp", obj, NULL); - object_property_add_const_link(obj, "xics", OBJECT(xi), &error_abort); - object_property_set_bool(obj, true, "realized", &local_err); + object_property_set_bool(child, true, "realized", &local_err); if (local_err) { error_propagate(errp, local_err); return; } - object_property_set_bool(child, true, "realized", &local_err); + obj = object_new(TYPE_PNV_ICP); + object_property_add_child(child, "icp", obj, NULL); + object_unref(obj); + object_property_add_const_link(obj, ICP_PROP_XICS, OBJECT(xi), + &error_abort); + object_property_add_const_link(obj, ICP_PROP_CPU, child, &error_abort); + object_property_set_bool(obj, true, "realized", &local_err); if (local_err) { - object_unparent(obj); error_propagate(errp, local_err); return; } @@ -140,8 +142,6 @@ static void pnv_core_realize_child(Object *child, XICSFabric *xi, Error **errp) error_propagate(errp, local_err); return; } - - xics_cpu_setup(xi, cpu, ICP(obj)); } static void pnv_core_realize(DeviceState *dev, Error **errp) diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index 2bf5bfe..9876c26 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -474,7 +474,8 @@ static void pnv_psi_realize(DeviceState *dev, Error **errp) } /* Create PSI interrupt control source */ - object_property_add_const_link(OBJECT(ics), "xics", obj, &error_abort); + object_property_add_const_link(OBJECT(ics), ICS_PROP_XICS, obj, + &error_abort); object_property_set_int(OBJECT(ics), PSI_NUM_INTERRUPTS, "nr-irqs", &err); if (err) { error_propagate(errp, err); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 91b4057..b2951d7 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -107,7 +107,8 @@ static ICSState *spapr_ics_create(sPAPRMachineState *spapr, obj = object_new(type_ics); object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort); - object_property_add_const_link(obj, "xics", OBJECT(spapr), &error_abort); + object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr), + &error_abort); object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err); if (local_err) { goto error; @@ -2441,6 +2442,12 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); } + if (g_str_equal("pci-bridge", qdev_fw_name(dev))) { + /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */ + PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); + return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); + } + return NULL; } @@ -2523,7 +2530,6 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, Error **errp) { sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; int i, fdt_offset, fdt_size; void *fdt; @@ -2538,10 +2544,10 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, fdt_offset = spapr_populate_memory_node(fdt, node, addr, SPAPR_MEMORY_BLOCK_SIZE); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); + spapr_drc_attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); addr += SPAPR_MEMORY_BLOCK_SIZE; if (!dev->hotplugged) { + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); /* guests expect coldplugged LMBs to be pre-allocated */ drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE); drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED); @@ -2554,7 +2560,6 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, if (dedicated_hp_event_source) { drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr_start / SPAPR_MEMORY_BLOCK_SIZE); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs, spapr_drc_index(drc)); @@ -2615,8 +2620,11 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, if (mem_dev && !kvmppc_is_mem_backend_page_size_ok(mem_dev)) { error_setg(errp, "Memory backend has bad page size. " "Use 'memory-backend-file' with correct mem-path."); - return; + goto out; } + +out: + g_free(mem_dev); } struct sPAPRDIMMState { @@ -2673,7 +2681,7 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms, drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); - if (drc->indicator_state != SPAPR_DR_INDICATOR_STATE_INACTIVE) { + if (drc->dev) { avail_lmbs++; } addr += SPAPR_MEMORY_BLOCK_SIZE; @@ -2697,10 +2705,11 @@ void spapr_lmb_release(DeviceState *dev) * during the unplug process. In this case recover it. */ if (ds == NULL) { ds = spapr_recover_pending_dimm_state(spapr, PC_DIMM(dev)); - if (ds->nr_lmbs) { - return; - } - } else if (--ds->nr_lmbs) { + /* The DRC being examined by the caller at least must be counted */ + g_assert(ds->nr_lmbs); + } + + if (--ds->nr_lmbs) { return; } @@ -2738,7 +2747,6 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, uint64_t addr_start, addr; int i; sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; sPAPRDIMMState *ds; addr_start = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, @@ -2758,14 +2766,12 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - drck->detach(drc, dev, errp); + spapr_drc_detach(drc, dev, errp); addr += SPAPR_MEMORY_BLOCK_SIZE; } drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, addr_start / SPAPR_MEMORY_BLOCK_SIZE); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs, spapr_drc_index(drc)); out: @@ -2820,7 +2826,6 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, { int index; sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; Error *local_err = NULL; CPUCore *cc = CPU_CORE(dev); int smt = kvmppc_smt_threads(); @@ -2838,8 +2843,7 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * smt); g_assert(drc); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - drck->detach(drc, dev, &local_err); + spapr_drc_detach(drc, dev, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -2883,8 +2887,8 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, } if (drc) { - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, &local_err); + spapr_drc_attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, + &local_err); if (local_err) { g_free(fdt); error_propagate(errp, local_err); diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 029a141..9fb896b 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -53,9 +53,6 @@ static void spapr_cpu_reset(void *opaque) static void spapr_cpu_destroy(PowerPCCPU *cpu) { - sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); - - xics_cpu_destroy(XICS_FABRIC(spapr), cpu); qemu_unregister_reset(spapr_cpu_reset, cpu); } @@ -140,28 +137,29 @@ static void spapr_cpu_core_realize_child(Object *child, Error **errp) sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); CPUState *cs = CPU(child); PowerPCCPU *cpu = POWERPC_CPU(cs); - Object *obj; + Object *obj = NULL; - obj = object_new(spapr->icp_type); - object_property_add_child(OBJECT(cpu), "icp", obj, &error_abort); - object_unref(obj); - object_property_add_const_link(obj, "xics", OBJECT(spapr), &error_abort); - object_property_set_bool(obj, true, "realized", &local_err); + object_property_set_bool(child, true, "realized", &local_err); if (local_err) { goto error; } - object_property_set_bool(child, true, "realized", &local_err); + spapr_cpu_init(spapr, cpu, &local_err); if (local_err) { goto error; } - spapr_cpu_init(spapr, cpu, &local_err); + obj = object_new(spapr->icp_type); + object_property_add_child(child, "icp", obj, &error_abort); + object_unref(obj); + object_property_add_const_link(obj, ICP_PROP_XICS, OBJECT(spapr), + &error_abort); + object_property_add_const_link(obj, ICP_PROP_CPU, child, &error_abort); + object_property_set_bool(obj, true, "realized", &local_err); if (local_err) { goto error; } - xics_cpu_setup(XICS_FABRIC(spapr), cpu, ICP(obj)); return; error: diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 39e7f30..5cb75bb 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -49,8 +49,6 @@ uint32_t spapr_drc_index(sPAPRDRConnector *drc) static uint32_t set_isolation_state(sPAPRDRConnector *drc, sPAPRDRIsolationState state) { - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state); /* if the guest is configuring a device attached to this DRC, we @@ -105,7 +103,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc, uint32_t drc_index = spapr_drc_index(drc); if (drc->configured) { trace_spapr_drc_set_isolation_state_finalizing(drc_index); - drck->detach(drc, DEVICE(drc->dev), NULL); + spapr_drc_detach(drc, DEVICE(drc->dev), NULL); } else { trace_spapr_drc_set_isolation_state_deferring(drc_index); } @@ -116,19 +114,9 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc, return RTAS_OUT_SUCCESS; } -static uint32_t set_indicator_state(sPAPRDRConnector *drc, - sPAPRDRIndicatorState state) -{ - trace_spapr_drc_set_indicator_state(spapr_drc_index(drc), state); - drc->indicator_state = state; - return RTAS_OUT_SUCCESS; -} - static uint32_t set_allocation_state(sPAPRDRConnector *drc, sPAPRDRAllocationState state) { - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - trace_spapr_drc_set_allocation_state(spapr_drc_index(drc), state); if (state == SPAPR_DR_ALLOCATION_STATE_USABLE) { @@ -140,17 +128,6 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, if (!drc->dev) { return RTAS_OUT_NO_SUCH_INDICATOR; } - if (drc->awaiting_release && drc->awaiting_allocation) { - /* kernel is acknowledging a previous hotplug event - * while we are already removing it. - * it's safe to ignore awaiting_allocation here since we know the - * situation is predicated on the guest either already having done - * so (boot-time hotplug), or never being able to acquire in the - * first place (hotplug followed by immediate unplug). - */ - drc->awaiting_allocation_skippable = true; - return RTAS_OUT_NO_SUCH_INDICATOR; - } } if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) { @@ -159,7 +136,7 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { uint32_t drc_index = spapr_drc_index(drc); trace_spapr_drc_set_allocation_state_finalizing(drc_index); - drck->detach(drc, DEVICE(drc->dev), NULL); + spapr_drc_detach(drc, DEVICE(drc->dev), NULL); } else if (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) { drc->awaiting_allocation = false; } @@ -167,9 +144,32 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, return RTAS_OUT_SUCCESS; } -static const char *get_name(sPAPRDRConnector *drc) +static const char *spapr_drc_name(sPAPRDRConnector *drc) { - return drc->name; + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + + /* human-readable name for a DRC to encode into the DT + * description. this is mainly only used within a guest in place + * of the unique DRC index. + * + * in the case of VIO/PCI devices, it corresponds to a "location + * code" that maps a logical device/function (DRC index) to a + * physical (or virtual in the case of VIO) location in the system + * by chaining together the "location label" for each + * encapsulating component. + * + * since this is more to do with diagnosing physical hardware + * issues than guest compatibility, we choose location codes/DRC + * names that adhere to the documented format, but avoid encoding + * the entire topology information into the label/code, instead + * just using the location codes based on the labels for the + * endpoints (VIO/PCI adaptor connectors), which is basically just + * "C" followed by an integer ID. + * + * DRC names as documented by PAPR+ v2.7, 13.5.2.4 + * location codes as documented by PAPR+ v2.7, 12.3.1.5 + */ + return g_strdup_printf("%s%d", drck->drc_name_prefix, drc->id); } /* has the guest been notified of device attachment? */ @@ -185,39 +185,25 @@ static void set_signalled(sPAPRDRConnector *drc) * based on the current allocation/indicator/power states * for the DR connector. */ -static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state) +static sPAPRDREntitySense physical_entity_sense(sPAPRDRConnector *drc) { - if (drc->dev) { - if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI && - drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { - /* for logical DR, we return a state of UNUSABLE - * iff the allocation state UNUSABLE. - * Otherwise, report the state as USABLE/PRESENT, - * as we would for PCI. - */ - *state = SPAPR_DR_ENTITY_SENSE_UNUSABLE; - } else { - /* this assumes all PCI devices are assigned to - * a 'live insertion' power domain, where QEMU - * manages power state automatically as opposed - * to the guest. present, non-PCI resources are - * unaffected by power state. - */ - *state = SPAPR_DR_ENTITY_SENSE_PRESENT; - } + /* this assumes all PCI devices are assigned to a 'live insertion' + * power domain, where QEMU manages power state automatically as + * opposed to the guest. present, non-PCI resources are unaffected + * by power state. + */ + return drc->dev ? SPAPR_DR_ENTITY_SENSE_PRESENT + : SPAPR_DR_ENTITY_SENSE_EMPTY; +} + +static sPAPRDREntitySense logical_entity_sense(sPAPRDRConnector *drc) +{ + if (drc->dev + && (drc->allocation_state != SPAPR_DR_ALLOCATION_STATE_UNUSABLE)) { + return SPAPR_DR_ENTITY_SENSE_PRESENT; } else { - if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { - /* PCI devices, and only PCI devices, use EMPTY - * in cases where we'd otherwise use UNUSABLE - */ - *state = SPAPR_DR_ENTITY_SENSE_EMPTY; - } else { - *state = SPAPR_DR_ENTITY_SENSE_UNUSABLE; - } + return SPAPR_DR_ENTITY_SENSE_UNUSABLE; } - - trace_spapr_drc_entity_sense(spapr_drc_index(drc), *state); - return RTAS_OUT_SUCCESS; } static void prop_get_index(Object *obj, Visitor *v, const char *name, @@ -228,13 +214,6 @@ static void prop_get_index(Object *obj, Visitor *v, const char *name, visit_type_uint32(v, name, &value, errp); } -static char *prop_get_name(Object *obj, Error **errp) -{ - sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj); - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - return g_strdup(drck->get_name(drc)); -} - static void prop_get_fdt(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -311,8 +290,8 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, } while (fdt_depth != 0); } -static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, - int fdt_start_offset, bool coldplug, Error **errp) +void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, + int fdt_start_offset, bool coldplug, Error **errp) { trace_spapr_drc_attach(spapr_drc_index(drc)); @@ -335,7 +314,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->isolation_state = SPAPR_DR_ISOLATION_STATE_UNISOLATED; } - drc->indicator_state = SPAPR_DR_INDICATOR_STATE_ACTIVE; + drc->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE; drc->dev = d; drc->fdt = fdt; @@ -363,7 +342,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, NULL, 0, NULL); } -static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) +void spapr_drc_detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) { trace_spapr_drc_detach(spapr_drc_index(drc)); @@ -401,14 +380,12 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) } if (drc->awaiting_allocation) { - if (!drc->awaiting_allocation_skippable) { - drc->awaiting_release = true; - trace_spapr_drc_awaiting_allocation(spapr_drc_index(drc)); - return; - } + drc->awaiting_release = true; + trace_spapr_drc_awaiting_allocation(spapr_drc_index(drc)); + return; } - drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE; + drc->dr_indicator = SPAPR_DR_INDICATOR_INACTIVE; /* Calling release callbacks based on spapr_drc_type(drc). */ switch (spapr_drc_type(drc)) { @@ -428,7 +405,6 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) } drc->awaiting_release = false; - drc->awaiting_allocation_skippable = false; g_free(drc->fdt); drc->fdt = NULL; drc->fdt_start_offset = 0; @@ -445,7 +421,6 @@ static void reset(DeviceState *d) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - sPAPRDREntitySense state; trace_spapr_drc_reset(spapr_drc_index(drc)); @@ -467,7 +442,7 @@ static void reset(DeviceState *d) * force removal if we are */ if (drc->awaiting_release) { - drck->detach(drc, DEVICE(drc->dev), NULL); + spapr_drc_detach(drc, DEVICE(drc->dev), NULL); } /* non-PCI devices may be awaiting a transition to UNUSABLE */ @@ -477,8 +452,7 @@ static void reset(DeviceState *d) } } - drck->entity_sense(drc, &state); - if (state == SPAPR_DR_ENTITY_SENSE_PRESENT) { + if (drck->dr_entity_sense(drc) == SPAPR_DR_ENTITY_SENSE_PRESENT) { drck->set_signalled(drc); } } @@ -488,8 +462,7 @@ static bool spapr_drc_needed(void *opaque) sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque; sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); bool rc = false; - sPAPRDREntitySense value; - drck->entity_sense(drc, &value); + sPAPRDREntitySense value = drck->dr_entity_sense(drc); /* If no dev is plugged in there is no need to migrate the DRC state */ if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) { @@ -524,7 +497,7 @@ static const VMStateDescription vmstate_spapr_drc = { .fields = (VMStateField []) { VMSTATE_UINT32(isolation_state, sPAPRDRConnector), VMSTATE_UINT32(allocation_state, sPAPRDRConnector), - VMSTATE_UINT32(indicator_state, sPAPRDRConnector), + VMSTATE_UINT32(dr_indicator, sPAPRDRConnector), VMSTATE_BOOL(configured, sPAPRDRConnector), VMSTATE_BOOL(awaiting_release, sPAPRDRConnector), VMSTATE_BOOL(awaiting_allocation, sPAPRDRConnector), @@ -596,45 +569,6 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type, object_property_set_bool(OBJECT(drc), true, "realized", NULL); g_free(prop_name); - /* human-readable name for a DRC to encode into the DT - * description. this is mainly only used within a guest in place - * of the unique DRC index. - * - * in the case of VIO/PCI devices, it corresponds to a - * "location code" that maps a logical device/function (DRC index) - * to a physical (or virtual in the case of VIO) location in the - * system by chaining together the "location label" for each - * encapsulating component. - * - * since this is more to do with diagnosing physical hardware - * issues than guest compatibility, we choose location codes/DRC - * names that adhere to the documented format, but avoid encoding - * the entire topology information into the label/code, instead - * just using the location codes based on the labels for the - * endpoints (VIO/PCI adaptor connectors), which is basically - * just "C" followed by an integer ID. - * - * DRC names as documented by PAPR+ v2.7, 13.5.2.4 - * location codes as documented by PAPR+ v2.7, 12.3.1.5 - */ - switch (spapr_drc_type(drc)) { - case SPAPR_DR_CONNECTOR_TYPE_CPU: - drc->name = g_strdup_printf("CPU %d", id); - break; - case SPAPR_DR_CONNECTOR_TYPE_PHB: - drc->name = g_strdup_printf("PHB %d", id); - break; - case SPAPR_DR_CONNECTOR_TYPE_VIO: - case SPAPR_DR_CONNECTOR_TYPE_PCI: - drc->name = g_strdup_printf("C%d", id); - break; - case SPAPR_DR_CONNECTOR_TYPE_LMB: - drc->name = g_strdup_printf("LMB %d", id); - break; - default: - g_assert(false); - } - /* PCI slot always start in a USABLE state, and stay there */ if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_USABLE; @@ -650,7 +584,6 @@ static void spapr_dr_connector_instance_init(Object *obj) object_property_add_uint32_ptr(obj, "id", &drc->id, NULL); object_property_add(obj, "index", "uint32", prop_get_index, NULL, NULL, NULL, NULL); - object_property_add_str(obj, "name", prop_get_name, NULL, NULL); object_property_add(obj, "fdt", "struct", prop_get_fdt, NULL, NULL, NULL, NULL); } @@ -664,12 +597,7 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) dk->realize = realize; dk->unrealize = unrealize; drck->set_isolation_state = set_isolation_state; - drck->set_indicator_state = set_indicator_state; drck->set_allocation_state = set_allocation_state; - drck->get_name = get_name; - drck->entity_sense = entity_sense; - drck->attach = attach; - drck->detach = detach; drck->release_pending = release_pending; drck->set_signalled = set_signalled; /* @@ -678,12 +606,27 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) dk->user_creatable = false; } +static void spapr_drc_physical_class_init(ObjectClass *k, void *data) +{ + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); + + drck->dr_entity_sense = physical_entity_sense; +} + +static void spapr_drc_logical_class_init(ObjectClass *k, void *data) +{ + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); + + drck->dr_entity_sense = logical_entity_sense; +} + static void spapr_drc_cpu_class_init(ObjectClass *k, void *data) { sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU; drck->typename = "CPU"; + drck->drc_name_prefix = "CPU "; } static void spapr_drc_pci_class_init(ObjectClass *k, void *data) @@ -692,6 +635,7 @@ static void spapr_drc_pci_class_init(ObjectClass *k, void *data) drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI; drck->typename = "28"; + drck->drc_name_prefix = "C"; } static void spapr_drc_lmb_class_init(ObjectClass *k, void *data) @@ -700,6 +644,7 @@ static void spapr_drc_lmb_class_init(ObjectClass *k, void *data) drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB; drck->typename = "MEM"; + drck->drc_name_prefix = "LMB "; } static const TypeInfo spapr_dr_connector_info = { @@ -716,6 +661,7 @@ static const TypeInfo spapr_drc_physical_info = { .name = TYPE_SPAPR_DRC_PHYSICAL, .parent = TYPE_SPAPR_DR_CONNECTOR, .instance_size = sizeof(sPAPRDRConnector), + .class_init = spapr_drc_physical_class_init, .abstract = true, }; @@ -723,6 +669,7 @@ static const TypeInfo spapr_drc_logical_info = { .name = TYPE_SPAPR_DRC_LOGICAL, .parent = TYPE_SPAPR_DR_CONNECTOR, .instance_size = sizeof(sPAPRDRConnector), + .class_init = spapr_drc_logical_class_init, .abstract = true, }; @@ -846,7 +793,7 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, g_array_append_val(drc_power_domains, drc_power_domain); /* ibm,drc-names */ - drc_names = g_string_append(drc_names, drck->get_name(drc)); + drc_names = g_string_append(drc_names, spapr_drc_name(drc)); drc_names = g_string_insert_len(drc_names, -1, "\0", 1); /* ibm,drc-types */ @@ -905,74 +852,78 @@ out: * RTAS calls */ -static bool sensor_type_is_dr(uint32_t sensor_type) +static uint32_t rtas_set_isolation_state(uint32_t idx, uint32_t state) { - switch (sensor_type) { - case RTAS_SENSOR_TYPE_ISOLATION_STATE: - case RTAS_SENSOR_TYPE_DR: - case RTAS_SENSOR_TYPE_ALLOCATION_STATE: - return true; + sPAPRDRConnector *drc = spapr_drc_by_index(idx); + sPAPRDRConnectorClass *drck; + + if (!drc) { + return RTAS_OUT_PARAM_ERROR; } - return false; + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + return drck->set_isolation_state(drc, state); } -static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, uint32_t nret, - target_ulong rets) +static uint32_t rtas_set_allocation_state(uint32_t idx, uint32_t state) { - uint32_t sensor_type; - uint32_t sensor_index; - uint32_t sensor_state; - uint32_t ret = RTAS_OUT_SUCCESS; - sPAPRDRConnector *drc; + sPAPRDRConnector *drc = spapr_drc_by_index(idx); sPAPRDRConnectorClass *drck; - if (nargs != 3 || nret != 1) { - ret = RTAS_OUT_PARAM_ERROR; - goto out; + if (!drc) { + return RTAS_OUT_PARAM_ERROR; } - sensor_type = rtas_ld(args, 0); - sensor_index = rtas_ld(args, 1); - sensor_state = rtas_ld(args, 2); + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + return drck->set_allocation_state(drc, state); +} - if (!sensor_type_is_dr(sensor_type)) { - goto out_unimplemented; - } +static uint32_t rtas_set_dr_indicator(uint32_t idx, uint32_t state) +{ + sPAPRDRConnector *drc = spapr_drc_by_index(idx); - /* if this is a DR sensor we can assume sensor_index == drc_index */ - drc = spapr_drc_by_index(sensor_index); if (!drc) { - trace_spapr_rtas_set_indicator_invalid(sensor_index); + return RTAS_OUT_PARAM_ERROR; + } + + trace_spapr_drc_set_dr_indicator(idx, state); + drc->dr_indicator = state; + return RTAS_OUT_SUCCESS; +} + +static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, + uint32_t token, + uint32_t nargs, target_ulong args, + uint32_t nret, target_ulong rets) +{ + uint32_t type, idx, state; + uint32_t ret = RTAS_OUT_SUCCESS; + + if (nargs != 3 || nret != 1) { ret = RTAS_OUT_PARAM_ERROR; goto out; } - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - switch (sensor_type) { + type = rtas_ld(args, 0); + idx = rtas_ld(args, 1); + state = rtas_ld(args, 2); + + switch (type) { case RTAS_SENSOR_TYPE_ISOLATION_STATE: - ret = drck->set_isolation_state(drc, sensor_state); + ret = rtas_set_isolation_state(idx, state); break; case RTAS_SENSOR_TYPE_DR: - ret = drck->set_indicator_state(drc, sensor_state); + ret = rtas_set_dr_indicator(idx, state); break; case RTAS_SENSOR_TYPE_ALLOCATION_STATE: - ret = drck->set_allocation_state(drc, sensor_state); + ret = rtas_set_allocation_state(idx, state); break; default: - goto out_unimplemented; + ret = RTAS_OUT_NOT_SUPPORTED; } out: rtas_st(rets, 0, ret); - return; - -out_unimplemented: - /* currently only DR-related sensors are implemented */ - trace_spapr_rtas_set_indicator_not_supported(sensor_index, sensor_type); - rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); } static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr, @@ -1010,7 +961,7 @@ static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr, goto out; } drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - ret = drck->entity_sense(drc, &sensor_state); + sensor_state = drck->dr_entity_sense(drc); out: rtas_st(rets, 0, ret); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 0c181bb..0b447f2 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1344,31 +1344,6 @@ static int spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev, return offset; } -static void spapr_phb_add_pci_device(sPAPRDRConnector *drc, - sPAPRPHBState *phb, - PCIDevice *pdev, - Error **errp) -{ - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - DeviceState *dev = DEVICE(pdev); - void *fdt = NULL; - int fdt_start_offset = 0, fdt_size; - - fdt = create_device_tree(&fdt_size); - fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); - if (!fdt_start_offset) { - error_setg(errp, "Failed to create pci child device tree node"); - goto out; - } - - drck->attach(drc, DEVICE(pdev), - fdt, fdt_start_offset, !dev->hotplugged, errp); -out: - if (*errp) { - g_free(fdt); - } -} - /* Callback to be called during DRC release. */ void spapr_phb_remove_pci_device_cb(DeviceState *dev) { @@ -1386,16 +1361,6 @@ void spapr_phb_remove_pci_device_cb(DeviceState *dev) object_unparent(OBJECT(dev)); } -static void spapr_phb_remove_pci_device(sPAPRDRConnector *drc, - sPAPRPHBState *phb, - PCIDevice *pdev, - Error **errp) -{ - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - - drck->detach(drc, DEVICE(pdev), errp); -} - static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb, uint32_t busnr, int32_t devfn) @@ -1432,6 +1397,8 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, Error *local_err = NULL; PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))); uint32_t slotnr = PCI_SLOT(pdev->devfn); + void *fdt = NULL; + int fdt_start_offset, fdt_size; /* if DR is disabled we don't need to do anything in the case of * hotplug or coldplug callbacks @@ -1441,10 +1408,10 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, * we need to let them know it's not enabled */ if (plugged_dev->hotplugged) { - error_setg(errp, QERR_BUS_NO_HOTPLUG, + error_setg(&local_err, QERR_BUS_NO_HOTPLUG, object_get_typename(OBJECT(phb))); } - return; + goto out; } g_assert(drc); @@ -1455,16 +1422,23 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, */ if (plugged_dev->hotplugged && bus->devices[PCI_DEVFN(slotnr, 0)] && PCI_FUNC(pdev->devfn) != 0) { - error_setg(errp, "PCI: slot %d function 0 already ocuppied by %s," + error_setg(&local_err, "PCI: slot %d function 0 already ocuppied by %s," " additional functions can no longer be exposed to guest.", slotnr, bus->devices[PCI_DEVFN(slotnr, 0)]->name); - return; + goto out; + } + + fdt = create_device_tree(&fdt_size); + fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0); + if (!fdt_start_offset) { + error_setg(&local_err, "Failed to create pci child device tree node"); + goto out; } - spapr_phb_add_pci_device(drc, phb, pdev, &local_err); + spapr_drc_attach(drc, DEVICE(pdev), fdt, fdt_start_offset, + !plugged_dev->hotplugged, &local_err); if (local_err) { - error_propagate(errp, local_err); - return; + goto out; } /* If this is function 0, signal hotplug for all the device functions. @@ -1481,13 +1455,19 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, func_drc = spapr_phb_get_pci_func_drc(phb, pci_bus_num(bus), PCI_DEVFN(slotnr, i)); func_drck = SPAPR_DR_CONNECTOR_GET_CLASS(func_drc); - func_drck->entity_sense(func_drc, &state); + state = func_drck->dr_entity_sense(func_drc); if (state == SPAPR_DR_ENTITY_SENSE_PRESENT) { spapr_hotplug_req_add_by_index(func_drc); } } } + +out: + if (local_err) { + error_propagate(errp, local_err); + g_free(fdt); + } } static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, @@ -1522,7 +1502,7 @@ static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, func_drc = spapr_phb_get_pci_func_drc(phb, pci_bus_num(bus), PCI_DEVFN(slotnr, i)); func_drck = SPAPR_DR_CONNECTOR_GET_CLASS(func_drc); - func_drck->entity_sense(func_drc, &state); + state = func_drck->dr_entity_sense(func_drc); if (state == SPAPR_DR_ENTITY_SENSE_PRESENT && !func_drck->release_pending(func_drc)) { error_setg(errp, @@ -1534,7 +1514,7 @@ static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, } } - spapr_phb_remove_pci_device(drc, phb, pdev, &local_err); + spapr_drc_detach(drc, DEVICE(pdev), &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1548,7 +1528,7 @@ static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler, func_drc = spapr_phb_get_pci_func_drc(phb, pci_bus_num(bus), PCI_DEVFN(slotnr, i)); func_drck = SPAPR_DR_CONNECTOR_GET_CLASS(func_drc); - func_drck->entity_sense(func_drc, &state); + state = func_drck->dr_entity_sense(func_drc); if (state == SPAPR_DR_ENTITY_SENSE_PRESENT) { spapr_hotplug_req_remove_by_index(func_drc); } diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 707c4d4..94a2799 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -293,12 +293,9 @@ static void rtas_ibm_os_term(PowerPCCPU *cpu, target_ulong args, uint32_t nret, target_ulong rets) { - target_ulong ret = 0; + qemu_system_guest_panicked(NULL); - qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, false, NULL, - &error_abort); - - rtas_st(rets, 0, ret); + rtas_st(rets, 0, RTAS_OUT_SUCCESS); } static void rtas_set_power_level(PowerPCCPU *cpu, sPAPRMachineState *spapr, diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 43d265f..3e8e3cf 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -39,12 +39,11 @@ spapr_iommu_ddw_reset(uint64_t buid, uint32_t cfgaddr) "buid=%"PRIx64" addr=%"PR spapr_drc_set_isolation_state(uint32_t index, int state) "drc: 0x%"PRIx32", state: %"PRIx32 spapr_drc_set_isolation_state_finalizing(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_set_isolation_state_deferring(uint32_t index) "drc: 0x%"PRIx32 -spapr_drc_set_indicator_state(uint32_t index, int state) "drc: 0x%"PRIx32", state: 0x%x" +spapr_drc_set_dr_indicator(uint32_t index, int state) "drc: 0x%"PRIx32", state: 0x%x" spapr_drc_set_allocation_state(uint32_t index, int state) "drc: 0x%"PRIx32", state: 0x%x" spapr_drc_set_allocation_state_finalizing(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_set_configured(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_set_configured_skipping(uint32_t index) "drc: 0x%"PRIx32", isolated device" -spapr_drc_entity_sense(uint32_t index, int state) "drc: 0x%"PRIx32", state: 0x%x" spapr_drc_attach(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_detach(uint32_t index) "drc: 0x%"PRIx32 spapr_drc_awaiting_isolated(uint32_t index) "drc: 0x%"PRIx32 @@ -61,8 +60,6 @@ spapr_ovec_parse_vector(int vector, int byte, uint16_t vec_len, uint8_t entry) " spapr_ovec_populate_dt(int byte, uint16_t vec_len, uint8_t entry) "encoding guest vector byte %3d / %3d: 0x%.2x" # hw/ppc/spapr_rtas.c -spapr_rtas_set_indicator_invalid(uint32_t index) "sensor index: 0x%"PRIx32 -spapr_rtas_set_indicator_not_supported(uint32_t index, uint32_t type) "sensor index: 0x%"PRIx32", type: %"PRIu32 spapr_rtas_get_sensor_state_not_supported(uint32_t index, uint32_t type) "sensor index: 0x%"PRIx32", type: %"PRIu32 spapr_rtas_get_sensor_state_invalid(uint32_t index) "sensor index: 0x%"PRIx32 spapr_rtas_ibm_configure_connector_invalid(uint32_t index) "DRC index: 0x%"PRIx32 |