diff options
author | Michael Brown <mcb30@ipxe.org> | 2024-10-28 22:58:56 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2024-10-28 23:07:14 +0000 |
commit | 19f44d2998f6197b70fa2726c551bc8fe6956fa2 (patch) | |
tree | c10207febe260530dfb7c733912994599a9594bf | |
parent | e0e102ee24bdab68b0318b505402f60cfb88a5f0 (diff) | |
download | ipxe-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.c | 7 | ||||
-rw-r--r-- | src/arch/riscv/include/ipxe/csr.h | 75 |
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 */ |