aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/spapr.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r--hw/ppc/spapr.c133
1 files changed, 47 insertions, 86 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 3ae7db1..f11422f 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 },
{ }
},
};