target/riscv/cpu.c | 2 ++ target/riscv/cpu_cfg_fields.h.inc | 1 + target/riscv/pmp.c | 12 ++++++++++++ target/riscv/pmp.h | 1 + 4 files changed, 16 insertions(+)
The Smpmpmt extension provides a mechanism to control memory attributes
at the granularity of PMP (Physical Memory Protection) registers, similar
to how Svpbmt controls memory attributes at the page level.
Version 0.6
https://github.com/riscv/riscv-isa-manual/blob/smpmpmt/src/smpmpmt.adoc#svpbmt
Signed-off-by: Jay Chang <jay.chang@sifive.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
---
target/riscv/cpu.c | 2 ++
target/riscv/cpu_cfg_fields.h.inc | 1 +
target/riscv/pmp.c | 12 ++++++++++++
target/riscv/pmp.h | 1 +
4 files changed, 16 insertions(+)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ae8b721e55..a0290f06f6 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -230,6 +230,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
+ ISA_EXT_DATA_ENTRY(smpmpmt, PRIV_VERSION_1_12_0, ext_smpmpmt),
ISA_EXT_DATA_ENTRY(svrsw60t59b, PRIV_VERSION_1_13_0, ext_svrsw60t59b),
ISA_EXT_DATA_ENTRY(svukte, PRIV_VERSION_1_13_0, ext_svukte),
ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_13_0, ext_svvptc),
@@ -1262,6 +1263,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false),
MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false),
+ MULTI_EXT_CFG_BOOL("smpmpmt", ext_smpmpmt, false),
MULTI_EXT_CFG_BOOL("svrsw60t59b", ext_svrsw60t59b, false),
MULTI_EXT_CFG_BOOL("svvptc", ext_svvptc, true),
diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc
index a154ecdc79..b1096da664 100644
--- a/target/riscv/cpu_cfg_fields.h.inc
+++ b/target/riscv/cpu_cfg_fields.h.inc
@@ -57,6 +57,7 @@ BOOL_FIELD(ext_svadu)
BOOL_FIELD(ext_svinval)
BOOL_FIELD(ext_svnapot)
BOOL_FIELD(ext_svpbmt)
+BOOL_FIELD(ext_smpmpmt)
BOOL_FIELD(ext_svrsw60t59b)
BOOL_FIELD(ext_svvptc)
BOOL_FIELD(ext_svukte)
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 3ef62d26ad..52a7677683 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -165,6 +165,18 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
"ignoring pmpcfg write - invalid\n");
} else {
uint8_t a_field = pmp_get_a_field(val);
+
+ if (!riscv_cpu_cfg(env)->ext_smpmpmt) {
+ /* If smpmpmt not supported, clear the MTMATCH bit */
+ val &= ~PMP_MTMATCH;
+ } else if ((val & PMP_MTMATCH) == PMP_MTMATCH) {
+ /*
+ * If trying to set reserved value (0x3) for MT field,
+ * preserve the original MT field from current config.
+ */
+ val = (val & ~PMP_MTMATCH) |
+ (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_MTMATCH);
+ }
/*
* When granularity g >= 1 (i.e., granularity > 4 bytes),
* the NA4 (Naturally Aligned 4-byte) mode is not selectable
diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h
index 271cf24169..467fb6b4b1 100644
--- a/target/riscv/pmp.h
+++ b/target/riscv/pmp.h
@@ -29,6 +29,7 @@ typedef enum {
PMP_WRITE = 1 << 1,
PMP_EXEC = 1 << 2,
PMP_AMATCH = (3 << 3),
+ PMP_MTMATCH = (3 << 5),
PMP_LOCK = 1 << 7
} pmp_priv_t;
--
2.48.1
On 11/4/25 4:26 AM, Jay Chang wrote:
> The Smpmpmt extension provides a mechanism to control memory attributes
> at the granularity of PMP (Physical Memory Protection) registers, similar
> to how Svpbmt controls memory attributes at the page level.
>
> Version 0.6
> https://github.com/riscv/riscv-isa-manual/blob/smpmpmt/src/smpmpmt.adoc#svpbmt
>
> Signed-off-by: Jay Chang <jay.chang@sifive.com>
> Reviewed-by: Frank Chang <frank.chang@sifive.com>
> ---
> target/riscv/cpu.c | 2 ++
> target/riscv/cpu_cfg_fields.h.inc | 1 +
> target/riscv/pmp.c | 12 ++++++++++++
> target/riscv/pmp.h | 1 +
> 4 files changed, 16 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index ae8b721e55..a0290f06f6 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -230,6 +230,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
> ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
> ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
> ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
> + ISA_EXT_DATA_ENTRY(smpmpmt, PRIV_VERSION_1_12_0, ext_smpmpmt),
We need to place smpmpmt in the correct riscv,isa order, i.e. right before smrnmi.
Otherwise LGTM. Thanks,
Daniel
> ISA_EXT_DATA_ENTRY(svrsw60t59b, PRIV_VERSION_1_13_0, ext_svrsw60t59b),
> ISA_EXT_DATA_ENTRY(svukte, PRIV_VERSION_1_13_0, ext_svukte),
> ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_13_0, ext_svvptc),
> @@ -1262,6 +1263,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
> MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false),
> MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
> MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false),
> + MULTI_EXT_CFG_BOOL("smpmpmt", ext_smpmpmt, false),
> MULTI_EXT_CFG_BOOL("svrsw60t59b", ext_svrsw60t59b, false),
> MULTI_EXT_CFG_BOOL("svvptc", ext_svvptc, true),
>
> diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc
> index a154ecdc79..b1096da664 100644
> --- a/target/riscv/cpu_cfg_fields.h.inc
> +++ b/target/riscv/cpu_cfg_fields.h.inc
> @@ -57,6 +57,7 @@ BOOL_FIELD(ext_svadu)
> BOOL_FIELD(ext_svinval)
> BOOL_FIELD(ext_svnapot)
> BOOL_FIELD(ext_svpbmt)
> +BOOL_FIELD(ext_smpmpmt)
> BOOL_FIELD(ext_svrsw60t59b)
> BOOL_FIELD(ext_svvptc)
> BOOL_FIELD(ext_svukte)
> diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
> index 3ef62d26ad..52a7677683 100644
> --- a/target/riscv/pmp.c
> +++ b/target/riscv/pmp.c
> @@ -165,6 +165,18 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
> "ignoring pmpcfg write - invalid\n");
> } else {
> uint8_t a_field = pmp_get_a_field(val);
> +
> + if (!riscv_cpu_cfg(env)->ext_smpmpmt) {
> + /* If smpmpmt not supported, clear the MTMATCH bit */
> + val &= ~PMP_MTMATCH;
> + } else if ((val & PMP_MTMATCH) == PMP_MTMATCH) {
> + /*
> + * If trying to set reserved value (0x3) for MT field,
> + * preserve the original MT field from current config.
> + */
> + val = (val & ~PMP_MTMATCH) |
> + (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_MTMATCH);
> + }
> /*
> * When granularity g >= 1 (i.e., granularity > 4 bytes),
> * the NA4 (Naturally Aligned 4-byte) mode is not selectable
> diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h
> index 271cf24169..467fb6b4b1 100644
> --- a/target/riscv/pmp.h
> +++ b/target/riscv/pmp.h
> @@ -29,6 +29,7 @@ typedef enum {
> PMP_WRITE = 1 << 1,
> PMP_EXEC = 1 << 2,
> PMP_AMATCH = (3 << 3),
> + PMP_MTMATCH = (3 << 5),
> PMP_LOCK = 1 << 7
> } pmp_priv_t;
>
© 2016 - 2025 Red Hat, Inc.