diff options
author | Peter Maydell | 2019-12-17 12:52:04 +0100 |
---|---|---|
committer | Peter Maydell | 2019-12-17 12:52:04 +0100 |
commit | 98ac38cd5ad5e9496277c943020bc4bf16adf10b (patch) | |
tree | cbcd38b8289c65f607064a17e4de4799497bf5a6 /hw/ppc/spapr.c | |
parent | Merge remote-tracking branch 'remotes/ehabkost/tags/x86-next-pull-request' in... (diff) | |
parent | pseries: Update SLOF firmware image (diff) | |
download | qemu-98ac38cd5ad5e9496277c943020bc4bf16adf10b.tar.gz qemu-98ac38cd5ad5e9496277c943020bc4bf16adf10b.tar.xz qemu-98ac38cd5ad5e9496277c943020bc4bf16adf10b.zip |
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-5.0-20191217' into staging
ppc patch queue 2019-12-17
This is the first pull request for the qemu-5.0 branch. It has a lot
of accumulated changes, including:
* SLOF update to support boot using the IOMMU (will become
necessary for secure guests)
* Clean ups to pnv handling of chip models
* A number of extensions to the powernv machine model
* TCG extensions to allow powernv emulated systems to run KVM guests
* Outline support for POWER10 chips in powernv
* Cleanups to the ibm,client-architecture-support feature negotiation path
* XIVE reworks to better handle the powernv machine
* Improvements to not waste interrupt queues and other semi-scarce
resources when using XIVE under KVM
# gpg: Signature made Tue 17 Dec 2019 04:42:20 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/dgibson/tags/ppc-for-5.0-20191217: (88 commits)
pseries: Update SLOF firmware image
ppc/pnv: Drop PnvChipClass::type
ppc/pnv: Introduce PnvChipClass::xscom_pcba() method
ppc/pnv: Drop pnv_chip_is_power9() and pnv_chip_is_power10() helpers
ppc/pnv: Pass content of the "compatible" property to pnv_dt_xscom()
ppc/pnv: Pass XSCOM base address and address size to pnv_dt_xscom()
ppc/pnv: Introduce PnvChipClass::xscom_core_base() method
ppc/pnv: Introduce PnvChipClass::intc_print_info() method
ppc/pnv: Drop pnv_is_power9() and pnv_is_power10() helpers
ppc/pnv: Introduce PnvMachineClass::dt_power_mgt()
ppc/pnv: Introduce PnvMachineClass and PnvMachineClass::compat
ppc/pnv: Drop PnvPsiClass::chip_type
ppc/pnv: Introduce PnvPsiClass::compat
ppc: Drop useless extern annotation for functions
ppc/pnv: Fix OCC common area region mapping
ppc/pnv: Introduce PBA registers
ppc/pnv: Make PnvXScomInterface an incomplete type
ppc/pnv: populate the DT with realized XSCOM devices
ppc/pnv: Loop on the whole hierarchy to populate the DT with the XSCOM nodes
target/ppc: Add SPR TBU40
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r-- | hw/ppc/spapr.c | 133 |
1 files changed, 47 insertions, 86 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3ae7db1563..f11422fc41 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -76,7 +76,6 @@ #include "hw/nmi.h" #include "hw/intc/intc.h" -#include "qemu/cutils.h" #include "hw/ppc/spapr_cpu_core.h" #include "hw/mem/memory-device.h" #include "hw/ppc/spapr_tpm_proxy.h" @@ -897,69 +896,6 @@ out: return ret; } -static bool spapr_hotplugged_dev_before_cas(void) -{ - Object *drc_container, *obj; - ObjectProperty *prop; - ObjectPropertyIterator iter; - - drc_container = container_get(object_get_root(), "/dr-connector"); - object_property_iter_init(&iter, drc_container); - while ((prop = object_property_iter_next(&iter))) { - if (!strstart(prop->type, "link<", NULL)) { - continue; - } - obj = object_property_get_link(drc_container, prop->name, NULL); - if (spapr_drc_needed(obj)) { - return true; - } - } - return false; -} - -static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset); - -int spapr_h_cas_compose_response(SpaprMachineState *spapr, - target_ulong addr, target_ulong size, - SpaprOptionVector *ov5_updates) -{ - void *fdt; - SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 }; - - if (spapr_hotplugged_dev_before_cas()) { - return 1; - } - - if (size < sizeof(hdr) || size > FW_MAX_SIZE) { - error_report("SLOF provided an unexpected CAS buffer size " - TARGET_FMT_lu " (min: %zu, max: %u)", - size, sizeof(hdr), FW_MAX_SIZE); - exit(EXIT_FAILURE); - } - - size -= sizeof(hdr); - - fdt = spapr_build_fdt(spapr, false); - _FDT((fdt_pack(fdt))); - - if (fdt_totalsize(fdt) + sizeof(hdr) > size) { - g_free(fdt); - trace_spapr_cas_failed(size); - return -1; - } - - cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); - cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); - trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); - - g_free(spapr->fdt_blob); - spapr->fdt_size = fdt_totalsize(fdt); - spapr->fdt_initial_size = spapr->fdt_size; - spapr->fdt_blob = fdt; - - return 0; -} - static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) { MachineState *ms = MACHINE(spapr); @@ -1197,7 +1133,7 @@ static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) } } -static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset) +void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space) { MachineState *machine = MACHINE(spapr); MachineClass *mc = MACHINE_GET_CLASS(machine); @@ -1207,8 +1143,8 @@ static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset) SpaprPhbState *phb; char *buf; - fdt = g_malloc0(FDT_MAX_SIZE); - _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); + fdt = g_malloc0(space); + _FDT((fdt_create_empty_tree(fdt, space))); /* Root node */ _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); @@ -1723,19 +1659,13 @@ static void spapr_machine_reset(MachineState *machine) */ fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE; - fdt = spapr_build_fdt(spapr, true); + fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE); rc = fdt_pack(fdt); /* Should only fail if we've built a corrupted tree */ assert(rc == 0); - if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { - error_report("FDT too big ! 0x%x bytes (max is 0x%x)", - fdt_totalsize(fdt), FDT_MAX_SIZE); - exit(1); - } - /* Load the fdt */ qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); @@ -1910,8 +1840,6 @@ static bool spapr_ov5_cas_needed(void *opaque) { SpaprMachineState *spapr = opaque; SpaprOptionVector *ov5_mask = spapr_ovec_new(); - SpaprOptionVector *ov5_legacy = spapr_ovec_new(); - SpaprOptionVector *ov5_removed = spapr_ovec_new(); bool cas_needed; /* Prior to the introduction of SpaprOptionVector, we had two option @@ -1943,17 +1871,11 @@ static bool spapr_ov5_cas_needed(void *opaque) spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); spapr_ovec_set(ov5_mask, OV5_DRMEM_V2); - /* spapr_ovec_diff returns true if bits were removed. we avoid using - * the mask itself since in the future it's possible "legacy" bits may be - * removed via machine options, which could generate a false positive - * that breaks migration. - */ - spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask); - cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy); + /* We need extra information if we have any bits outside the mask + * defined above */ + cas_needed = !spapr_ovec_subset(spapr->ov5, ov5_mask); spapr_ovec_cleanup(ov5_mask); - spapr_ovec_cleanup(ov5_legacy); - spapr_ovec_cleanup(ov5_removed); return cas_needed; } @@ -2564,7 +2486,7 @@ static void spapr_set_vsmt_mode(SpaprMachineState *spapr, Error **errp) " requires the use of VSMT mode %d.\n", smp_threads, kvm_smt, spapr->vsmt); } - kvmppc_hint_smt_possible(&local_err); + kvmppc_error_append_smt_possible_hint(&local_err); goto out; } } @@ -4275,6 +4197,42 @@ static void spapr_pic_print_info(InterruptStatsProvider *obj, kvm_irqchip_in_kernel() ? "in-kernel" : "emulated"); } +static int spapr_match_nvt(XiveFabric *xfb, uint8_t format, + uint8_t nvt_blk, uint32_t nvt_idx, + bool cam_ignore, uint8_t priority, + uint32_t logic_serv, XiveTCTXMatch *match) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(xfb); + XivePresenter *xptr = XIVE_PRESENTER(spapr->xive); + XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); + int count; + + /* This is a XIVE only operation */ + assert(spapr->active_intc == SPAPR_INTC(spapr->xive)); + + count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, + priority, logic_serv, match); + if (count < 0) { + return count; + } + + /* + * When we implement the save and restore of the thread interrupt + * contexts in the enter/exit CPU handlers of the machine and the + * escalations in QEMU, we should be able to handle non dispatched + * vCPUs. + * + * Until this is done, the sPAPR machine should find at least one + * matching context always. + */ + if (count == 0) { + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: NVT %x/%x is not dispatched\n", + nvt_blk, nvt_idx); + } + + return count; +} + int spapr_get_vcpu_id(PowerPCCPU *cpu) { return cpu->vcpu_id; @@ -4371,6 +4329,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); + XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); mc->desc = "pSeries Logical Partition (PAPR compliant)"; mc->ignore_boot_device_suffixes = true; @@ -4447,6 +4406,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) smc->linux_pci_probe = true; smc->smp_threads_vsmt = true; smc->nr_xirqs = SPAPR_NR_XIRQS; + xfc->match_nvt = spapr_match_nvt; } static const TypeInfo spapr_machine_info = { @@ -4465,6 +4425,7 @@ static const TypeInfo spapr_machine_info = { { TYPE_PPC_VIRTUAL_HYPERVISOR }, { TYPE_XICS_FABRIC }, { TYPE_INTERRUPT_STATS_PROVIDER }, + { TYPE_XIVE_FABRIC }, { } }, }; |