提交 9746211b 编写于 作者: P Peter Maydell

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: NPeter Maydell <peter.maydell@linaro.org>
......@@ -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
......@@ -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);
}
}
......
......@@ -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,
error_setg(errp, "Unable to connect CPU%ld to kernel XICS: %s", vcpu_id,
strerror(errno));
exit(1);
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)
......
......@@ -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);
}
......
......@@ -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)
......
......@@ -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);
......
......@@ -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;
/* The DRC being examined by the caller at least must be counted */
g_assert(ds->nr_lmbs);
}
} else if (--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);
......
......@@ -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:
......
此差异已折叠。
......@@ -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);
}
......
......@@ -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,
......
......@@ -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
......
......@@ -125,7 +125,7 @@ typedef enum {
} sPAPRDRAllocationState;
/*
* LED/visual indicator state
* DR-indicator (LED/visual indicator)
*
* set via set-indicator RTAS calls
* as documented by PAPR+ 2.7 13.5.3.4, Table 177,
......@@ -137,10 +137,10 @@ typedef enum {
* action: (currently unused)
*/
typedef enum {
SPAPR_DR_INDICATOR_STATE_INACTIVE = 0,
SPAPR_DR_INDICATOR_STATE_ACTIVE = 1,
SPAPR_DR_INDICATOR_STATE_IDENTIFY = 2,
SPAPR_DR_INDICATOR_STATE_ACTION = 3,
SPAPR_DR_INDICATOR_INACTIVE = 0,
SPAPR_DR_INDICATOR_ACTIVE = 1,
SPAPR_DR_INDICATOR_IDENTIFY = 2,
SPAPR_DR_INDICATOR_ACTION = 3,
} sPAPRDRIndicatorState;
/*
......@@ -184,12 +184,13 @@ typedef struct sPAPRDRConnector {
uint32_t id;
Object *owner;
const char *name;
/* DR-indicator */
uint32_t dr_indicator;
/* sensor/indicator states */
uint32_t isolation_state;
uint32_t allocation_state;
uint32_t indicator_state;
/* configure-connector state */
void *fdt;
......@@ -200,7 +201,6 @@ typedef struct sPAPRDRConnector {
bool awaiting_release;
bool signalled;
bool awaiting_allocation;
bool awaiting_allocation_skippable;
/* device pointer, via link property */
DeviceState *dev;
......@@ -213,22 +213,17 @@ typedef struct sPAPRDRConnectorClass {
/*< public >*/
sPAPRDRConnectorTypeShift typeshift;
const char *typename; /* used in device tree, PAPR 13.5.2.6 & C.6.1 */
const char *drc_name_prefix; /* used other places in device tree */
sPAPRDREntitySense (*dr_entity_sense)(sPAPRDRConnector *drc);
/* accessors for guest-visible (generally via RTAS) DR state */
uint32_t (*set_isolation_state)(sPAPRDRConnector *drc,
sPAPRDRIsolationState state);
uint32_t (*set_indicator_state)(sPAPRDRConnector *drc,
sPAPRDRIndicatorState state);
uint32_t (*set_allocation_state)(sPAPRDRConnector *drc,
sPAPRDRAllocationState state);
const char *(*get_name)(sPAPRDRConnector *drc);
uint32_t (*entity_sense)(sPAPRDRConnector *drc, sPAPRDREntitySense *state);
/* QEMU interfaces for managing hotplug operations */
void (*attach)(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
int fdt_start_offset, bool coldplug, Error **errp);
void (*detach)(sPAPRDRConnector *drc, DeviceState *d, Error **errp);
bool (*release_pending)(sPAPRDRConnector *drc);
void (*set_signalled)(sPAPRDRConnector *drc);
} sPAPRDRConnectorClass;
......@@ -243,4 +238,8 @@ sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id);
int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
uint32_t drc_type_mask);
void spapr_drc_attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
int fdt_start_offset, bool coldplug, Error **errp);
void spapr_drc_detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp);
#endif /* HW_SPAPR_DRC_H */
......@@ -65,10 +65,10 @@ typedef struct XICSFabric XICSFabric;
struct ICPStateClass {
DeviceClass parent_class;
void (*realize)(DeviceState *dev, Error **errp);
void (*pre_save)(ICPState *s);
int (*post_load)(ICPState *s, int version_id);
void (*cpu_setup)(ICPState *icp, PowerPCCPU *cpu);
void (*realize)(ICPState *icp, Error **errp);
void (*pre_save)(ICPState *icp);
int (*post_load)(ICPState *icp, int version_id);
void (*reset)(ICPState *icp);
};
struct ICPState {
......@@ -85,6 +85,9 @@ struct ICPState {
XICSFabric *xics;
};
#define ICP_PROP_XICS "xics"
#define ICP_PROP_CPU "cpu"
struct PnvICPState {
ICPState parent_obj;
......@@ -110,7 +113,7 @@ struct PnvICPState {
struct ICSStateClass {
DeviceClass parent_class;
void (*realize)(DeviceState *dev, Error **errp);
void (*realize)(ICSState *s, Error **errp);
void (*pre_save)(ICSState *s);
int (*post_load)(ICSState *s, int version_id);
void (*reject)(ICSState *s, uint32_t irq);
......@@ -129,6 +132,8 @@ struct ICSState {
XICSFabric *xics;
};
#define ICS_PROP_XICS "xics"
static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
{
return (ics->offset != 0) && (nr >= ics->offset)
......@@ -182,8 +187,6 @@ void spapr_dt_xics(int nr_servers, void *fdt, uint32_t phandle);
qemu_irq xics_get_qirq(XICSFabric *xi, int irq);
ICPState *xics_icp_get(XICSFabric *xi, int server);
void xics_cpu_setup(XICSFabric *xi, PowerPCCPU *cpu, ICPState *icp);
void xics_cpu_destroy(XICSFabric *xi, PowerPCCPU *cpu);
/* Internal XICS interfaces */
void icp_set_cppr(ICPState *icp, uint8_t cppr);
......
......@@ -478,7 +478,7 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
}
}
bool kvmppc_is_mem_backend_page_size_ok(char *obj_path)
bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path)
{
Object *mem_obj = object_resolve_path(obj_path, NULL);
char *mempath = object_property_get_str(mem_obj, "mem-path", NULL);
......@@ -486,6 +486,7 @@ bool kvmppc_is_mem_backend_page_size_ok(char *obj_path)
if (mempath) {
pagesize = qemu_mempath_getpagesize(mempath);
g_free(mempath);
} else {
pagesize = getpagesize();
}
......@@ -499,7 +500,7 @@ static inline void kvm_fixup_page_sizes(PowerPCCPU *cpu)
{
}
bool kvmppc_is_mem_backend_page_size_ok(char *obj_path)
bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path)
{
return true;
}
......
......@@ -64,7 +64,7 @@ int kvmppc_enable_hwrng(void);
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
bool kvmppc_is_mem_backend_page_size_ok(char *obj_path);
bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path);
#else
......@@ -211,7 +211,7 @@ static inline uint64_t kvmppc_rma_size(uint64_t current_size,
return ram_size;
}
static inline bool kvmppc_is_mem_backend_page_size_ok(char *obj_path)
static inline bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path)
{
return true;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册