Skip to content

[RISCV]Support Sspmp, Sspmpen and Smpmpdeleg Extensions#207696

Open
ChunyuLiao wants to merge 1 commit into
llvm:mainfrom
ChunyuLiao:spmp
Open

[RISCV]Support Sspmp, Sspmpen and Smpmpdeleg Extensions#207696
ChunyuLiao wants to merge 1 commit into
llvm:mainfrom
ChunyuLiao:spmp

Conversation

@ChunyuLiao

Copy link
Copy Markdown
Member

@llvmorg-github-actions llvmorg-github-actions Bot added backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Jul 6, 2026
@llvmorg-github-actions

llvmorg-github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-backend-risc-v

Author: Liao Chunyu (ChunyuLiao)

Changes

Spec states: https://riscv.atlassian.net/browse/RVS-921


Full diff: https://github.com/llvm/llvm-project/pull/207696.diff

9 Files Affected:

  • (modified) clang/test/Driver/print-supported-extensions-riscv.c (+3)
  • (modified) clang/test/Preprocessor/riscv-target-features.c (+33)
  • (modified) llvm/docs/RISCVUsage.rst (+3)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+10)
  • (modified) llvm/lib/Target/RISCV/RISCVSystemOperands.td (+4)
  • (modified) llvm/test/CodeGen/RISCV/features-info.ll (+3)
  • (modified) llvm/test/MC/RISCV/attribute-arch.s (+9)
  • (added) llvm/test/MC/RISCV/spmp-csr-names.s (+50)
  • (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+3)
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 34c651891538d..f56887cc449cf 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -135,6 +135,7 @@
 // CHECK-NEXT:     smepmp               1.0       'Smepmp' (Enhanced Physical Memory Protection)
 // CHECK-NEXT:     smmpm                1.0       'Smmpm' (Machine-level Pointer Masking for M-mode)
 // CHECK-NEXT:     smnpm                1.0       'Smnpm' (Machine-level Pointer Masking for next lower privilege mode)
+// CHECK-NEXT:     smpmpdeleg           1.0       'Smpmpdeleg' (Sharing Hardware Resources between PMP and SPMP)
 // CHECK-NEXT:     smrnmi               1.0       'Smrnmi' (Resumable Non-Maskable Interrupts)
 // CHECK-NEXT:     smstateen            1.0       'Smstateen' (Machine-mode view of the state-enable extension)
 // CHECK-NEXT:     ssaia                1.0       'Ssaia' (Advanced Interrupt Architecture Supervisor Level)
@@ -147,6 +148,8 @@
 // CHECK-NEXT:     ssdbltrp             1.0       'Ssdbltrp' (Double Trap Supervisor Level)
 // CHECK-NEXT:     ssnpm                1.0       'Ssnpm' (Supervisor-level Pointer Masking for next lower privilege mode)
 // CHECK-NEXT:     sspm                 1.0       'Sspm' (Indicates Supervisor-mode Pointer Masking)
+// CHECK-NEXT:     sspmp                1.0       'Sspmp' (S-level Physical Memory Protection (SPMP))
+// CHECK-NEXT:     sspmpen              1.0       'Sspmpen' (Optimizing Context Switching of SPMP Entries)
 // CHECK-NEXT:     ssqosid              1.0       'Ssqosid' (Quality-of-Service (QoS) Identifiers)
 // CHECK-NEXT:     ssstateen            1.0       'Ssstateen' (Supervisor-mode view of the state-enable extension)
 // CHECK-NEXT:     ssstrict             1.0       'Ssstrict' (No non-conforming extensions are present)
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index 28031814da16a..7762a217f906a 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -38,6 +38,7 @@
 // CHECK-NOT: __riscv_smctr{{.*$}}
 // CHECK-NOT: __riscv_smdbltrp {{.*$}}
 // CHECK-NOT: __riscv_smepmp {{.*$}}
+// CHECK-NOT: __riscv_smpmpdeleg {{.*$}}
 // CHECK-NOT: __riscv_smmpm{{.*$}}
 // CHECK-NOT: __riscv_smnpm{{.*$}}
 // CHECK-NOT: __riscv_smpmpmt {{.*$}}
@@ -53,6 +54,8 @@
 // CHECK-NOT: __riscv_ssdbltrp {{.*$}}
 // CHECK-NOT: __riscv_ssnpm{{.*$}}
 // CHECK-NOT: __riscv_sspm{{.*$}}
