]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[riscv] Check if seed CSR is accessible from S-mode
authorMichael Brown <mcb30@ipxe.org>
Mon, 28 Oct 2024 22:58:56 +0000 (22:58 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 28 Oct 2024 23:07:14 +0000 (23:07 +0000)
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>
src/arch/riscv/core/zkr.c
src/arch/riscv/include/ipxe/csr.h [new file with mode: 0644]

index bf16096711428535992abfff78d63b3c0f13412a..4b6316ea0415639f536c40c1a15664fddaa004d0 100644 (file)
@@ -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 (file)
index 0000000..c149744
--- /dev/null
@@ -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 */