aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-09-03 17:20:39 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-09-03 17:20:40 +0100
commit3b3f0646a40b0a6e30817f931cafefe743fb0c33 (patch)
tree3c5a045b2defdd5e52d95d4f37233942cc0488a5 /hw
parent3483534ec314f6057e66966bfceaa9df02c28fbf (diff)
parentb1e815674343a171e51ce447495957e289091e9f (diff)
downloadqemu-3b3f0646a40b0a6e30817f931cafefe743fb0c33.zip
qemu-3b3f0646a40b0a6e30817f931cafefe743fb0c33.tar.gz
qemu-3b3f0646a40b0a6e30817f931cafefe743fb0c33.tar.bz2
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>
Diffstat (limited to 'hw')
-rw-r--r--hw/ppc/pnv.c81
-rw-r--r--hw/ppc/pnv_xscom.c20
-rw-r--r--hw/ppc/spapr.c29
-rw-r--r--hw/ppc/spapr_cpu_core.c5
-rw-r--r--hw/ppc/spapr_hcall.c2
-rw-r--r--hw/ppc/spapr_pci.c40
-rw-r--r--hw/ppc/spapr_pci_nvlink2.c40
-rw-r--r--hw/ppc/spapr_rtas.c15
8 files changed, 177 insertions, 55 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index d95086f..3f08db7 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -434,9 +434,14 @@ static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
.fdt = fdt,
.offset = isa_offset,
};
+ uint32_t phandle;
_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
* can not use object_child_foreach() */
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);
}
+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)
{
PnvMachineState *pnv = PNV_MACHINE(machine);
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
MemoryRegion *ram;
char *fw_filename;
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 */
i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
i, machine->cpu_type);
if (!object_class_by_name(chip_typename)) {
- error_report("invalid CPU model '%.*s' for %s machine",
- i, machine->cpu_type, MACHINE_GET_CLASS(machine)->name);
+ error_report("invalid chip model '%.*s' for %s machine",
+ i, machine->cpu_type, mc->name);
exit(1);
}
@@ -1346,25 +1372,47 @@ static void pnv_machine_class_props_init(ObjectClass *oc)
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);
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);
mc->desc = "IBM PowerNV (Non-Virtualized)";
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
* storage */
mc->no_parallel = 1;
mc->default_boot_order = NULL;
- mc->default_ram_size = 1 * GiB;
- xic->icp_get = pnv_icp_get;
- xic->ics_get = pnv_ics_get;
- xic->ics_resend = pnv_ics_resend;
+ /*
+ * RAM defaults to less than 2048 for 32-bit hosts, and large
+ * enough to fit the maximum initrd size at it's load address
+ */
+ mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
ispc->print_info = pnv_pic_print_info;
pnv_machine_class_props_init(oc);
@@ -1384,10 +1432,27 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data)
.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[] = {
+ DEFINE_PNV_MACHINE_TYPE("powernv8", pnv_machine_power8_class_init),
+ DEFINE_PNV_MACHINE_TYPE("powernv9", pnv_machine_power9_class_init),
{
.name = TYPE_PNV_MACHINE,
.parent = TYPE_MACHINE,
+ .abstract = true,
.instance_size = sizeof(PnvMachineState),
.instance_init = pnv_machine_instance_init,
.class_init = pnv_machine_class_init,
diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c
index 0e31c57..67aab98 100644
--- a/hw/ppc/pnv_xscom.c
+++ b/hw/ppc/pnv_xscom.c
@@ -106,6 +106,16 @@ static uint64_t xscom_read_default(PnvChip *chip, uint32_t pcba)
case 0x201302a: /* CAPP stuff */
case 0x2013801: /* 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;
default:
return -1;
@@ -138,6 +148,16 @@ static bool xscom_write_default(PnvChip *chip, uint32_t pcba, uint64_t val)
case 0x2013801: /* 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 */
case PRD_P8_IPOLL_REG_MASK:
case PRD_P8_IPOLL_REG_STATUS:
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index baedadf..ea56499 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1168,6 +1168,7 @@ static void spapr_dt_ov5_platform_support(SpaprMachineState *spapr, void *fdt,
static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt)
{
MachineState *machine = MACHINE(spapr);
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
int chosen;
const char *boot_device = machine->boot_order;
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));
}
+ /* 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);
g_free(stdout_path);
@@ -1752,7 +1758,7 @@ static void spapr_machine_reset(MachineState *machine)
spapr_ovec_cleanup(spapr->ov5_cas);
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;
int index;
bool hotplugged = spapr_drc_hotplugged(dev);
+ int i;
core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index);
if (!core_slot) {
@@ -3862,13 +3869,26 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
core_slot->cpu = OBJECT(dev);
if (smc->pre_2_10_has_unused_icps) {
- int i;
-
for (i = 0; i < cc->nr_threads; i++) {
cs = CPU(core->threads[i]);
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,
@@ -4470,6 +4490,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
spapr_caps_add_properties(smc, &error_abort);
smc->irq = &spapr_irq_dual;
smc->dr_phb_enabled = true;
+ smc->linux_pci_probe = true;
}
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)
{
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
static GlobalProperty compat[] = {
/* Only allow 4kiB and 64kiB IOMMU pagesizes */
{ TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" },
};
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, compat, G_N_ELEMENTS(compat));
}
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index bf47fbd..1d93de8 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -41,11 +41,6 @@ static void spapr_cpu_reset(void *opaque)
* using an RTAS call */
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;
lpcr = env->spr[SPR_LPCR];
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index e20a946..23e4bdb 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1811,7 +1811,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
spapr_ovec_cleanup(ov5_updates);
if (spapr->cas_reboot) {
- qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ qemu_system_reset_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET);
}
return H_SUCCESS;
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index deb0b0c..a777fb3 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -280,7 +280,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
unsigned int irq, max_irqs = 0;
SpaprPhbState *phb = NULL;
PCIDevice *pdev = NULL;
- spapr_pci_msi *msi;
+ SpaprPciMsi *msi;
int *config_addr_key;
Error *err = NULL;
int i;
@@ -328,7 +328,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
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 */
if (!req_num) {
@@ -415,7 +415,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, SpaprMachineState *spapr,
irq, req_num);
/* Add MSI device to cache */
- msi = g_new(spapr_pci_msi, 1);
+ msi = g_new(SpaprPciMsi, 1);
msi->first_irq = irq;
msi->num = req_num;
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);
SpaprPhbState *phb = NULL;
PCIDevice *pdev = NULL;
- spapr_pci_msi *msi;
+ SpaprPciMsi *msi;
/* Find SpaprPhbState */
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 */
- 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)) {
trace_spapr_pci_msi("Failed to return vector", config_addr);
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);
if (state == SPAPR_DR_ENTITY_SENSE_PRESENT
&& !spapr_drc_unplug_requested(func_drc)) {
- error_setg(errp,
- "PCI: slot %d, function %d still present. "
- "Must unplug all non-0 functions first.",
- slotnr, i);
- return;
+ /*
+ * Attempting to remove function 0 of a multifunction
+ * device will will cascade into removing all child
+ * functions, even if their unplug weren't requested
+ * 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());
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
- spapr_pci_msi *msi = opaque;
+ SpaprPciMsi *msi = opaque;
if (!smc->legacy_irq_allocation) {
spapr_irq_msi_free(spapr, msi->first_irq, msi->num);
@@ -2118,7 +2120,7 @@ static const VMStateDescription vmstate_spapr_pci_lsi = {
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32_EQUAL(irq, struct spapr_pci_lsi, NULL),
+ VMSTATE_UINT32_EQUAL(irq, SpaprPciLsi, NULL),
VMSTATE_END_OF_LIST()
},
@@ -2129,9 +2131,9 @@ static const VMStateDescription vmstate_spapr_pci_msi = {
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField []) {
- VMSTATE_UINT32(key, spapr_pci_msi_mig),
- VMSTATE_UINT32(value.first_irq, spapr_pci_msi_mig),
- VMSTATE_UINT32(value.num, spapr_pci_msi_mig),
+ VMSTATE_UINT32(key, SpaprPciMsiMig),
+ VMSTATE_UINT32(value.first_irq, SpaprPciMsiMig),
+ VMSTATE_UINT32(value.num, SpaprPciMsiMig),
VMSTATE_END_OF_LIST()
},
};
@@ -2163,12 +2165,12 @@ static int spapr_pci_pre_save(void *opaque)
if (!sphb->msi_devs_num) {
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);
for (i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) {
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;
@@ -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_size, SpaprPhbState, pre_2_8_migration),
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_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()
},
};
diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c
index eda8c75..4aa89ed 100644
--- a/hw/ppc/spapr_pci_nvlink2.c
+++ b/hw/ppc/spapr_pci_nvlink2.c
@@ -39,11 +39,7 @@
#define SPAPR_GPU_NUMA_ID (cpu_to_be32(1))
-struct spapr_phb_pci_nvgpu_config {
- 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 {
+typedef struct SpaprPhbPciNvGpuSlot {
uint64_t tgt;
uint64_t gpa;
unsigned numa_id;
@@ -54,12 +50,18 @@ struct spapr_phb_pci_nvgpu_config {
PCIDevice *npdev;
uint32_t link_speed;
} 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;
};
-static struct spapr_phb_pci_nvgpu_slot *
-spapr_nvgpu_get_slot(struct spapr_phb_pci_nvgpu_config *nvgpus, uint64_t tgt)
+static SpaprPhbPciNvGpuSlot *
+spapr_nvgpu_get_slot(SpaprPhbPciNvGpuConfig *nvgpus, uint64_t tgt)
{
int i;
@@ -81,13 +83,13 @@ spapr_nvgpu_get_slot(struct spapr_phb_pci_nvgpu_config *nvgpus, uint64_t tgt)
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,
MemoryRegion *mr, Error **errp)
{
MachineState *machine = MACHINE(qdev_get_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) {
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;
}
-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,
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;
if (!nvslot) {
@@ -138,7 +140,7 @@ static void spapr_phb_pci_collect_nvgpu(PCIBus *bus, PCIDevice *pdev,
if (tgt) {
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_npu = object_property_get_link(po, "nvlink2-atsd-mr[0]",
NULL);
@@ -177,7 +179,7 @@ void spapr_phb_nvgpu_setup(SpaprPhbState *sphb, Error **errp)
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_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 */
for (i = 0, valid_gpu_num = 0; i < sphb->nvgpus->num; ++i) {
Object *nvmrobj;
- struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
+ SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i];
if (!nvslot->gpdev) {
continue;
@@ -242,7 +244,7 @@ void spapr_phb_nvgpu_free(SpaprPhbState *sphb)
}
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),
"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) {
- struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
+ SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i];
if (!nvslot->gpdev) {
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 */
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),
"nvlink2-mr[0]", NULL);
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) {
- struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
+ SpaprPhbPciNvGpuSlot *nvslot = &sphb->nvgpus->slots[i];
/* Skip "slot" without attached GPU */
if (!nvslot->gpdev) {
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 526b489..bee3835 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -266,6 +266,7 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
target_ulong args,
uint32_t nret, target_ulong rets)
{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
MachineState *ms = MACHINE(qdev_get_machine());
unsigned int max_cpus = ms->smp.max_cpus;
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,
ms->smp.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);
g_free(param_val);
break;