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:
parent
c47d43a8af
commit
820dcfceb3
@ -137,7 +137,7 @@ ramstage-y += misc.c
|
|||||||
ramstage-y += smp.c
|
ramstage-y += smp.c
|
||||||
ramstage-y += boot.c
|
ramstage-y += boot.c
|
||||||
ramstage-y += tables.c
|
ramstage-y += tables.c
|
||||||
ramstage-y += payload.S
|
ramstage-y += payload.c
|
||||||
ramstage-$(ARCH_RISCV_PMP) += pmp.c
|
ramstage-$(ARCH_RISCV_PMP) += pmp.c
|
||||||
ramstage-y += \
|
ramstage-y += \
|
||||||
$(top)/src/lib/memchr.c \
|
$(top)/src/lib/memchr.c \
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <arch/encoding.h>
|
#include <arch/encoding.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <arch/smp/smp.h>
|
#include <arch/smp/smp.h>
|
||||||
|
#include <mcall.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A pointer to the Flattened Device Tree passed to coreboot by the boot ROM.
|
* 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!
|
* This pointer is only used in ramstage!
|
||||||
*/
|
*/
|
||||||
const void *rom_fdt;
|
|
||||||
|
|
||||||
static void do_arch_prog_run(struct prog *prog)
|
static void do_arch_prog_run(struct prog *prog)
|
||||||
{
|
{
|
||||||
void (*doit)(void *) = prog_entry(prog);
|
void (*doit)(int hart_id, void *fdt);
|
||||||
void riscvpayload(const void *fdt, void *payload);
|
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) {
|
if (ENV_RAMSTAGE && prog_type(prog) == PROG_PAYLOAD) {
|
||||||
/*
|
run_payload(prog, fdt, RISCV_PAYLOAD_MODE_S);
|
||||||
* FIXME: This is wrong and will crash. Linux can't (in early
|
return;
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
void arch_prog_run(struct prog *prog)
|
||||||
|
@ -50,6 +50,7 @@ _start:
|
|||||||
|
|
||||||
# initialize hart-local storage
|
# initialize hart-local storage
|
||||||
csrr a0, mhartid
|
csrr a0, mhartid
|
||||||
|
csrrw a1, mscratch, zero
|
||||||
call hls_init
|
call hls_init
|
||||||
|
|
||||||
li a0, CONFIG_RISCV_WORKING_HARTID
|
li a0, CONFIG_RISCV_WORKING_HARTID
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
#ifndef ARCH_RISCV_INCLUDE_ARCH_BOOT_H
|
#ifndef ARCH_RISCV_INCLUDE_ARCH_BOOT_H
|
||||||
#define 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
|
#endif
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <main_decl.h>
|
#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
|
#endif
|
||||||
|
@ -52,9 +52,14 @@ typedef struct {
|
|||||||
int ipi_pending;
|
int ipi_pending;
|
||||||
uint64_t *timecmp;
|
uint64_t *timecmp;
|
||||||
uint64_t *time;
|
uint64_t *time;
|
||||||
|
void *fdt;
|
||||||
struct blocker entry;
|
struct blocker entry;
|
||||||
} hls_t;
|
} hls_t;
|
||||||
|
|
||||||
|
_Static_assert(
|
||||||
|
sizeof(hls_t) == HLS_SIZE,
|
||||||
|
"HLS_SIZE must equal to sizeof(hls_t)");
|
||||||
|
|
||||||
#define MACHINE_STACK_TOP() ({ \
|
#define MACHINE_STACK_TOP() ({ \
|
||||||
/* coverity[uninit_use] : FALSE */ \
|
/* coverity[uninit_use] : FALSE */ \
|
||||||
register uintptr_t sp asm ("sp"); \
|
register uintptr_t sp asm ("sp"); \
|
||||||
@ -66,7 +71,8 @@ typedef struct {
|
|||||||
|
|
||||||
#define MACHINE_STACK_SIZE RISCV_PGSIZE
|
#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 */
|
/* This function is used to initialize HLS()->time/HLS()->timecmp */
|
||||||
void mtime_init(void);
|
void mtime_init(void);
|
||||||
|
@ -34,10 +34,11 @@
|
|||||||
|
|
||||||
int mcalldebug; // set this interactively for copious debug.
|
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());
|
printk(BIOS_SPEW, "hart %d: HLS is %p\n", hart_id, HLS());
|
||||||
memset(HLS(), 0, sizeof(*HLS()));
|
memset(HLS(), 0, sizeof(*HLS()));
|
||||||
|
HLS()->fdt = fdt;
|
||||||
HLS()->hart_id = hart_id;
|
HLS()->hart_id = hart_id;
|
||||||
|
|
||||||
mtime_init();
|
mtime_init();
|
||||||
|
@ -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
51
src/arch/riscv/payload.c
Normal 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");
|
||||||
|
}
|
@ -28,18 +28,19 @@
|
|||||||
#include <arch/encoding.h>
|
#include <arch/encoding.h>
|
||||||
#include <arch/stages.h>
|
#include <arch/stages.h>
|
||||||
#include <arch/smp/smp.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
|
* Save the FDT pointer before entering ramstage, because mscratch
|
||||||
* might be overwritten in the trap handler, and there is code in
|
* might be overwritten in the trap handler, and there is code in
|
||||||
* ramstage that generates misaligned access faults.
|
* ramstage that generates misaligned access faults.
|
||||||
*/
|
*/
|
||||||
if (ENV_RAMSTAGE)
|
HLS()->hart_id = hart_id;
|
||||||
rom_fdt = (const void *)read_csr(mscratch);
|
HLS()->fdt = fdt;
|
||||||
|
smp_pause(CONFIG_RISCV_WORKING_HARTID);
|
||||||
|
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user