|
|
a19a21 |
From 04f7fe2423a4de8d2fea7068b3fb316e15e76eaa Mon Sep 17 00:00:00 2001
|
|
|
a19a21 |
From: Greg Kurz <gkurz@redhat.com>
|
|
|
a19a21 |
Date: Tue, 19 Jan 2021 15:09:49 -0500
|
|
|
a19a21 |
Subject: [PATCH 1/9] spapr: Improve handling of fdt buffer size
|
|
|
a19a21 |
|
|
|
a19a21 |
RH-Author: Greg Kurz <gkurz@redhat.com>
|
|
|
a19a21 |
Message-id: <20210119150954.1017058-2-gkurz@redhat.com>
|
|
|
a19a21 |
Patchwork-id: 100682
|
|
|
a19a21 |
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 1/6] spapr: Improve handling of fdt buffer size
|
|
|
a19a21 |
Bugzilla: 1901837
|
|
|
a19a21 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
a19a21 |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
a19a21 |
RH-Acked-by: David Gibson <dgibson@redhat.com>
|
|
|
a19a21 |
|
|
|
a19a21 |
From: David Gibson <david@gibson.dropbear.id.au>
|
|
|
a19a21 |
|
|
|
a19a21 |
Previously, spapr_build_fdt() constructed the device tree in a fixed
|
|
|
a19a21 |
buffer of size FDT_MAX_SIZE. This is a bit inflexible, but more
|
|
|
a19a21 |
importantly it's awkward for the case where we use it during CAS. In
|
|
|
a19a21 |
that case the guest firmware supplies a buffer and we have to
|
|
|
a19a21 |
awkwardly check that what we generated fits into it afterwards, after
|
|
|
a19a21 |
doing a lot of size checks during spapr_build_fdt().
|
|
|
a19a21 |
|
|
|
a19a21 |
Simplify this by having spapr_build_fdt() take a 'space' parameter.
|
|
|
a19a21 |
For the CAS case, we pass in the buffer size provided by SLOF, for the
|
|
|
a19a21 |
machine init case, we continue to pass FDT_MAX_SIZE.
|
|
|
a19a21 |
|
|
|
a19a21 |
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
|
a19a21 |
Reviewed-by: Cedric Le Goater <clg@fr.ibm.com>
|
|
|
a19a21 |
Reviewed-by: Greg Kurz <groug@kaod.org>
|
|
|
a19a21 |
(cherry picked from commit 97b32a6afa78ae68fb16344b9a144b6f433f42a2)
|
|
|
a19a21 |
Signed-off-by: Greg Kurz <gkurz@redhat.com>
|
|
|
a19a21 |
Signed-off-by: Jon Maloy <jmaloy.redhat.com>
|
|
|
a19a21 |
---
|
|
|
a19a21 |
hw/ppc/spapr.c | 33 +++++++++++----------------------
|
|
|
a19a21 |
1 file changed, 11 insertions(+), 22 deletions(-)
|
|
|
a19a21 |
|
|
|
a19a21 |
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
|
|
|
a19a21 |
index c74079702d..92f63ad035 100644
|
|
|
a19a21 |
--- a/hw/ppc/spapr.c
|
|
|
a19a21 |
+++ b/hw/ppc/spapr.c
|
|
|
a19a21 |
@@ -918,7 +918,8 @@ static bool spapr_hotplugged_dev_before_cas(void)
|
|
|
a19a21 |
return false;
|
|
|
a19a21 |
}
|
|
|
a19a21 |
|
|
|
a19a21 |
-static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset);
|
|
|
a19a21 |
+static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset,
|
|
|
a19a21 |
+ size_t space);
|
|
|
a19a21 |
|
|
|
a19a21 |
int spapr_h_cas_compose_response(SpaprMachineState *spapr,
|
|
|
a19a21 |
target_ulong addr, target_ulong size,
|
|
|
a19a21 |
@@ -931,24 +932,17 @@ int spapr_h_cas_compose_response(SpaprMachineState *spapr,
|
|
|
a19a21 |
return 1;
|
|
|
a19a21 |
}
|
|
|
a19a21 |
|
|
|
a19a21 |
- if (size < sizeof(hdr) || size > FW_MAX_SIZE) {
|
|
|
a19a21 |
- error_report("SLOF provided an unexpected CAS buffer size "
|
|
|
a19a21 |
- TARGET_FMT_lu " (min: %zu, max: %u)",
|
|
|
a19a21 |
- size, sizeof(hdr), FW_MAX_SIZE);
|
|
|
a19a21 |
+ if (size < sizeof(hdr)) {
|
|
|
a19a21 |
+ error_report("SLOF provided insufficient CAS buffer "
|
|
|
a19a21 |
+ TARGET_FMT_lu " (min: %zu)", size, sizeof(hdr));
|
|
|
a19a21 |
exit(EXIT_FAILURE);
|
|
|
a19a21 |
}
|
|
|
a19a21 |
|
|
|
a19a21 |
size -= sizeof(hdr);
|
|
|
a19a21 |
|
|
|
a19a21 |
- fdt = spapr_build_fdt(spapr, false);
|
|
|
a19a21 |
+ fdt = spapr_build_fdt(spapr, false, size);
|
|
|
a19a21 |
_FDT((fdt_pack(fdt)));
|
|
|
a19a21 |
|
|
|
a19a21 |
- if (fdt_totalsize(fdt) + sizeof(hdr) > size) {
|
|
|
a19a21 |
- g_free(fdt);
|
|
|
a19a21 |
- trace_spapr_cas_failed(size);
|
|
|
a19a21 |
- return -1;
|
|
|
a19a21 |
- }
|
|
|
a19a21 |
-
|
|
|
a19a21 |
cpu_physical_memory_write(addr, &hdr, sizeof(hdr));
|
|
|
a19a21 |
cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt));
|
|
|
a19a21 |
trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr));
|
|
|
a19a21 |
@@ -1198,7 +1192,8 @@ static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt)
|
|
|
a19a21 |
}
|
|
|
a19a21 |
}
|
|
|
a19a21 |
|
|
|
a19a21 |
-static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset)
|
|
|
a19a21 |
+static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset,
|
|
|
a19a21 |
+ size_t space)
|
|
|
a19a21 |
{
|
|
|
a19a21 |
MachineState *machine = MACHINE(spapr);
|
|
|
a19a21 |
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
|
|
a19a21 |
@@ -1208,8 +1203,8 @@ static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset)
|
|
|
a19a21 |
SpaprPhbState *phb;
|
|
|
a19a21 |
char *buf;
|
|
|
a19a21 |
|
|
|
a19a21 |
- fdt = g_malloc0(FDT_MAX_SIZE);
|
|
|
a19a21 |
- _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
|
|
|
a19a21 |
+ fdt = g_malloc0(space);
|
|
|
a19a21 |
+ _FDT((fdt_create_empty_tree(fdt, space)));
|
|
|
a19a21 |
|
|
|
a19a21 |
/* Root node */
|
|
|
a19a21 |
_FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp"));
|
|
|
a19a21 |
@@ -1724,19 +1719,13 @@ static void spapr_machine_reset(MachineState *machine)
|
|
|
a19a21 |
*/
|
|
|
a19a21 |
fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE;
|
|
|
a19a21 |
|
|
|
a19a21 |
- fdt = spapr_build_fdt(spapr, true);
|
|
|
a19a21 |
+ fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE);
|
|
|
a19a21 |
|
|
|
a19a21 |
rc = fdt_pack(fdt);
|
|
|
a19a21 |
|
|
|
a19a21 |
/* Should only fail if we've built a corrupted tree */
|
|
|
a19a21 |
assert(rc == 0);
|
|
|
a19a21 |
|
|
|
a19a21 |
- if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
|
|
|
a19a21 |
- error_report("FDT too big ! 0x%x bytes (max is 0x%x)",
|
|
|
a19a21 |
- fdt_totalsize(fdt), FDT_MAX_SIZE);
|
|
|
a19a21 |
- exit(1);
|
|
|
a19a21 |
- }
|
|
|
a19a21 |
-
|
|
|
a19a21 |
/* Load the fdt */
|
|
|
a19a21 |
qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
|
|
|
a19a21 |
cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
|
|
|
a19a21 |
--
|
|
|
a19a21 |
2.18.2
|
|
|
a19a21 |
|