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 += 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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
|
@ -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/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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue