firmware: Add RNMI handler infrastructure

Implement basic Resumable NMI (RNMI) handler support for the RISC-V
Smrnmi extension.

The new _trap_rnmi_handler assembly entry point saves context using the
Smrnmi MN* CSRs (MNSCRATCH, MNEPC, MNSTATUS, MNCAUSE) and returns via
mnret. It dispatches to sbi_trap_rnmi_handler(), which optionally calls
a platform-specific ops->rnmi_handler callback for actual NMI
processing. If no platform handler is registered or it fails, the
event is reported as an unhandled NMI.

The RNMI handler reuses the generic trap context structure but stores MN*
CSR values (MNEPC, MNSTATUS, MNCAUSE) into the corresponding generic
fields (mepc, mstatus, cause) for compatibility with existing trap
infrastructure.

Signed-off-by: Evgeny Voevodin <evvoevod@tenstorrent.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/050ae6d2762ba8d5b9dfb3cc1960a23aa3d6c549.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:04 +00:00
committed by Anup Patel
parent b63606f981
commit 00fec20b49
4 changed files with 166 additions and 0 deletions
+39
View File
@@ -20,6 +20,7 @@
#include <sbi/sbi_irqchip.h>
#include <sbi/sbi_trap_ldst.h>
#include <sbi/sbi_pmu.h>
#include <sbi/sbi_platform.h>
#include <sbi/sbi_scratch.h>
#include <sbi/sbi_sse.h>
#include <sbi/sbi_timer.h>
@@ -375,3 +376,41 @@ trap_done:
sbi_trap_set_context(scratch, tcntx->prev_context);
return tcntx;
}
/**
* Default Resumable NMI (RNMI) handler
*
* This function is called from the _trap_rnmi_handler assembly code.
* It provides a simple wrapper that calls the platform-specific
* NMI handler if registered. If no handler is registered, it prints
* diagnostic information and hangs, similar to unhandled traps.
*
* Note: The trap context stores NMI CSR values (MNCAUSE, MNEPC, MNSTATUS)
* in the generic trap context fields (cause, mepc, mstatus).
*
* @param tcntx Pointer to trap context (saved on stack)
* @return Same trap context pointer (needed for restore macros)
*/
struct sbi_trap_context *sbi_trap_rnmi_handler(struct sbi_trap_context *tcntx)
{
int rc;
const struct sbi_platform *plat = sbi_platform_thishart_ptr();
const struct sbi_platform_operations *ops = sbi_platform_ops(plat);
/* Call platform-specific NMI handler if registered */
if (ops && ops->rnmi_handler) {
rc = ops->rnmi_handler(tcntx);
if (rc) {
/* Platform handler failed to handle NMI */
sbi_trap_error("platform NMI handler failed", rc, tcntx);
}
return tcntx;
}
/* No platform handler - treat as unhandled NMI */
sbi_trap_error("unhandled NMI (no platform rnmi_handler)",
SBI_ENOTSUPP, tcntx);
/* Never returns */
return tcntx;
}