mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 17:53:56 -06:00
Merge remote-tracking branch 'origin/master' into HEAD
Resolve conflicts around apb. Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
commit
acc95bc850
579 changed files with 67167 additions and 9215 deletions
|
@ -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);
|
||||
|
|
96
hw/ppc/pnv.c
96
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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
228
hw/ppc/spapr.c
228
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.11
|
||||
* pseries-2.12
|
||||
*/
|
||||
static void spapr_machine_2_11_instance_options(MachineState *machine)
|
||||
static void spapr_machine_2_12_instance_options(MachineState *machine)
|
||||
{
|
||||
}
|
||||
|
||||
static void spapr_machine_2_11_class_options(MachineClass *mc)
|
||||
static void spapr_machine_2_12_class_options(MachineClass *mc)
|
||||
{
|
||||
/* Defaults for the latest behaviour inherited from the base class */
|
||||
}
|
||||
|
||||
DEFINE_SPAPR_MACHINE(2_11, "2.11", true);
|
||||
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)
|
||||
{
|
||||
spapr_machine_2_12_class_options(mc);
|
||||
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_11);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue