Skip to content

Commit

Permalink
spapr: Fix implementation of Open Firmware client interface
Browse files Browse the repository at this point in the history
This addresses the comments from v22.

The functional changes are (the VOF ones need retesting with Pegasos2):

(VOF) setprop will start failing if the machine class callback
did not handle it;
(VOF) unit addresses are lowered in path_offset();
(SPAPR) /chosen/bootargs is initialized from kernel_cmdline if
the client did not change it.

Fixes: 5c991e5 ("spapr: Implement Open Firmware client interface")
Cc: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Message-Id: <20210708065625.548396-1-aik@ozlabs.ru>
Tested-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
  • Loading branch information
aik authored and dgibson committed Jul 9, 2021
1 parent 89bb5a4 commit 21bde1e
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 68 deletions.
4 changes: 2 additions & 2 deletions MAINTAINERS
Expand Up @@ -1362,8 +1362,8 @@ F: include/hw/pci-host/mv64361.h

Virtual Open Firmware (VOF)
M: Alexey Kardashevskiy <aik@ozlabs.ru>
M: David Gibson <david@gibson.dropbear.id.au>
M: Greg Kurz <groug@kaod.org>
R: David Gibson <david@gibson.dropbear.id.au>
R: Greg Kurz <groug@kaod.org>
L: qemu-ppc@nongnu.org
S: Maintained
F: hw/ppc/spapr_vof*
Expand Down
10 changes: 1 addition & 9 deletions hw/ppc/spapr.c
Expand Up @@ -1645,15 +1645,7 @@ static void spapr_machine_reset(MachineState *machine)

fdt = spapr_build_fdt(spapr, true, FDT_MAX_SIZE);
if (spapr->vof) {
target_ulong stack_ptr = 0;

spapr_vof_reset(spapr, fdt, &stack_ptr, &error_fatal);

spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT,
stack_ptr, spapr->initrd_base,
spapr->initrd_size);
/* VOF is 32bit BE so enforce MSR here */
first_ppc_cpu->env.msr &= ~((1ULL << MSR_SF) | (1ULL << MSR_LE));
spapr_vof_reset(spapr, fdt, &error_fatal);
/*
* Do not pack the FDT as the client may change properties.
* VOF client does not expect the FDT so we do not load it to the VM.
Expand Down
5 changes: 2 additions & 3 deletions hw/ppc/spapr_hcall.c
Expand Up @@ -1080,7 +1080,7 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu,
SpaprOptionVector *ov1_guest, *ov5_guest;
bool guest_radix;
bool raw_mode_supported = false;
bool guest_xive, reset_fdt = false;
bool guest_xive;
CPUState *cs;
void *fdt;
uint32_t max_compat = spapr->max_compat_pvr;
Expand Down Expand Up @@ -1233,8 +1233,7 @@ target_ulong do_client_architecture_support(PowerPCCPU *cpu,
spapr_setup_hpt(spapr);
}

reset_fdt = spapr->vof != NULL;
fdt = spapr_build_fdt(spapr, reset_fdt, fdt_bufsize);
fdt = spapr_build_fdt(spapr, spapr->vof != NULL, fdt_bufsize);
g_free(spapr->fdt_blob);
spapr->fdt_size = fdt_totalsize(fdt);
spapr->fdt_initial_size = spapr->fdt_size;
Expand Down
32 changes: 23 additions & 9 deletions hw/ppc/spapr_vof.c
Expand Up @@ -8,6 +8,7 @@
#include "qapi/error.h"
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
#include "hw/ppc/spapr_cpu_core.h"
#include "hw/ppc/fdt.h"
#include "hw/ppc/vof.h"
#include "sysemu/sysemu.h"
Expand All @@ -29,13 +30,19 @@ target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr,
void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt)
{
char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
int chosen;

vof_build_dt(fdt, spapr->vof);

_FDT(chosen = fdt_path_offset(fdt, "/chosen"));
_FDT(fdt_setprop_string(fdt, chosen, "bootargs",
spapr->vof->bootargs ? : ""));
if (spapr->vof->bootargs) {
int chosen;

_FDT(chosen = fdt_path_offset(fdt, "/chosen"));
/*
* If the client did not change "bootargs", spapr_dt_chosen() must have
* stored machine->kernel_cmdline in it before getting here.
*/
_FDT(fdt_setprop_string(fdt, chosen, "bootargs", spapr->vof->bootargs));
}

/*
* SLOF-less setup requires an open instance of stdout for early
Expand All @@ -48,20 +55,21 @@ void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt)
}
}

void spapr_vof_reset(SpaprMachineState *spapr, void *fdt,
target_ulong *stack_ptr, Error **errp)
void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp)
{
target_ulong stack_ptr;
Vof *vof = spapr->vof;
PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);

vof_init(vof, spapr->rma_size, errp);

*stack_ptr = vof_claim(vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE);
if (*stack_ptr == -1) {
stack_ptr = vof_claim(vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE);
if (stack_ptr == -1) {
error_setg(errp, "Memory allocation for stack failed");
return;
}
/* Stack grows downwards plus reserve space for the minimum stack frame */
*stack_ptr += VOF_STACK_SIZE - 0x20;
stack_ptr += VOF_STACK_SIZE - 0x20;

