lib: sbi: Move Zkr entropy initialization from fw_base.S to init_coldboot

Current placement of entropy initialization via Zkr extension requires a
trap-based mechanism to handle absent Zkr extension case. In presence of
Smrnmi extension no trap-based mechanisms should be used before Smrnmi is
detected and enabled otherwise trap will jump to undefined location.
Move stack guard initialization into init_coldboot function body after
device tree has been parsed so we know if Zkr extension is implemented by
the platform which helps to avoid trap-based discovery.
init_coldboot() is a safe place to initialize entropy because it doesn't
return so no check of __stack_chk_guard against value on entry
will be done.

Signed-off-by: Evgeny Voevodin <evvoevod@tenstorrent.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/acd52b0f3468758bc5f09e6a45662341b31d4d87.1778176768.git.evvoevod@tenstorrent.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Evgeny Voevodin
2026-05-07 18:08:06 +00:00
committed by Anup Patel
parent 882b8b081c
commit 0cfd6c0b5e
2 changed files with 31 additions and 32 deletions
+31
View File
@@ -218,6 +218,8 @@ static void wake_coldboot_harts(struct sbi_scratch *scratch)
__smp_store_release(&coldboot_done, 1);
}
unsigned long __stack_chk_guard = 0x95B5FF5A;
static unsigned long entry_count_offset;
static unsigned long init_count_offset;
@@ -269,6 +271,35 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
if (rc)
sbi_hart_hang();
/*
* Initialize stack guard via Zkr entropy source if Zkr is
* implemented according to device tree. Writing new seed value
* to __stack_chk_guard is safe here because function doesn't
* return and no check against value on entry will be done.
*/
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;
while (chunks) {
unsigned long seed = csr_swap(CSR_SEED, 0);
unsigned long opst = seed & SEED_OPTS_MASK;
if (opst == SEED_OPTS_DEAD) {
res = false;
break;
}
if (opst == SEED_OPTS_ES16) {
guard_val = (guard_val << 16) | (seed & SEED_ENTROPY_MASK);
chunks--;
}
continue;
}
if (res)
__stack_chk_guard = guard_val;
}
rc = sbi_timer_init(scratch, true);
if (rc)
sbi_hart_hang();