ppc patch queue 2018-08-29
Another pull request for ppc-for-4.2. Includes * Several powernv patches which were pulled last minute from the last PULL, now that some problems with them have been sorted out * A fix for -no-reboot which has been broken since the pseries-rhel4.1.0 machine type * Add some host threads information which AIX guests will need to properly scale the PURR and SPURR * Change behaviour to match x86 when unplugging function 0 of a multifunction PCI device * A number of TCG fixes in FPU emulation And a handful of other assorted fixes and cleanups. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAl1nZFcACgkQbDjKyiDZ s5L8fBAA1QbR+f52mp8+v4rHm33nr7mLmOw1Dx4+fyFaEi1nwyacvg20APt8bPPC l3j33NpLCsSVjqHM4zzOfR49mwfsqrhfbdVPCP46Dx7R0jPJaukfuxqxrs90A9Xn F34pMIVS6AWJerj9+6IA4pfYDIlFfOEA0Fq02hg8qtnw4CRqDoCI97JHNyQjXqWI fBq7ZmBqOmdawNpeMCfus/pNA32FVC4BVznpeGQlpKO7aKOU8vp6JPbb2HYftoCm 8/DLrLiF06PLqdtKYpErwZ+ZXNFmT25rRf6JVhjnVHhtRr5y3oTG/7Y+LM5Cydbj fQ8iQYQew8CxZ7Z3WsdsId3ovw7WM8vpf6dlyI7KTqVQEf108WISHPd68iWrzu10 rw9g/wdCrPbZrFzsVWUff9tJevW1vjDAa8q8iwb2BORpjZykqWWzPMBKHxc/Uso8 tZHMQIIbZ6UNESJj60yVJ44tXcVzxNSDXyjflN33PLjj8STHUKrZrOl2c4gjPGJy xskfiAwNWtZcnnHhUqbPnusJ99HJGhduyve6FvJQgTzSepqcrXmFFjq0+zfZG86i qw6LC70qU56ZpAjySZGw6oMU1cK6weJ6OR9pZvUbt8QQ0LTDoF5U8BePf3nGDOPh uR7+FtiraNo260P2UpLSzKq1sbRy+4SoLiePWBCxJC+Dr9NIVW4= =sJgq -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.2-20190829' into staging ppc patch queue 2018-08-29 Another pull request for ppc-for-4.2. Includes * Several powernv patches which were pulled last minute from the last PULL, now that some problems with them have been sorted out * A fix for -no-reboot which has been broken since the pseries-rhel4.1.0 machine type * Add some host threads information which AIX guests will need to properly scale the PURR and SPURR * Change behaviour to match x86 when unplugging function 0 of a multifunction PCI device * A number of TCG fixes in FPU emulation And a handful of other assorted fixes and cleanups. # gpg: Signature made Thu 29 Aug 2019 06:36:23 BST # gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full] # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full] # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full] # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown] # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-4.2-20190829: spapr: Set compat mode in spapr_core_plug() spapr/pci: Convert types to QEMU coding style spapr_pci: Advertise BAR reallocation capability spapr: Use SHUTDOWN_CAUSE_SUBSYSTEM_RESET for CAS reboots powerpc/spapr: Add host threads parameter to ibm,get_system_parameter pseries: Update SLOF firmware image target/ppc: Refactor emulation of vmrgew and vmrgow instructions target/ppc: Fix do_float_check_status vs inexact target/ppc: Set float_tininess_before_rounding at cpu reset pseries: Fix compat_pvr on reset spapr_pci: remove all child functions in function zero unplug ppc: Fix xscvdpspn for SNAN ppc: Fix xsmaddmdp and friends tests/boot-serial-test: add support for all the PowerNV machines ppc/pnv: Introduce PowerNV machines with fixed CPU models ppc/pnv: Generate phandle for the "interrupt-parent" property ppc/pnv: add more dummy XSCOM addresses for the P9 CAPP ppc/pnv: update skiboot to v6.4 ppc/pnv: Set default ram size to 1.75GB Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3b3f0646a4
81
hw/ppc/pnv.c
81
hw/ppc/pnv.c
@ -434,9 +434,14 @@ static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
|
|||||||
.fdt = fdt,
|
.fdt = fdt,
|
||||||
.offset = isa_offset,
|
.offset = isa_offset,
|
||||||
};
|
};
|
||||||
|
uint32_t phandle;
|
||||||
|
|
||||||
_FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
|
_FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
|
||||||
|
|
||||||
|
phandle = qemu_fdt_alloc_phandle(fdt);
|
||||||
|
assert(phandle > 0);
|
||||||
|
_FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
|
||||||
|
|
||||||
/* ISA devices are not necessarily parented to the ISA bus so we
|
/* ISA devices are not necessarily parented to the ISA bus so we
|
||||||
* can not use object_child_foreach() */
|
* can not use object_child_foreach() */
|
||||||
qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
|
qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
|
||||||
@ -600,9 +605,20 @@ static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
|
|||||||
pnv_psi_pic_print_info(&chip9->psi, mon);
|
pnv_psi_pic_print_info(&chip9->psi, mon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
|
||||||
|
{
|
||||||
|
PowerPCCPUClass *ppc_default =
|
||||||
|
POWERPC_CPU_CLASS(object_class_by_name(default_type));
|
||||||
|
PowerPCCPUClass *ppc =
|
||||||
|
POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
|
||||||
|
|
||||||
|
return ppc_default->pvr_match(ppc_default, ppc->pvr);
|
||||||
|
}
|
||||||
|
|
||||||
static void pnv_init(MachineState *machine)
|
static void pnv_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
PnvMachineState *pnv = PNV_MACHINE(machine);
|
PnvMachineState *pnv = PNV_MACHINE(machine);
|
||||||
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||||
MemoryRegion *ram;
|
MemoryRegion *ram;
|
||||||
char *fw_filename;
|
char *fw_filename;
|
||||||
long fw_size;
|
long fw_size;
|
||||||
@ -662,13 +678,23 @@ static void pnv_init(MachineState *machine)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check compatibility of the specified CPU with the machine
|
||||||
|
* default.
|
||||||
|
*/
|
||||||
|
if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
|
||||||
|
error_report("invalid CPU model '%s' for %s machine",
|
||||||
|
machine->cpu_type, mc->name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the processor chips */
|
/* Create the processor chips */
|
||||||
i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
|
i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
|
||||||
chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
|
chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
|
||||||
i, machine->cpu_type);
|
i, machine->cpu_type);
|
||||||
if (!object_class_by_name(chip_typename)) {
|
if (!object_class_by_name(chip_typename)) {
|
||||||
error_report("invalid CPU model '%.*s' for %s machine",
|
error_report("invalid chip model '%.*s' for %s machine",
|
||||||
i, machine->cpu_type, MACHINE_GET_CLASS(machine)->name);
|
i, machine->cpu_type, mc->name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,25 +1372,47 @@ static void pnv_machine_class_props_init(ObjectClass *oc)
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pnv_machine_class_init(ObjectClass *oc, void *data)
|
static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
|
XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
|
||||||
|
|
||||||
|
mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
|
||||||
|
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
|
||||||
|
|
||||||
|
xic->icp_get = pnv_icp_get;
|
||||||
|
xic->ics_get = pnv_ics_get;
|
||||||
|
xic->ics_resend = pnv_ics_resend;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
|
||||||
|
mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
|
||||||
|
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
|
||||||
|
|
||||||
|
mc->alias = "powernv";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pnv_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
|
InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
|
||||||
|
|
||||||
mc->desc = "IBM PowerNV (Non-Virtualized)";
|
mc->desc = "IBM PowerNV (Non-Virtualized)";
|
||||||
mc->init = pnv_init;
|
mc->init = pnv_init;
|
||||||
mc->reset = pnv_reset;
|
mc->reset = pnv_reset;
|
||||||
mc->max_cpus = MAX_CPUS;
|
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
|
mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
|
||||||
* storage */
|
* storage */
|
||||||
mc->no_parallel = 1;
|
mc->no_parallel = 1;
|
||||||
mc->default_boot_order = NULL;
|
mc->default_boot_order = NULL;
|
||||||
mc->default_ram_size = 1 * GiB;
|
/*
|
||||||
xic->icp_get = pnv_icp_get;
|
* RAM defaults to less than 2048 for 32-bit hosts, and large
|
||||||
xic->ics_get = pnv_ics_get;
|
* enough to fit the maximum initrd size at it's load address
|
||||||
xic->ics_resend = pnv_ics_resend;
|
*/
|
||||||
|
mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
|
||||||
ispc->print_info = pnv_pic_print_info;
|
ispc->print_info = pnv_pic_print_info;
|
||||||
|
|
||||||
pnv_machine_class_props_init(oc);
|
pnv_machine_class_props_init(oc);
|
||||||
@ -1384,10 +1432,27 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data)
|
|||||||
.parent = TYPE_PNV9_CHIP, \
|
.parent = TYPE_PNV9_CHIP, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DEFINE_PNV_MACHINE_TYPE(cpu, class_initfn) \
|
||||||
|
{ \
|
||||||
|
.name = MACHINE_TYPE_NAME(cpu), \
|
||||||
|
.parent = TYPE_PNV_MACHINE, \
|
||||||
|
.instance_size = sizeof(PnvMachineState), \
|
||||||
|
.instance_init = pnv_machine_instance_init, \
|
||||||
|
.class_init = class_initfn, \
|
||||||
|
.interfaces = (InterfaceInfo[]) { \
|
||||||
|
{ TYPE_XICS_FABRIC }, \
|
||||||
|
{ TYPE_INTERRUPT_STATS_PROVIDER }, \
|
||||||
|
{ }, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
static const TypeInfo types[] = {
|
static const TypeInfo types[] = {
|
||||||
|
DEFINE_PNV_MACHINE_TYPE("powernv8", pnv_machine_power8_class_init),
|
||||||
|
DEFINE_PNV_MACHINE_TYPE("powernv9", pnv_machine_power9_class_init),
|
||||||
{
|
{
|
||||||
.name = TYPE_PNV_MACHINE,
|
.name = TYPE_PNV_MACHINE,
|
||||||
.parent = TYPE_MACHINE,
|
.parent = TYPE_MACHINE,
|
||||||
|
.abstract = true,
|
||||||
.instance_size = sizeof(PnvMachineState),
|
.instance_size = sizeof(PnvMachineState),
|
||||||
.instance_init = pnv_machine_instance_init,
|
.instance_init = pnv_machine_instance_init,
|
||||||
.class_init = pnv_machine_class_init,
|
.class_init = pnv_machine_class_init,
|
||||||
|
@ -106,6 +106,16 @@ static uint64_t xscom_read_default(PnvChip *chip, uint32_t pcba)
|
|||||||
case 0x201302a: /* CAPP stuff */
|
case 0x201302a: /* CAPP stuff */
|
||||||
case 0x2013801: /* CAPP stuff */
|
case 0x2013801: /* CAPP stuff */
|
||||||
case 0x2013802: /* CAPP stuff */
|
case 0x2013802: /* CAPP stuff */
|
||||||
|
|
||||||
|
/* P9 CAPP regs */
|
||||||
|
case 0x2010841:
|
||||||
|
case 0x2010842:
|
||||||
|
case 0x201082a:
|
||||||
|
case 0x2010828:
|
||||||
|
case 0x4010841:
|
||||||
|
case 0x4010842:
|
||||||
|
case 0x401082a:
|
||||||
|
case 0x4010828:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
@ -138,6 +148,16 @@ static bool xscom_write_default(PnvChip *chip, uint32_t pcba, uint64_t val)
|
|||||||
case 0x2013801: /* CAPP stuff */
|
case 0x2013801: /* CAPP stuff */
|
||||||
case 0x2013802: /* CAPP stuff */
|
case 0x2013802: /* CAPP stuff */
|
||||||
|
|
||||||
|
/* P9 CAPP regs */
|
||||||
|
case 0x2010841:
|
||||||
|
case 0x2010842:
|
||||||
|
case 0x201082a:
|
||||||
|
case 0x2010828:
|
||||||
|
case 0x4010841:
|
||||||
|
case 0x4010842:
|
||||||
|
case 0x401082a:
|
||||||
|
case 0x4010828:
|
||||||
|
|
||||||
/* P8 PRD registers */
|
/* P8 PRD registers */
|
||||||
case PRD_P8_IPOLL_REG_MASK:
|
case PRD_P8_IPOLL_REG_MASK:
|
||||||
case PRD_P8_IPOLL_REG_STATUS:
|
case PRD_P8_IPOLL_REG_STATUS:
|
||||||
|
@ -1168,6 +1168,7 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
|
|||||||
static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt)
|
static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt)
|
||||||
{
|
{
|
||||||
MachineState *machine = MACHINE(spapr);
|
MachineState *machine = MACHINE(spapr);
|
||||||
|
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
|
||||||
int chosen;
|
int chosen;
|
||||||
const char *boot_device = machine->boot_order;
|
const char *boot_device = machine->boot_order;
|
||||||
char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
|
char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
|
||||||
@ -1225,6 +1226,11 @@ static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt)
|
|||||||
_FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path));
|
_FDT(fdt_setprop_string(fdt, chosen, "stdout-path", stdout_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We can deal with BAR reallocation just fine, advertise it to the guest */
|
||||||
|
if (smc->linux_pci_probe) {
|
||||||
|
_FDT(fdt_setprop_cell(fdt, chosen, "linux,pci-probe-only", 0));
|
||||||
|
}
|
||||||
|
|
||||||
spapr_dt_ov5_platform_support(spapr, fdt, chosen);
|
spapr_dt_ov5_platform_support(spapr, fdt, chosen);
|
||||||
|
|
||||||
g_free(stdout_path);
|
g_free(stdout_path);
|
||||||
@ -1752,7 +1758,7 @@ static void spapr_machine_reset(MachineState *machine)
|
|||||||
spapr_ovec_cleanup(spapr->ov5_cas);
|
spapr_ovec_cleanup(spapr->ov5_cas);
|
||||||
spapr->ov5_cas = spapr_ovec_new();
|
spapr->ov5_cas = spapr_ovec_new();
|
||||||
|
|
||||||
ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal);
|
ppc_set_compat_all(spapr->max_compat_pvr, &error_fatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3829,6 +3835,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||||||
CPUArchId *core_slot;
|
CPUArchId *core_slot;
|
||||||
int index;
|
int index;
|
||||||
bool hotplugged = spapr_drc_hotplugged(dev);
|
bool hotplugged = spapr_drc_hotplugged(dev);
|
||||||
|
int i;
|
||||||
|
|
||||||
core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index);
|
core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index);
|
||||||
if (!core_slot) {
|
if (!core_slot) {
|
||||||
@ -3862,13 +3869,26 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||||||
core_slot->cpu = OBJECT(dev);
|
core_slot->cpu = OBJECT(dev);
|
||||||
|
|
||||||
if (smc->pre_2_10_has_unused_icps) {
|
if (smc->pre_2_10_has_unused_icps) {
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < cc->nr_threads; i++) {
|
for (i = 0; i < cc->nr_threads; i++) {
|
||||||
cs = CPU(core->threads[i]);
|
cs = CPU(core->threads[i]);
|
||||||
pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index);
|
pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set compatibility mode to match the boot CPU, which was either set
|
||||||
|
* by the machine reset code or by CAS.
|
||||||
|
*/
|
||||||
|
if (hotplugged) {
|
||||||
|
for (i = 0; i < cc->nr_threads; i++) {
|
||||||
|
ppc_set_compat(core->threads[i], POWERPC_CPU(first_cpu)->compat_pvr,
|
||||||
|
&local_err);
|
||||||
|
if (local_err) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||||
@ -4470,6 +4490,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
|||||||
spapr_caps_add_properties(smc, &error_abort);
|
spapr_caps_add_properties(smc, &error_abort);
|
||||||
smc->irq = &spapr_irq_dual;
|
smc->irq = &spapr_irq_dual;
|
||||||
smc->dr_phb_enabled = true;
|
smc->dr_phb_enabled = true;
|
||||||
|
smc->linux_pci_probe = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo spapr_machine_info = {
|
static const TypeInfo spapr_machine_info = {
|
||||||
@ -4529,12 +4550,14 @@ DEFINE_SPAPR_MACHINE(4_2, "4.2", true);
|
|||||||
*/
|
*/
|
||||||
static void spapr_machine_4_1_class_options(MachineClass *mc)
|
static void spapr_machine_4_1_class_options(MachineClass *mc)
|
||||||
{
|
{
|
||||||
|
SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
static GlobalProperty compat[] = {
|
static GlobalProperty compat[] = {
|
||||||
/* Only allow 4kiB and 64kiB IOMMU pagesizes */
|
/* Only allow 4kiB and 64kiB IOMMU pagesizes */
|
||||||
{ TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" },
|
{ TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" },
|
||||||
};
|
};
|
||||||
|
|
||||||
spapr_machine_4_2_class_options(mc);
|
spapr_machine_4_2_class_options(mc);
|
||||||
|
smc->linux_pci_probe = false;
|
||||||
compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
|
compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
|
||||||
compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,6 @@ static void spapr_cpu_reset(void *opaque)
|
|||||||
* using an RTAS call */
|
* using an RTAS call */
|
||||||
cs->halted = 1;
|
cs->halted = 1;
|
||||||
|
|
||||||
/* Set compatibility mode to match the boot CPU, which was either set
|
|
||||||
* by the machine reset code or by CAS. This should never fail.
|
|
||||||
*/
|
|
||||||
ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &error_abort);
|
|
||||||
|
|
||||||
env->spr[SPR_HIOR] = 0;
|
env->spr[SPR_HIOR] = 0;
|
||||||
|
|
||||||
lpcr = env->spr[SPR_LPCR];
|
lpcr = env->spr[SPR_LPCR];
|
||||||
|
@ -1811,7 +1811,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
|
|||||||
spapr_ovec_cleanup(ov5_updates);
|
spapr_ovec_cleanup(ov5_updates);
|
||||||
|
|
||||||
if (spapr->cas_reboot) {
|
if (spapr->cas_reboot) {
|
||||||
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
|
qemu_system_reset_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
return H_SUCCESS;
|
return H_SUCCESS;
|
||||||
|
@ -280,7 +280,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
|||||||
unsigned int irq, max_irqs = 0;
|
unsigned int irq, max_irqs = 0;
|
||||||
SpaprPhbState *phb = NULL;
|
SpaprPhbState *phb = NULL;
|
||||||
PCIDevice *pdev = NULL;
|
PCIDevice *pdev = NULL;
|
||||||
spapr_pci_msi *msi;
|
SpaprPciMsi *msi;
|
||||||
int *config_addr_key;
|
int *config_addr_key;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
int i;
|
int i;
|
||||||
@ -328,7 +328,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msi = (spapr_pci_msi *) g_hash_table_lookup(phb->msi, &config_addr);
|
msi = (SpaprPciMsi *) g_hash_table_lookup(phb->msi, &config_addr);
|
||||||
|
|
||||||
/* Releasing MSIs */
|
/* Releasing MSIs */
|
||||||
if (!req_num) {
|
if (!req_num) {
|
||||||
@ -415,7 +415,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
|||||||
irq, req_num);
|
irq, req_num);
|
||||||
|
|
||||||
/* Add MSI device to cache */
|
/* Add MSI device to cache */
|
||||||
msi = g_new(spapr_pci_msi, 1);
|
msi = g_new(SpaprPciMsi, 1);
|
||||||
msi->first_irq = irq;
|
msi->first_irq = irq;
|
||||||
msi->num = req_num;
|
msi->num = req_num;
|
||||||
config_addr_key = g_new(int, 1);
|
config_addr_key = g_new(int, 1);
|
||||||
@ -446,7 +446,7 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
|
|||||||
unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3);
|
unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3);
|
||||||
SpaprPhbState *phb = NULL;
|
SpaprPhbState *phb = NULL;
|
||||||
PCIDevice *pdev = NULL;
|
PCIDevice *pdev = NULL;
|
||||||
spapr_pci_msi *msi;
|
SpaprPciMsi *msi;
|
||||||
|
|
||||||
/* Find SpaprPhbState */
|
/* Find SpaprPhbState */
|
||||||
phb = spapr_pci_find_phb(spapr, buid);
|
phb = spapr_pci_find_phb(spapr, buid);
|
||||||
@ -459,7 +459,7 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find device descriptor and start IRQ */
|
/* Find device descriptor and start IRQ */
|
||||||
msi = (spapr_pci_msi *) g_hash_table_lookup(phb->msi, &config_addr);
|
msi = (SpaprPciMsi *) g_hash_table_lookup(phb->msi, &config_addr);
|
||||||
if (!msi || !msi->first_irq || !msi->num || (ioa_intr_num >= msi->num)) {
|
if (!msi || !msi->first_irq || !msi->num || (ioa_intr_num >= msi->num)) {
|
||||||
trace_spapr_pci_msi("Failed to return vector", config_addr);
|
trace_spapr_pci_msi("Failed to return vector", config_addr);
|
||||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||||
@ -1700,11 +1700,13 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
|
|||||||
state = func_drck->dr_entity_sense(func_drc);
|
state = func_drck->dr_entity_sense(func_drc);
|
||||||
if (state == SPAPR_DR_ENTITY_SENSE_PRESENT
|
if (state == SPAPR_DR_ENTITY_SENSE_PRESENT
|
||||||
&& !spapr_drc_unplug_requested(func_drc)) {
|
&& !spapr_drc_unplug_requested(func_drc)) {
|
||||||
error_setg(errp,
|
/*
|
||||||
"PCI: slot %d, function %d still present. "
|
* Attempting to remove function 0 of a multifunction
|
||||||
"Must unplug all non-0 functions first.",
|
* device will will cascade into removing all child
|
||||||
slotnr, i);
|
* functions, even if their unplug weren't requested
|
||||||
return;
|
* beforehand.
|
||||||
|
*/
|
||||||
|
spapr_drc_detach(func_drc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1804,7 +1806,7 @@ static void spapr_phb_destroy_msi(gpointer opaque)
|
|||||||
{
|
{
|
||||||
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||||
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
||||||
spapr_pci_msi *msi = opaque;
|
SpaprPciMsi *msi = opaque;
|
||||||
|
|
||||||
if (!smc->legacy_irq_allocation) {
|
if (!smc->legacy_irq_allocation) {
|
||||||
spapr_irq_msi_free(spapr, msi->first_irq, msi->num);
|
spapr_irq_msi_free(spapr, msi->first_irq, msi->num);
|
||||||
@ -2118,7 +2120,7 @@ static const VMStateDescription vmstate_spapr_pci_lsi = {
|
|||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT32_EQUAL(irq, struct spapr_pci_lsi, NULL),
|
VMSTATE_UINT32_EQUAL(irq, SpaprPciLsi, NULL),
|
||||||
|
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
},
|
},
|
||||||
@ -2129,9 +2131,9 @@ static const VMStateDescription vmstate_spapr_pci_msi = {
|
|||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.fields = (VMStateField []) {
|
.fields = (VMStateField []) {
|
||||||
VMSTATE_UINT32(key, spapr_pci_msi_mig),
|
VMSTATE_UINT32(key, SpaprPciMsiMig),
|
||||||
VMSTATE_UINT32(value.first_irq, spapr_pci_msi_mig),
|
VMSTATE_UINT32(value.first_irq, SpaprPciMsiMig),
|
||||||
VMSTATE_UINT32(value.num, spapr_pci_msi_mig),
|
VMSTATE_UINT32(value.num, SpaprPciMsiMig),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -2163,12 +2165,12 @@ static int spapr_pci_pre_save(void *opaque)
|
|||||||
if (!sphb->msi_devs_num) {
|
if (!sphb->msi_devs_num) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
sphb->msi_devs = g_new(spapr_pci_msi_mig, sphb->msi_devs_num);
|
sphb->msi_devs = g_new(SpaprPciMsiMig, sphb->msi_devs_num);
|
||||||
|
|
||||||
g_hash_table_iter_init(&iter, sphb->msi);
|
g_hash_table_iter_init(&iter, sphb->msi);
|
||||||
for (i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) {
|
for (i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) {
|
||||||
sphb->msi_devs[i].key = *(uint32_t *) key;
|
sphb->msi_devs[i].key = *(uint32_t *) key;
|
||||||
sphb->msi_devs[i].value = *(spapr_pci_msi *) value;
|
sphb->msi_devs[i].value = *(SpaprPciMsi *) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2215,10 +2217,10 @@ static const VMStateDescription vmstate_spapr_pci = {
|
|||||||
VMSTATE_UINT64_TEST(mig_io_win_addr, SpaprPhbState, pre_2_8_migration),
|
VMSTATE_UINT64_TEST(mig_io_win_addr, SpaprPhbState, pre_2_8_migration),
|
||||||
VMSTATE_UINT64_TEST(mig_io_win_size, SpaprPhbState, pre_2_8_migration),
|
VMSTATE_UINT64_TEST(mig_io_win_size, SpaprPhbState, pre_2_8_migration),
|
||||||
VMSTATE_STRUCT_ARRAY(lsi_table, SpaprPhbState, PCI_NUM_PINS, 0,
|
VMSTATE_STRUCT_ARRAY(lsi_table, SpaprPhbState, PCI_NUM_PINS, 0,
|
||||||
vmstate_spapr_pci_lsi, struct spapr_pci_lsi),
|
vmstate_spapr_pci_lsi, SpaprPciLsi),
|
||||||
VMSTATE_INT32(msi_devs_num, SpaprPhbState),
|
VMSTATE_INT32(msi_devs_num, SpaprPhbState),
|
||||||
VMSTATE_STRUCT_VARRAY_ALLOC(msi_devs, SpaprPhbState, msi_devs_num, 0,
|
VMSTATE_STRUCT_VARRAY_ALLOC(msi_devs, SpaprPhbState, msi_devs_num, 0,
|
||||||
vmstate_spapr_pci_msi, spapr_pci_msi_mig),
|
vmstate_spapr_pci_msi, SpaprPciMsiMig),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -39,11 +39,7 @@
|
|||||||
|
|
||||||
#define SPAPR_GPU_NUMA_ID (cpu_to_be32(1))
|
#define SPAPR_GPU_NUMA_ID (cpu_to_be32(1))
|
||||||
|
|
||||||
struct spapr_phb_pci_nvgpu_config {
|
typedef struct SpaprPhbPciNvGpuSlot {
|
||||||
uint64_t nv2_ram_current;
|
|
||||||
uint64_t nv2_atsd_current;
|
|
||||||
int num; /* number of non empty (i.e. tgt!=0) entries in slots[] */
|
|
||||||
struct spapr_phb_pci_nvgpu_slot {
|
|
||||||
uint64_t tgt;
|
uint64_t tgt;
|
||||||
uint64_t gpa;
|
uint64_t gpa;
|
||||||
unsigned numa_id;
|
unsigned numa_id;
|
||||||
@ -54,12 +50,18 @@ struct spapr_phb_pci_nvgpu_config {
|
|||||||
PCIDevice *npdev;
|
PCIDevice *npdev;
|
||||||
uint32_t link_speed;
|
uint32_t link_speed;
|
||||||
} links[NVGPU_MAX_LINKS];
|
} links[NVGPU_MAX_LINKS];
|
||||||
} slots[NVGPU_MAX_NUM];
|
} SpaprPhbPciNvGpuSlot;
|
||||||
|
|
||||||
|
struct SpaprPhbPciNvGpuConfig {
|
||||||
|
uint64_t nv2_ram_current;
|
||||||
|
uint64_t nv2_atsd_current;
|
||||||
|
int num; /* number of non empty (i.e. tgt!=0) entries in slots[] */
|
||||||
|
SpaprPhbPciNvGpuSlot slots[NVGPU_MAX_NUM];
|
||||||
Error *errp;
|
Error *errp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct spapr_phb_pci_nvgpu_slot *
|
static SpaprPhbPciNvGpuSlot *
|
||||||
spapr_nvgpu_get_slot(struct spapr_phb_pci_nvgpu_config *nvgpus, uint64_t tgt)
|
spapr_nvgpu_get_slot(SpaprPhbPciNvGpuConfig *nvgpus, uint64_t tgt)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -81,13 +83,13 @@ spapr_nvgpu_get_slot(struct spapr_phb_pci_nvgpu_config *nvgpus, uint64_t tgt)
|
|||||||
return &nvgpus->slots[i];
|
return &nvgpus->slots[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spapr_pci_collect_nvgpu(struct spapr_phb_pci_nvgpu_config *nvgpus,
|
static void spapr_pci_collect_nvgpu(SpaprPhbPciNvGpuConfig *nvgpus,
|
||||||
PCIDevice *pdev, uint64_t tgt,
|
PCIDevice *pdev, uint64_t tgt,
|
||||||
MemoryRegion *mr, Error **errp)
|
MemoryRegion *mr, Error **errp)
|
||||||
{
|
{
|
||||||
MachineState *machine = MACHINE(qdev_get_machine());
|
MachineState *machine = MACHINE(qdev_get_machine());
|
||||||
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
|
SpaprMachineState *spapr = SPAPR_MACHINE(machine);
|
||||||
struct spapr_phb_pci_nvgpu_slot *nvslot = spapr_nvgpu_get_slot(nvgpus, tgt);
|
SpaprPhbPciNvGpuSlot *nvslot = spapr_nvgpu_get_slot(nvgpus, tgt);
|
||||||
|
|
||||||
if (!nvslot) {
|
if (!nvslot) {
|
||||||
error_setg(errp, "Found too many GPUs per vPHB");
|
error_setg(errp, "Found too many GPUs per vPHB");
|
||||||
@ -102,11 +104,11 @@ static void spapr_pci_collect_nvgpu(struct spapr_phb_pci_nvgpu_config *nvgpus,
|
|||||||
++spapr->gpu_numa_id;
|
++spapr->gpu_numa_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spapr_pci_collect_nvnpu(struct spapr_phb_pci_nvgpu_config *nvgpus,
|
static void spapr_pci_collect_nvnpu(SpaprPhbPciNvGpuConfig *nvgpus,
|
||||||
PCIDevice *pdev, uint64_t tgt,
|
PCIDevice *pdev, uint64_t tgt,
|
||||||
MemoryRegion *mr, Error **errp)
|
MemoryRegion *mr, Error **errp)
|
||||||
{
|
{
|
||||||
struct spapr_phb_pci_nvgpu_slot *nvslot = spapr_nvgpu_get_slot(nvgpus, tgt);
|
SpaprPhbPciNvGpuSlot *nvslot = spapr_nvgpu_get_slot(nvgpus, tgt);
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (!nvslot) {
|
if (!nvslot) {
|
||||||
@ -138,7 +140,7 @@ static void spapr_phb_pci_collect_nvgpu(PCIBus *bus, PCIDevice *pdev,
|
|||||||
|
|
||||||
if (tgt) {
|
if (tgt) {
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
struct spapr_phb_pci_nvgpu_config *nvgpus = opaque;
|
SpaprPhbPciNvGpuConfig *nvgpus = opaque;
|
||||||
Object *mr_gpu = object_property_get_link(po, "nvlink2-mr[0]", NULL);
|
Object *mr_gpu = object_property_get_link(po, "nvlink2-mr[0]", NULL);
|
||||||
Object *mr_npu = object_property_get_link(po, "nvlink2-atsd-mr[0]",
|
Object *mr_npu = object_property_get_link(po, "nvlink2-atsd-mr[0]",
|
||||||
NULL);
|
NULL);
|
||||||
@ -177,7 +179,7 @@ void spapr_phb_nvgpu_setup(SpaprPhbState *sphb, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sphb->nvgpus = g_new0(struct spapr_phb_pci_nvgpu_config, 1);
|
sphb->nvgpus = g_new0(SpaprPhbPciNvGpuConfig, 1);
|
||||||
sphb->nvgpus->nv2_ram_current = sphb->nv2_gpa_win_addr;
|
sphb->nvgpus->nv2_ram_current = sphb->nv2_gpa_win_addr;
|
||||||
sphb->nvgpus->nv2_atsd_current = sphb->nv2_atsd_win_addr;
|
sphb->nvgpus->nv2_atsd_current = sphb->nv2_atsd_win_addr;
|
||||||
|
|
||||||
@ -194,7 +196,7 @@ void spapr_phb_nvgpu_setup(SpaprPhbState *sphb, Error **errp)
|
|||||||
/* Add found GPU RAM and ATSD MRs if found */
|
/* Add found GPU RAM and ATSD MRs if found */
|
||||||
for (i = 0, valid_gpu_num = 0; i < sphb->nvgpus->num; ++i) {
|
for (i = 0, valid_gpu_num = 0; i < sphb->nvgpus->num; ++i) {
|
||||||
Object *nvmrobj;
|
Object *nvmrobj;
|
||||||
struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
|
SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i];
|
||||||
|
|
||||||
if (!nvslot->gpdev) {
|
if (!nvslot->gpdev) {
|
||||||
continue;
|
continue;
|
||||||
@ -242,7 +244,7 @@ void spapr_phb_nvgpu_free(SpaprPhbState *sphb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sphb->nvgpus->num; ++i) {
|
for (i = 0; i < sphb->nvgpus->num; ++i) {
|
||||||
struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
|
SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i];
|
||||||
Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev),
|
Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev),
|
||||||
"nvlink2-mr[0]", NULL);
|
"nvlink2-mr[0]", NULL);
|
||||||
|
|
||||||
@ -276,7 +278,7 @@ void spapr_phb_nvgpu_populate_dt(SpaprPhbState *sphb, void *fdt, int bus_off,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; (i < sphb->nvgpus->num) && (atsdnum < ARRAY_SIZE(atsd)); ++i) {
|
for (i = 0; (i < sphb->nvgpus->num) && (atsdnum < ARRAY_SIZE(atsd)); ++i) {
|
||||||
struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
|
SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i];
|
||||||
|
|
||||||
if (!nvslot->gpdev) {
|
if (!nvslot->gpdev) {
|
||||||
continue;
|
continue;
|
||||||
@ -354,7 +356,7 @@ void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
|
|||||||
|
|
||||||
/* Add memory nodes for GPU RAM and mark them unusable */
|
/* Add memory nodes for GPU RAM and mark them unusable */
|
||||||
for (i = 0; i < sphb->nvgpus->num; ++i) {
|
for (i = 0; i < sphb->nvgpus->num; ++i) {
|
||||||
struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
|
SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i];
|
||||||
Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev),
|
Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev),
|
||||||
"nvlink2-mr[0]", NULL);
|
"nvlink2-mr[0]", NULL);
|
||||||
uint32_t associativity[] = {
|
uint32_t associativity[] = {
|
||||||
@ -398,7 +400,7 @@ void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt, int offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sphb->nvgpus->num; ++i) {
|
for (i = 0; i < sphb->nvgpus->num; ++i) {
|
||||||
struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
|
SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i];
|
||||||
|
|
||||||
/* Skip "slot" without attached GPU */
|
/* Skip "slot" without attached GPU */
|
||||||
if (!nvslot->gpdev) {
|
if (!nvslot->gpdev) {
|
||||||
|
@ -266,6 +266,7 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
|
|||||||
target_ulong args,
|
target_ulong args,
|
||||||
uint32_t nret, target_ulong rets)
|
uint32_t nret, target_ulong rets)
|
||||||
{
|
{
|
||||||
|
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||||
MachineState *ms = MACHINE(qdev_get_machine());
|
MachineState *ms = MACHINE(qdev_get_machine());
|
||||||
unsigned int max_cpus = ms->smp.max_cpus;
|
unsigned int max_cpus = ms->smp.max_cpus;
|
||||||
target_ulong parameter = rtas_ld(args, 0);
|
target_ulong parameter = rtas_ld(args, 0);
|
||||||
@ -283,6 +284,20 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
|
|||||||
current_machine->ram_size / MiB,
|
current_machine->ram_size / MiB,
|
||||||
ms->smp.cpus,
|
ms->smp.cpus,
|
||||||
max_cpus);
|
max_cpus);
|
||||||
|
if (pcc->n_host_threads > 0) {
|
||||||
|
char *hostthr_val, *old = param_val;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add HostThrs property. This property is not present in PAPR but
|
||||||
|
* is expected by some guests to communicate the number of physical
|
||||||
|
* host threads per core on the system so that they can scale
|
||||||
|
* information which varies based on the thread configuration.
|
||||||
|
*/
|
||||||
|
hostthr_val = g_strdup_printf(",HostThrs=%d", pcc->n_host_threads);
|
||||||
|
param_val = g_strconcat(param_val, hostthr_val, NULL);
|
||||||
|
g_free(hostthr_val);
|
||||||
|
g_free(old);
|
||||||
|
}
|
||||||
ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
|
ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
|
||||||
g_free(param_val);
|
g_free(param_val);
|
||||||
break;
|
break;
|
||||||
|
@ -34,15 +34,21 @@
|
|||||||
|
|
||||||
typedef struct SpaprPhbState SpaprPhbState;
|
typedef struct SpaprPhbState SpaprPhbState;
|
||||||
|
|
||||||
typedef struct spapr_pci_msi {
|
typedef struct SpaprPciMsi {
|
||||||
uint32_t first_irq;
|
uint32_t first_irq;
|
||||||
uint32_t num;
|
uint32_t num;
|
||||||
} spapr_pci_msi;
|
} SpaprPciMsi;
|
||||||
|
|
||||||
typedef struct spapr_pci_msi_mig {
|
typedef struct SpaprPciMsiMig {
|
||||||
uint32_t key;
|
uint32_t key;
|
||||||
spapr_pci_msi value;
|
SpaprPciMsi value;
|
||||||
} spapr_pci_msi_mig;
|
} SpaprPciMsiMig;
|
||||||
|
|
||||||
|
typedef struct SpaprPciLsi {
|
||||||
|
uint32_t irq;
|
||||||
|
} SpaprPciLsi;
|
||||||
|
|
||||||
|
typedef struct SpaprPhbPciNvGpuConfig SpaprPhbPciNvGpuConfig;
|
||||||
|
|
||||||
struct SpaprPhbState {
|
struct SpaprPhbState {
|
||||||
PCIHostState parent_obj;
|
PCIHostState parent_obj;
|
||||||
@ -63,14 +69,12 @@ struct SpaprPhbState {
|
|||||||
AddressSpace iommu_as;
|
AddressSpace iommu_as;
|
||||||
MemoryRegion iommu_root;
|
MemoryRegion iommu_root;
|
||||||
|
|
||||||
struct spapr_pci_lsi {
|
SpaprPciLsi lsi_table[PCI_NUM_PINS];
|
||||||
uint32_t irq;
|
|
||||||
} lsi_table[PCI_NUM_PINS];
|
|
||||||
|
|
||||||
GHashTable *msi;
|
GHashTable *msi;
|
||||||
/* Temporary cache for migration purposes */
|
/* Temporary cache for migration purposes */
|
||||||
int32_t msi_devs_num;
|
int32_t msi_devs_num;
|
||||||
spapr_pci_msi_mig *msi_devs;
|
SpaprPciMsiMig *msi_devs;
|
||||||
|
|
||||||
QLIST_ENTRY(SpaprPhbState) list;
|
QLIST_ENTRY(SpaprPhbState) list;
|
||||||
|
|
||||||
@ -89,7 +93,7 @@ struct SpaprPhbState {
|
|||||||
hwaddr mig_io_win_addr, mig_io_win_size;
|
hwaddr mig_io_win_addr, mig_io_win_size;
|
||||||
hwaddr nv2_gpa_win_addr;
|
hwaddr nv2_gpa_win_addr;
|
||||||
hwaddr nv2_atsd_win_addr;
|
hwaddr nv2_atsd_win_addr;
|
||||||
struct spapr_phb_pci_nvgpu_config *nvgpus;
|
SpaprPhbPciNvGpuConfig *nvgpus;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
|
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
|
||||||
|
@ -121,6 +121,7 @@ struct SpaprMachineClass {
|
|||||||
bool legacy_irq_allocation;
|
bool legacy_irq_allocation;
|
||||||
bool broken_host_serial_model; /* present real host info to the guest */
|
bool broken_host_serial_model; /* present real host info to the guest */
|
||||||
bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
|
bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
|
||||||
|
bool linux_pci_probe;
|
||||||
|
|
||||||
void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
|
void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
|
||||||
uint64_t *buid, hwaddr *pio,
|
uint64_t *buid, hwaddr *pio,
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
||||||
implementation for certain IBM POWER hardware. The sources are at
|
implementation for certain IBM POWER hardware. The sources are at
|
||||||
https://github.com/aik/SLOF, and the image currently in qemu is
|
https://github.com/aik/SLOF, and the image currently in qemu is
|
||||||
built from git tag qemu-slof-20190719.
|
built from git tag qemu-slof-20190827.
|
||||||
|
|
||||||
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
|
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
|
||||||
legacy x86 software to communicate with an attached serial console as
|
legacy x86 software to communicate with an attached serial console as
|
||||||
|
Binary file not shown.
BIN
pc-bios/slof.bin
BIN
pc-bios/slof.bin
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit 7bfe584e321946771692711ff83ad2b5850daca7
|
Subproject commit ea221600a116883137ef90b2b7ab7d2472bc4f10
|
@ -1 +1 @@
|
|||||||
Subproject commit 261ca8e779e5138869a45f174caa49be6a274501
|
Subproject commit 3a6fdede6ce117facec0108afe716cf5d0472c3f
|
@ -191,6 +191,7 @@ typedef struct PowerPCCPUClass {
|
|||||||
const PPCHash64Options *hash64_opts;
|
const PPCHash64Options *hash64_opts;
|
||||||
struct ppc_radix_page_info *radix_page_info;
|
struct ppc_radix_page_info *radix_page_info;
|
||||||
uint32_t lrg_decr_bits;
|
uint32_t lrg_decr_bits;
|
||||||
|
int n_host_threads;
|
||||||
void (*init_proc)(CPUPPCState *env);
|
void (*init_proc)(CPUPPCState *env);
|
||||||
int (*check_pow)(CPUPPCState *env);
|
int (*check_pow)(CPUPPCState *env);
|
||||||
int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx);
|
int (*handle_mmu_fault)(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx);
|
||||||
|
@ -630,19 +630,15 @@ static void do_float_check_status(CPUPPCState *env, uintptr_t raddr)
|
|||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
int status = get_float_exception_flags(&env->fp_status);
|
int status = get_float_exception_flags(&env->fp_status);
|
||||||
bool inexact_happened = false;
|
|
||||||
|
|
||||||
if (status & float_flag_overflow) {
|
if (status & float_flag_overflow) {
|
||||||
float_overflow_excp(env);
|
float_overflow_excp(env);
|
||||||
} else if (status & float_flag_underflow) {
|
} else if (status & float_flag_underflow) {
|
||||||
float_underflow_excp(env);
|
float_underflow_excp(env);
|
||||||
} else if (status & float_flag_inexact) {
|
|
||||||
float_inexact_excp(env);
|
|
||||||
inexact_happened = true;
|
|
||||||
}
|
}
|
||||||
|
if (status & float_flag_inexact) {
|
||||||
/* if the inexact flag was not set */
|
float_inexact_excp(env);
|
||||||
if (inexact_happened == false) {
|
} else {
|
||||||
env->fpscr &= ~(1 << FPSCR_FI); /* clear the FPSCR[FI] bit */
|
env->fpscr &= ~(1 << FPSCR_FI); /* clear the FPSCR[FI] bit */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2887,12 +2883,40 @@ void helper_xscvqpdp(CPUPPCState *env, uint32_t opcode,
|
|||||||
|
|
||||||
uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
|
uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
|
||||||
{
|
{
|
||||||
uint64_t result;
|
uint64_t result, sign, exp, frac;
|
||||||
|
|
||||||
float_status tstat = env->fp_status;
|
float_status tstat = env->fp_status;
|
||||||
set_float_exception_flags(0, &tstat);
|
set_float_exception_flags(0, &tstat);
|
||||||
|
|
||||||
result = (uint64_t)float64_to_float32(xb, &tstat);
|
sign = extract64(xb, 63, 1);
|
||||||
|
exp = extract64(xb, 52, 11);
|
||||||
|
frac = extract64(xb, 0, 52) | 0x10000000000000ULL;
|
||||||
|
|
||||||
|
if (unlikely(exp == 0 && extract64(frac, 0, 52) != 0)) {
|
||||||
|
/* DP denormal operand. */
|
||||||
|
/* Exponent override to DP min exp. */
|
||||||
|
exp = 1;
|
||||||
|
/* Implicit bit override to 0. */
|
||||||
|
frac = deposit64(frac, 53, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(exp < 897 && frac != 0)) {
|
||||||
|
/* SP tiny operand. */
|
||||||
|
if (897 - exp > 63) {
|
||||||
|
frac = 0;
|
||||||
|
} else {
|
||||||
|
/* Denormalize until exp = SP min exp. */
|
||||||
|
frac >>= (897 - exp);
|
||||||
|
}
|
||||||
|
/* Exponent override to SP min exp - 1. */
|
||||||
|
exp = 896;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sign << 31;
|
||||||
|
result |= extract64(exp, 10, 1) << 30;
|
||||||
|
result |= extract64(exp, 0, 7) << 23;
|
||||||
|
result |= extract64(frac, 29, 23);
|
||||||
|
|
||||||
/* hardware replicates result to both words of the doubleword result. */
|
/* hardware replicates result to both words of the doubleword result. */
|
||||||
return (result << 32) | result;
|
return (result << 32) | result;
|
||||||
}
|
}
|
||||||
|
@ -350,6 +350,28 @@ static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use this macro if one instruction is realized with direct
|
||||||
|
* translation, and second one with helper.
|
||||||
|
*/
|
||||||
|
#define GEN_VXFORM_TRANS_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)\
|
||||||
|
static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
|
||||||
|
{ \
|
||||||
|
if ((Rc(ctx->opcode) == 0) && \
|
||||||
|
((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
|
||||||
|
if (unlikely(!ctx->altivec_enabled)) { \
|
||||||
|
gen_exception(ctx, POWERPC_EXCP_VPU); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
trans_##name0(ctx); \
|
||||||
|
} else if ((Rc(ctx->opcode) == 1) && \
|
||||||
|
((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
|
||||||
|
gen_##name1(ctx); \
|
||||||
|
} else { \
|
||||||
|
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
/* Adds support to provide invalid mask */
|
/* Adds support to provide invalid mask */
|
||||||
#define GEN_VXFORM_DUAL_EXT(name0, flg0, flg2_0, inval0, \
|
#define GEN_VXFORM_DUAL_EXT(name0, flg0, flg2_0, inval0, \
|
||||||
name1, flg1, flg2_1, inval1) \
|
name1, flg1, flg2_1, inval1) \
|
||||||
@ -431,20 +453,13 @@ GEN_VXFORM(vmrglb, 6, 4);
|
|||||||
GEN_VXFORM(vmrglh, 6, 5);
|
GEN_VXFORM(vmrglh, 6, 5);
|
||||||
GEN_VXFORM(vmrglw, 6, 6);
|
GEN_VXFORM(vmrglw, 6, 6);
|
||||||
|
|
||||||
static void gen_vmrgew(DisasContext *ctx)
|
static void trans_vmrgew(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
TCGv_i64 tmp;
|
int VT = rD(ctx->opcode);
|
||||||
TCGv_i64 avr;
|
int VA = rA(ctx->opcode);
|
||||||
int VT, VA, VB;
|
int VB = rB(ctx->opcode);
|
||||||
if (unlikely(!ctx->altivec_enabled)) {
|
TCGv_i64 tmp = tcg_temp_new_i64();
|
||||||
gen_exception(ctx, POWERPC_EXCP_VPU);
|
TCGv_i64 avr = tcg_temp_new_i64();
|
||||||
return;
|
|
||||||
}
|
|
||||||
VT = rD(ctx->opcode);
|
|
||||||
VA = rA(ctx->opcode);
|
|
||||||
VB = rB(ctx->opcode);
|
|
||||||
tmp = tcg_temp_new_i64();
|
|
||||||
avr = tcg_temp_new_i64();
|
|
||||||
|
|
||||||
get_avr64(avr, VB, true);
|
get_avr64(avr, VB, true);
|
||||||
tcg_gen_shri_i64(tmp, avr, 32);
|
tcg_gen_shri_i64(tmp, avr, 32);
|
||||||
@ -462,21 +477,14 @@ static void gen_vmrgew(DisasContext *ctx)
|
|||||||
tcg_temp_free_i64(avr);
|
tcg_temp_free_i64(avr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_vmrgow(DisasContext *ctx)
|
static void trans_vmrgow(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
TCGv_i64 t0, t1;
|
int VT = rD(ctx->opcode);
|
||||||
TCGv_i64 avr;
|
int VA = rA(ctx->opcode);
|
||||||
int VT, VA, VB;
|
int VB = rB(ctx->opcode);
|
||||||
if (unlikely(!ctx->altivec_enabled)) {
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
gen_exception(ctx, POWERPC_EXCP_VPU);
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||||
return;
|
TCGv_i64 avr = tcg_temp_new_i64();
|
||||||
}
|
|
||||||
VT = rD(ctx->opcode);
|
|
||||||
VA = rA(ctx->opcode);
|
|
||||||
VB = rB(ctx->opcode);
|
|
||||||
t0 = tcg_temp_new_i64();
|
|
||||||
t1 = tcg_temp_new_i64();
|
|
||||||
avr = tcg_temp_new_i64();
|
|
||||||
|
|
||||||
get_avr64(t0, VB, true);
|
get_avr64(t0, VB, true);
|
||||||
get_avr64(t1, VA, true);
|
get_avr64(t1, VA, true);
|
||||||
@ -936,14 +944,14 @@ GEN_VXFORM_ENV(vminfp, 5, 17);
|
|||||||
GEN_VXFORM_HETRO(vextublx, 6, 24)
|
GEN_VXFORM_HETRO(vextublx, 6, 24)
|
||||||
GEN_VXFORM_HETRO(vextuhlx, 6, 25)
|
GEN_VXFORM_HETRO(vextuhlx, 6, 25)
|
||||||
GEN_VXFORM_HETRO(vextuwlx, 6, 26)
|
GEN_VXFORM_HETRO(vextuwlx, 6, 26)
|
||||||
GEN_VXFORM_DUAL(vmrgow, PPC_NONE, PPC2_ALTIVEC_207,
|
GEN_VXFORM_TRANS_DUAL(vmrgow, PPC_NONE, PPC2_ALTIVEC_207,
|
||||||
vextuwlx, PPC_NONE, PPC2_ISA300)
|
vextuwlx, PPC_NONE, PPC2_ISA300)
|
||||||
GEN_VXFORM_HETRO(vextubrx, 6, 28)
|
GEN_VXFORM_HETRO(vextubrx, 6, 28)
|
||||||
GEN_VXFORM_HETRO(vextuhrx, 6, 29)
|
GEN_VXFORM_HETRO(vextuhrx, 6, 29)
|
||||||
GEN_VXFORM_HETRO(vextuwrx, 6, 30)
|
GEN_VXFORM_HETRO(vextuwrx, 6, 30)
|
||||||
GEN_VXFORM_TRANS(lvsl, 6, 31)
|
GEN_VXFORM_TRANS(lvsl, 6, 31)
|
||||||
GEN_VXFORM_TRANS(lvsr, 6, 32)
|
GEN_VXFORM_TRANS(lvsr, 6, 32)
|
||||||
GEN_VXFORM_DUAL(vmrgew, PPC_NONE, PPC2_ALTIVEC_207, \
|
GEN_VXFORM_TRANS_DUAL(vmrgew, PPC_NONE, PPC2_ALTIVEC_207,
|
||||||
vextuwrx, PPC_NONE, PPC2_ISA300)
|
vextuwrx, PPC_NONE, PPC2_ISA300)
|
||||||
|
|
||||||
#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
|
#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
|
||||||
|
@ -1308,7 +1308,7 @@ static void gen_##name(DisasContext *ctx) \
|
|||||||
} \
|
} \
|
||||||
xt = gen_vsr_ptr(xT(ctx->opcode)); \
|
xt = gen_vsr_ptr(xT(ctx->opcode)); \
|
||||||
xa = gen_vsr_ptr(xA(ctx->opcode)); \
|
xa = gen_vsr_ptr(xA(ctx->opcode)); \
|
||||||
if (ctx->opcode & PPC_BIT(25)) { \
|
if (ctx->opcode & PPC_BIT32(25)) { \
|
||||||
/* \
|
/* \
|
||||||
* AxT + B \
|
* AxT + B \
|
||||||
*/ \
|
*/ \
|
||||||
|
@ -8770,6 +8770,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
|
|||||||
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
|
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
|
||||||
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
|
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
|
||||||
pcc->lrg_decr_bits = 32;
|
pcc->lrg_decr_bits = 32;
|
||||||
|
pcc->n_host_threads = 8;
|
||||||
#endif
|
#endif
|
||||||
pcc->excp_model = POWERPC_EXCP_POWER8;
|
pcc->excp_model = POWERPC_EXCP_POWER8;
|
||||||
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
|
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
|
||||||
@ -8981,6 +8982,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
|
|||||||
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
|
pcc->hash64_opts = &ppc_hash64_opts_POWER7;
|
||||||
pcc->radix_page_info = &POWER9_radix_page_info;
|
pcc->radix_page_info = &POWER9_radix_page_info;
|
||||||
pcc->lrg_decr_bits = 56;
|
pcc->lrg_decr_bits = 56;
|
||||||
|
pcc->n_host_threads = 4;
|
||||||
#endif
|
#endif
|
||||||
pcc->excp_model = POWERPC_EXCP_POWER9;
|
pcc->excp_model = POWERPC_EXCP_POWER9;
|
||||||
pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
|
pcc->bus_model = PPC_FLAGS_INPUT_POWER9;
|
||||||
@ -10461,6 +10463,10 @@ static void ppc_cpu_reset(CPUState *s)
|
|||||||
s->exception_index = POWERPC_EXCP_NONE;
|
s->exception_index = POWERPC_EXCP_NONE;
|
||||||
env->error_code = 0;
|
env->error_code = 0;
|
||||||
|
|
||||||
|
/* tininess for underflow is detected before rounding */
|
||||||
|
set_float_detect_tininess(float_tininess_before_rounding,
|
||||||
|
&env->fp_status);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
|
for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
|
||||||
ppc_spr_t *spr = &env->spr_cb[i];
|
ppc_spr_t *spr = &env->spr_cb[i];
|
||||||
|
|
||||||
|
@ -103,7 +103,8 @@ static testdef_t tests[] = {
|
|||||||
{ "ppc64", "pseries",
|
{ "ppc64", "pseries",
|
||||||
"-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken",
|
"-machine cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken",
|
||||||
"Open Firmware" },
|
"Open Firmware" },
|
||||||
{ "ppc64", "powernv", "-cpu POWER8", "OPAL" },
|
{ "ppc64", "powernv8", "", "OPAL" },
|
||||||
|
{ "ppc64", "powernv9", "", "OPAL" },
|
||||||
{ "ppc64", "sam460ex", "-device e1000", "8086 100e" },
|
{ "ppc64", "sam460ex", "-device e1000", "8086 100e" },
|
||||||
{ "i386", "isapc", "-cpu qemu32 -device sga", "SGABIOS" },
|
{ "i386", "isapc", "-cpu qemu32 -device sga", "SGABIOS" },
|
||||||
{ "i386", "pc", "-device sga", "SGABIOS" },
|
{ "i386", "pc", "-device sga", "SGABIOS" },
|
||||||
|
@ -77,9 +77,15 @@ static void test_xscom_cfam_id(QTestState *qts, const PnvChip *chip)
|
|||||||
static void test_cfam_id(const void *data)
|
static void test_cfam_id(const void *data)
|
||||||
{
|
{
|
||||||
const PnvChip *chip = data;
|
const PnvChip *chip = data;
|
||||||
|
const char *machine = "powernv8";
|
||||||
QTestState *qts;
|
QTestState *qts;
|
||||||
|
|
||||||
qts = qtest_initf("-M powernv,accel=tcg -cpu %s", chip->cpu_model);
|
if (chip->chip_type == PNV_CHIP_POWER9) {
|
||||||
|
machine = "powernv9";
|
||||||
|
}
|
||||||
|
|
||||||
|
qts = qtest_initf("-M %s,accel=tcg -cpu %s",
|
||||||
|
machine, chip->cpu_model);
|
||||||
test_xscom_cfam_id(qts, chip);
|
test_xscom_cfam_id(qts, chip);
|
||||||
qtest_quit(qts);
|
qtest_quit(qts);
|
||||||
}
|
}
|
||||||
@ -113,8 +119,14 @@ static void test_core(const void *data)
|
|||||||
{
|
{
|
||||||
const PnvChip *chip = data;
|
const PnvChip *chip = data;
|
||||||
QTestState *qts;
|
QTestState *qts;
|
||||||
|
const char *machine = "powernv8";
|
||||||
|
|
||||||
qts = qtest_initf("-M powernv,accel=tcg -cpu %s", chip->cpu_model);
|
if (chip->chip_type == PNV_CHIP_POWER9) {
|
||||||
|
machine = "powernv9";
|
||||||
|
}
|
||||||
|
|
||||||
|
qts = qtest_initf("-M %s,accel=tcg -cpu %s",
|
||||||
|
machine, chip->cpu_model);
|
||||||
test_xscom_core(qts, chip);
|
test_xscom_core(qts, chip);
|
||||||
qtest_quit(qts);
|
qtest_quit(qts);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user