aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/ppc/spapr.c61
-rw-r--r--hw/ppc/spapr_hcall.c55
2 files changed, 53 insertions, 63 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index df5bea1bd4..3dedb41d48 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,63 +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,
- size_t space);
-
-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)) {
- error_report("SLOF provided insufficient CAS buffer "
- TARGET_FMT_lu " (min: %zu)", size, sizeof(hdr));
- exit(EXIT_FAILURE);
- }
-
- size -= sizeof(hdr);
-
- fdt = spapr_build_fdt(spapr, false, size);
- _FDT((fdt_pack(fdt)));
-
- 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);
@@ -1191,8 +1133,7 @@ static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt)
}
}
-static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset,
- size_t space)
+void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space)
{
MachineState *machine = MACHINE(spapr);
MachineClass *mc = MACHINE_GET_CLASS(machine);
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 05a7ca275b..0f19be794c 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1,4 +1,5 @@
#include "qemu/osdep.h"
+#include "qemu/cutils.h"
#include "qapi/error.h"
#include "sysemu/hw_accel.h"
#include "sysemu/runstate.h"
@@ -15,6 +16,7 @@
#include "cpu-models.h"
#include "trace.h"
#include "kvm_ppc.h"
+#include "hw/ppc/fdt.h"
#include "hw/ppc/spapr_ovec.h"
#include "mmu-book3s-v3.h"
#include "hw/mem/memory-device.h"
@@ -1638,6 +1640,26 @@ static uint32_t cas_check_pvr(SpaprMachineState *spapr, PowerPCCPU *cpu,
return best_compat;
}
+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 target_ulong h_client_architecture_support(PowerPCCPU *cpu,
SpaprMachineState *spapr,
target_ulong opcode,
@@ -1645,6 +1667,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
{
/* Working address in data buffer */
target_ulong addr = ppc64_phys_to_real(args[0]);
+ target_ulong fdt_buf = args[1];
+ target_ulong fdt_bufsize = args[2];
target_ulong ov_table;
uint32_t cas_pvr;
SpaprOptionVector *ov1_guest, *ov5_guest, *ov5_cas_old, *ov5_updates;
@@ -1788,16 +1812,41 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
spapr_irq_update_active_intc(spapr);
+ if (spapr_hotplugged_dev_before_cas()) {
+ spapr->cas_reboot = true;
+ }
+
if (!spapr->cas_reboot) {
+ void *fdt;
+ SpaprDeviceTreeUpdateHeader hdr = { .version_id = 1 };
+
/* If spapr_machine_reset() did not set up a HPT but one is necessary
* (because the guest isn't going to use radix) then set it up here. */
if ((spapr->patb_entry & PATE1_GR) && !guest_radix) {
/* legacy hash or new hash: */
spapr_setup_hpt_and_vrma(spapr);
}
- spapr->cas_reboot =
- (spapr_h_cas_compose_response(spapr, args[1], args[2],
- ov5_updates) != 0);
+
+ if (fdt_bufsize < sizeof(hdr)) {
+ error_report("SLOF provided insufficient CAS buffer "
+ TARGET_FMT_lu " (min: %zu)", fdt_bufsize, sizeof(hdr));
+ exit(EXIT_FAILURE);
+ }
+
+ fdt_bufsize -= sizeof(hdr);
+
+ fdt = spapr_build_fdt(spapr, false, fdt_bufsize);
+ _FDT((fdt_pack(fdt)));
+
+ cpu_physical_memory_write(fdt_buf, &hdr, sizeof(hdr));
+ cpu_physical_memory_write(fdt_buf + 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;
}
spapr_ovec_cleanup(ov5_updates);