Message ID | 20191129053356.232413-3-david@gibson.dropbear.id.au |
---|---|
State | New |
Headers | show |
Series | spapr: Improvements to CAS feature negotiation | expand |
On 29/11/2019 06:33, David Gibson wrote: > Previously, spapr_build_fdt() constructed the device tree in a fixed > buffer of size FDT_MAX_SIZE. This is a bit inflexible, but more > importantly it's awkward for the case where we use it during CAS. In > that case the guest firmware supplies a buffer and we have to > awkwardly check that what we generated fits into it afterwards, after > doing a lot of size checks during spapr_build_fdt(). > > Simplify this by having spapr_build_fdt() take a 'space' parameter. > For the CAS case, we pass in the buffer size provided by SLOF, for the > machine init case, we continue to pass FDT_MAX_SIZE. > > Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Cedric Le Goater <clg@fr.ibm.com> > --- > hw/ppc/spapr.c | 33 +++++++++++---------------------- > 1 file changed, 11 insertions(+), 22 deletions(-) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index d9c9a2bcee..d34e317f48 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -917,7 +917,8 @@ static bool spapr_hotplugged_dev_before_cas(void) > return false; > } > > -static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset); > +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, > @@ -930,24 +931,17 @@ int spapr_h_cas_compose_response(SpaprMachineState *spapr, > 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); > + 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); > + fdt = spapr_build_fdt(spapr, false, size); > _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)); > @@ -1197,7 +1191,8 @@ static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) > } > } > > -static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset) > +static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, > + size_t space) > { > MachineState *machine = MACHINE(spapr); > MachineClass *mc = MACHINE_GET_CLASS(machine); > @@ -1207,8 +1202,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 +1718,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)); >
On Fri, 29 Nov 2019 16:33:54 +1100 David Gibson <david@gibson.dropbear.id.au> wrote: > Previously, spapr_build_fdt() constructed the device tree in a fixed > buffer of size FDT_MAX_SIZE. This is a bit inflexible, but more > importantly it's awkward for the case where we use it during CAS. In > that case the guest firmware supplies a buffer and we have to > awkwardly check that what we generated fits into it afterwards, after > doing a lot of size checks during spapr_build_fdt(). > > Simplify this by having spapr_build_fdt() take a 'space' parameter. > For the CAS case, we pass in the buffer size provided by SLOF, for the > machine init case, we continue to pass FDT_MAX_SIZE. > > Signed-off-by: David Gibson <david@gibson.dropbear.id.au> > --- Reviewed-by: Greg Kurz <groug@kaod.org> > hw/ppc/spapr.c | 33 +++++++++++---------------------- > 1 file changed, 11 insertions(+), 22 deletions(-) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index d9c9a2bcee..d34e317f48 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -917,7 +917,8 @@ static bool spapr_hotplugged_dev_before_cas(void) > return false; > } > > -static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset); > +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, > @@ -930,24 +931,17 @@ int spapr_h_cas_compose_response(SpaprMachineState *spapr, > 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); > + 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); > + fdt = spapr_build_fdt(spapr, false, size); > _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)); > @@ -1197,7 +1191,8 @@ static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) > } > } > > -static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset) > +static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, > + size_t space) > { > MachineState *machine = MACHINE(spapr); > MachineClass *mc = MACHINE_GET_CLASS(machine); > @@ -1207,8 +1202,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 +1718,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));
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d9c9a2bcee..d34e317f48 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -917,7 +917,8 @@ static bool spapr_hotplugged_dev_before_cas(void) return false; } -static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset); +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, @@ -930,24 +931,17 @@ int spapr_h_cas_compose_response(SpaprMachineState *spapr, 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); + 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); + fdt = spapr_build_fdt(spapr, false, size); _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)); @@ -1197,7 +1191,8 @@ static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt) } } -static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset) +static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, + size_t space) { MachineState *machine = MACHINE(spapr); MachineClass *mc = MACHINE_GET_CLASS(machine); @@ -1207,8 +1202,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 +1718,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));
Previously, spapr_build_fdt() constructed the device tree in a fixed buffer of size FDT_MAX_SIZE. This is a bit inflexible, but more importantly it's awkward for the case where we use it during CAS. In that case the guest firmware supplies a buffer and we have to awkwardly check that what we generated fits into it afterwards, after doing a lot of size checks during spapr_build_fdt(). Simplify this by having spapr_build_fdt() take a 'space' parameter. For the CAS case, we pass in the buffer size provided by SLOF, for the machine init case, we continue to pass FDT_MAX_SIZE. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> --- hw/ppc/spapr.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-)