+// CHECK-NOT: __riscv_sspmp {{.*$}}
+// CHECK-NOT: __riscv_sspmpen {{.*$}}
 // CHECK-NOT: __riscv_ssqosid{{.*$}}
 // CHECK-NOT: __riscv_ssstateen {{.*$}}
 // CHECK-NOT: __riscv_ssstrict {{.*$}}
@@ -1347,6 +1350,36 @@
 // RUN:   -o - | FileCheck --check-prefix=CHECK-SSCSRIND-EXT %s
 // CHECK-SSCSRIND-EXT: __riscv_sscsrind  1000000{{$}}
 
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32isspmp1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-SSPMP-EXT %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64isspmp1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-SSPMP-EXT %s
+// CHECK-SSPMP-EXT: __riscv_sscsrind  1000000{{$}}
+// CHECK-SSPMP-EXT: __riscv_sspmp  1000000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32isspmpen1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-SSPMPEN-EXT %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64isspmpen1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-SSPMPEN-EXT %s
+// CHECK-SSPMPEN-EXT: __riscv_sscsrind  1000000{{$}}
+// CHECK-SSPMPEN-EXT: __riscv_sspmp  1000000{{$}}
+// CHECK-SSPMPEN-EXT: __riscv_sspmpen  1000000{{$}}
+
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32ismpmpdeleg1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-SMPMPDELEG-EXT %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64ismpmpdeleg1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-SMPMPDELEG-EXT %s
+// CHECK-SMPMPDELEG-EXT: __riscv_smcsrind  1000000{{$}}
+// CHECK-SMPMPDELEG-EXT: __riscv_smpmpdeleg  1000000{{$}}
+// CHECK-SMPMPDELEG-EXT: __riscv_sscsrind  1000000{{$}}
+// CHECK-SMPMPDELEG-EXT: __riscv_sspmp  1000000{{$}}
+
 // RUN: %clang --target=riscv32 \
 // RUN:   -march=rv32ismdbltrp1p0 -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-SMDBLTRP-EXT %s
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 548f25ac2e596..c24210d7f1871 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -139,6 +139,7 @@ on support follow.
      ``Smepmp``        Supported
      ``Smmpm``         Supported
      ``Smnpm``         Supported
+     ``Smpmpdeleg``    Support
      ``Smrnmi``        Supported
      ``Smstateen``     Assembly Support
      ``Ssaia``         Supported
@@ -151,6 +152,8 @@ on support follow.
      ``Ssdbltrp``      Supported
      ``Ssnpm``         Supported
      ``Sspm``          Supported
+     ``Sspmp``         Support
+     ``Sspmpen``       Support
      ``Ssqosid``       Assembly Support
      ``Ssstateen``     Assembly Support (`See note <#riscv-profiles-extensions-note>`__)
      ``Ssstrict``      Assembly Support (`See note <#riscv-profiles-extensions-note>`__)
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 361be64352499..ecb238094852d 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1095,6 +1095,16 @@ def FeatureStdExtSsccfg
 def FeatureStdExtSsccptr
     : RISCVExtension<1, 0, "Main memory supports page table reads">;
 
+def FeatureStdExtSspmp
+    : RISCVExtension<1, 0, "S-level Physical Memory Protection (SPMP)",
+                     [FeatureStdExtSscsrind]>;
+def FeatureStdExtSspmpen
+    : RISCVExtension<1, 0, "Optimizing Context Switching of SPMP Entries", [FeatureStdExtSspmp]>;
+
+def FeatureStdExtSmpmpdeleg
+    : RISCVExtension<1, 0, "Sharing Hardware Resources between PMP and SPMP",
+                     [FeatureStdExtSmcsrind, FeatureStdExtSspmp]>;
+
 def FeatureStdExtSscofpmf
     : RISCVExtension<1, 0, "Count Overflow and Mode-Based Filtering">;
 
diff --git a/llvm/lib/Target/RISCV/RISCVSystemOperands.td b/llvm/lib/Target/RISCV/RISCVSystemOperands.td
index 66e3484ff0955..463d209214785 100644
--- a/llvm/lib/Target/RISCV/RISCVSystemOperands.td
+++ b/llvm/lib/Target/RISCV/RISCVSystemOperands.td
@@ -166,6 +166,9 @@ def : SysReg<"scountovf", 0xDA0>;
 def : SysReg<"satp", 0x180>;
 let isDeprecatedName = 1 in
 def : SysReg<"sptbr", 0x180>;
