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..38f9bf2e 100644 --- a/lib/sbi/sbi_init.c +++ b/lib/sbi/sbi_init.c @@ -280,20 +280,26 @@ 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; + 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)