diff mbox series

[13/15] riscv: clear the instruction cache and all registers when booting

Message ID 20190813154747.24256-14-hch@lst.de (mailing list archive)
State New, archived
Headers show
Series [01/15] irqchip/sifive-plic: set max threshold for ignored handlers | expand

Commit Message

Christoph Hellwig Aug. 13, 2019, 3:47 p.m. UTC
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 <hch@lst.de>
---
 arch/riscv/include/asm/csr.h |  1 +
 arch/riscv/kernel/head.S     | 86 ++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

Comments

Alan Kao Aug. 14, 2019, 1 a.m. UTC | #1
Hi Christoph,

On Tue, Aug 13, 2019 at 05:47:45PM +0200, Christoph Hellwig wrote:
> 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.  

Sure.

> +#ifdef CONFIG_FPU

But it doesn't really mean that the running system has an FPU given CONFIG_FPU
enabled.  Normally the existence of an FPU is checked in riscv_fill_hwcap by
searching device tree, where the code looks like


bool has_fpu = false; // this one is global
...
#ifdef CONFIG_FPU
        if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
                has_fpu = true;
#endif


Or does CONFIG_FPU have a more intuitive meaning when CONFIG_M_MODE is enabled?

> +	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 */
Alan Kao Aug. 14, 2019, 1:07 a.m. UTC | #2
Please ignore the previous mail, I must have missed this part of the patch,
> 
> > +	csrr	t0, CSR_MISA
> > +	andi	t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
> > +	bnez	t0, .Lreset_regs_done
> > +

In S-mode we were not able to obtain the ISA information in misa, but now
the nommu port is in M-mode so this is rather straightforward.
Christoph Hellwig Aug. 14, 2019, 4:35 a.m. UTC | #3
On Wed, Aug 14, 2019 at 09:00:14AM +0800, Alan Kao wrote:
> But it doesn't really mean that the running system has an FPU given CONFIG_FPU
> enabled.  Normally the existence of an FPU is checked in riscv_fill_hwcap by
> searching device tree, where the code looks like
> 
> 
> bool has_fpu = false; // this one is global
> ...
> #ifdef CONFIG_FPU
>         if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
>                 has_fpu = true;
> #endif
> 
> 
> Or does CONFIG_FPU have a more intuitive meaning when CONFIG_M_MODE is enabled?

No, it doesn't..

> 
> > +	csrr	t0, CSR_MISA
> > +	andi	t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
> > +	bnez	t0, .Lreset_regs_done

... which is why we have these few lines of code that check the
caps returns from the misa CSR, similar to the elf_caps check quoted
above.
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 64f8fe84b88f..a804272a5f19 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 275c2ab1e990..b603edb29e73 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,6 +52,12 @@  _start_kernel:
 	csrw CSR_XIP, zero
 
 #ifdef CONFIG_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.
@@ -201,6 +208,85 @@  relocate:
 	j .Lsecondary_park
 END(_start)
 
+#ifdef CONFIG_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_M_MODE */
+
 __PAGE_ALIGNED_BSS
 	/* Empty zero page */
 	.balign PAGE_SIZE