if (spapr->kernel_size &&
vof_claim(vof, spapr->kernel_addr, spapr->kernel_size, 0) == -1) {
Expand All @@ -77,6 +85,12 @@ void spapr_vof_reset(SpaprMachineState *spapr, void *fdt,

spapr_vof_client_dt_finalize(spapr, fdt);

spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT,
stack_ptr, spapr->initrd_base,
spapr->initrd_size);
/* VOF is 32bit BE so enforce MSR here */
first_ppc_cpu->env.msr &= ~((1ULL << MSR_SF) | (1ULL << MSR_LE));

/*
* At this point the expected allocation map is:
*
Expand Down
30 changes: 17 additions & 13 deletions hw/ppc/vof.c
Expand Up @@ -144,15 +144,16 @@ static int path_offset(const void *fdt, const char *path)
* the lower case forms of the hexadecimal digits in the range a..f,
* suppressing leading zeros".
*/
at = strchr(path, '@');
if (!at) {
return fdt_path_offset(fdt, path);
}

p = g_strdup(path);
for (at = at - path + p + 1; *at; ++at) {
*at = tolower(*at);
for (at = strchr(p, '@'); at && *at; ) {
if (*at == '/') {
at = strchr(at, '@');
} else {
*at = tolower(*at);
++at;
}
}

return fdt_path_offset(fdt, p);
}

Expand Down Expand Up @@ -300,6 +301,7 @@ static uint32_t vof_setprop(MachineState *ms, void *fdt, Vof *vof,
char trval[64] = "";
char nodepath[VOF_MAX_PATH] = "";
Object *vmo = object_dynamic_cast(OBJECT(ms), TYPE_VOF_MACHINE_IF);
VofMachineIfClass *vmc;
g_autofree char *val = NULL;

if (vallen > VOF_MAX_SETPROPLEN) {
Expand All @@ -322,13 +324,13 @@ static uint32_t vof_setprop(MachineState *ms, void *fdt, Vof *vof,
goto trace_exit;
}

if (vmo) {
VofMachineIfClass *vmc = VOF_MACHINE_GET_CLASS(vmo);
if (!vmo) {
goto trace_exit;
}

if (vmc->setprop &&
!vmc->setprop(ms, nodepath, propname, val, vallen)) {
goto trace_exit;
}
vmc = VOF_MACHINE_GET_CLASS(vmo);
if (!vmc->setprop || !vmc->setprop(ms, nodepath, propname, val, vallen)) {
goto trace_exit;
}

ret = fdt_setprop(fdt, offset, propname, val, vallen);
Expand Down Expand Up @@ -919,6 +921,8 @@ static uint32_t vof_client_handle(MachineState *ms, void *fdt, Vof *vof,
ret = -1;
}

#undef cmpserv

return ret;
}

Expand Down
3 changes: 1 addition & 2 deletions include/hw/ppc/spapr.h
Expand Up @@ -964,8 +964,7 @@ void spapr_set_all_lpcrs(target_ulong value, target_ulong mask);
hwaddr spapr_get_rtas_addr(void);
bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr);

void spapr_vof_reset(SpaprMachineState *spapr, void *fdt,
target_ulong *stack_ptr, Error **errp);
void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp);
void spapr_vof_quiesce(MachineState *ms);
bool spapr_vof_setprop(MachineState *ms, const char *path, const char *propname,
void *val, int vallen);
Expand Down
Binary file modified pc-bios/vof.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion pc-bios/vof/ci.c
Expand Up @@ -69,7 +69,7 @@ static int call_ci(const char *service, int nargs, int nret, ...)
}

if (ci_entry((uint32_t)(&args)) < 0) {
return PROM_ERROR;
return -1;
}

return (nret > 0) ? args.args[nargs] : 0;
Expand Down
26 changes: 0 additions & 26 deletions pc-bios/vof/libc.c
Expand Up @@ -54,32 +54,6 @@ int memcmp(const void *ptr1, const void *ptr2, size_t n)
return 0;
}

void *memmove(void *dest, const void *src, size_t n)
{
char *cdest;
const char *csrc;
int i;

/* Do the buffers overlap in a bad way? */
if (src < dest && src + n >= dest) {
/* Copy from end to start */
cdest = dest + n - 1;
csrc = src + n - 1;
for (i = 0; i < n; i++) {
*cdest-- = *csrc--;
}
} else {
/* Normal copy is possible */
cdest = dest;
csrc = src;
for (i = 0; i < n; i++) {
*cdest++ = *csrc++;
}
}

return dest;
}

void *memset(void *dest, int c, size_t size)
{
unsigned char *d = (unsigned char *)dest;
Expand Down
2 changes: 1 addition & 1 deletion pc-bios/vof/main.c
Expand Up @@ -6,7 +6,7 @@ void do_boot(unsigned long addr, unsigned long _r3, unsigned long _r4)
register unsigned long r4 __asm__("r4") = _r4;
register unsigned long r5 __asm__("r5") = (unsigned long) _prom_entry;

((client *)(uint32_t)addr)();
((void (*)(void))(uint32_t)addr)();
}

void entry_c(void)
Expand Down
2 changes: 0 additions & 2 deletions pc-bios/vof/vof.h
Expand Up @@ -10,11 +10,9 @@ typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;
#define NULL (0)
#define PROM_ERROR (-1u)
typedef unsigned long ihandle;
typedef unsigned long phandle;
typedef int size_t;
typedef void client(void);

/* globals */
extern void _prom_entry(void); /* OF CI entry point (i.e. this firmware) */
Expand Down

0 comments on commit 21bde1e

Please sign in to comment.