@@ -394,9 +394,14 @@ trap_done:
struct sbi_trap_context *sbi_trap_rnmi_handler(struct sbi_trap_context *tcntx)
{
int rc;
+ struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
const struct sbi_platform *plat = sbi_platform_thishart_ptr();
const struct sbi_platform_operations *ops = sbi_platform_ops(plat);
+ /* Update trap context pointer so nested traps chain correctly */
+ tcntx->prev_context = sbi_trap_get_context(scratch);
+ sbi_trap_set_context(scratch, tcntx);
+
/* Call platform-specific NMI handler if registered */
if (ops && ops->rnmi_handler) {
rc = ops->rnmi_handler(tcntx);
@@ -404,14 +409,15 @@ struct sbi_trap_context *sbi_trap_rnmi_handler(struct sbi_trap_context *tcntx)
/* Platform handler failed to handle NMI */
sbi_trap_error("platform NMI handler failed", rc, tcntx);
}
- return tcntx;
+ goto done;
}
/* No platform handler - treat as unhandled NMI */
sbi_trap_error("unhandled NMI (no platform rnmi_handler)",
SBI_ENOTSUPP, tcntx);
- /* Never returns */
+done:
+ sbi_trap_set_context(scratch, tcntx->prev_context);
return tcntx;
}
Before an RNMI is taken, an earlier SBI trap may have already used the same slot on the M-mode exception stack to save its trap context. When the RNMI later comes in, it reuses that same stack slot for its own trap context, but sbi_trap_rnmi_handler() never links prev_context to the previously active trap context, so it still holds the value left there by that earlier trap context. sbi_trap_error() then walks this chain with `for (tc = tcntx; tc; tc = tc->prev_context) depth++;` to count the depth before printing anything. If this stale prev_context happens to point back to tcntx itself, the loop never terminates, hanging the hart before any diagnostics are even printed. Update sbi_trap_rnmi_handler() so that sbi_scratch points to the new trap context on entry, and points back to the previous context on exit, the same way sbi_trap_handler() does. This serves two purposes: it makes tcntx->prev_context always point to the correct previous trap context (or NULL when there isn't one) instead of stale data, fixing the hang described above; and it lets an exception taken while already inside RNMI handling correctly chain back to the RNMI's trap context, instead of the RNMI context being silently dropped from the chain and never printed. Together, these let sbi_trap_error() print every nested trap context in the chain, including the RNMI's own state. Fixes: 8cdb5b1023df ("firmware: Add RNMI handler infrastructure") Suggested-by: Nick Hu <nick.hu@sifive.com> Signed-off-by: Nia Su <nia.su@sifive.com> --- lib/sbi/sbi_trap.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)