aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-05-05 20:29:14 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-05-05 20:29:14 +0100
commitd90f154867ec0ec22fd719164b88716e8fd48672 (patch)
tree507b11b0bd6884cb0fb41c3e1612cff300a5cdbc /hw/ppc
parentd45a5270d075ea589f0b0ddcf963a5fea1f500ac (diff)
parent4bb32cd7b1e42c46d274b727c8be8e45b4df3814 (diff)
Merge remote-tracking branch 'remotes/dg-gitlab/tags/ppc-for-6.1-20210504' into staging
ppc patch queue 2021-05-04 Here's the first ppc pull request for qemu-6.1. It has a wide variety of stuff accumulated during the 6.0 freeze. Highlights are: * Multi-phase reset cleanups for PAPR * Preliminary cleanups towards allowing !CONFIG_TCG for the ppc target * Cleanup of AIL logic and extension to POWER10 * Further improvements to handling of hot unplug failures on PAPR * Allow much larger numbers of CPU on pseries * Support for the H_SCM_HEALTH hypercall * Add support for the Pegasos II board * Substantial cleanup to hflag handling * Assorted minor fixes and cleanups # gpg: Signature made Tue 04 May 2021 06:52:39 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/dg-gitlab/tags/ppc-for-6.1-20210504: (46 commits) hw/ppc/pnv_psi: Use device_cold_reset() instead of device_legacy_reset() hw/ppc/spapr_vio: Reset TCE table object with device_cold_reset() hw/intc/spapr_xive: Use device_cold_reset() instead of device_legacy_reset() target/ppc: removed VSCR from SPR registration target/ppc: Reduce the size of ppc_spr_t target/ppc: Clean up _spr_register et al target/ppc: Add POWER10 exception model target/ppc: rework AIL logic in interrupt delivery target/ppc: move opcode table logic to translate.c target/ppc: code motion from translate_init.c.inc to gdbstub.c spapr_drc.c: handle hotunplug errors in drc_unisolate_logical() spapr.h: increase FDT_MAX_SIZE spapr.c: do not use MachineClass::max_cpus to limit CPUs ppc: Rename current DAWR macros and variables target/ppc: POWER10 supports scv target/ppc: Fix POWER9 radix guest HV interrupt AIL behaviour docs/system: ppc: Add documentation for ppce500 machine roms/u-boot: Bump ppce500 u-boot to v2021.04 to fix broken pci support roms/Makefile: Update ppce500 u-boot build directory name ppc/spapr: Add support for implement support for H_SCM_HEALTH ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/Kconfig9
-rw-r--r--hw/ppc/mac_newworld.c4
-rw-r--r--hw/ppc/meson.build2
-rw-r--r--hw/ppc/pegasos2.c144
-rw-r--r--hw/ppc/pnv_core.c3
-rw-r--r--hw/ppc/pnv_psi.c4
-rw-r--r--hw/ppc/spapr.c19
-rw-r--r--hw/ppc/spapr_drc.c23
-rw-r--r--hw/ppc/spapr_hcall.c8
-rw-r--r--hw/ppc/spapr_nvdimm.c36
-rw-r--r--hw/ppc/spapr_rtas.c2
-rw-r--r--hw/ppc/spapr_vio.c2
12 files changed, 246 insertions, 10 deletions
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index d11dc30509..e51e0e5e5a 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -68,6 +68,15 @@ config SAM460EX
select USB_OHCI
select FDT_PPC
+config PEGASOS2
+ bool
+ select MV64361
+ select VT82C686
+ select IDE_VIA
+ select SMBUS_EEPROM
+# This should come with VT82C686
+ select ACPI_X86
+
config PREP
bool
imply PCI_DEVICES
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index f24abf71af..7bb7ac3997 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -155,6 +155,10 @@ static void ppc_core99_init(MachineState *machine)
}
/* allocate RAM */
+ if (machine->ram_size > 2 * GiB) {
+ error_report("RAM size more than 2 GiB is not supported");
+ exit(1);
+ }
memory_region_add_subregion(get_system_memory(), 0, machine->ram);
/* allocate and load firmware ROM */
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index 218631c883..86d6f379d1 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -78,5 +78,7 @@ ppc_ss.add(when: 'CONFIG_E500', if_true: files(
))
# PowerPC 440 Xilinx ML507 reference board.
ppc_ss.add(when: 'CONFIG_VIRTEX', if_true: files('virtex_ml507.c'))
+# Pegasos2
+ppc_ss.add(when: 'CONFIG_PEGASOS2', if_true: files('pegasos2.c'))
hw_arch += {'ppc': ppc_ss}
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
new file mode 100644
index 0000000000..0bfd0928aa
--- /dev/null
+++ b/hw/ppc/pegasos2.c
@@ -0,0 +1,144 @@
+/*
+ * QEMU PowerPC CHRP (Genesi/bPlan Pegasos II) hardware System Emulator
+ *
+ * Copyright (c) 2018-2020 BALATON Zoltan
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/ppc/ppc.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci_host.h"
+#include "hw/irq.h"
+#include "hw/pci-host/mv64361.h"
+#include "hw/isa/vt82c686.h"
+#include "hw/ide/pci.h"
+#include "hw/i2c/smbus_eeprom.h"
+#include "hw/qdev-properties.h"
+#include "sysemu/reset.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/fw-path-provider.h"
+#include "elf.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "exec/address-spaces.h"
+#include "trace.h"
+#include "qemu/datadir.h"
+#include "sysemu/device_tree.h"
+
+#define PROM_FILENAME "pegasos2.rom"
+#define PROM_ADDR 0xfff00000
+#define PROM_SIZE 0x80000
+
+#define BUS_FREQ_HZ 133333333
+
+static void pegasos2_cpu_reset(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+
+ cpu_reset(CPU(cpu));
+ cpu->env.spr[SPR_HID1] = 7ULL << 28;
+}
+
+static void pegasos2_init(MachineState *machine)
+{
+ PowerPCCPU *cpu = NULL;
+ MemoryRegion *rom = g_new(MemoryRegion, 1);
+ DeviceState *mv;
+ PCIBus *pci_bus;
+ PCIDevice *dev;
+ I2CBus *i2c_bus;
+ const char *fwname = machine->firmware ?: PROM_FILENAME;
+ char *filename;
+ int sz;
+ uint8_t *spd_data;
+
+ /* init CPU */
+ cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
+ if (PPC_INPUT(&cpu->env) != PPC_FLAGS_INPUT_6xx) {
+ error_report("Incompatible CPU, only 6xx bus supported");
+ exit(1);
+ }
+
+ /* Set time-base frequency */
+ cpu_ppc_tb_init(&cpu->env, BUS_FREQ_HZ / 4);
+ qemu_register_reset(pegasos2_cpu_reset, cpu);
+
+ /* RAM */
+ memory_region_add_subregion(get_system_memory(), 0, machine->ram);
+
+ /* allocate and load firmware */
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, fwname);
+ if (!filename) {
+ error_report("Could not find firmware '%s'", fwname);
+ exit(1);
+ }
+ memory_region_init_rom(rom, NULL, "pegasos2.rom", PROM_SIZE, &error_fatal);
+ memory_region_add_subregion(get_system_memory(), PROM_ADDR, rom);
+ sz = load_elf(filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1,
+ PPC_ELF_MACHINE, 0, 0);
+ if (sz <= 0) {
+ sz = load_image_targphys(filename, PROM_ADDR, PROM_SIZE);
+ }
+ if (sz <= 0 || sz > PROM_SIZE) {
+ error_report("Could not load firmware '%s'", filename);
+ exit(1);
+ }
+ g_free(filename);
+
+ /* Marvell Discovery II system controller */
+ mv = DEVICE(sysbus_create_simple(TYPE_MV64361, -1,
+ ((qemu_irq *)cpu->env.irq_inputs)[PPC6xx_INPUT_INT]));
+ pci_bus = mv64361_get_pci_bus(mv, 1);
+
+ /* VIA VT8231 South Bridge (multifunction PCI device) */
+ /* VT8231 function 0: PCI-to-ISA Bridge */
+ dev = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(12, 0), true,
+ TYPE_VT8231_ISA);
+ qdev_connect_gpio_out(DEVICE(dev), 0,
+ qdev_get_gpio_in_named(mv, "gpp", 31));
+
+ /* VT8231 function 1: IDE Controller */
+ dev = pci_create_simple(pci_bus, PCI_DEVFN(12, 1), "via-ide");
+ pci_ide_create_devs(dev);
+
+ /* VT8231 function 2-3: USB Ports */
+ pci_create_simple(pci_bus, PCI_DEVFN(12, 2), "vt82c686b-usb-uhci");
+ pci_create_simple(pci_bus, PCI_DEVFN(12, 3), "vt82c686b-usb-uhci");
+
+ /* VT8231 function 4: Power Management Controller */
+ dev = pci_create_simple(pci_bus, PCI_DEVFN(12, 4), TYPE_VT8231_PM);
+ i2c_bus = I2C_BUS(qdev_get_child_bus(DEVICE(dev), "i2c"));
+ spd_data = spd_data_generate(DDR, machine->ram_size);
+ smbus_eeprom_init_one(i2c_bus, 0x57, spd_data);
+
+ /* VT8231 function 5-6: AC97 Audio & Modem */
+ pci_create_simple(pci_bus, PCI_DEVFN(12, 5), TYPE_VIA_AC97);
+ pci_create_simple(pci_bus, PCI_DEVFN(12, 6), TYPE_VIA_MC97);
+
+ /* other PC hardware */
+ pci_vga_init(pci_bus);
+}
+
+static void pegasos2_machine(MachineClass *mc)
+{
+ mc->desc = "Genesi/bPlan Pegasos II";
+ mc->init = pegasos2_init;
+ mc->block_default_type = IF_IDE;
+ mc->default_boot_order = "cd";
+ mc->default_display = "std";
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("7400_v2.9");
+ mc->default_ram_id = "pegasos2.ram";
+ mc->default_ram_size = 512 * MiB;
+}
+
+DEFINE_MACHINE("pegasos2", pegasos2_machine)
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index bd2bf2e044..8c2a15a0fb 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -29,6 +29,7 @@
#include "hw/ppc/pnv_xscom.h"
#include "hw/ppc/xics.h"
#include "hw/qdev-properties.h"
+#include "helper_regs.h"
static const char *pnv_core_cpu_typename(PnvCore *pc)
{
@@ -55,8 +56,8 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
env->gpr[3] = PNV_FDT_ADDR;
env->nip = 0x10;
env->msr |= MSR_HVB; /* Hypervisor mode */
-
env->spr[SPR_HRMOR] = pc->hrmor;
+ hreg_compute_hflags(env);
pcc->intc_reset(pc->chip, cpu);
}
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index 382ac20fa6..cd9a2c5952 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -465,7 +465,7 @@ static void pnv_psi_reset(DeviceState *dev)
static void pnv_psi_reset_handler(void *dev)
{
- device_legacy_reset(DEVICE(dev));
+ device_cold_reset(DEVICE(dev));
}
static void pnv_psi_realize(DeviceState *dev, Error **errp)
@@ -709,7 +709,7 @@ static void pnv_psi_p9_mmio_write(void *opaque, hwaddr addr,
break;
case PSIHB9_INTERRUPT_CONTROL:
if (val & PSIHB9_IRQ_RESET) {
- device_legacy_reset(DEVICE(&psi9->source));
+ device_cold_reset(DEVICE(&psi9->source));
}
psi->regs[reg] = val;
break;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 5951e805bd..8f40319aee 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -98,7 +98,7 @@
*
* We load our kernel at 4M, leaving space for SLOF initial image
*/
-#define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */
+#define FDT_MAX_ADDR 0x80000000 /* FDT must stay below that */
#define FW_MAX_SIZE 0x400000
#define FW_FILE_NAME "slof.bin"
#define FW_OVERHEAD 0x2800000
@@ -1615,11 +1615,11 @@ static void spapr_machine_reset(MachineState *machine)
spapr_clear_pending_events(spapr);
/*
- * We place the device tree and RTAS just below either the top of the RMA,
+ * We place the device tree just below either the top of the RMA,
* or just below 2GB, whichever is lower, so that it can be
* processed with 32-bit real mode code if necessary
*/
- fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE;
+ fdt_addr = MIN(spapr->rma_size, FDT_MAX_ADDR) - FDT_MAX_SIZE;
fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE);
@@ -2692,7 +2692,7 @@ static void spapr_machine_init(MachineState *machine)
spapr->rma_size = spapr_rma_size(spapr, &error_fatal);
/* Setup a load limit for the ramdisk leaving room for SLOF and FDT */
- load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD;
+ load_limit = MIN(spapr->rma_size, FDT_MAX_ADDR) - FW_OVERHEAD;
/*
* VSMT must be set in order to be able to compute VCPU ids, ie to
@@ -4485,7 +4485,16 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
mc->init = spapr_machine_init;
mc->reset = spapr_machine_reset;
mc->block_default_type = IF_SCSI;
- mc->max_cpus = 1024;
+
+ /*
+ * Setting max_cpus to INT32_MAX. Both KVM and TCG max_cpus values
+ * should be limited by the host capability instead of hardcoded.
+ * max_cpus for KVM guests will be checked in kvm_init(), and TCG
+ * guests are welcome to have as many CPUs as the host are capable
+ * of emulate.
+ */
+ mc->max_cpus = INT32_MAX;
+
mc->no_parallel = 1;
mc->default_boot_order = "";
mc->default_ram_size = 512 * MiB;
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index b8c2f3daf7..a2f2634601 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -150,9 +150,32 @@ static uint32_t drc_isolate_logical(SpaprDrc *drc)
static uint32_t drc_unisolate_logical(SpaprDrc *drc)
{
+ SpaprMachineState *spapr = NULL;
+
switch (drc->state) {
case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
+ /*
+ * Unisolating a logical DRC that was marked for unplug
+ * means that the kernel is refusing the removal.
+ */
+ if (drc->unplug_requested && drc->dev) {
+ if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB) {
+ spapr = SPAPR_MACHINE(qdev_get_machine());
+
+ spapr_memory_unplug_rollback(spapr, drc->dev);
+ }
+
+ drc->unplug_requested = false;
+ error_report("Device hotunplug rejected by the guest "
+ "for device %s", drc->dev->id);
+
+ /*
+ * TODO: send a QAPI DEVICE_UNPLUG_ERROR event when
+ * it is implemented.
+ */
+ }
+
return RTAS_OUT_SUCCESS; /* Nothing to do */
case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
break; /* see below */
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 2a464a42e6..16c719c3de 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1394,7 +1394,13 @@ static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu,
return H_P4;
}
- if (mflags == AIL_RESERVED) {
+ if (mflags == 1) {
+ /* AIL=1 is reserved in POWER8/POWER9/POWER10 */
+ return H_UNSUPPORTED_FLAG;
+ }
+
+ if (mflags == 2 && (pcc->insns_flags2 & PPC2_ISA310)) {
+ /* AIL=2 is reserved in POWER10 (ISA v3.1) */
return H_UNSUPPORTED_FLAG;
}
diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c
index b46c36917c..252204e25f 100644
--- a/hw/ppc/spapr_nvdimm.c
+++ b/hw/ppc/spapr_nvdimm.c
@@ -31,6 +31,10 @@
#include "qemu/range.h"
#include "hw/ppc/spapr_numa.h"
+/* DIMM health bitmap bitmap indicators. Taken from kernel's papr_scm.c */
+/* SCM device is unable to persist memory contents */
+#define PAPR_PMEM_UNARMED PPC_BIT(0)
+
bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
uint64_t size, Error **errp)
{
@@ -467,6 +471,37 @@ static target_ulong h_scm_unbind_all(PowerPCCPU *cpu, SpaprMachineState *spapr,
return H_SUCCESS;
}
+static target_ulong h_scm_health(PowerPCCPU *cpu, SpaprMachineState *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+
+ NVDIMMDevice *nvdimm;
+ uint64_t hbitmap = 0;
+ uint32_t drc_index = args[0];
+ SpaprDrc *drc = spapr_drc_by_index(drc_index);
+ const uint64_t hbitmap_mask = PAPR_PMEM_UNARMED;
+
+
+ /* Ensure that the drc is valid & is valid PMEM dimm and is plugged in */
+ if (!drc || !drc->dev ||
+ spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PMEM) {
+ return H_PARAMETER;
+ }
+
+ nvdimm = NVDIMM(drc->dev);
+
+ /* Update if the nvdimm is unarmed and send its status via health bitmaps */
+ if (object_property_get_bool(OBJECT(nvdimm), NVDIMM_UNARMED_PROP, NULL)) {
+ hbitmap |= PAPR_PMEM_UNARMED;
+ }
+
+ /* Update the out args with health bitmap/mask */
+ args[0] = hbitmap;
+ args[1] = hbitmap_mask;
+
+ return H_SUCCESS;
+}
+
static void spapr_scm_register_types(void)
{
/* qemu/scm specific hcalls */
@@ -475,6 +510,7 @@ static void spapr_scm_register_types(void)
spapr_register_hypercall(H_SCM_BIND_MEM, h_scm_bind_mem);
spapr_register_hypercall(H_SCM_UNBIND_MEM, h_scm_unbind_mem);
spapr_register_hypercall(H_SCM_UNBIND_ALL, h_scm_unbind_all);
+ spapr_register_hypercall(H_SCM_HEALTH, h_scm_health);
}
type_init(spapr_scm_register_types)
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 59dbea4e22..03355b4c0a 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -49,6 +49,7 @@
#include "target/ppc/mmu-hash64.h"
#include "target/ppc/mmu-book3s-v3.h"
#include "migration/blocker.h"
+#include "helper_regs.h"
static void rtas_display_character(PowerPCCPU *cpu, SpaprMachineState *spapr,
uint32_t token, uint32_t nargs,
@@ -161,6 +162,7 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
cpu_synchronize_state(CPU(newcpu));
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
+ hreg_compute_hflags(env);
/* Enable Power-saving mode Exit Cause exceptions for the new CPU */
lpcr = env->spr[SPR_LPCR];
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index ef06e0362c..b59452bcd6 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -310,7 +310,7 @@ int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
{
if (dev->tcet) {
- device_legacy_reset(DEVICE(dev->tcet));
+ device_cold_reset(DEVICE(dev->tcet));
}
free_crq(dev);
}