summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Voevodin <[email protected]>2026-05-19 22:50:14 +0000
committerAnup Patel <[email protected]>2026-06-12 18:59:16 +0530
commitb508e6e25eb23a6a188f8cfea94f338c85c75cab (patch)
treea05677e12200df70dc5b291314ac5f87c1413b23
parentecc92e87a990e3f45081fbf2c84ad342d9226aaa (diff)
lib: sbi: Apply budget restriction when polling Zkr CSR state transition
Zkr architecture doesn't define a time limit on state transitions which results in hanging on unresponsive or event-driven platforms. To prevent this, we need to limit polling iterations and fall back in case the budget is over, and stack guard keeps its initial value. The budget is configurable with CONFIG_ZKR_POLL_BUDGET, defaulting to 1000 iterations. Successful reads do not consume a try. Signed-off-by: Evgeny Voevodin <[email protected]> Reviewed-by: Anup Patel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Anup Patel <[email protected]>
-rw-r--r--lib/sbi/Kconfig12
-rw-r--r--lib/sbi/sbi_init.c15
2 files changed, 24 insertions, 3 deletions
diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index c6cc04bc..89245a25 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -6,6 +6,18 @@ config CONSOLE_EARLY_BUFFER_SIZE
int "Early console buffer size (bytes)"
default 256
+config ZKR_POLL_BUDGET
+ int "Zkr seed polling budget (iterations)"
+ default 1000
+ help
+ Maximum number of iterations to poll CSR_SEED when initializing
+ the stack guard variable. The Zkr specification doesn't define
+ a time limit on transitioning to ES16 between polls, which
+ makes it impossible to tell whether entropy is being
+ accumulated slowly or the entropy source is not functioning.
+ This also limits the wait time on systems with an event-driven
+ entropy source. A successful read doesn't consume a try.
+
config SBI_ECALL_TIME
bool "Timer extension"
default y
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 4e34bbc5..658fe37f 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -280,20 +280,29 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
if (sbi_hart_has_extension(scratch, SBI_HART_EXT_ZKR)) {
unsigned long guard_val = 0;
int chunks = sizeof(unsigned long) / sizeof(uint16_t);
- bool res = true;
+#ifndef CONFIG_ZKR_POLL_BUDGET
+#define CONFIG_ZKR_POLL_BUDGET 1000
+#endif
+ unsigned int tries = CONFIG_ZKR_POLL_BUDGET;
+ bool res = false;
- while (chunks) {
+ while (chunks && tries) {
unsigned long seed = csr_swap(CSR_SEED, 0);
unsigned long opst = seed & SEED_OPTS_MASK;
+ res = false;
if (opst == SEED_OPTS_DEAD) {
- res = false;
break;
}
if (opst == SEED_OPTS_ES16) {
guard_val = (guard_val << 16) | (seed & SEED_ENTROPY_MASK);
chunks--;
+ res = true;
+ /* Successful read doesn't consume a try */
+ tries++;
}
+
+ tries--;
continue;
}
if (res)