https://gcc.gnu.org/g:6522e2f3b89beb5d6e9499925480acbbacc3e214
commit 6522e2f3b89beb5d6e9499925480acbbacc3e214 Author: Christoph Müllner <[email protected]> Date: Thu Jul 24 23:08:40 2025 +0200 RISC-V: Add support for resumable non-maskable interrupt (RNMI) handlers The Smrnmi extension introduces the nmret instruction to return from RNMI handlers. We already have basic Smrnmi support. This patch introduces support for the nmret instruction and the ability to set the function attribute `__attribute__ ((interrupt ("rnmi")))` to let the compiler generate RNMI handlers. The attribute name is proposed in a PR for the RISC C API and approved by LLVM maintainers: https://github.com/riscv-non-isa/riscv-c-api-doc/pull/116 gcc/ChangeLog: * config/riscv/riscv.cc (enum riscv_privilege_levels): Add RNMI_MODE. (riscv_handle_type_attribute): Handle 'rnmi' interrupt attribute. (riscv_expand_epilogue): Generate nmret for RNMI handlers. (riscv_get_interrupt_type): Handle 'rnmi' interrupt attribute. * config/riscv/riscv.md (riscv_rnmi): Add nmret INSN. * doc/extend.texi: Add documentation for 'rnmi' interrupt attribute. gcc/testsuite/ChangeLog: * gcc.target/riscv/interrupt-rnmi.c: New test. Signed-off-by: Christoph Müllner <[email protected]> (cherry picked from commit 1603eeb6c8ea9cf68762a7755307077c7fb143d3) Diff: --- gcc/config/riscv/riscv.cc | 17 +++++++++++++---- gcc/config/riscv/riscv.md | 8 ++++++++ gcc/doc/extend.texi | 4 ++-- gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c | 11 +++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index c3cceb4af75b..8e72b34ae794 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -170,7 +170,7 @@ struct GTY(()) riscv_frame_info { }; enum riscv_privilege_levels { - UNKNOWN_MODE, USER_MODE, SUPERVISOR_MODE, MACHINE_MODE + UNKNOWN_MODE, USER_MODE, SUPERVISOR_MODE, MACHINE_MODE, RNMI_MODE }; struct GTY(()) mode_switching_info { @@ -6925,12 +6925,17 @@ riscv_handle_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args, } string = TREE_STRING_POINTER (cst); - if (strcmp (string, "user") && strcmp (string, "supervisor") - && strcmp (string, "machine")) + if (!strcmp (string, "rnmi") && !TARGET_SMRNMI) + { + error ("attribute 'rnmi' requires the Smrnmi ISA extension"); + *no_add_attrs = true; + } + else if (strcmp (string, "user") && strcmp (string, "supervisor") + && strcmp (string, "machine") && strcmp (string, "rnmi")) { warning (OPT_Wattributes, "argument to %qE attribute is not %<\"user\"%>, %<\"supervisor\"%>, " - "or %<\"machine\"%>", name); + "%<\"machine\"%>, or %<\"rnmi\"%>", name); *no_add_attrs = true; } } @@ -9715,6 +9720,8 @@ riscv_expand_epilogue (int style) emit_jump_insn (gen_riscv_mret ()); else if (mode == SUPERVISOR_MODE) emit_jump_insn (gen_riscv_sret ()); + else if (mode == RNMI_MODE) + emit_jump_insn (gen_riscv_mnret ()); else emit_jump_insn (gen_riscv_uret ()); } @@ -12062,6 +12069,8 @@ riscv_get_interrupt_type (tree decl) return USER_MODE; else if (!strcmp (string, "supervisor")) return SUPERVISOR_MODE; + else if (!strcmp (string, "rnmi")) + return RNMI_MODE; else /* Must be "machine". */ return MACHINE_MODE; } diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 26b9fb4c2553..10d40bd86847 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -121,6 +121,7 @@ UNSPECV_MRET UNSPECV_SRET UNSPECV_URET + UNSPECV_MNRET ;; Blockage and synchronization. UNSPECV_BLOCKAGE @@ -4185,6 +4186,13 @@ "uret" [(set_attr "type" "ret")]) +(define_insn "riscv_mnret" + [(return) + (unspec_volatile [(const_int 0)] UNSPECV_MNRET)] + "TARGET_SMRNMI" + "mnret" + [(set_attr "type" "ret")]) + (define_insn "stack_tie<mode>" [(set (mem:BLK (scratch)) (unspec:BLK [(match_operand:X 0 "register_operand" "r") diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 3c653cea2556..6a5462e5642a 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -5632,8 +5632,8 @@ void f (void) __attribute__ ((interrupt ("user"))); @end smallexample Permissible values for this parameter are @code{user}, @code{supervisor}, -and @code{machine}. If there is no parameter, then it defaults to -@code{machine}. +@code{machine}, and @code{rnmi}. If there is no parameter, then it +defaults to @code{machine}. @cindex @code{riscv_vector_cc} function attribute, RISC-V @item riscv_vector_cc diff --git a/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c b/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c new file mode 100644 index 000000000000..f3401080823e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c @@ -0,0 +1,11 @@ +/* Verify the return instruction is mnret. */ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_smrnmi" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_smrnmi" { target { rv64 } } } */ + +void __attribute__ ((interrupt ("rnmi"))) +foo (void) +{ +} + +/* { dg-final { scan-assembler {\mmnret} } } */
