From 5e4291812b584c48966d6163ba1e31642681eedf Mon Sep 17 00:00:00 2001 From: Nickolai Zeldovich Date: Thu, 1 Oct 2026 17:06:46 -0400 Subject: [PATCH] firmware: fw_base: add an acquire fence after the _boot_status wait loop Non-boot harts exit _wait_for_boot_hart on a plain load of _boot_status and go on to read platform.hart_index2id and other data the boot hart relocated before publishing. Nothing orders those loads after the status load, so under RVWMO a hart can read the unrelocated pointer and fault through it before mtvec is set. Pair the boot hart's release fence with a "fence r, rw" after the loop. Signed-off-by: Nickolai Zeldovich Co-Authored-By: Claude Fable 5.1 --- firmware/fw_base.S | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/firmware/fw_base.S b/firmware/fw_base.S index a76ddc1b61..294787a27e 100644 --- a/firmware/fw_base.S +++ b/firmware/fw_base.S @@ -407,6 +407,17 @@ _wait_for_boot_hart: div t2, t2, zero div t2, t2, zero bne t0, t1, _wait_for_boot_hart + /* + * Acquire: order the _boot_status load above before every later + * load (platform.hart_count, platform.hart_index2id, the scratch + * space, ...). The boot hart publishes with "fence rw, rw" before + * its store to _boot_status, but without a matching acquire here + * RVWMO lets a waiting hart that saw BOOT_STATUS_BOOT_HART_DONE + * still read pre-relocation values, e.g. the unrelocated + * platform.hart_index2id pointer, and fault through it before + * mtvec is set. + */ + fence r, rw _start_warm: /* Reset all registers except ra, a0, a1, a2, a3 and a4 for non-boot HART */