+def : SysReg<"spmpen", 0x183>;
+let isRV32Only = 1 in
+def : SysReg<"spmpenh", 0x193>;
 
 //===----------------------------------------------------------------------===//
 // Supervisor Timer Compare
@@ -324,6 +327,7 @@ def : SysReg<"mtval2", 0x34B>;
 def : SysReg<"menvcfg", 0x30A>;
 let isRV32Only = 1 in
 def : SysReg<"menvcfgh", 0x31A>;
+def : SysReg<"mpmpdeleg", 0x316>;
 def : SysReg<"mseccfg", 0x747>;
 let isRV32Only = 1 in
 def : SysReg<"mseccfgh", 0x757>;
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 8abe64b8ecda4..4117e38d9c47d 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -164,6 +164,7 @@
 ; CHECK-NEXT:   smepmp                           - 'Smepmp' (Enhanced Physical Memory Protection).
 ; CHECK-NEXT:   smmpm                            - 'Smmpm' (Machine-level Pointer Masking for M-mode).
 ; CHECK-NEXT:   smnpm                            - 'Smnpm' (Machine-level Pointer Masking for next lower privilege mode).
+; CHECK-NEXT:   smpmpdeleg                       - 'Smpmpdeleg' (Sharing Hardware Resources between PMP and SPMP).
 ; CHECK-NEXT:   smrnmi                           - 'Smrnmi' (Resumable Non-Maskable Interrupts).
 ; CHECK-NEXT:   smstateen                        - 'Smstateen' (Machine-mode view of the state-enable extension).
 ; CHECK-NEXT:   ssaia                            - 'Ssaia' (Advanced Interrupt Architecture Supervisor Level).
@@ -176,6 +177,8 @@
 ; CHECK-NEXT:   ssdbltrp                         - 'Ssdbltrp' (Double Trap Supervisor Level).
 ; CHECK-NEXT:   ssnpm                            - 'Ssnpm' (Supervisor-level Pointer Masking for next lower privilege mode).
 ; CHECK-NEXT:   sspm                             - 'Sspm' (Indicates Supervisor-mode Pointer Masking).
+; CHECK-NEXT:   sspmp                            - 'Sspmp' (S-level Physical Memory Protection (SPMP)).
+; CHECK-NEXT:   sspmpen                          - 'Sspmpen' (Optimizing Context Switching of SPMP Entries).
 ; CHECK-NEXT:   ssqosid                          - 'Ssqosid' (Quality-of-Service (QoS) Identifiers).
 ; CHECK-NEXT:   ssstateen                        - 'Ssstateen' (Supervisor-mode view of the state-enable extension).
 ; CHECK-NEXT:   ssstrict                         - 'Ssstrict' (No non-conforming extensions are present).
diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s
index 367ec6f04d953..53a2a0527ceed 100644
--- a/llvm/test/MC/RISCV/attribute-arch.s
+++ b/llvm/test/MC/RISCV/attribute-arch.s
@@ -357,6 +357,9 @@
 .attribute arch, "rv32i_smepmp1p0"
 # CHECK: attribute      5, "rv32i2p1_smepmp1p0"
 
+.attribute arch, "rv32i_smpmpdeleg1p0"
+# CHECK: attribute      5, "rv32i2p1_smcsrind1p0_smpmpdeleg1p0_sscsrind1p0_sspmp1p0"
+
 .attribute arch, "rv32i_smpmpmt0p6"
 # CHECK: attribute      5, "rv32i2p1_smpmpmt0p6"
 
@@ -375,6 +378,12 @@
 .attribute arch, "rv32i_sscounterenw1p0"
 # CHECK: attribute      5, "rv32i2p1_sscounterenw1p0"
 
+.attribute arch, "rv32i_sspmp1p0"
+# CHECK: attribute      5, "rv32i2p1_sscsrind1p0_sspmp1p0"
+
+.attribute arch, "rv32i_sspmpen1p0"
+# CHECK: attribute      5, "rv32i2p1_sscsrind1p0_sspmp1p0_sspmpen1p0"
+
 .attribute arch, "rv32i_ssqosid1p0"
 # CHECK: attribute      5, "rv32i2p1_ssqosid1p0"
 
