aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2024-10-28 22:58:56 +0000
committerMichael Brown <mcb30@ipxe.org>2024-10-28 23:07:14 +0000
commit19f44d2998f6197b70fa2726c551bc8fe6956fa2 (patch)
treec10207febe260530dfb7c733912994599a9594bf
parente0e102ee24bdab68b0318b505402f60cfb88a5f0 (diff)
downloadipxe-19f44d2998f6197b70fa2726c551bc8fe6956fa2.tar.gz
[riscv] Check if seed CSR is accessible from S-mode
The seed CSR defined by the Zkr extension is accessible only in M-mode by default. Older versions of OpenSBI (prior to version 1.4) do not set mseccfg.sseed, with the result that attempts to access the seed CSR from S-mode will raise an illegal instruction exception. Add a facility for testing the accessibility of arbitrary CSRs, and use it to check that the seed CSR is accessible before reporting the seed CSR entropy source as being functional. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/arch/riscv/core/zkr.c7
-rw-r--r--src/arch/riscv/include/ipxe/csr.h75
2 files changed, 82 insertions, 0 deletions
diff --git a/src/arch/riscv/core/zkr.c b/src/arch/riscv/core/zkr.c
index bf1609671..4b6316ea0 100644
--- a/src/arch/riscv/core/zkr.c
+++ b/src/arch/riscv/core/zkr.c
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <errno.h>
#include <ipxe/hart.h>
+#include <ipxe/csr.h>
#include <ipxe/entropy.h>
#include <ipxe/drbg.h>
@@ -60,6 +61,12 @@ static int zkr_entropy_enable ( void ) {
return rc;
}
+ /* Check if seed CSR is accessible in S-mode */
+ if ( ! csr_can_write ( "seed", 0 ) ) {
+ DBGC ( colour, "ZKR cannot access seed CSR\n" );
+ return -ENOTSUP;
+ }
+
/* RISC-V ISA mandates that 128 bits of full entropy shall be
* obtained from 256 entropy bits read from the seed CSR.
*
diff --git a/src/arch/riscv/include/ipxe/csr.h b/src/arch/riscv/include/ipxe/csr.h
new file mode 100644
index 000000000..c14974472
--- /dev/null
+++ b/src/arch/riscv/include/ipxe/csr.h
@@ -0,0 +1,75 @@
+#ifndef _IPXE_CSR_H
+#define _IPXE_CSR_H
+
+/** @file
+ *
+ * Control and status registers (CSRs)
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/**
+ * Check if CSR can be read
+ *
+ * @v name CSR name
+ * @v allowed CSR can be read
+ */
+#define csr_can_read( name ) ( { \
+ unsigned long stvec_orig; \
+ unsigned long stvec_temp; \
+ unsigned long csr; \
+ int allowed = 0; \
+ \
+ __asm__ __volatile__ ( /* Set temporary trap vector */ \
+ "la %3, 1f\n\t" \
+ "csrrw %2, stvec, %3\n\t" \
+ /* Try reading CSR */ \
+ "csrr %1, " name "\n\t" \
+ /* Mark as allowed if not trapped */ \
+ "addi %0, %0, 1\n\t" \
+ /* Temporary trap vector */ \
+ ".balign 4\n\t" \
+ "\n1:\n\t" \
+ /* Restore original trap vector */ \
+ "csrw stvec, %2\n\t" \
+ : "+r" ( allowed ), \
+ "=r" ( csr ), \
+ "=r" ( stvec_orig ), \
+ "=r" ( stvec_temp ) ); \
+ allowed; \
+ } )
+
+/**
+ * Check if CSR can be written
+ *
+ * @v name CSR name
+ * @v value Value to write
+ * @v allowed CSR can be written
+ */
+#define csr_can_write( name, value ) ( { \
+ unsigned long stvec_orig; \
+ unsigned long stvec_temp; \
+ unsigned long csr = (value); \
+ int allowed = 0; \
+ \
+ __asm__ __volatile__ ( /* Set temporary trap vector */ \
+ "la %3, 1f\n\t" \
+ "csrrw %2, stvec, %3\n\t" \
+ /* Try writing CSR */ \
+ "csrrw %1, " name ", %1\n\t" \
+ /* Mark as allowed if not trapped */ \
+ "addi %0, %0, 1\n\t" \
+ /* Temporary trap vector */ \
+ ".balign 4\n\t" \
+ "\n1:\n\t" \
+ /* Restore original trap vector */ \
+ "csrw stvec, %2\n\t" \
+ : "+r" ( allowed ), \
+ "+r" ( csr ), \
+ "=r" ( stvec_orig ), \
+ "=r" ( stvec_temp ) ); \
+ allowed; \
+ } )
+
+#endif /* _IPXE_CSR_H */