When we get booted we want a clear slate without any leaks from previous supervisors or the firmware. Flush the instruction cache and then clear all registers to known good values. This is really important for the upcoming nommu support that runs on M-mode, but can't really harm when running in S-mode either. Vaguely based on the concepts from opensbi.
Signed-off-by: Christoph Hellwig <h...@lst.de> --- arch/riscv/include/asm/csr.h | 1 + arch/riscv/kernel/head.S | 88 +++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index d0b5113e1a54..ee0101278608 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -83,6 +83,7 @@ /* symbolic CSR names: */ #define CSR_MHARTID 0xf14 #define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 #define CSR_MIE 0x304 #define CSR_MTVEC 0x305 #define CSR_MSCRATCH 0x340 diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index 583784cb3a32..25867b99cc95 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -11,6 +11,7 @@ #include <asm/thread_info.h> #include <asm/page.h> #include <asm/csr.h> +#include <asm/hwcap.h> #include <asm/image.h> __INIT @@ -51,12 +52,18 @@ _start_kernel: csrw CSR_XIP, zero #ifdef CONFIG_RISCV_M_MODE + /* flush the instruction cache */ + fence.i + + /* Reset all registers except ra, a0, a1 */ + call reset_regs + /* * The hartid in a0 is expected later on, and we have no firmware * to hand it to us. */ csrr a0, CSR_MHARTID -#endif +#endif /* CONFIG_RISCV_M_MODE */ /* Load the global pointer */ .option push @@ -203,6 +210,85 @@ relocate: j .Lsecondary_park END(_start) +#ifdef CONFIG_RISCV_M_MODE +ENTRY(reset_regs) + li sp, 0 + li gp, 0 + li tp, 0 + li t0, 0 + li t1, 0 + li t2, 0 + li s0, 0 + li s1, 0 + li a2, 0 + li a3, 0 + li a4, 0 + li a5, 0 + li a6, 0 + li a7, 0 + li s2, 0 + li s3, 0 + li s4, 0 + li s5, 0 + li s6, 0 + li s7, 0 + li s8, 0 + li s9, 0 + li s10, 0 + li s11, 0 + li t3, 0 + li t4, 0 + li t5, 0 + li t6, 0 + csrw sscratch, 0 + +#ifdef CONFIG_FPU + csrr t0, CSR_MISA + andi t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D) + bnez t0, .Lreset_regs_done + + li t1, SR_FS + csrs CSR_XSTATUS, t1 + fmv.s.x f0, zero + fmv.s.x f1, zero + fmv.s.x f2, zero + fmv.s.x f3, zero + fmv.s.x f4, zero + fmv.s.x f5, zero + fmv.s.x f6, zero + fmv.s.x f7, zero + fmv.s.x f8, zero + fmv.s.x f9, zero + fmv.s.x f10, zero + fmv.s.x f11, zero + fmv.s.x f12, zero + fmv.s.x f13, zero + fmv.s.x f14, zero + fmv.s.x f15, zero + fmv.s.x f16, zero + fmv.s.x f17, zero + fmv.s.x f18, zero + fmv.s.x f19, zero + fmv.s.x f20, zero + fmv.s.x f21, zero + fmv.s.x f22, zero + fmv.s.x f23, zero + fmv.s.x f24, zero + fmv.s.x f25, zero + fmv.s.x f26, zero + fmv.s.x f27, zero + fmv.s.x f28, zero + fmv.s.x f29, zero + fmv.s.x f30, zero + fmv.s.x f31, zero + csrw fcsr, 0 + /* note that the caller must clear SR_FS */ +#endif /* CONFIG_FPU */ +.Lreset_regs_done: + ret +END(reset_regs) +#endif /* CONFIG_RISCV_M_MODE */ + __PAGE_ALIGNED_BSS /* Empty zero page */ .balign PAGE_SIZE -- 2.20.1