riscv: Simplify payload handling

1. Simplify payload code and convert it to C
2. Save the FDT pointer to HLS (hart-local storage).
3. Don't use mscratch to pass FDT pointer as it is used for exception handling.

Change-Id: I32bf2a99e07a65358a7f19b899259f0816eb45e8
Signed-off-by: Xiang Wang <wxjstz@126.com>
Signed-off-by: Philipp Hug <philipp@hug.cx>
Reviewed-on: https://review.coreboot.org/c/31179
Reviewed-by: ron minnich <rminnich@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Xiang Wang 2018-07-19 17:35:39 +08:00 committed by ron minnich
parent c47d43a8af
commit 820dcfceb3
10 changed files with 94 additions and 59 deletions

View File

@ -137,7 +137,7 @@ ramstage-y += misc.c
ramstage-y += smp.c
ramstage-y += boot.c
ramstage-y += tables.c
ramstage-y += payload.S
ramstage-y += payload.c
ramstage-$(ARCH_RISCV_PMP) += pmp.c
ramstage-y += \
$(top)/src/lib/memchr.c \

View File

@ -19,6 +19,7 @@
#include <arch/encoding.h>
#include <console/console.h>
#include <arch/smp/smp.h>
#include <mcall.h>
/*
* A pointer to the Flattened Device Tree passed to coreboot by the boot ROM.
@ -26,27 +27,29 @@
*
* This pointer is only used in ramstage!
*/
const void *rom_fdt;
static void do_arch_prog_run(struct prog *prog)
{
void (*doit)(void *) = prog_entry(prog);
void riscvpayload(const void *fdt, void *payload);
void (*doit)(int hart_id, void *fdt);
int hart_id;
void *fdt = prog_entry_arg(prog);
/*
* If prog_entry_arg is not set (e.g. by fit_payload), use fdt from HLS
* instead.
*/
if (fdt == NULL)
fdt = HLS()->fdt;
if (ENV_RAMSTAGE && prog_type(prog) == PROG_PAYLOAD) {
/*
* FIXME: This is wrong and will crash. Linux can't (in early
* boot) access memory that's before its own loading address.
* We need to copy the FDT to a place where Linux can access it.
*/
const void *fdt = rom_fdt;
printk(BIOS_SPEW, "FDT is at %p\n", fdt);
printk(BIOS_SPEW, "OK, let's go\n");
riscvpayload(fdt, doit);
run_payload(prog, fdt, RISCV_PAYLOAD_MODE_S);
return;
}
doit(prog_entry_arg(prog));
doit = prog_entry(prog);
hart_id = HLS()->hart_id;
doit(hart_id, fdt);
}
void arch_prog_run(struct prog *prog)

View File

@ -50,6 +50,7 @@ _start:
# initialize hart-local storage
csrr a0, mhartid
csrrw a1, mscratch, zero
call hls_init
li a0, CONFIG_RISCV_WORKING_HARTID

View File

@ -16,6 +16,12 @@
#ifndef ARCH_RISCV_INCLUDE_ARCH_BOOT_H
#define ARCH_RISCV_INCLUDE_ARCH_BOOT_H
extern const void *rom_fdt;
#include <program_loading.h>
#define RISCV_PAYLOAD_MODE_U 0
#define RISCV_PAYLOAD_MODE_S 1
#define RISCV_PAYLOAD_MODE_M 3
void run_payload(struct prog *prog, void *fdt, int payload_mode);
#endif

View File

@ -18,6 +18,7 @@
#include <main_decl.h>
void stage_entry(void) __attribute__((section(".text.stage_entry")));
void stage_entry(int hart_id, void *fdt)
__attribute__((section(".text.stage_entry")));
#endif

View File

@ -52,9 +52,14 @@ typedef struct {
int ipi_pending;
uint64_t *timecmp;
uint64_t *time;
void *fdt;
struct blocker entry;
} hls_t;
_Static_assert(
sizeof(hls_t) == HLS_SIZE,
"HLS_SIZE must equal to sizeof(hls_t)");
#define MACHINE_STACK_TOP() ({ \
/* coverity[uninit_use] : FALSE */ \
register uintptr_t sp asm ("sp"); \
@ -66,7 +71,8 @@ typedef struct {
#define MACHINE_STACK_SIZE RISCV_PGSIZE
void hls_init(uint32_t hart_id); // need to call this before launching linux
// need to call this before launching linux
void hls_init(uint32_t hart_id, void *fdt);
/* This function is used to initialize HLS()->time/HLS()->timecmp */
void mtime_init(void);

View File

@ -34,10 +34,11 @@
int mcalldebug; // set this interactively for copious debug.
void hls_init(uint32_t hart_id)
void hls_init(uint32_t hart_id, void *fdt)
{
printk(BIOS_SPEW, "hart %d: HLS is %p\n", hart_id, HLS());
memset(HLS(), 0, sizeof(*HLS()));
HLS()->fdt = fdt;
HLS()->hart_id = hart_id;
mtime_init();

View File

@ -1,35 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2016 Google Inc
* Copyright (C) 2018 Jonathan Neuschäfer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
// "return" to a payload. a0: FDT, a1: entry point
.global riscvpayload
riscvpayload:
/* Load the entry point */
mv t0, a1
csrw mepc, t0
csrr t0, mstatus
/* Set mstatus.MPP (the previous privilege mode) to supervisor mode */
li t1, ~(3<<11)
and t0, t0, t1
li t2, (1<<11)
or t0, t0, t2
csrw mstatus, t0
/* Pass the right arguments and jump! */
mv a1, a0
csrr a0, mhartid
mret

51
src/arch/riscv/payload.c Normal file
View File

@ -0,0 +1,51 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2016 Google Inc
* Copyright (C) 2018 HardenedLinux
* Copyright (C) 2018 Jonathan Neuschäfer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdint.h>
#include <arch/boot.h>
#include <arch/encoding.h>
#include <console/console.h>
void run_payload(struct prog *prog, void *fdt, int payload_mode)
{
void (*doit)(int hart_id, void *fdt) = prog_entry(prog);
int hart_id = read_csr(mhartid);
uintptr_t status = read_csr(mstatus);
status &= ~MSTATUS_MPIE;
status &= ~MSTATUS_MPP;
switch (payload_mode) {
case RISCV_PAYLOAD_MODE_U:
break;
case RISCV_PAYLOAD_MODE_S:
status |= MSTATUS_SPP;
break;
case RISCV_PAYLOAD_MODE_M:
doit(hart_id, fdt);
return;
default:
die("wrong privilege level for payload");
break;
}
write_csr(mstatus, status);
write_csr(mepc, doit);
asm volatile(
"mv a0, %0\n\t"
"mv a1, %0\n\t"
"mret" ::"r"(hart_id),
"r"(fdt)
: "a0", "a1");
}

View File

@ -28,18 +28,19 @@
#include <arch/encoding.h>
#include <arch/stages.h>
#include <arch/smp/smp.h>
#include <rules.h>
#include <mcall.h>
void stage_entry(void)
void stage_entry(int hart_id, void *fdt)
{
smp_pause(CONFIG_RISCV_WORKING_HARTID);
/*
* Save the FDT pointer before entering ramstage, because mscratch
* might be overwritten in the trap handler, and there is code in
* ramstage that generates misaligned access faults.
*/
if (ENV_RAMSTAGE)
rom_fdt = (const void *)read_csr(mscratch);
HLS()->hart_id = hart_id;
HLS()->fdt = fdt;
smp_pause(CONFIG_RISCV_WORKING_HARTID);
main();
}