Skip to content

Commit 1454db1

Browse files
futoglenary
andauthored
[RISCV] Support resumable non-maskable interrupt handlers (#148134)
The `rnmi` interrupt attribute value has been added for the `Smrnmi` extension. --------- Co-authored-by: Sam Elliott <[email protected]>
1 parent e136fb0 commit 1454db1

File tree

11 files changed

+448
-5
lines changed

11 files changed

+448
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ LoongArch Support
198198
RISC-V Support
199199
^^^^^^^^^^^^^^
200200

201+
- Add support for `__attribute__((interrupt("rnmi")))` to be used with the `Smrnmi` extension.
202+
With this the `Smrnmi` extension is fully supported.
203+
201204
CUDA/HIP Language Changes
202205
^^^^^^^^^^^^^^^^^^^^^^^^^
203206

clang/include/clang/Basic/Attr.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,6 +2361,7 @@ def RISCVInterrupt : InheritableAttr, TargetSpecificAttr<TargetRISCV> {
23612361
[
23622362
"supervisor",
23632363
"machine",
2364+
"rnmi",
23642365
"qci-nest",
23652366
"qci-nonest",
23662367
"SiFive-CLIC-preemptible",
@@ -2369,6 +2370,7 @@ def RISCVInterrupt : InheritableAttr, TargetSpecificAttr<TargetRISCV> {
23692370
[
23702371
"supervisor",
23712372
"machine",
2373+
"rnmi",
23722374
"qcinest",
23732375
"qcinonest",
23742376
"SiFiveCLICPreemptible",

clang/include/clang/Basic/AttrDocs.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2905,10 +2905,13 @@ the backend to generate appropriate function entry/exit code so that it can be
29052905
used directly as an interrupt service routine.
29062906

29072907
Permissible values for this parameter are ``machine``, ``supervisor``,
2908-
``qci-nest``, ``qci-nonest``, ``SiFive-CLIC-preemptible``, and
2908+
``rnmi``, ``qci-nest``, ``qci-nonest``, ``SiFive-CLIC-preemptible``, and
29092909
``SiFive-CLIC-stack-swap``. If there is no parameter, then it defaults to
29102910
``machine``.
29112911

2912+
The ``rnmi`` value is used for resumable non-maskable interrupts. It requires the
2913+
standard Smrnmi extension.
2914+
29122915
The ``qci-nest`` and ``qci-nonest`` values require Qualcomm's Xqciint extension
29132916
and are used for Machine-mode Interrupts and Machine-mode Non-maskable
29142917
interrupts. These use the following instructions from Xqciint to save and

clang/lib/CodeGen/Targets/RISCV.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,9 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
817817
case RISCVInterruptAttr::supervisor:
818818
Kind = "supervisor";
819819
break;
820+
case RISCVInterruptAttr::rnmi:
821+
Kind = "rnmi";
822+
break;
820823
case RISCVInterruptAttr::qcinest:
821824
Kind = "qci-nest";
822825
break;

clang/lib/Sema/SemaRISCV.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1552,9 +1552,11 @@ void SemaRISCV::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
15521552
HasSiFiveCLICType = true;
15531553
break;
15541554
case RISCVInterruptAttr::supervisor:
1555+
case RISCVInterruptAttr::rnmi:
15551556
case RISCVInterruptAttr::qcinest:
15561557
case RISCVInterruptAttr::qcinonest:
1557-
// "supervisor" and "qci-(no)nest" cannot be combined with any other types
1558+
// "supervisor", "rnmi" and "qci-(no)nest" cannot be combined with any
1559+
// other types
15581560
HasUnaryType = true;
15591561
break;
15601562
}
@@ -1608,6 +1610,14 @@ void SemaRISCV::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
16081610
return;
16091611
}
16101612
} break;
1613+
case RISCVInterruptAttr::rnmi: {
1614+
if (!HasFeature("smrnmi")) {
1615+
Diag(AL.getLoc(),
1616+
diag::err_riscv_attribute_interrupt_requires_extension)
1617+
<< RISCVInterruptAttr::ConvertInterruptTypeToStr(Type) << "Smrnmi";
1618+
return;
1619+
}
1620+
} break;
16111621
default:
16121622
break;
16131623
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %clang_cc1 -triple riscv32-unknown-elf -target-feature +smrnmi -emit-llvm -DCHECK_IR < %s | FileCheck %s
2+
// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -target-feature +smrnmi -verify=enabled,both -fsyntax-only
3+
// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -verify=disabled,both -fsyntax-only
4+
// RUN: %clang_cc1 %s -triple riscv32-unknown-elf -target-feature -srnmi -verify=disabled,both -fsyntax-only
5+
6+
#if defined(CHECK_IR)
7+
// CHECK-LABEL: foo_rnmi_interrupt() #0
8+
// CHECK: ret void
9+
__attribute__((interrupt("rnmi")))
10+
void foo_rnmi_interrupt(void) {}
11+
12+
// CHECK-LABEL: @foo_rnmi_rnmi_interrupt() #0
13+
// CHECK: ret void
14+
__attribute__((interrupt("rnmi", "rnmi")))
15+
void foo_rnmi_rnmi_interrupt(void) {}
16+
17+
// CHECK: attributes #0
18+
// CHECK: "interrupt"="rnmi"
19+
#else
20+
21+
__attribute__((interrupt("rnmi"))) void test_rnmi(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'rnmi' requires extension 'Smrnmi'}}
22+
__attribute__((interrupt("rnmi", "rnmi"))) void test_rnmi_rnmi(void) {} // disabled-error {{RISC-V 'interrupt' attribute 'rnmi' requires extension 'Smrnmi'}}
23+
24+
__attribute__((interrupt("rnmi", "supervisor"))) void foo_rnmi_supervisor(void) {} // both-error {{RISC-V 'interrupt' attribute contains invalid combination of interrupt types}}
25+
__attribute__((interrupt("rnmi", "machine"))) void foo_rnmi_machine(void) {} // both-error {{RISC-V 'interrupt' attribute contains invalid combination of interrupt types}}
26+
27+
__attribute__((interrupt("RNMI"))) void test_RNMI(void) {} // both-warning {{'interrupt' attribute argument not supported: "RNMI"}}
28+
#endif

llvm/docs/RISCVUsage.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ on support follow.
136136
``Smepmp`` Supported
137137
``Smmpm`` Supported
138138
``Smnpm`` Supported
139-
``Smrnmi`` Assembly Support
139+
``Smrnmi`` Supported
140140
``Smstateen`` Assembly Support
141141
``Ssaia`` Supported
142142
``Ssccfg`` Supported

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22550,6 +22550,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
2255022550
constexpr StringLiteral SupportedInterruptKinds[] = {
2255122551
"machine",
2255222552
"supervisor",
22553+
"rnmi",
2255322554
"qci-nest",
2255422555
"qci-nonest",
2255522556
"SiFive-CLIC-preemptible",
@@ -22567,6 +22568,8 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
2256722568
reportFatalUsageError(
2256822569
"'SiFive-CLIC-*' interrupt kinds require XSfmclic extension");
2256922570

22571+
if (Kind == "rnmi" && !Subtarget.hasStdExtSmrnmi())
22572+
reportFatalUsageError("'rnmi' interrupt kind requires Srnmi extension");
2257022573
const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
2257122574
if (Kind.starts_with("SiFive-CLIC-preemptible") && TFI->hasFP(MF))
2257222575
reportFatalUsageError("'SiFive-CLIC-preemptible' interrupt kinds cannot "
@@ -23212,7 +23215,11 @@ RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
2321223215

2321323216
if (Kind == "supervisor")
2321423217
RetOpc = RISCVISD::SRET_GLUE;
23215-
else if (Kind == "qci-nest" || Kind == "qci-nonest") {
23218+
else if (Kind == "rnmi") {
23219+
assert(STI.hasFeature(RISCV::FeatureStdExtSmrnmi) &&
23220+
"Need Smrnmi extension for rnmi");
23221+
RetOpc = RISCVISD::MNRET_GLUE;
23222+
} else if (Kind == "qci-nest" || Kind == "qci-nonest") {
2321623223
assert(STI.hasFeature(RISCV::FeatureVendorXqciint) &&
2321723224
"Need Xqciint for qci-(no)nest");
2321823225
RetOpc = RISCVISD::QC_C_MILEAVERET_GLUE;

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ def riscv_sret_glue : RVSDNode<"SRET_GLUE", SDTNone,
7575
[SDNPHasChain, SDNPOptInGlue]>;
7676
def riscv_mret_glue : RVSDNode<"MRET_GLUE", SDTNone,
7777
[SDNPHasChain, SDNPOptInGlue]>;
78+
def riscv_mnret_glue : RVSDNode<"MNRET_GLUE", SDTNone,
79+
[SDNPHasChain, SDNPOptInGlue]>;
7880
def riscv_mileaveret_glue : RVSDNode<"QC_C_MILEAVERET_GLUE", SDTNone,
7981
[SDNPHasChain, SDNPOptInGlue]>;
8082

@@ -935,7 +937,6 @@ def MRET : Priv<"mret", 0b0011000>, Sched<[]> {
935937
let rs1 = 0;
936938
let rs2 = 0b00010;
937939
}
938-
} // isBarrier = 1, isReturn = 1, isTerminator = 1
939940

940941
let Predicates = [HasStdExtSmrnmi] in {
941942
def MNRET : Priv<"mnret", 0b0111000>, Sched<[]> {
@@ -944,6 +945,8 @@ def MNRET : Priv<"mnret", 0b0111000>, Sched<[]> {
944945
let rs2 = 0b00010;
945946
}
946947
}// Predicates = [HasStdExtSmrnmi]
948+
} // isBarrier = 1, isReturn = 1, isTerminator = 1
949+
947950

948951
def WFI : Priv<"wfi", 0b0001000>, Sched<[]> {
949952
let rd = 0;
@@ -1801,6 +1804,8 @@ def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
18011804

18021805
def : Pat<(riscv_sret_glue), (SRET)>;
18031806
def : Pat<(riscv_mret_glue), (MRET)>;
1807+
let Predicates = [HasStdExtSmrnmi] in
1808+
def : Pat<(riscv_mnret_glue), (MNRET)>;
18041809

18051810
let isCall = 1, Defs = [X1] in {
18061811
let Predicates = [NoStdExtZicfilp] in
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
; RUN: not llc -mtriple riscv32-unknown-elf -mattr=-smrnmi -o - %s 2>&1 \
2+
; RUN: | FileCheck %s
3+
; RUN: not llc -mtriple riscv64-unknown-elf -mattr=-smrnmi -o - %s 2>&1 \
4+
; RUN: | FileCheck %s
5+
6+
; CHECK: LLVM ERROR: 'rnmi' interrupt kind requires Srnmi extension
7+
define void @test_rnmi() "interrupt"="rnmi" {
8+
ret void
9+
}

0 commit comments

Comments
 (0)