aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/e500.c4
-rw-r--r--hw/ppc/pnv.c96
-rw-r--r--hw/ppc/pnv_bmc.c2
-rw-r--r--hw/ppc/pnv_core.c18
-rw-r--r--hw/ppc/pnv_lpc.c16
-rw-r--r--hw/ppc/pnv_psi.c4
-rw-r--r--hw/ppc/pnv_xscom.c10
-rw-r--r--hw/ppc/prep.c1
-rw-r--r--hw/ppc/spapr.c224
-rw-r--r--hw/ppc/spapr_cpu_core.c42
-rw-r--r--hw/ppc/spapr_events.c22
-rw-r--r--hw/ppc/spapr_hcall.c1
-rw-r--r--hw/ppc/spapr_pci.c19
-rw-r--r--hw/ppc/spapr_pci_vfio.c47
-rw-r--r--hw/ppc/spapr_rtas.c30
-rw-r--r--hw/ppc/spapr_vio.c5
-rw-r--r--hw/ppc/trace-events4
17 files changed, 335 insertions, 210 deletions
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 5cf0dabef3..c4fe06ea2a 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -685,6 +685,8 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,
int i, j, k;
dev = qdev_create(NULL, TYPE_OPENPIC);
+ object_property_add_child(qdev_get_machine(), "pic", OBJECT(dev),
+ &error_fatal);
qdev_prop_set_uint32(dev, "model", params->mpic_version);
qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
@@ -884,6 +886,8 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
/* PCI */
dev = qdev_create(NULL, "e500-pcihost");
+ object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev),
+ &error_abort);
qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot);
qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]);
qdev_init_nofail(dev);
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index c35c439d81..9475e8479c 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -77,8 +77,7 @@ static const char *pnv_chip_core_typename(const PnvChip *o)
* that has a different "affinity". In practice, it means one range
* per chip.
*/
-static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
- hwaddr size)
+static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
{
char *mem_name;
uint64_t mem_reg_property[2];
@@ -119,7 +118,7 @@ static int get_cpus_node(void *fdt)
* device tree, used in XSCOM to address cores and in interrupt
* servers.
*/
-static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
+static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
{
CPUState *cs = CPU(DEVICE(pc->threads));
DeviceClass *dc = DEVICE_GET_CLASS(cs);
@@ -228,8 +227,8 @@ static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
servers_prop, sizeof(servers_prop))));
}
-static void powernv_populate_icp(PnvChip *chip, void *fdt, uint32_t pir,
- uint32_t nr_threads)
+static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
+ uint32_t nr_threads)
{
uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
char *name;
@@ -277,13 +276,13 @@ static int pnv_chip_lpc_offset(PnvChip *chip, void *fdt)
return offset;
}
-static void powernv_populate_chip(PnvChip *chip, void *fdt)
+static void pnv_dt_chip(PnvChip *chip, void *fdt)
{
const char *typename = pnv_chip_core_typename(chip);
size_t typesize = object_type_get_instance_size(typename);
int i;
- pnv_xscom_populate(chip, fdt, 0);
+ pnv_dt_xscom(chip, fdt, 0);
/* The default LPC bus of a multichip system is on chip 0. It's
* recognized by the firmware (skiboot) using a "primary"
@@ -298,20 +297,18 @@ static void powernv_populate_chip(PnvChip *chip, void *fdt)
for (i = 0; i < chip->nr_cores; i++) {
PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
- powernv_create_core_node(chip, pnv_core, fdt);
+ pnv_dt_core(chip, pnv_core, fdt);
/* Interrupt Control Presenters (ICP). One per core. */
- powernv_populate_icp(chip, fdt, pnv_core->pir,
- CPU_CORE(pnv_core)->nr_threads);
+ pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
}
if (chip->ram_size) {
- powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start,
- chip->ram_size);
+ pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
}
}
-static void powernv_populate_rtc(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
{
uint32_t io_base = d->ioport_id;
uint32_t io_regs[] = {
@@ -331,7 +328,7 @@ static void powernv_populate_rtc(ISADevice *d, void *fdt, int lpc_off)
_FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
}
-static void powernv_populate_serial(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
{
const char compatible[] = "ns16550\0pnpPNP,501";
uint32_t io_base = d->ioport_id;
@@ -362,7 +359,7 @@ static void powernv_populate_serial(ISADevice *d, void *fdt, int lpc_off)
_FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
}
-static void powernv_populate_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
+static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
{
const char compatible[] = "bt\0ipmi-bt";
uint32_t io_base;
@@ -401,17 +398,17 @@ typedef struct ForeachPopulateArgs {
int offset;
} ForeachPopulateArgs;
-static int powernv_populate_isa_device(DeviceState *dev, void *opaque)
+static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
{
ForeachPopulateArgs *args = opaque;
ISADevice *d = ISA_DEVICE(dev);
if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
- powernv_populate_rtc(d, args->fdt, args->offset);
+ pnv_dt_rtc(d, args->fdt, args->offset);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
- powernv_populate_serial(d, args->fdt, args->offset);
+ pnv_dt_serial(d, args->fdt, args->offset);
} else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
- powernv_populate_ipmi_bt(d, args->fdt, args->offset);
+ pnv_dt_ipmi_bt(d, args->fdt, args->offset);
} else {
error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
d->ioport_id);
@@ -420,7 +417,7 @@ static int powernv_populate_isa_device(DeviceState *dev, void *opaque)
return 0;
}
-static void powernv_populate_isa(ISABus *bus, void *fdt, int lpc_offset)
+static void pnv_dt_isa(ISABus *bus, void *fdt, int lpc_offset)
{
ForeachPopulateArgs args = {
.fdt = fdt,
@@ -429,14 +426,13 @@ static void powernv_populate_isa(ISABus *bus, void *fdt, int lpc_offset)
/* ISA devices are not necessarily parented to the ISA bus so we
* can not use object_child_foreach() */
- qbus_walk_children(BUS(bus), powernv_populate_isa_device,
- NULL, NULL, NULL, &args);
+ qbus_walk_children(BUS(bus), pnv_dt_isa_device, NULL, NULL, NULL, &args);
}
-static void *powernv_create_fdt(MachineState *machine)
+static void *pnv_dt_create(MachineState *machine)
{
const char plat_compat[] = "qemu,powernv\0ibm,powernv";
- PnvMachineState *pnv = POWERNV_MACHINE(machine);
+ PnvMachineState *pnv = PNV_MACHINE(machine);
void *fdt;
char *buf;
int off;
@@ -479,15 +475,15 @@ static void *powernv_create_fdt(MachineState *machine)
/* Populate device tree for each chip */
for (i = 0; i < pnv->num_chips; i++) {
- powernv_populate_chip(pnv->chips[i], fdt);
+ pnv_dt_chip(pnv->chips[i], fdt);
}
/* Populate ISA devices on chip 0 */
lpc_offset = pnv_chip_lpc_offset(pnv->chips[0], fdt);
- powernv_populate_isa(pnv->isa_bus, fdt, lpc_offset);
+ pnv_dt_isa(pnv->isa_bus, fdt, lpc_offset);
if (pnv->bmc) {
- pnv_bmc_populate_sensors(pnv->bmc, fdt);
+ pnv_dt_bmc_sensors(pnv->bmc, fdt);
}
return fdt;
@@ -495,17 +491,17 @@ static void *powernv_create_fdt(MachineState *machine)
static void pnv_powerdown_notify(Notifier *n, void *opaque)
{
- PnvMachineState *pnv = POWERNV_MACHINE(qdev_get_machine());
+ PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
if (pnv->bmc) {
pnv_bmc_powerdown(pnv->bmc);
}
}
-static void ppc_powernv_reset(void)
+static void pnv_reset(void)
{
MachineState *machine = MACHINE(qdev_get_machine());
- PnvMachineState *pnv = POWERNV_MACHINE(machine);
+ PnvMachineState *pnv = PNV_MACHINE(machine);
void *fdt;
Object *obj;
@@ -524,7 +520,7 @@ static void ppc_powernv_reset(void)
pnv->bmc = IPMI_BMC(obj);
}
- fdt = powernv_create_fdt(machine);
+ fdt = pnv_dt_create(machine);
/* Pack resulting tree */
_FDT((fdt_pack(fdt)));
@@ -552,9 +548,9 @@ static ISABus *pnv_isa_create(PnvChip *chip)
return isa_bus;
}
-static void ppc_powernv_init(MachineState *machine)
+static void pnv_init(MachineState *machine)
{
- PnvMachineState *pnv = POWERNV_MACHINE(machine);
+ PnvMachineState *pnv = PNV_MACHINE(machine);
MemoryRegion *ram;
char *fw_filename;
long fw_size;
@@ -567,7 +563,7 @@ static void ppc_powernv_init(MachineState *machine)
}
ram = g_new(MemoryRegion, 1);
- memory_region_allocate_system_memory(ram, NULL, "ppc_powernv.ram",
+ memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
machine->ram_size);
memory_region_add_subregion(get_system_memory(), 0, ram);
@@ -655,7 +651,7 @@ static void ppc_powernv_init(MachineState *machine)
serial_hds_isa_init(pnv->isa_bus, 0, MAX_SERIAL_PORTS);
/* Create an RTC ISA device too */
- rtc_init(pnv->isa_bus, 2000, NULL);
+ mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
/* OpenPOWER systems use a IPMI SEL Event message to notify the
* host to powerdown */
@@ -974,7 +970,7 @@ static void pnv_chip_class_init(ObjectClass *klass, void *data)
static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
{
- PnvMachineState *pnv = POWERNV_MACHINE(xi);
+ PnvMachineState *pnv = PNV_MACHINE(xi);
int i;
for (i = 0; i < pnv->num_chips; i++) {
@@ -987,7 +983,7 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
static void pnv_ics_resend(XICSFabric *xi)
{
- PnvMachineState *pnv = POWERNV_MACHINE(xi);
+ PnvMachineState *pnv = PNV_MACHINE(xi);
int i;
for (i = 0; i < pnv->num_chips; i++) {
@@ -1021,7 +1017,7 @@ static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
static void pnv_pic_print_info(InterruptStatsProvider *obj,
Monitor *mon)
{
- PnvMachineState *pnv = POWERNV_MACHINE(obj);
+ PnvMachineState *pnv = PNV_MACHINE(obj);
int i;
CPUState *cs;
@@ -1039,13 +1035,13 @@ static void pnv_pic_print_info(InterruptStatsProvider *obj,
static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
- visit_type_uint32(v, name, &POWERNV_MACHINE(obj)->num_chips, errp);
+ visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
}
static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
- PnvMachineState *pnv = POWERNV_MACHINE(obj);
+ PnvMachineState *pnv = PNV_MACHINE(obj);
uint32_t num_chips;
Error *local_err = NULL;
@@ -1067,13 +1063,13 @@ static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
pnv->num_chips = num_chips;
}
-static void powernv_machine_initfn(Object *obj)
+static void pnv_machine_initfn(Object *obj)
{
- PnvMachineState *pnv = POWERNV_MACHINE(obj);
+ PnvMachineState *pnv = PNV_MACHINE(obj);
pnv->num_chips = 1;
}
-static void powernv_machine_class_props_init(ObjectClass *oc)
+static void pnv_machine_class_props_init(ObjectClass *oc)
{
object_class_property_add(oc, "num-chips", "uint32",
pnv_get_num_chips, pnv_set_num_chips,
@@ -1083,15 +1079,15 @@ static void powernv_machine_class_props_init(ObjectClass *oc)
NULL);
}
-static void powernv_machine_class_init(ObjectClass *oc, void *data)
+static void pnv_machine_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
mc->desc = "IBM PowerNV (Non-Virtualized)";
- mc->init = ppc_powernv_init;
- mc->reset = ppc_powernv_reset;
+ mc->init = pnv_init;
+ mc->reset = pnv_reset;
mc->max_cpus = MAX_CPUS;
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
@@ -1104,7 +1100,7 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data)
xic->ics_resend = pnv_ics_resend;
ispc->print_info = pnv_pic_print_info;
- powernv_machine_class_props_init(oc);
+ pnv_machine_class_props_init(oc);
}
#define DEFINE_PNV_CHIP_TYPE(type, class_initfn) \
@@ -1116,11 +1112,11 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data)
static const TypeInfo types[] = {
{
- .name = TYPE_POWERNV_MACHINE,
+ .name = TYPE_PNV_MACHINE,
.parent = TYPE_MACHINE,
.instance_size = sizeof(PnvMachineState),
- .instance_init = powernv_machine_initfn,
- .class_init = powernv_machine_class_init,
+ .instance_init = pnv_machine_initfn,
+ .class_init = pnv_machine_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_XICS_FABRIC },
{ TYPE_INTERRUPT_STATS_PROVIDER },
diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c
index 7b60b4c360..b2cf441ee7 100644
--- a/hw/ppc/pnv_bmc.c
+++ b/hw/ppc/pnv_bmc.c
@@ -73,7 +73,7 @@ void pnv_bmc_powerdown(IPMIBmc *bmc)
pnv_gen_oem_sel(bmc, SOFT_OFF);
}
-void pnv_bmc_populate_sensors(IPMIBmc *bmc, void *fdt)
+void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt)
{
int offset;
int i;
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 82ff440b33..7e8a76df44 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -37,7 +37,7 @@ static const char *pnv_core_cpu_typename(PnvCore *pc)
return cpu_type;
}
-static void powernv_cpu_reset(void *opaque)
+static void pnv_cpu_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
@@ -54,7 +54,7 @@ static void powernv_cpu_reset(void *opaque)
env->msr |= MSR_HVB; /* Hypervisor mode */
}
-static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
+static void pnv_cpu_init(PowerPCCPU *cpu, Error **errp)
{
CPUPPCState *env = &cpu->env;
int core_pir;
@@ -73,7 +73,7 @@ static void powernv_cpu_init(PowerPCCPU *cpu, Error **errp)
/* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
- qemu_register_reset(powernv_cpu_reset, cpu);
+ qemu_register_reset(pnv_cpu_reset, cpu);
}
/*
@@ -126,7 +126,6 @@ static void pnv_core_realize_child(Object *child, XICSFabric *xi, Error **errp)
Error *local_err = NULL;
CPUState *cs = CPU(child);
PowerPCCPU *cpu = POWERPC_CPU(cs);
- Object *obj;
object_property_set_bool(child, true, "realized", &local_err);
if (local_err) {
@@ -134,21 +133,14 @@ static void pnv_core_realize_child(Object *child, XICSFabric *xi, Error **errp)
return;
}
- 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);
+ cpu->intc = icp_create(child, TYPE_PNV_ICP, xi, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
- powernv_cpu_init(cpu, &local_err);
+ pnv_cpu_init(cpu, &local_err);
if (local_err) {
- object_unparent(obj);
error_propagate(errp, local_err);
return;
}
diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index f03a80a29b..c42b4a8f6c 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -92,7 +92,7 @@ enum {
#define LPC_HC_REGS_OPB_SIZE 0x00001000
-static int pnv_lpc_populate(PnvXScomInterface *dev, void *fdt, int xscom_offset)
+static int pnv_lpc_dt_xscom(PnvXScomInterface *dev, void *fdt, int xscom_offset)
{
const char compat[] = "ibm,power8-lpc\0ibm,lpc";
char *name;
@@ -146,13 +146,13 @@ static bool opb_write(PnvLpcController *lpc, uint32_t addr, uint8_t *data,
return success;
}
-#define ECCB_CTL_READ (1ull << (63 - 15))
+#define ECCB_CTL_READ PPC_BIT(15)
#define ECCB_CTL_SZ_LSH (63 - 7)
-#define ECCB_CTL_SZ_MASK (0xfull << ECCB_CTL_SZ_LSH)
-#define ECCB_CTL_ADDR_MASK 0xffffffffu;
+#define ECCB_CTL_SZ_MASK PPC_BITMASK(4, 7)
+#define ECCB_CTL_ADDR_MASK PPC_BITMASK(32, 63)
-#define ECCB_STAT_OP_DONE (1ull << (63 - 52))
-#define ECCB_STAT_OP_ERR (1ull << (63 - 52))
+#define ECCB_STAT_OP_DONE PPC_BIT(52)
+#define ECCB_STAT_OP_ERR PPC_BIT(52)
#define ECCB_STAT_RD_DATA_LSH (63 - 37)
#define ECCB_STAT_RD_DATA_MASK (0xffffffff << ECCB_STAT_RD_DATA_LSH)
@@ -482,7 +482,7 @@ static void pnv_lpc_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
- xdc->populate = pnv_lpc_populate;
+ xdc->dt_xscom = pnv_lpc_dt_xscom;
dc->realize = pnv_lpc_realize;
}
@@ -515,7 +515,7 @@ type_init(pnv_lpc_register_types)
*/
static void pnv_lpc_isa_irq_handler_cpld(void *opaque, int n, int level)
{
- PnvMachineState *pnv = POWERNV_MACHINE(qdev_get_machine());
+ PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
uint32_t old_state = pnv->cpld_irqstate;
PnvLpcController *lpc = PNV_LPC(opaque);
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 9876c26622..5b969127c3 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -510,7 +510,7 @@ static void pnv_psi_realize(DeviceState *dev, Error **errp)
}
}
-static int pnv_psi_populate(PnvXScomInterface *dev, void *fdt, int xscom_offset)
+static int pnv_psi_dt_xscom(PnvXScomInterface *dev, void *fdt, int xscom_offset)
{
const char compat[] = "ibm,power8-psihb-x\0ibm,psihb-x";
char *name;
@@ -546,7 +546,7 @@ static void pnv_psi_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
- xdc->populate = pnv_psi_populate;
+ xdc->dt_xscom = pnv_psi_dt_xscom;
dc->realize = pnv_psi_realize;
dc->props = pnv_psi_properties;
diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c
index 38bc85f117..e51d634f40 100644
--- a/hw/ppc/pnv_xscom.c
+++ b/hw/ppc/pnv_xscom.c
@@ -207,15 +207,15 @@ typedef struct ForeachPopulateArgs {
int xscom_offset;
} ForeachPopulateArgs;
-static int xscom_populate_child(Object *child, void *opaque)
+static int xscom_dt_child(Object *child, void *opaque)
{
if (object_dynamic_cast(child, TYPE_PNV_XSCOM_INTERFACE)) {
ForeachPopulateArgs *args = opaque;
PnvXScomInterface *xd = PNV_XSCOM_INTERFACE(child);
PnvXScomInterfaceClass *xc = PNV_XSCOM_INTERFACE_GET_CLASS(xd);
- if (xc->populate) {
- _FDT((xc->populate(xd, args->fdt, args->xscom_offset)));
+ if (xc->dt_xscom) {
+ _FDT((xc->dt_xscom(xd, args->fdt, args->xscom_offset)));
}
}
return 0;
@@ -224,7 +224,7 @@ static int xscom_populate_child(Object *child, void *opaque)
static const char compat_p8[] = "ibm,power8-xscom\0ibm,xscom";
static const char compat_p9[] = "ibm,power9-xscom\0ibm,xscom";
-int pnv_xscom_populate(PnvChip *chip, void *fdt, int root_offset)
+int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset)
{
uint64_t reg[] = { cpu_to_be64(PNV_XSCOM_BASE(chip)),
cpu_to_be64(PNV_XSCOM_SIZE) };
@@ -255,7 +255,7 @@ int pnv_xscom_populate(PnvChip *chip, void *fdt, int root_offset)
args.fdt = fdt;
args.xscom_offset = xscom_offset;
- object_child_foreach(OBJECT(chip), xscom_populate_child, &args);
+ object_child_foreach(OBJECT(chip), xscom_dt_child, &args);
return 0;
}
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 6f8accc397..af08ac319a 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -42,6 +42,7 @@
#include "hw/loader.h"
#include "hw/timer/mc146818rtc.h"
#include "hw/isa/pc87312.h"
+#include "hw/net/ne2000-isa.h"
#include "sysemu/block-backend.h"
#include "sysemu/arch_init.h"
#include "sysemu/kvm.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 1ac7eb0f8c..dfd352c473 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -641,6 +641,26 @@ static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr)
}
+static uint32_t spapr_pc_dimm_node(MemoryDeviceInfoList *list, ram_addr_t addr)
+{
+ MemoryDeviceInfoList *info;
+
+ for (info = list; info; info = info->next) {
+ MemoryDeviceInfo *value = info->value;
+
+ if (value && value->type == MEMORY_DEVICE_INFO_KIND_DIMM) {
+ PCDIMMDeviceInfo *pcdimm_info = value->u.dimm.data;
+
+ if (pcdimm_info->addr >= addr &&
+ addr < (pcdimm_info->addr + pcdimm_info->size)) {
+ return pcdimm_info->node;
+ }
+ }
+ }
+
+ return -1;
+}
+
/*
* Adds ibm,dynamic-reconfiguration-memory node.
* Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation
@@ -658,6 +678,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
lmb_size;
uint32_t *int_buf, *cur_index, buf_len;
int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
+ MemoryDeviceInfoList *dimms = NULL;
/*
* Don't create the node if there is no hotpluggable memory
@@ -692,6 +713,11 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
goto out;
}
+ if (hotplug_lmb_start) {
+ MemoryDeviceInfoList **prev = &dimms;
+ qmp_pc_dimm_device_list(qdev_get_machine(), &prev);
+ }
+
/* ibm,dynamic-memory */
int_buf[0] = cpu_to_be32(nr_lmbs);
cur_index++;
@@ -709,7 +735,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc));
dynamic_memory[3] = cpu_to_be32(0); /* reserved */
- dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL));
+ dynamic_memory[4] = cpu_to_be32(spapr_pc_dimm_node(dimms, addr));
if (memory_region_present(get_system_memory(), addr)) {
dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
} else {
@@ -732,6 +758,7 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE;
}
+ qapi_free_MemoryDeviceInfoList(dimms);
ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len);
if (ret < 0) {
goto out;
@@ -916,9 +943,8 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
_FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate",
RTAS_EVENT_SCAN_RATE));
- if (msi_nonbroken) {
- _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0));
- }
+ g_assert(msi_nonbroken);
+ _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0));
/*
* According to PAPR, rtas ibm,os-term does not guarantee a return
@@ -1427,7 +1453,7 @@ static int spapr_reset_drcs(Object *child, void *opaque)
return 0;
}
-static void ppc_spapr_reset(void)
+static void spapr_machine_reset(void)
{
MachineState *machine = MACHINE(qdev_get_machine());
sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
@@ -1440,7 +1466,10 @@ static void ppc_spapr_reset(void)
/* Check for unknown sysbus devices */
foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);
- if (kvm_enabled() && kvmppc_has_cap_mmu_radix()) {
+ first_ppc_cpu = POWERPC_CPU(first_cpu);
+ if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
+ ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
+ spapr->max_compat_pvr)) {
/* If using KVM with radix mode available, VCPUs can be started
* without a HPT because KVM will start them in radix mode.
* Set the GR bit in PATB so that we know there is no HPT. */
@@ -1475,7 +1504,7 @@ static void ppc_spapr_reset(void)
spapr_ovec_cleanup(spapr->ov5_cas);
spapr->ov5_cas = spapr_ovec_new();
- ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal);
+ ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal);
}
fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
@@ -1499,7 +1528,6 @@ static void ppc_spapr_reset(void)
g_free(fdt);
/* Set up the entry state */
- first_ppc_cpu = POWERPC_CPU(first_cpu);
first_ppc_cpu->env.gpr[3] = fdt_addr;
first_ppc_cpu->env.gpr[5] = 0;
first_cpu->halted = 0;
@@ -2265,7 +2293,7 @@ out:
}
/* pSeries LPAR / sPAPR hardware init */
-static void ppc_spapr_init(MachineState *machine)
+static void spapr_machine_init(MachineState *machine)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
@@ -2793,7 +2821,7 @@ static void spapr_set_vsmt(Object *obj, Visitor *v, const char *name,
visit_type_uint32(v, name, (uint32_t *)opaque, errp);
}
-static void spapr_machine_initfn(Object *obj)
+static void spapr_instance_init(Object *obj)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
@@ -3180,12 +3208,10 @@ void spapr_core_release(DeviceState *dev)
if (smc->pre_2_10_has_unused_icps) {
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
- sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(cc));
- size_t size = object_type_get_instance_size(scc->cpu_type);
int i;
for (i = 0; i < cc->nr_threads; i++) {
- CPUState *cs = CPU(sc->threads + i * size);
+ CPUState *cs = CPU(sc->threads[i]);
pre_2_10_vmstate_register_dummy_icp(cs->cpu_index);
}
@@ -3231,7 +3257,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(dev);
- CPUState *cs = CPU(core->threads);
+ CPUState *cs = CPU(core->threads[0]);
sPAPRDRConnector *drc;
Error *local_err = NULL;
int smt = kvmppc_smt_threads();
@@ -3276,15 +3302,12 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
core_slot->cpu = OBJECT(dev);
if (smc->pre_2_10_has_unused_icps) {
- sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(cc));
- size_t size = object_type_get_instance_size(scc->cpu_type);
int i;
for (i = 0; i < cc->nr_threads; i++) {
sPAPRCPUCore *sc = SPAPR_CPU_CORE(dev);
- void *obj = sc->threads + i * size;
- cs = CPU(obj);
+ cs = CPU(sc->threads[i]);
pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index);
}
}
@@ -3563,6 +3586,139 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id)
return cpu ? ICP(cpu->intc) : NULL;
}
+#define ICS_IRQ_FREE(ics, srcno) \
+ (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK)))
+
+static int ics_find_free_block(ICSState *ics, int num, int alignnum)
+{
+ int first, i;
+
+ for (first = 0; first < ics->nr_irqs; first += alignnum) {
+ if (num > (ics->nr_irqs - first)) {
+ return -1;
+ }
+ for (i = first; i < first + num; ++i) {
+ if (!ICS_IRQ_FREE(ics, i)) {
+ break;
+ }
+ }
+ if (i == (first + num)) {
+ return first;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Allocate the IRQ number and set the IRQ type, LSI or MSI
+ */
+static void spapr_irq_set_lsi(sPAPRMachineState *spapr, int irq, bool lsi)
+{
+ ics_set_irq_type(spapr->ics, irq - spapr->ics->offset, lsi);
+}
+
+int spapr_irq_alloc(sPAPRMachineState *spapr, int irq_hint, bool lsi,
+ Error **errp)
+{
+ ICSState *ics = spapr->ics;
+ int irq;
+
+ if (!ics) {
+ return -1;
+ }
+ if (irq_hint) {
+ if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
+ error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
+ return -1;
+ }
+ irq = irq_hint;
+ } else {
+ irq = ics_find_free_block(ics, 1, 1);
+ if (irq < 0) {
+ error_setg(errp, "can't allocate IRQ: no IRQ left");
+ return -1;
+ }
+ irq += ics->offset;
+ }
+
+ spapr_irq_set_lsi(spapr, irq, lsi);
+ trace_spapr_irq_alloc(irq);
+
+ return irq;
+}
+
+/*
+ * Allocate block of consecutive IRQs, and return the number of the first IRQ in
+ * the block. If align==true, aligns the first IRQ number to num.
+ */
+int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi,
+ bool align, Error **errp)
+{
+ ICSState *ics = spapr->ics;
+ int i, first = -1;
+
+ if (!ics) {
+ return -1;
+ }
+
+ /*
+ * MSIMesage::data is used for storing VIRQ so
+ * it has to be aligned to num to support multiple
+ * MSI vectors. MSI-X is not affected by this.
+ * The hint is used for the first IRQ, the rest should
+ * be allocated continuously.
+ */
+ if (align) {
+ assert((num == 1) || (num == 2) || (num == 4) ||
+ (num == 8) || (num == 16) || (num == 32));
+ first = ics_find_free_block(ics, num, num);
+ } else {
+ first = ics_find_free_block(ics, num, 1);
+ }
+ if (first < 0) {
+ error_setg(errp, "can't find a free %d-IRQ block", num);
+ return -1;
+ }
+
+ first += ics->offset;
+ for (i = first; i < first + num; ++i) {
+ spapr_irq_set_lsi(spapr, i, lsi);
+ }
+
+ trace_spapr_irq_alloc_block(first, num, lsi, align);
+
+ return first;
+}
+
+void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num)
+{
+ ICSState *ics = spapr->ics;
+ int srcno = irq - ics->offset;
+ int i;
+
+ if (ics_valid_irq(ics, irq)) {
+ trace_spapr_irq_free(0, irq, num);
+ for (i = srcno; i < srcno + num; ++i) {
+ if (ICS_IRQ_FREE(ics, i)) {
+ trace_spapr_irq_free_warn(0, i + ics->offset);
+ }
+ memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
+ }
+ }
+}
+
+qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq)
+{
+ ICSState *ics = spapr->ics;
+
+ if (ics_valid_irq(ics, irq)) {
+ return ics->qirqs[irq - ics->offset];
+ }
+
+ return NULL;
+}
+
static void spapr_pic_print_info(InterruptStatsProvider *obj,
Monitor *mon)
{
@@ -3622,8 +3778,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
* functions for the specific versioned machine types can override
* these details for backwards compatibility
*/
- mc->init = ppc_spapr_init;
- mc->reset = ppc_spapr_reset;
+ mc->init = spapr_machine_init;
+ mc->reset = spapr_machine_reset;
mc->block_default_type = IF_SCSI;
mc->max_cpus = 1024;
mc->no_parallel = 1;
@@ -3670,7 +3826,7 @@ static const TypeInfo spapr_machine_info = {
.parent = TYPE_MACHINE,
.abstract = true,
.instance_size = sizeof(sPAPRMachineState),
- .instance_init = spapr_machine_initfn,
+ .instance_init = spapr_instance_init,
.instance_finalize = spapr_machine_finalizefn,
.class_size = sizeof(sPAPRMachineClass),
.class_init = spapr_machine_class_init,
@@ -3714,27 +3870,47 @@ static const TypeInfo spapr_machine_info = {
type_init(spapr_machine_register_##suffix)
/*
+ * pseries-2.12
+ */
+static void spapr_machine_2_12_instance_options(MachineState *machine)
+{
+}
+
+static void spapr_machine_2_12_class_options(MachineClass *mc)
+{
+ /* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(2_12, "2.12", true);
+
+/*
* pseries-2.11
*/
+#define SPAPR_COMPAT_2_11 \
+ HW_COMPAT_2_11
+
static void spapr_machine_2_11_instance_options(MachineState *machine)
{
+ spapr_machine_2_12_instance_options(machine);
}
static void spapr_machine_2_11_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ spapr_machine_2_12_class_options(mc);
+ SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
}
-DEFINE_SPAPR_MACHINE(2_11, "2.11", true);
+DEFINE_SPAPR_MACHINE(2_11, "2.11", false);
/*
* pseries-2.10
*/
#define SPAPR_COMPAT_2_10 \
- HW_COMPAT_2_10 \
+ HW_COMPAT_2_10
static void spapr_machine_2_10_instance_options(MachineState *machine)
{
+ spapr_machine_2_11_instance_options(machine);
}
static void spapr_machine_2_10_class_options(MachineClass *mc)
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 3a4c174012..ac19b2e0b7 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -6,6 +6,7 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "hw/cpu/core.h"
#include "hw/ppc/spapr_cpu_core.h"
#include "target/ppc/cpu.h"
@@ -26,6 +27,7 @@ static void spapr_cpu_reset(void *opaque)
PowerPCCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
cpu_reset(cs);
@@ -35,6 +37,13 @@ static void spapr_cpu_reset(void *opaque)
cs->halted = 1;
env->spr[SPR_HIOR] = 0;
+
+ /* Disable Power-saving mode Exit Cause exceptions for the CPU.
+ * This can cause issues when rebooting the guest if a secondary
+ * is awaken */
+ if (cs != first_cpu) {
+ env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
+ }
}
static void spapr_cpu_destroy(PowerPCCPU *cpu)
@@ -79,13 +88,11 @@ const char *spapr_get_cpu_core_type(const char *cpu_type)
static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
{
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
- sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
- size_t size = object_type_get_instance_size(scc->cpu_type);
CPUCore *cc = CPU_CORE(dev);
int i;
for (i = 0; i < cc->nr_threads; i++) {
- void *obj = sc->threads + i * size;
+ Object *obj = OBJECT(sc->threads[i]);
DeviceState *dev = DEVICE(obj);
CPUState *cs = CPU(dev);
PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -104,7 +111,6 @@ static void spapr_cpu_core_realize_child(Object *child,
Error *local_err = NULL;
CPUState *cs = CPU(child);
PowerPCCPU *cpu = POWERPC_CPU(cs);
- Object *obj;
object_property_set_bool(child, true, "realized", &local_err);
if (local_err) {
@@ -116,21 +122,14 @@ static void spapr_cpu_core_realize_child(Object *child,
goto error;
}
- 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);
+ cpu->intc = icp_create(child, spapr->icp_type, XICS_FABRIC(spapr),
+ &local_err);
if (local_err) {
- goto free_icp;
+ goto error;
}
return;
-free_icp:
- object_unparent(obj);
error:
error_propagate(errp, local_err);
}
@@ -146,9 +145,8 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
CPUCore *cc = CPU_CORE(OBJECT(dev));
- size_t size;
Error *local_err = NULL;
- void *obj;
+ Object *obj;
int i, j;
if (!spapr) {
@@ -156,18 +154,16 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
return;
}
- size = object_type_get_instance_size(scc->cpu_type);
- sc->threads = g_malloc0(size * cc->nr_threads);
+ sc->threads = g_new(PowerPCCPU *, cc->nr_threads);
for (i = 0; i < cc->nr_threads; i++) {
char id[32];
CPUState *cs;
PowerPCCPU *cpu;
- obj = sc->threads + i * size;
+ obj = object_new(scc->cpu_type);
- object_initialize(obj, size, scc->cpu_type);
cs = CPU(obj);
- cpu = POWERPC_CPU(cs);
+ cpu = sc->threads[i] = POWERPC_CPU(obj);
cs->cpu_index = cc->core_id + i;
cpu->vcpu_id = (cc->core_id * spapr->vsmt / smp_threads) + i;
if (kvm_enabled() && !kvm_vcpu_id_is_valid(cpu->vcpu_id)) {
@@ -192,7 +188,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
}
for (j = 0; j < cc->nr_threads; j++) {
- obj = sc->threads + j * size;
+ obj = OBJECT(sc->threads[j]);
spapr_cpu_core_realize_child(obj, spapr, &local_err);
if (local_err) {
@@ -203,7 +199,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
err:
while (--i >= 0) {
- obj = sc->threads + i * size;
+ obj = OBJECT(sc->threads[i]);
object_unparent(obj);
}
g_free(sc->threads);
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index e377fc7dde..86836f0626 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -282,8 +282,7 @@ void spapr_dt_events(sPAPRMachineState *spapr, void *fdt)
continue;
}
- interrupts[0] = cpu_to_be32(source->irq);
- interrupts[1] = 0;
+ spapr_dt_xics_irq(interrupts, source->irq, false);
_FDT(node_offset = fdt_add_subnode(fdt, event_sources, source_name));
_FDT(fdt_setprop(fdt, node_offset, "interrupts", interrupts,
@@ -293,9 +292,6 @@ void spapr_dt_events(sPAPRMachineState *spapr, void *fdt)
irq_ranges[count++] = cpu_to_be32(1);
}
- irq_ranges[count] = cpu_to_be32(count);
- count++;
-
_FDT((fdt_setprop(fdt, event_sources, "interrupt-controller", NULL, 0)));
_FDT((fdt_setprop_cell(fdt, event_sources, "#interrupt-cells", 2)));
_FDT((fdt_setprop(fdt, event_sources, "interrupt-ranges",
@@ -472,9 +468,8 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
rtas_event_log_queue(spapr, entry);
- qemu_irq_pulse(xics_get_qirq(XICS_FABRIC(spapr),
- rtas_event_log_to_irq(spapr,
- RTAS_LOG_TYPE_EPOW)));
+ qemu_irq_pulse(spapr_qirq(spapr,
+ rtas_event_log_to_irq(spapr, RTAS_LOG_TYPE_EPOW)));
}
static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
@@ -556,9 +551,8 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
rtas_event_log_queue(spapr, entry);
- qemu_irq_pulse(xics_get_qirq(XICS_FABRIC(spapr),
- rtas_event_log_to_irq(spapr,
- RTAS_LOG_TYPE_HOTPLUG)));
+ qemu_irq_pulse(spapr_qirq(spapr,
+ rtas_event_log_to_irq(spapr, RTAS_LOG_TYPE_HOTPLUG)));
}
void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc)
@@ -678,7 +672,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPRMachineState *spapr,
spapr_event_sources_get_source(spapr->event_sources, i);
g_assert(source->enabled);
- qemu_irq_pulse(xics_get_qirq(XICS_FABRIC(spapr), source->irq));
+ qemu_irq_pulse(spapr_qirq(spapr, source->irq));
}
}
@@ -718,7 +712,7 @@ void spapr_events_init(sPAPRMachineState *spapr)
spapr->event_sources = spapr_event_sources_new();
spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_EPOW,
- spapr_ics_alloc(spapr->ics, 0, false,
+ spapr_irq_alloc(spapr, 0, false,
&error_fatal));
/* NOTE: if machine supports modern/dedicated hotplug event source,
@@ -731,7 +725,7 @@ void spapr_events_init(sPAPRMachineState *spapr)
*/
if (spapr->use_hotplug_event_source) {
spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_HOT_PLUG,
- spapr_ics_alloc(spapr->ics, 0, false,
+ spapr_irq_alloc(spapr, 0, false,
&error_fatal));
}
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index be22a6b289..51eba52e86 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -13,7 +13,6 @@
#include "trace.h"
#include "kvm_ppc.h"
#include "hw/ppc/spapr_ovec.h"
-#include "qemu/error-report.h"
#include "mmu-book3s-v3.h"
struct SPRSyncState {
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index f38be2f0b4..37f18b3d32 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -314,7 +314,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return;
}
- spapr_ics_free(spapr->ics, msi->first_irq, msi->num);
+ spapr_irq_free(spapr, msi->first_irq, msi->num);
if (msi_present(pdev)) {
spapr_msi_setmsg(pdev, 0, false, 0, 0);
}
@@ -352,7 +352,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
}
/* Allocate MSIs */
- irq = spapr_ics_alloc_block(spapr->ics, req_num, false,
+ irq = spapr_irq_alloc_block(spapr, req_num, false,
ret_intr_type == RTAS_TYPE_MSI, &err);
if (err) {
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
@@ -363,7 +363,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
/* Release previous MSIs */
if (msi) {
- spapr_ics_free(spapr->ics, msi->first_irq, msi->num);
+ spapr_irq_free(spapr, msi->first_irq, msi->num);
g_hash_table_remove(phb->msi, &config_addr);
}
@@ -723,7 +723,7 @@ static void spapr_msi_write(void *opaque, hwaddr addr,
trace_spapr_pci_msi_write(addr, data, irq);
- qemu_irq_pulse(xics_get_qirq(XICS_FABRIC(spapr), irq));
+ qemu_irq_pulse(spapr_qirq(spapr, irq));
}
static const MemoryRegionOps spapr_msi_ops = {
@@ -1675,7 +1675,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
uint32_t irq;
Error *local_err = NULL;
- irq = spapr_ics_alloc_block(spapr->ics, 1, true, false, &local_err);
+ irq = spapr_irq_alloc_block(spapr, 1, true, false, &local_err);
if (local_err) {
error_propagate(errp, local_err);
error_prepend(errp, "can't allocate LSIs: ");
@@ -1696,9 +1696,9 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
/* DMA setup */
if (((sphb->page_size_mask & qemu_getrampagesize()) == 0)
&& kvm_enabled()) {
- error_report("System page size 0x%lx is not enabled in page_size_mask "
- "(0x%"PRIx64"). Performance may be slow",
- qemu_getrampagesize(), sphb->page_size_mask);
+ warn_report("System page size 0x%lx is not enabled in page_size_mask "
+ "(0x%"PRIx64"). Performance may be slow",
+ qemu_getrampagesize(), sphb->page_size_mask);
}
for (i = 0; i < windows_supported; ++i) {
@@ -2121,8 +2121,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
irqmap[2] = 0;
irqmap[3] = cpu_to_be32(j+1);
irqmap[4] = cpu_to_be32(xics_phandle);
- irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].irq);
- irqmap[6] = cpu_to_be32(0x8);
+ spapr_dt_xics_irq(&irqmap[5], phb->lsi_table[lsi_num].irq, true);
}
}
/* Write interrupt map */
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 8448e0b024..053efb03bd 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -29,31 +29,6 @@
#include "qemu/error-report.h"
#include "sysemu/qtest.h"
-#define TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE "spapr-pci-vfio-host-bridge"
-
-#define SPAPR_PCI_VFIO_HOST_BRIDGE(obj) \
- OBJECT_CHECK(sPAPRPHBVFIOState, (obj), TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE)
-
-typedef struct sPAPRPHBVFIOState sPAPRPHBVFIOState;
-
-struct sPAPRPHBVFIOState {
- sPAPRPHBState phb;
-
- int32_t iommugroupid;
-};
-
-static Property spapr_phb_vfio_properties[] = {
- DEFINE_PROP_INT32("iommu", sPAPRPHBVFIOState, iommugroupid, -1),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void spapr_phb_vfio_instance_init(Object *obj)
-{
- if (!qtest_enabled()) {
- error_report("spapr-pci-vfio-host-bridge is deprecated");
- }
-}
-
bool spapr_phb_eeh_available(sPAPRPHBState *sphb)
{
return vfio_eeh_as_ok(&sphb->iommu_as);
@@ -218,25 +193,3 @@ int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb)
return RTAS_OUT_SUCCESS;
}
-
-static void spapr_phb_vfio_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->props = spapr_phb_vfio_properties;
-}
-
-static const TypeInfo spapr_phb_vfio_info = {
- .name = TYPE_SPAPR_PCI_VFIO_HOST_BRIDGE,
- .parent = TYPE_SPAPR_PCI_HOST_BRIDGE,
- .instance_size = sizeof(sPAPRPHBVFIOState),
- .instance_init = spapr_phb_vfio_instance_init,
- .class_init = spapr_phb_vfio_class_init,
-};
-
-static void spapr_pci_vfio_register_types(void)
-{
- type_register_static(&spapr_phb_vfio_info);
-}
-
-type_init(spapr_pci_vfio_register_types)
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index cdf0b607a0..2b89e1d448 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -162,6 +162,8 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
if (cpu != NULL) {
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ Error *local_err = NULL;
if (!cs->halted) {
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
@@ -173,7 +175,19 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
* new cpu enters */
kvm_cpu_synchronize_state(cs);
+ /* Set compatibility mode to match existing cpus */
+ ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
+ return;
+ }
+
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
+
+ /* Enable Power-saving mode Exit Cause exceptions for the new CPU */
+ env->spr[SPR_LPCR] |= pcc->lpcr_pm;
+
env->nip = start;
env->gpr[3] = r3;
cs->halted = 0;
@@ -197,19 +211,15 @@ static void rtas_stop_self(PowerPCCPU *cpu, sPAPRMachineState *spapr,
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
cs->halted = 1;
qemu_cpu_kick(cs);
- /*
- * While stopping a CPU, the guest calls H_CPPR which
- * effectively disables interrupts on XICS level.
- * However decrementer interrupts in TCG can still
- * wake the CPU up so here we disable interrupts in MSR
- * as well.
- * As rtas_start_cpu() resets the whole MSR anyway, there is
- * no need to bother with specific bits, we just clear it.
- */
- env->msr = 0;
+
+ /* Disable Power-saving mode Exit Cause exceptions for the CPU.
+ * This could deliver an interrupt on a dying CPU and crash the
+ * guest */
+ env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
}
static inline int sysparm_st(target_ulong addr, target_ulong len,
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index ea3bc8bd9e..472dd6f33a 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -126,8 +126,9 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
}
if (dev->irq) {
- uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0};
+ uint32_t ints_prop[2];
+ spapr_dt_xics_irq(ints_prop, dev->irq, false);
ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
sizeof(ints_prop));
if (ret < 0) {
@@ -454,7 +455,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
dev->qdev.id = id;
}
- dev->irq = spapr_ics_alloc(spapr->ics, dev->irq, false, &local_err);
+ dev->irq = spapr_irq_alloc(spapr, dev->irq, false, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index 4a6a6490fa..b7c3e64b5e 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -12,6 +12,10 @@ spapr_pci_msi_retry(unsigned config_addr, unsigned req_num, unsigned max_irqs) "
# hw/ppc/spapr.c
spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes"
spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes"
+spapr_irq_alloc(int irq) "irq %d"
+spapr_irq_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d"
+spapr_irq_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs"
+spapr_irq_free_warn(int src, int irq) "Source#%d, irq %d is already free"
# hw/ppc/spapr_hcall.c
spapr_cas_pvr_try(uint32_t pvr) "0x%x"