diff --git a/llvm/test/MC/RISCV/spmp-csr-names.s b/llvm/test/MC/RISCV/spmp-csr-names.s
new file mode 100644
index 0000000000000..fb6bce657b351
--- /dev/null
+++ b/llvm/test/MC/RISCV/spmp-csr-names.s
@@ -0,0 +1,50 @@
+# RUN: llvm-mc %s -triple=riscv32 -M no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-INST,CHECK-ENC %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 < %s \
+# RUN:     | llvm-objdump -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST-ALIAS %s
+# RUN: llvm-mc %s -triple=riscv64 -M no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-INST,CHECK-ENC %s
+# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \
+# RUN:     | llvm-objdump -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST-ALIAS %s
+# RUN: llvm-mc %s -triple=riscv32 -defsym=RV32=1 -M no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=RV32-INST,RV32-ENC %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -defsym=RV32=1 < %s \
+# RUN:     | llvm-objdump -d - \
+# RUN:     | FileCheck -check-prefix=RV32-ALIAS %s
+# RUN: not llvm-mc %s -triple=riscv64 -defsym=RV32=1 2>&1 \
+# RUN:     | FileCheck -check-prefix=CHECK-RV64-ERR %s
+
+# spmpen
+# CHECK-INST: csrrs t1, spmpen, zero
+# CHECK-ENC: encoding: [0x73,0x23,0x30,0x18]
+# CHECK-INST-ALIAS: csrr t1, spmpen
+# CHECK-INST: csrrs t2, spmpen, zero
+# CHECK-ENC: encoding: [0xf3,0x23,0x30,0x18]
+# CHECK-INST-ALIAS: csrr t2, spmpen
+csrrs t1, spmpen, zero
+csrrs t2, 0x183, zero
+
+# mpmpdeleg
+# CHECK-INST: csrrs t1, mpmpdeleg, zero
+# CHECK-ENC: encoding: [0x73,0x23,0x60,0x31]
+# CHECK-INST-ALIAS: csrr t1, mpmpdeleg
+# CHECK-INST: csrrs t2, mpmpdeleg, zero
+# CHECK-ENC: encoding: [0xf3,0x23,0x60,0x31]
+# CHECK-INST-ALIAS: csrr t2, mpmpdeleg
+csrrs t1, mpmpdeleg, zero
+csrrs t2, 0x316, zero
+
+.ifdef RV32
+# spmpenh
+# RV32-INST: csrrs t1, spmpenh, zero
+# RV32-ENC: encoding: [0x73,0x23,0x30,0x19]
+# RV32-ALIAS: csrr t1, spmpenh
+# RV32-INST: csrrs t2, spmpenh, zero
+# RV32-ENC: encoding: [0xf3,0x23,0x30,0x19]
+# RV32-ALIAS: csrr t2, spmpenh
+# CHECK-RV64-ERR: error: system register 'spmpenh' is RV32 only
+csrrs t1, spmpenh, zero
+csrrs t2, 0x193, zero
+.endif
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 837a72913dc7d..ea0c1dbd9b6e8 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1504,6 +1504,7 @@ R"(All available -march extensions for RISC-V
     smepmp               1.0
     smmpm                1.0
     smnpm                1.0
+    smpmpdeleg           1.0
     smrnmi               1.0
     smstateen            1.0
     ssaia                1.0
@@ -1516,6 +1517,8 @@ R"(All available -march extensions for RISC-V
     ssdbltrp             1.0
     ssnpm                1.0
     sspm                 1.0
+    sspmp                1.0
+    sspmpen              1.0
     ssqosid              1.0
     ssstateen            1.0
     ssstrict             1.0


def FeatureStdExtSmpmpdeleg
: RISCVExtension<1, 0, "Sharing Hardware Resources between PMP and SPMP",
[FeatureStdExtSmcsrind, FeatureStdExtSspmp]>;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is not yet supported in the spec, and I don't know add Sm1p13.

This extension is mandatory for implementations that support both Sspmp and Sm1p13.

Perhaps we need to support Sm1p13, like GCC's mpriv-spec?

: RISCVExtension<1, 0, "Main memory supports page table reads">;

def FeatureStdExtSspmp
: RISCVExtension<1, 0, "S-level Physical Memory Protection (SPMP)",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the extension isn't ratified yet. So this should be RISCVExperimentalExtension unless you're planning on holding this patch until it is ratified.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code changes are minimal. Let's wait for the spec to be ratified.

def : SysReg<"menvcfg", 0x30A>;
let isRV32Only = 1 in
def : SysReg<"menvcfgh", 0x31A>;
def : SysReg<"mpmpdeleg", 0x316>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the priv-csrs.adoc file in this PR riscv/riscv-isa-manual#3225 has this register in the same section as pmpcfg*

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl'

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants