mirror of https://github.com/xemu-project/xemu.git
ppc patch queue 2020-04-07
An assortment of fixes for qemu-5.0, including a number for the FWNMI feature which is new this release. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAl6MAv4ACgkQbDjKyiDZ s5LxjhAAuyKEYD0n6U5JL/+4zIe2YPZbzyUJL4ZeTCwcKgPY71bvOO+57/ATHOBU 7DJ92glrdN1DN5iA6tpI3nTEA6ghDOR3/16UizqC0CdT17a5V4LOhcZ76ZbtPXyM ct9bZPEkGvnHsr5UGZ9fcGLeapHYQa6GEww1BI0Ed8Sa6D3yX+mk9x4PTMQKN8+R P8GmLUt6CYNxtvv15mILNA5BsFJDpAYKh3WSqYrXD0UF10w0UKI/Ma0hfqevrpiE aXF/TQOnEzirQEQ5jAgFy88einu70LuJx5ws96CJJAUPrjhi9vWuuHe4hk03z795 CFpjWBwB5Kf/bkwkJgzQ2SxOHRnFPaQPCJG1Baf2B+VXdo/6R9Y7tq+ia3qDq4QK +O30HVHjzGFerURiTFh5yvaT7nN24BL6L3vSU/njyLpy2hy8Kfa8q4ic2k17DBGn ZfD844r+8mFLiSCr+g11iLBYqFRtzqdvCYYJlhdJxQISzQdDHIoobNfWglv9uTD2 CZ6wPPdw7nGIPdBIxsTmztJREgLVO0oeXa/0yZG//gaQKHhxDeD2iajSd87Z20Cl bZ8K/mDE3QSt8KQOtq22whivJIwzUAi6XWcRTnCaCs39rYRoVRo9Ey55KnV1b6gI WjkCCzoPrGxrDMyHw9o571QvWWynANCHBzolUR8p9VU0abBugI4= =F8JM -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-5.0-20200407' into staging ppc patch queue 2020-04-07 An assortment of fixes for qemu-5.0, including a number for the FWNMI feature which is new this release. # gpg: Signature made Tue 07 Apr 2020 05:35:10 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-5.0-20200407: ppc/pnv: Create BMC devices only when defaults are enabled pseries: Update SLOF firmware image hw/ppc/ppc440_uc.c: Remove incorrect iothread locking from dcr_write_pcie() spapr: Fix failure path for attempting to hot unplug PCI bridges ppc/spapr: Don't kill the guest if a recovered FWNMI machine check delivery fails ppc/spapr: Add FWNMI machine check delivery warnings ppc/spapr: Improve FWNMI machine check delivery corner case comments ppc/spapr: KVM FWNMI should not be enabled until guest requests it vfio/spapr: Fix page size calculation hw/ppc/e500.c: Handle qemu_find_file() failure Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c185e22112
|
@ -1047,6 +1047,10 @@ void ppce500_init(MachineState *machine)
|
|||
}
|
||||
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name);
|
||||
if (!filename) {
|
||||
error_report("could not find firmware/kernel file '%s'", payload_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
payload_size = load_elf(filename, NULL, NULL, NULL,
|
||||
&bios_entry, &loadaddr, NULL, NULL,
|
||||
|
|
32
hw/ppc/pnv.c
32
hw/ppc/pnv.c
|
@ -571,10 +571,29 @@ static void pnv_powerdown_notify(Notifier *n, void *opaque)
|
|||
|
||||
static void pnv_reset(MachineState *machine)
|
||||
{
|
||||
PnvMachineState *pnv = PNV_MACHINE(machine);
|
||||
IPMIBmc *bmc;
|
||||
void *fdt;
|
||||
|
||||
qemu_devices_reset();
|
||||
|
||||
/*
|
||||
* The machine should provide by default an internal BMC simulator.
|
||||
* If not, try to use the BMC device that was provided on the command
|
||||
* line.
|
||||
*/
|
||||
bmc = pnv_bmc_find(&error_fatal);
|
||||
if (!pnv->bmc) {
|
||||
if (!bmc) {
|
||||
warn_report("machine has no BMC device. Use '-device "
|
||||
"ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
|
||||
"to define one");
|
||||
} else {
|
||||
pnv_bmc_set_pnor(bmc, pnv->pnor);
|
||||
pnv->bmc = bmc;
|
||||
}
|
||||
}
|
||||
|
||||
fdt = pnv_dt_create(machine);
|
||||
|
||||
/* Pack resulting tree */
|
||||
|
@ -833,9 +852,6 @@ static void pnv_init(MachineState *machine)
|
|||
}
|
||||
g_free(chip_typename);
|
||||
|
||||
/* Create the machine BMC simulator */
|
||||
pnv->bmc = pnv_bmc_create(pnv->pnor);
|
||||
|
||||
/* Instantiate ISA bus on chip 0 */
|
||||
pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
|
||||
|
||||
|
@ -845,8 +861,14 @@ static void pnv_init(MachineState *machine)
|
|||
/* Create an RTC ISA device too */
|
||||
mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
|
||||
|
||||
/* Create the IPMI BT device for communication with the BMC */
|
||||
pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
|
||||
/*
|
||||
* Create the machine BMC simulator and the IPMI BT device for
|
||||
* communication with the BMC
|
||||
*/
|
||||
if (defaults_enabled()) {
|
||||
pnv->bmc = pnv_bmc_create(pnv->pnor);
|
||||
pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* OpenPOWER systems use a IPMI SEL Event message to notify the
|
||||
|
|
|
@ -213,6 +213,18 @@ static const IPMINetfn hiomap_netfn = {
|
|||
.cmd_handlers = hiomap_cmds
|
||||
};
|
||||
|
||||
|
||||
void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor)
|
||||
{
|
||||
object_ref(OBJECT(pnor));
|
||||
object_property_add_const_link(OBJECT(bmc), "pnor", OBJECT(pnor),
|
||||
&error_abort);
|
||||
|
||||
/* Install the HIOMAP protocol handlers to access the PNOR */
|
||||
ipmi_sim_register_netfn(IPMI_BMC_SIMULATOR(bmc), IPMI_NETFN_OEM,
|
||||
&hiomap_netfn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Instantiate the machine BMC. PowerNV uses the QEMU internal
|
||||
* simulator but it could also be external.
|
||||
|
@ -232,3 +244,36 @@ IPMIBmc *pnv_bmc_create(PnvPnor *pnor)
|
|||
|
||||
return IPMI_BMC(obj);
|
||||
}
|
||||
|
||||
typedef struct ForeachArgs {
|
||||
const char *name;
|
||||
Object *obj;
|
||||
} ForeachArgs;
|
||||
|
||||
static int bmc_find(Object *child, void *opaque)
|
||||
{
|
||||
ForeachArgs *args = opaque;
|
||||
|
||||
if (object_dynamic_cast(child, args->name)) {
|
||||
if (args->obj) {
|
||||
return 1;
|
||||
}
|
||||
args->obj = child;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
IPMIBmc *pnv_bmc_find(Error **errp)
|
||||
{
|
||||
ForeachArgs args = { TYPE_IPMI_BMC_SIMULATOR, NULL };
|
||||
int ret;
|
||||
|
||||
ret = object_child_foreach_recursive(object_get_root(), bmc_find, &args);
|
||||
if (ret) {
|
||||
error_setg(errp, "machine should have only one BMC device. "
|
||||
"Use '-nodefaults'");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return args.obj ? IPMI_BMC(args.obj) : NULL;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "cpu.h"
|
||||
#include "hw/irq.h"
|
||||
|
@ -1183,9 +1182,7 @@ static void dcr_write_pcie(void *opaque, int dcrn, uint32_t val)
|
|||
case PEGPL_CFGMSK:
|
||||
s->cfg_mask = val;
|
||||
size = ~(val & 0xfffffffe) + 1;
|
||||
qemu_mutex_lock_iothread();
|
||||
pcie_host_mmcfg_update(PCIE_HOST_BRIDGE(s), val & 1, s->cfg_base, size);
|
||||
qemu_mutex_unlock_iothread();
|
||||
break;
|
||||
case PEGPL_MSGBAH:
|
||||
s->msg_base = ((uint64_t)val << 32) | (s->msg_base & 0xffffffff);
|
||||
|
|
|
@ -517,9 +517,10 @@ static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val,
|
|||
}
|
||||
|
||||
if (kvm_enabled()) {
|
||||
if (kvmppc_set_fwnmi() < 0) {
|
||||
error_setg(errp, "Firmware Assisted Non-Maskable Interrupts(FWNMI) "
|
||||
"not supported by KVM");
|
||||
if (!kvmppc_get_fwnmi()) {
|
||||
error_setg(errp,
|
||||
"Firmware Assisted Non-Maskable Interrupts(FWNMI) not supported by KVM.");
|
||||
error_append_hint(errp, "Try appending -machine cap-fwnmi=off\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -833,11 +833,28 @@ static void spapr_mce_dispatch_elog(PowerPCCPU *cpu, bool recovered)
|
|||
/* get rtas addr from fdt */
|
||||
rtas_addr = spapr_get_rtas_addr();
|
||||
if (!rtas_addr) {
|
||||
qemu_system_guest_panicked(NULL);
|
||||
if (!recovered) {
|
||||
error_report(
|
||||
"FWNMI: Unable to deliver machine check to guest: rtas_addr not found.");
|
||||
qemu_system_guest_panicked(NULL);
|
||||
} else {
|
||||
warn_report(
|
||||
"FWNMI: Unable to deliver machine check to guest: rtas_addr not found. "
|
||||
"Machine check recovered.");
|
||||
}
|
||||
g_free(ext_elog);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* By taking the interlock, we assume that the MCE will be
|
||||
* delivered to the guest. CAUTION: don't add anything that could
|
||||
* prevent the MCE to be delivered after this line, otherwise the
|
||||
* guest won't be able to release the interlock and ultimately
|
||||
* hang/crash?
|
||||
*/
|
||||
spapr->fwnmi_machine_check_interlock = cpu->vcpu_id;
|
||||
|
||||
stq_be_phys(&address_space_memory, rtas_addr + RTAS_ERROR_LOG_OFFSET,
|
||||
env->gpr[3]);
|
||||
cpu_physical_memory_write(rtas_addr + RTAS_ERROR_LOG_OFFSET +
|
||||
|
@ -860,17 +877,13 @@ void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered)
|
|||
Error *local_err = NULL;
|
||||
|
||||
if (spapr->fwnmi_machine_check_addr == -1) {
|
||||
/*
|
||||
* This implies that we have hit a machine check either when the
|
||||
* guest has not registered FWNMI (i.e., "ibm,nmi-register" not
|
||||
* called) or between system reset and "ibm,nmi-register".
|
||||
* Fall back to the old machine check behavior in such cases.
|
||||
*/
|
||||
/* Non-FWNMI case, deliver it like an architected CPU interrupt. */
|
||||
cs->exception_index = POWERPC_EXCP_MCHECK;
|
||||
ppc_cpu_do_interrupt(cs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for FWNMI interlock. */
|
||||
while (spapr->fwnmi_machine_check_interlock != -1) {
|
||||
/*
|
||||
* Check whether the same CPU got machine check error
|
||||
|
@ -878,12 +891,25 @@ void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered)
|
|||
* that CPU called "ibm,nmi-interlock")
|
||||
*/
|
||||
if (spapr->fwnmi_machine_check_interlock == cpu->vcpu_id) {
|
||||
qemu_system_guest_panicked(NULL);
|
||||
if (!recovered) {
|
||||
error_report(
|
||||
"FWNMI: Unable to deliver machine check to guest: nested machine check.");
|
||||
qemu_system_guest_panicked(NULL);
|
||||
} else {
|
||||
warn_report(
|
||||
"FWNMI: Unable to deliver machine check to guest: nested machine check. "
|
||||
"Machine check recovered.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
qemu_cond_wait_iothread(&spapr->fwnmi_machine_check_interlock_cond);
|
||||
/* Meanwhile if the system is reset, then just return */
|
||||
if (spapr->fwnmi_machine_check_addr == -1) {
|
||||
/*
|
||||
* If the machine was reset while waiting for the interlock,
|
||||
* abort the delivery. The machine check applies to a context
|
||||
* that no longer exists, so it wouldn't make sense to deliver
|
||||
* it now.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -894,12 +920,13 @@ void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered)
|
|||
* We don't want to abort so we let the migration to continue.
|
||||
* In a rare case, the machine check handler will run on the target.
|
||||
* Though this is not preferable, it is better than aborting
|
||||
* the migration or killing the VM.
|
||||
* the migration or killing the VM. It is okay to call
|
||||
* migrate_del_blocker on a blocker that was not added (which the
|
||||
* nmi-interlock handler would do when it's called after this).
|
||||
*/
|
||||
warn_report("Received a fwnmi while migration was in progress");
|
||||
}
|
||||
|
||||
spapr->fwnmi_machine_check_interlock = cpu->vcpu_id;
|
||||
spapr_mce_dispatch_elog(cpu, recovered);
|
||||
}
|
||||
|
||||
|
|
|
@ -1663,6 +1663,7 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
|
|||
|
||||
if (pc->is_bridge) {
|
||||
error_setg(errp, "PCI: Hot unplug of PCI bridges not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
/* ensure any other present functions are pending unplug */
|
||||
|
|
|
@ -437,6 +437,13 @@ static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
|
|||
return;
|
||||
}
|
||||
|
||||
if (kvm_enabled()) {
|
||||
if (kvmppc_set_fwnmi() < 0) {
|
||||
rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
spapr->fwnmi_system_reset_addr = sreset_addr;
|
||||
spapr->fwnmi_machine_check_addr = mce_addr;
|
||||
|
||||
|
@ -455,6 +462,9 @@ static void rtas_ibm_nmi_interlock(PowerPCCPU *cpu,
|
|||
}
|
||||
|
||||
if (spapr->fwnmi_machine_check_addr == -1) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"FWNMI: ibm,nmi-interlock RTAS called with FWNMI not registered.\n");
|
||||
|
||||
/* NMI register not called */
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
|
|
|
@ -147,7 +147,7 @@ int vfio_spapr_create_window(VFIOContainer *container,
|
|||
{
|
||||
int ret = 0;
|
||||
IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
|
||||
uint64_t pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
|
||||
uint64_t pagesize = memory_region_iommu_get_min_page_size(iommu_mr), pgmask;
|
||||
unsigned entries, bits_total, bits_per_level, max_levels;
|
||||
struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
|
||||
long rampagesize = qemu_minrampagesize();
|
||||
|
@ -159,8 +159,8 @@ int vfio_spapr_create_window(VFIOContainer *container,
|
|||
if (pagesize > rampagesize) {
|
||||
pagesize = rampagesize;
|
||||
}
|
||||
pagesize = 1ULL << (63 - clz64(container->pgsizes &
|
||||
(pagesize | (pagesize - 1))));
|
||||
pgmask = container->pgsizes & (pagesize | (pagesize - 1));
|
||||
pagesize = pgmask ? (1ULL << (63 - clz64(pgmask))) : 0;
|
||||
if (!pagesize) {
|
||||
error_report("Host doesn't support page size 0x%"PRIx64
|
||||
", the supported mask is 0x%lx",
|
||||
|
|
|
@ -241,6 +241,8 @@ struct PnvMachineState {
|
|||
void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt);
|
||||
void pnv_bmc_powerdown(IPMIBmc *bmc);
|
||||
IPMIBmc *pnv_bmc_create(PnvPnor *pnor);
|
||||
IPMIBmc *pnv_bmc_find(Error **errp);
|
||||
void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
|
||||
|
||||
/*
|
||||
* POWER8 MMIO base addresses
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
|
||||
implementation for certain IBM POWER hardware. The sources are at
|
||||
https://github.com/aik/SLOF, and the image currently in qemu is
|
||||
built from git tag qemu-slof-20200317.
|
||||
built from git tag qemu-slof-20200327.
|
||||
|
||||
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
|
||||
legacy x86 software to communicate with an attached serial console as
|
||||
|
|
BIN
pc-bios/slof.bin
BIN
pc-bios/slof.bin
Binary file not shown.
|
@ -1 +1 @@
|
|||
Subproject commit ab6984f5a6d054e1f634dda855b32e5357111974
|
||||
Subproject commit 8e012d6fddb62be833d746cef3f03e6c8beecde0
|
|
@ -88,6 +88,7 @@ static int cap_ppc_safe_indirect_branch;
|
|||
static int cap_ppc_count_cache_flush_assist;
|
||||
static int cap_ppc_nested_kvm_hv;
|
||||
static int cap_large_decr;
|
||||
static int cap_fwnmi;
|
||||
|
||||
static uint32_t debug_inst_opcode;
|
||||
|
||||
|
@ -136,6 +137,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
|||
kvmppc_get_cpu_characteristics(s);
|
||||
cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
|
||||
cap_large_decr = kvmppc_get_dec_bits();
|
||||
cap_fwnmi = kvm_vm_check_extension(s, KVM_CAP_PPC_FWNMI);
|
||||
/*
|
||||
* Note: setting it to false because there is not such capability
|
||||
* in KVM at this moment.
|
||||
|
@ -2064,6 +2066,11 @@ void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
|
|||
}
|
||||
}
|
||||
|
||||
bool kvmppc_get_fwnmi(void)
|
||||
{
|
||||
return cap_fwnmi;
|
||||
}
|
||||
|
||||
int kvmppc_set_fwnmi(void)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
|
||||
|
|
|
@ -27,6 +27,7 @@ void kvmppc_enable_h_page_init(void);
|
|||
void kvmppc_set_papr(PowerPCCPU *cpu);
|
||||
int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr);
|
||||
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
|
||||
bool kvmppc_get_fwnmi(void);
|
||||
int kvmppc_set_fwnmi(void);
|
||||
int kvmppc_smt_threads(void);
|
||||
void kvmppc_error_append_smt_possible_hint(Error *const *errp);
|
||||
|
@ -163,6 +164,11 @@ static inline void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
|
|||
{
|
||||
}
|
||||
|
||||
static inline bool kvmppc_get_fwnmi(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int kvmppc_set_fwnmi(void)
|
||||
{
|
||||
return -1;
|
||||
|
|
Loading…
Reference in New Issue