aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-06-13 11:56:00 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-06-13 11:56:00 +0100
commit9746211baa6ff1275e9c726c6f3a3bcfe4b1f8bd (patch)
treea53b570a5344370b8d6991ae1c84691024330a80 /hw
parent8e3cf49c47064da19f4bfb1c5bf16e6e613f1bfa (diff)
parent593080936a06a04eacc589350e3a7ebc02f2ed8e (diff)
downloadqemu-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.objs3
-rw-r--r--hw/intc/xics.c95
-rw-r--r--hw/intc/xics_kvm.c45
-rw-r--r--hw/intc/xics_pnv.c6
-rw-r--r--hw/ppc/pnv_core.c16
-rw-r--r--hw/ppc/pnv_psi.c3
-rw-r--r--hw/ppc/spapr.c44
-rw-r--r--hw/ppc/spapr_cpu_core.c22
-rw-r--r--hw/ppc/spapr_drc.c289
-rw-r--r--hw/ppc/spapr_pci.c72
-rw-r--r--hw/ppc/spapr_rtas.c7
-rw-r--r--hw/ppc/trace-events5
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