ppc patch queue for 20201-02-10
Here's the latest batch of patches for the ppc target and machine types. Highlights are: * Several fixes for E500 from Bin Meng * Fixes and cleanups for PowerNV from Cédric Le Goater * Assorted other fixes and cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAmAjelUACgkQbDjKyiDZ s5JmcBAAjtwD51w82MLCN7dqC6Har/i40tcoxRPafMk6aOn1Sxif58PQF270hDGv Y3fYJ7q4XB1DHK+lpGw+KgEciKukRLnISTSyXCw6T1gE4PSc+xkf+AGzrKgJHcs4 vbS8JaGysgWogW+uDJttxteYAhoYCB3UqgpXwkINXydd7dhkL80OtypjhSemQ9K9 nF8AatUkdRrsE2fFCJXaxplm9l1SN3jNB+pA0VOhOyjE9fAH9j4dpE/EwIn27O/k 32Yw2psxe51LY8RmhuP2OO8qp3VfnlLODioLvnU2BVrUSdP6f9IURfMBbAfQ3Ege i1OOw7IFfcX1PDuDuvjD2TI11fpLl3O4hS9wtxIdg/fHZtZlApz6MTDtGkB53agD 5/UKBhZqvJfyBlZYbWl51Yp2pmFSlLmjAOynZWyx8jpy0uwghXETebXyFdE82ZVW YhHqx9XOttbeY2F/6HyZ0f5MKNFvWcUcYI+MsiZgORQVD2gVly1dN8P/yUJUkeWI ZwkYT3AhJK8Cg0hQepIJ2jO/raoSp7JyoseBh3suC1cYBZrT9tXzmJWsKbFeaLbi /BGiIpag/d3EXi8AJKO47CbAaAz+PYaof7v1dIgJxdpmgBgduteNZNdp7te6zgMv mEeAPM3Y02IZFXUtB1dIK9LLYBRwOuhR73YJn2NMzkfy9M+Uf/0= =udvb -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dg-gitlab/tags/ppc-for-6.0-20210210' into staging ppc patch queue for 20201-02-10 Here's the latest batch of patches for the ppc target and machine types. Highlights are: * Several fixes for E500 from Bin Meng * Fixes and cleanups for PowerNV from Cédric Le Goater * Assorted other fixes and cleanups # gpg: Signature made Wed 10 Feb 2021 06:16:53 GMT # 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/dg-gitlab/tags/ppc-for-6.0-20210210: target/ppc: Add E500 L2CSR0 write helper hw/net: fsl_etsec: Reverse the RCTRL.RSF logic hw/ppc: e500: Fill in correct <clock-frequency> for the serial nodes hw/ppc: e500: Use a macro for the platform clock frequency ppc/pnv: Set default RAM size to 1 GB spapr_numa.c: fix ibm,max-associativity-domains calculation spapr_numa.c: create spapr_numa_initial_nvgpu_numa_id() helper spapr: move spapr_machine_using_legacy_numa() to spapr_numa.c ppc/pnv: Introduce a LPC FW memory region attribute to map the PNOR ppc/pnv: Remove default disablement of the PNOR contents ppc/pnv: Discard internal BMC initialization when BMC is external ppc/pnv: Simplify pnv_bmc_create() ppc/pnv: Use skiboot addresses to load kernel and ramfs ppc/xive: Add firmware bit when dumping the ENDs ppc/pnv: Add trace events for PCI event notification target/ppc: Remove unused MMU definitions spapr: Adjust firmware path of PCI devices spapr.c: add 'name' property for hotplugged CPUs nodes spapr.c: use g_auto* with 'nodename' in CPU DT functions Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
7b2c4cdd79
@ -24,6 +24,7 @@
|
||||
#include "hw/ppc/xive_regs.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
@ -1319,6 +1320,8 @@ static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val)
|
||||
uint8_t blk;
|
||||
uint32_t idx;
|
||||
|
||||
trace_pnv_xive_ic_hw_trigger(addr, val);
|
||||
|
||||
if (val & XIVE_TRIGGER_END) {
|
||||
xive_error(xive, "IC: END trigger at @0x%"HWADDR_PRIx" data 0x%"PRIx64,
|
||||
addr, val);
|
||||
|
@ -236,3 +236,6 @@ xive_tctx_tm_write(uint64_t offset, unsigned int size, uint64_t value) "@0x0x%"P
|
||||
xive_tctx_tm_read(uint64_t offset, unsigned int size, uint64_t value) "@0x0x%"PRIx64" sz=%d val=0x%" PRIx64
|
||||
xive_presenter_notify(uint8_t nvt_blk, uint32_t nvt_idx, uint8_t ring) "found NVT 0x%x/0x%x ring=0x%x"
|
||||
xive_end_source_read(uint8_t end_blk, uint32_t end_idx, uint64_t addr) "END 0x%x/0x%x @0x0x%"PRIx64
|
||||
|
||||
# pnv_xive.c
|
||||
pnv_xive_ic_hw_trigger(uint64_t addr, uint64_t val) "@0x%"PRIx64" val=0x%"PRIx64
|
||||
|
@ -1294,7 +1294,7 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon)
|
||||
|
||||
pq = xive_get_field32(END_W1_ESn, end->w1);
|
||||
|
||||
monitor_printf(mon, " %08x %c%c %c%c%c%c%c%c%c prio:%d nvt:%02x/%04x",
|
||||
monitor_printf(mon, " %08x %c%c %c%c%c%c%c%c%c%c prio:%d nvt:%02x/%04x",
|
||||
end_idx,
|
||||
pq & XIVE_ESB_VAL_P ? 'P' : '-',
|
||||
pq & XIVE_ESB_VAL_Q ? 'Q' : '-',
|
||||
@ -1305,6 +1305,7 @@ void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon)
|
||||
xive_end_is_escalate(end) ? 'e' : '-',
|
||||
xive_end_is_uncond_escalation(end) ? 'u' : '-',
|
||||
xive_end_is_silent_escalation(end) ? 's' : '-',
|
||||
xive_end_is_firmware(end) ? 'f' : '-',
|
||||
priority, nvt_blk, nvt_idx);
|
||||
|
||||
if (qaddr_base) {
|
||||
|
@ -502,7 +502,7 @@ ssize_t etsec_rx_ring_write(eTSEC *etsec, const uint8_t *buf, size_t size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((etsec->regs[RCTRL].value & RCTRL_RSF) && (size < 60)) {
|
||||
if (!(etsec->regs[RCTRL].value & RCTRL_RSF) && (size < 60)) {
|
||||
/* CRC is not in the packet yet, so short frame is below 60 bytes */
|
||||
RING_DEBUG("%s: Drop short frame\n", __func__);
|
||||
return -1;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qom/object.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define phb_error(phb, fmt, ...) \
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "phb4[%d:%d]: " fmt "\n", \
|
||||
@ -1257,6 +1258,8 @@ static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno)
|
||||
uint64_t data = XIVE_TRIGGER_PQ | offset | srcno;
|
||||
MemTxResult result;
|
||||
|
||||
trace_pnv_phb4_xive_notify(notif_port, data);
|
||||
|
||||
address_space_stq_be(&address_space_memory, notif_port, data,
|
||||
MEMTXATTRS_UNSPECIFIED, &result);
|
||||
if (result != MEMTX_OK) {
|
||||
|
@ -20,3 +20,6 @@ unin_data_write(uint64_t addr, unsigned len, uint64_t val) "write addr 0x%"PRIx6
|
||||
unin_data_read(uint64_t addr, unsigned len, uint64_t val) "read addr 0x%"PRIx64 " len %d val 0x%"PRIx64
|
||||
unin_write(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64
|
||||
unin_read(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64
|
||||
|
||||
# pnv_phb4.c
|
||||
pnv_phb4_xive_notify(uint64_t notif_port, uint64_t data) "notif=@0x%"PRIx64" data=0x%"PRIx64
|
||||
|
@ -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) {
|
||||
|
27
hw/ppc/pnv.c
27
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);
|
||||
|
||||
@ -871,6 +875,14 @@ static void pnv_init(MachineState *machine)
|
||||
pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -37,6 +46,20 @@ static bool spapr_numa_is_symmetrical(MachineState *ms)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -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),
|
||||
|
@ -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));
|
||||
|
@ -210,4 +210,6 @@ static inline unsigned spapr_phb_windows_supported(SpaprPhbState *sphb)
|
||||
return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1;
|
||||
}
|
||||
|
||||
char *spapr_pci_fw_dev_name(PCIDevice *dev);
|
||||
|
||||
#endif /* PCI_HOST_SPAPR_H */
|
||||
|
@ -58,6 +58,7 @@ struct PnvChip {
|
||||
MemoryRegion xscom;
|
||||
AddressSpace xscom_as;
|
||||
|
||||
MemoryRegion *fw_mr;
|
||||
gchar *dt_isa_nodename;
|
||||
};
|
||||
|
||||
|
@ -851,7 +851,6 @@ int spapr_max_server_number(SpaprMachineState *spapr);
|
||||
void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
|
||||
uint64_t pte0, uint64_t pte1);
|
||||
void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered);
|
||||
bool spapr_machine_using_legacy_numa(SpaprMachineState *spapr);
|
||||
|
||||
/* DRC callbacks. */
|
||||
void spapr_core_release(DeviceState *dev);
|
||||
|
@ -31,5 +31,6 @@ int spapr_numa_fixup_cpu_dt(SpaprMachineState *spapr, void *fdt,
|
||||
int offset, PowerPCCPU *cpu);
|
||||
int spapr_numa_write_assoc_lookup_arrays(SpaprMachineState *spapr, void *fdt,
|
||||
int offset);
|
||||
unsigned int spapr_numa_initial_nvgpu_numa_id(MachineState *machine);
|
||||
|
||||
#endif /* HW_SPAPR_NUMA_H */
|
||||
|
@ -236,6 +236,8 @@ typedef struct XiveEND {
|
||||
(be32_to_cpu((end)->w0) & END_W0_UNCOND_ESCALATE)
|
||||
#define xive_end_is_silent_escalation(end) \
|
||||
(be32_to_cpu((end)->w0) & END_W0_SILENT_ESCALATE)
|
||||
#define xive_end_is_firmware(end) \
|
||||
(be32_to_cpu((end)->w0) & END_W0_FIRMWARE)
|
||||
|
||||
static inline uint64_t xive_end_qaddr(XiveEND *end)
|
||||
{
|
||||
|
@ -1919,6 +1919,7 @@ typedef PowerPCCPU ArchCPU;
|
||||
#define SPR_750FX_HID2 (0x3F8)
|
||||
#define SPR_Exxx_L1FINV0 (0x3F8)
|
||||
#define SPR_L2CR (0x3F9)
|
||||
#define SPR_Exxx_L2CSR0 (0x3F9)
|
||||
#define SPR_L3CR (0x3FA)
|
||||
#define SPR_750_TDCH (0x3FA)
|
||||
#define SPR_IABR2 (0x3FA)
|
||||
@ -1974,6 +1975,11 @@ typedef PowerPCCPU ArchCPU;
|
||||
#define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */
|
||||
#define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */
|
||||
|
||||
/* E500 L2CSR0 */
|
||||
#define E500_L2CSR0_L2FI (1 << 21) /* L2 cache flash invalidate */
|
||||
#define E500_L2CSR0_L2FL (1 << 11) /* L2 cache flush */
|
||||
#define E500_L2CSR0_L2LFC (1 << 10) /* L2 cache lock flash clear */
|
||||
|
||||
/* HID0 bits */
|
||||
#define HID0_DEEPNAP (1 << 24) /* pre-2.06 */
|
||||
#define HID0_DOZE (1 << 23) /* pre-2.06 */
|
||||
@ -2205,9 +2211,6 @@ enum {
|
||||
* may be needed for precise access rights control and precise exceptions.
|
||||
*/
|
||||
enum {
|
||||
/* 1 bit to define user level / supervisor access */
|
||||
ACCESS_USER = 0x00,
|
||||
ACCESS_SUPER = 0x01,
|
||||
/* Type of instruction that generated the access */
|
||||
ACCESS_CODE = 0x10, /* Code fetch access */
|
||||
ACCESS_INT = 0x20, /* Integer load/store access */
|
||||
|
@ -1735,6 +1735,16 @@ static void spr_write_e500_l1csr1(DisasContext *ctx, int sprn, int gprn)
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
|
||||
static void spr_write_e500_l2csr0(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
|
||||
tcg_gen_andi_tl(t0, cpu_gpr[gprn],
|
||||
~(E500_L2CSR0_L2FI | E500_L2CSR0_L2FL | E500_L2CSR0_L2LFC));
|
||||
gen_store_spr(sprn, t0);
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
|
||||
static void spr_write_booke206_mmucsr0(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
gen_helper_booke206_tlbflush(cpu_env, cpu_gpr[gprn]);
|
||||
@ -5029,6 +5039,12 @@ static void init_proc_e500(CPUPPCState *env, int version)
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_e500_l1csr1,
|
||||
0x00000000);
|
||||
if (version != fsl_e500v1 && version != fsl_e500v2) {
|
||||
spr_register(env, SPR_Exxx_L2CSR0, "L2CSR0",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_e500_l2csr0,
|
||||
0x00000000);
|
||||
}
|
||||
spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
|
Loading…
Reference in New Issue
Block a user