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:
Peter Maydell 2020-04-07 11:19:31 +01:00
commit c185e22112
15 changed files with 149 additions and 27 deletions

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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");
}
}
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;

View File

@ -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",

View File

@ -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

View File

@ -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

Binary file not shown.

@ -1 +1 @@
Subproject commit ab6984f5a6d054e1f634dda855b32e5357111974
Subproject commit 8e012d6fddb62be833d746cef3f03e6c8beecde0

View File

@ -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);

View File

@ -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;