diff options
Diffstat (limited to 'hw/ppc')
| -rw-r--r-- | hw/ppc/e500.c | 10 | ||||
| -rw-r--r-- | hw/ppc/pnv.c | 27 | ||||
| -rw-r--r-- | hw/ppc/pnv_bmc.c | 22 | ||||
| -rw-r--r-- | hw/ppc/pnv_lpc.c | 15 | ||||
| -rw-r--r-- | hw/ppc/spapr.c | 44 | ||||
| -rw-r--r-- | hw/ppc/spapr_numa.c | 27 | ||||
| -rw-r--r-- | hw/ppc/spapr_pci.c | 33 |
7 files changed, 107 insertions, 71 deletions
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index c64b5d08bd..01517a6c6c 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -74,6 +74,8 @@ #define MPC8544_I2C_IRQ 43 #define RTC_REGS_OFFSET 0x68 +#define PLATFORM_CLK_FREQ_HZ (400 * 1000 * 1000) + struct boot_info { uint32_t dt_base; @@ -124,7 +126,7 @@ static void dt_serial_create(void *fdt, unsigned long long offset, qemu_fdt_setprop_string(fdt, ser, "compatible", "ns16550"); qemu_fdt_setprop_cells(fdt, ser, "reg", offset, 0x100); qemu_fdt_setprop_cell(fdt, ser, "cell-index", idx); - qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", 0); + qemu_fdt_setprop_cell(fdt, ser, "clock-frequency", PLATFORM_CLK_FREQ_HZ); qemu_fdt_setprop_cells(fdt, ser, "interrupts", 42, 2); qemu_fdt_setprop_phandle(fdt, ser, "interrupt-parent", mpic); qemu_fdt_setprop_string(fdt, "/aliases", alias, ser); @@ -320,8 +322,8 @@ static int ppce500_load_device_tree(PPCE500MachineState *pms, int fdt_size; void *fdt; uint8_t hypercall[16]; - uint32_t clock_freq = 400000000; - uint32_t tb_freq = 400000000; + uint32_t clock_freq = PLATFORM_CLK_FREQ_HZ; + uint32_t tb_freq = PLATFORM_CLK_FREQ_HZ; int i; char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; char *soc; @@ -890,7 +892,7 @@ void ppce500_init(MachineState *machine) env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i; env->mpic_iack = pmc->ccsrbar_base + MPC8544_MPIC_REGS_OFFSET + 0xa0; - ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500); + ppc_booke_timers_init(cpu, PLATFORM_CLK_FREQ_HZ, PPC_TIMER_E500); /* Register reset handler */ if (!i) { diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 14fc9758a9..77af846cdf 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -21,6 +21,7 @@ #include "qemu-common.h" #include "qemu/datadir.h" #include "qemu/units.h" +#include "qemu/cutils.h" #include "qapi/error.h" #include "sysemu/qtest.h" #include "sysemu/sysemu.h" @@ -65,9 +66,9 @@ #define FW_MAX_SIZE (16 * MiB) #define KERNEL_LOAD_ADDR 0x20000000 -#define KERNEL_MAX_SIZE (256 * MiB) -#define INITRD_LOAD_ADDR 0x60000000 -#define INITRD_MAX_SIZE (256 * MiB) +#define KERNEL_MAX_SIZE (128 * MiB) +#define INITRD_LOAD_ADDR 0x28000000 +#define INITRD_MAX_SIZE (128 * MiB) static const char *pnv_chip_core_typename(const PnvChip *o) { @@ -725,8 +726,11 @@ static void pnv_init(MachineState *machine) DeviceState *dev; /* allocate RAM */ - if (machine->ram_size < (1 * GiB)) { - warn_report("skiboot may not work with < 1GB of RAM"); + if (machine->ram_size < mc->default_ram_size) { + char *sz = size_to_str(mc->default_ram_size); + error_report("Invalid RAM size, should be bigger than %s", sz); + g_free(sz); + exit(EXIT_FAILURE); } memory_region_add_subregion(get_system_memory(), 0, machine->ram); @@ -872,6 +876,14 @@ static void pnv_init(MachineState *machine) } /* + * The PNOR is mapped on the LPC FW address space by the BMC. + * Since we can not reach the remote BMC machine with LPC memops, + * map it always for now. + */ + memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET, + &pnv->pnor->mmio); + + /* * OpenPOWER systems use a IPMI SEL Event message to notify the * host to powerdown */ @@ -1150,6 +1162,7 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); + chip->fw_mr = &chip8->lpc.isa_fw; chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", (uint64_t) PNV_XSCOM_BASE(chip), PNV_XSCOM_LPC_BASE); @@ -1479,6 +1492,7 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), &chip9->lpc.xscom_regs); + chip->fw_mr = &chip9->lpc.isa_fw; chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", (uint64_t) PNV9_LPCM_BASE(chip)); @@ -1592,6 +1606,7 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), &chip10->lpc.xscom_regs); + chip->fw_mr = &chip10->lpc.isa_fw; chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", (uint64_t) PNV10_LPCM_BASE(chip)); } @@ -1983,7 +1998,7 @@ static void pnv_machine_class_init(ObjectClass *oc, void *data) * 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; + mc->default_ram_size = 1 * GiB; mc->default_ram_id = "pnv.ram"; ispc->print_info = pnv_pic_print_info; nc->nmi_monitor_handler = pnv_nmi; diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c index 67ebb16c4d..b9bf5735ea 100644 --- a/hw/ppc/pnv_bmc.c +++ b/hw/ppc/pnv_bmc.c @@ -51,6 +51,11 @@ typedef struct OemSel { #define SOFT_OFF 0x00 #define SOFT_REBOOT 0x01 +static bool pnv_bmc_is_simulator(IPMIBmc *bmc) +{ + return object_dynamic_cast(OBJECT(bmc), TYPE_IPMI_BMC_SIMULATOR); +} + static void pnv_gen_oem_sel(IPMIBmc *bmc, uint8_t reboot) { /* IPMI SEL Event are 16 bytes long */ @@ -79,6 +84,10 @@ void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt) const struct ipmi_sdr_compact *sdr; uint16_t nextrec; + if (!pnv_bmc_is_simulator(bmc)) { + return; + } + offset = fdt_add_subnode(fdt, 0, "bmc"); _FDT(offset); @@ -243,6 +252,10 @@ static const IPMINetfn hiomap_netfn = { void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor) { + if (!pnv_bmc_is_simulator(bmc)) { + return; + } + object_ref(OBJECT(pnor)); object_property_add_const_link(OBJECT(bmc), "pnor", OBJECT(pnor)); @@ -260,13 +273,8 @@ IPMIBmc *pnv_bmc_create(PnvPnor *pnor) Object *obj; obj = object_new(TYPE_IPMI_BMC_SIMULATOR); - object_ref(OBJECT(pnor)); - object_property_add_const_link(obj, "pnor", OBJECT(pnor)); qdev_realize(DEVICE(obj), NULL, &error_fatal); - - /* Install the HIOMAP protocol handlers to access the PNOR */ - ipmi_sim_register_netfn(IPMI_BMC_SIMULATOR(obj), IPMI_NETFN_OEM, - &hiomap_netfn); + pnv_bmc_set_pnor(IPMI_BMC(obj), pnor); return IPMI_BMC(obj); } @@ -291,7 +299,7 @@ static int bmc_find(Object *child, void *opaque) IPMIBmc *pnv_bmc_find(Error **errp) { - ForeachArgs args = { TYPE_IPMI_BMC_SIMULATOR, NULL }; + ForeachArgs args = { TYPE_IPMI_BMC, NULL }; int ret; ret = object_child_foreach_recursive(object_get_root(), bmc_find, &args); diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c index 5903590220..bcbca3db97 100644 --- a/hw/ppc/pnv_lpc.c +++ b/hw/ppc/pnv_lpc.c @@ -824,8 +824,6 @@ ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp) ISABus *isa_bus; qemu_irq *irqs; qemu_irq_handler handler; - PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); - bool hostboot_mode = !!pnv->fw_load_addr; /* let isa_bus_new() create its own bridge on SysBus otherwise * devices specified on the command line won't find the bus and @@ -851,18 +849,5 @@ ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp) isa_bus_irqs(isa_bus, irqs); - /* - * TODO: Map PNOR on the LPC FW address space on demand ? - */ - memory_region_add_subregion(&lpc->isa_fw, PNOR_SPI_OFFSET, - &pnv->pnor->mmio); - /* - * Start disabled. The HIOMAP protocol will activate the mapping - * with HIOMAP_C_CREATE_WRITE_WINDOW - */ - if (!hostboot_mode) { - memory_region_set_enabled(&pnv->pnor->mmio, false); - } - return isa_bus; } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 612356e9ec..85fe65f894 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -296,15 +296,6 @@ static hwaddr spapr_node0_size(MachineState *machine) return machine->ram_size; } -bool spapr_machine_using_legacy_numa(SpaprMachineState *spapr) -{ - MachineState *machine = MACHINE(spapr); - SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); - - return smc->pre_5_2_numa_associativity || - machine->numa_state->num_nodes <= 1; -} - static void add_str(GString *s, const gchar *s1) { g_string_append_len(s, s1, strlen(s1) + 1); @@ -791,7 +782,6 @@ static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) CPUState *cs; int n_cpus; int cpus_offset; - char *nodename; int i; cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); @@ -819,6 +809,7 @@ static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) PowerPCCPU *cpu = POWERPC_CPU(cs); int index = spapr_get_vcpu_id(cpu); DeviceClass *dc = DEVICE_GET_CLASS(cs); + g_autofree char *nodename = NULL; int offset; if (!spapr_is_thread0_in_vcore(spapr, cpu)) { @@ -827,7 +818,6 @@ static void spapr_dt_cpus(void *fdt, SpaprMachineState *spapr) nodename = g_strdup_printf("%s@%x", dc->fw_name, index); offset = fdt_add_subnode(fdt, cpus_offset, nodename); - g_free(nodename); _FDT(offset); spapr_dt_cpu(cs, fdt, offset, spapr); } @@ -2780,16 +2770,7 @@ static void spapr_machine_init(MachineState *machine) } - /* - * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. - * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is - * called from vPHB reset handler so we initialize the counter here. - * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM - * must be equally distant from any other node. - * The final value of spapr->gpu_numa_id is going to be written to - * max-associativity-domains in spapr_build_fdt(). - */ - spapr->gpu_numa_id = MAX(1, machine->numa_state->num_nodes); + spapr->gpu_numa_id = spapr_numa_initial_nvgpu_numa_id(machine); /* Init numa_assoc_array */ spapr_numa_associativity_init(spapr, machine); @@ -3055,6 +3036,7 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); + PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); if (d) { void *spapr = CAST(void, bus->parent, "spapr-vscsi"); @@ -3128,6 +3110,10 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); } + if (pcidev) { + return spapr_pci_fw_dev_name(pcidev); + } + return NULL; } @@ -3749,15 +3735,27 @@ int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, PowerPCCPU *cpu = POWERPC_CPU(cs); DeviceClass *dc = DEVICE_GET_CLASS(cs); int id = spapr_get_vcpu_id(cpu); - char *nodename; + g_autofree char *nodename = NULL; int offset; nodename = g_strdup_printf("%s@%x", dc->fw_name, id); offset = fdt_add_subnode(fdt, 0, nodename); - g_free(nodename); spapr_dt_cpu(cs, fdt, offset, spapr); + /* + * spapr_dt_cpu() does not fill the 'name' property in the + * CPU node. The function is called during boot process, before + * and after CAS, and overwriting the 'name' property written + * by SLOF is not allowed. + * + * Write it manually after spapr_dt_cpu(). This makes the hotplug + * CPUs more compatible with the coldplugged ones, which have + * the 'name' property. Linux Kernel also relies on this + * property to identify CPU nodes. + */ + _FDT((fdt_setprop_string(fdt, offset, "name", nodename))); + *fdt_start_offset = offset; return 0; } diff --git a/hw/ppc/spapr_numa.c b/hw/ppc/spapr_numa.c index b50796bbe3..779f18b994 100644 --- a/hw/ppc/spapr_numa.c +++ b/hw/ppc/spapr_numa.c @@ -19,6 +19,15 @@ /* Moved from hw/ppc/spapr_pci_nvlink2.c */ #define SPAPR_GPU_NUMA_ID (cpu_to_be32(1)) +static bool spapr_machine_using_legacy_numa(SpaprMachineState *spapr) +{ + MachineState *machine = MACHINE(spapr); + SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); + + return smc->pre_5_2_numa_associativity || + machine->numa_state->num_nodes <= 1; +} + static bool spapr_numa_is_symmetrical(MachineState *ms) { int src, dst; @@ -38,6 +47,20 @@ static bool spapr_numa_is_symmetrical(MachineState *ms) } /* + * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. + * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is + * called from vPHB reset handler so we initialize the counter here. + * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM + * must be equally distant from any other node. + * The final value of spapr->gpu_numa_id is going to be written to + * max-associativity-domains in spapr_build_fdt(). + */ +unsigned int spapr_numa_initial_nvgpu_numa_id(MachineState *machine) +{ + return MAX(1, machine->numa_state->num_nodes); +} + +/* * This function will translate the user distances into * what the kernel understand as possible values: 10 * (local distance), 20, 40, 80 and 160, and return the equivalent @@ -288,6 +311,8 @@ void spapr_numa_write_rtas_dt(SpaprMachineState *spapr, void *fdt, int rtas) { MachineState *ms = MACHINE(spapr); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); + uint32_t number_nvgpus_nodes = spapr->gpu_numa_id - + spapr_numa_initial_nvgpu_numa_id(ms); uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x3), @@ -295,7 +320,7 @@ void spapr_numa_write_rtas_dt(SpaprMachineState *spapr, void *fdt, int rtas) cpu_to_be32(0x1), }; uint32_t nr_refpoints = ARRAY_SIZE(refpoints); - uint32_t maxdomain = ms->numa_state->num_nodes + spapr->gpu_numa_id; + uint32_t maxdomain = ms->numa_state->num_nodes + number_nvgpus_nodes; uint32_t maxdomains[] = { cpu_to_be32(4), cpu_to_be32(maxdomain), diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 24b4972300..f1c7479816 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1344,15 +1344,29 @@ static int spapr_dt_pci_bus(SpaprPhbState *sphb, PCIBus *bus, return offset; } +char *spapr_pci_fw_dev_name(PCIDevice *dev) +{ + const gchar *basename; + int slot = PCI_SLOT(dev->devfn); + int func = PCI_FUNC(dev->devfn); + uint32_t ccode = pci_default_read_config(dev, PCI_CLASS_PROG, 3); + + basename = dt_name_from_class((ccode >> 16) & 0xff, (ccode >> 8) & 0xff, + ccode & 0xff); + + if (func != 0) { + return g_strdup_printf("%s@%x,%x", basename, slot, func); + } else { + return g_strdup_printf("%s@%x", basename, slot); + } +} + /* create OF node for pci device and required OF DT properties */ static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev, void *fdt, int parent_offset) { int offset; - const gchar *basename; - gchar *nodename; - int slot = PCI_SLOT(dev->devfn); - int func = PCI_FUNC(dev->devfn); + g_autofree gchar *nodename = spapr_pci_fw_dev_name(dev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); ResourceProps rp; SpaprDrc *drc = drc_from_dev(sphb, dev); @@ -1369,19 +1383,8 @@ static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev, uint32_t pci_status = pci_default_read_config(dev, PCI_STATUS, 2); gchar *loc_code; - basename = dt_name_from_class((ccode >> 16) & 0xff, (ccode >> 8) & 0xff, - ccode & 0xff); - - if (func != 0) { - nodename = g_strdup_printf("%s@%x,%x", basename, slot, func); - } else { - nodename = g_strdup_printf("%s@%x", basename, slot); - } - _FDT(offset = fdt_add_subnode(fdt, parent_offset, nodename)); - g_free(nodename); - /* in accordance with PAPR+ v2.7 13.6.3, Table 181 */ _FDT(fdt_setprop_cell(fdt, offset, "vendor-id", vendor_id)); _FDT(fdt_setprop_cell(fdt, offset, "device-id", device_id)); |