Skip to content

Commit

Permalink
spapr: Add /chosen to FDT only at reset time to preserve kernel and i…
Browse files Browse the repository at this point in the history
…nitramdisk

Since "spapr: Render full FDT on ibm,client-architecture-support" we build
the entire flatten device tree (FDT) twice - at the reset time and
when "ibm,client-architecture-support" (CAS) is called. The full FDT from
CAS is then applied on top of the SLOF internal device tree.

This is mostly ok, however there is a case when the QEMU is started with
-initrd and for some reason the guest decided to move/unpack the init RAM
disk image - the guest correctly notifies SLOF about the change but
at CAS it is overridden with the QEMU initial location addresses and
the guest may fail to boot if the original initrd memory was changed.

This fixes the problem by only adding the /chosen node at the reset time
to prevent the original QEMU's linux,initrd-start/linux,initrd-end to
override the updated addresses.

This only treats /chosen differently as we know there is a special case
already and it is unlikely anything else will need to change /chosen at CAS
we are better off not touching /chosen after we handed it over to SLOF.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20191024041308.5673-1-aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
  • Loading branch information
aik authored and vivier committed Nov 18, 2019
1 parent 0a83b47 commit a49f62b
Showing 1 changed file with 15 additions and 10 deletions.
25 changes: 15 additions & 10 deletions hw/ppc/spapr.c
Expand Up @@ -917,7 +917,7 @@ static bool spapr_hotplugged_dev_before_cas(void)
return false;
}

static void *spapr_build_fdt(SpaprMachineState *spapr);
static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset);

int spapr_h_cas_compose_response(SpaprMachineState *spapr,
target_ulong addr, target_ulong size,
Expand All @@ -939,7 +939,7 @@ int spapr_h_cas_compose_response(SpaprMachineState *spapr,

size -= sizeof(hdr);

fdt = spapr_build_fdt(spapr);
fdt = spapr_build_fdt(spapr, false);
_FDT((fdt_pack(fdt)));

if (fdt_totalsize(fdt) + sizeof(hdr) > size) {
Expand Down Expand Up @@ -1197,7 +1197,7 @@ static void spapr_dt_hypervisor(SpaprMachineState *spapr, void *fdt)
}
}

static void *spapr_build_fdt(SpaprMachineState *spapr)
static void *spapr_build_fdt(SpaprMachineState *spapr, bool reset)
{
MachineState *machine = MACHINE(spapr);
MachineClass *mc = MACHINE_GET_CLASS(machine);
Expand Down Expand Up @@ -1297,19 +1297,24 @@ static void *spapr_build_fdt(SpaprMachineState *spapr)
spapr_dt_rtas(spapr, fdt);

/* /chosen */
spapr_dt_chosen(spapr, fdt);
if (reset) {
spapr_dt_chosen(spapr, fdt);
}

/* /hypervisor */
if (kvm_enabled()) {
spapr_dt_hypervisor(spapr, fdt);
}

/* Build memory reserve map */
if (spapr->kernel_size) {
_FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
}
if (spapr->initrd_size) {
_FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size)));
if (reset) {
if (spapr->kernel_size) {
_FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
}
if (spapr->initrd_size) {
_FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base,
spapr->initrd_size)));
}
}

/* ibm,client-architecture-support updates */
Expand Down Expand Up @@ -1718,7 +1723,7 @@ static void spapr_machine_reset(MachineState *machine)
*/
fdt_addr = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FDT_MAX_SIZE;

fdt = spapr_build_fdt(spapr);
fdt = spapr_build_fdt(spapr, true);

rc = fdt_pack(fdt);

Expand Down

0 comments on commit a49f62b

Please sign in to comment.