Smcdeleg requires MINH to read as zero through sireg*. The RV64 callback
masks it by modifying the machine register; the RV32 high-half callback
does not mask it.
Return a masked copy without changing mcyclecfg or minstretcfg. Test both
configuration registers on RV32 and RV64.
Fixes: d9fa41e10156 ("target/riscv: Bugfix make bit 62 read-only 0 for sireg*
cfg CSR read")
Reviewed-by: Chao Liu <[email protected]>
Signed-off-by: TANG Tiancheng <[email protected]>
---
target/riscv/tcg/csr.c | 8 ++--
tests/tcg/riscv32/smcdeleg-minh-rv32.S | 78 ++++++++++++++++++++++++++++++++++
tests/tcg/riscv32/system/meson.build | 7 +++
tests/tcg/riscv64/smcdeleg-minh.S | 78 ++++++++++++++++++++++++++++++++++
tests/tcg/riscv64/system/meson.build | 7 +++
5 files changed, 174 insertions(+), 4 deletions(-)
diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index
f2fe7700fdc64600eff1bb0aef28a0ca212d687c..32c8282dfcb3ec578150f107ccc8bd753085a050
100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -1610,7 +1610,7 @@ static int rmw_cd_ctr_cfg(CPURISCVState *env, int
cfg_index, target_ulong *val,
wr_mask &= ~MCYCLECFG_BIT_MINH;
env->mcyclecfg = (new_val & wr_mask) | (env->mcyclecfg & ~wr_mask);
} else {
- *val = env->mcyclecfg &= ~MHPMEVENT_BIT_MINH;
+ *val = env->mcyclecfg & ~MCYCLECFG_BIT_MINH;
}
break;
case 2: /* INSTRETCFG */
@@ -1619,7 +1619,7 @@ static int rmw_cd_ctr_cfg(CPURISCVState *env, int
cfg_index, target_ulong *val,
env->minstretcfg = (new_val & wr_mask) |
(env->minstretcfg & ~wr_mask);
} else {
- *val = env->minstretcfg &= ~MHPMEVENT_BIT_MINH;
+ *val = env->minstretcfg & ~MINSTRETCFG_BIT_MINH;
}
break;
default:
@@ -1645,7 +1645,7 @@ static int rmw_cd_ctr_cfgh(CPURISCVState *env, int
cfg_index, target_ulong *val,
cfgh = (new_val & wr_mask) | (cfgh & ~wr_mask);
env->mcyclecfg = deposit64(env->mcyclecfg, 32, 32, cfgh);
} else {
- *val = cfgh;
+ *val = cfgh & ~MCYCLECFGH_BIT_MINH;
}
break;
case 2: /* INSTRETCFGH */
@@ -1655,7 +1655,7 @@ static int rmw_cd_ctr_cfgh(CPURISCVState *env, int
cfg_index, target_ulong *val,
cfgh = (new_val & wr_mask) | (cfgh & ~wr_mask);
env->minstretcfg = deposit64(env->minstretcfg, 32, 32, cfgh);
} else {
- *val = cfgh;
+ *val = cfgh & ~MINSTRETCFGH_BIT_MINH;
}
break;
default:
diff --git a/tests/tcg/riscv32/smcdeleg-minh-rv32.S
b/tests/tcg/riscv32/smcdeleg-minh-rv32.S
new file mode 100644
index
0000000000000000000000000000000000000000..db467b95cf1441e3440f59097401cf6956d294d3
--- /dev/null
+++ b/tests/tcg/riscv32/smcdeleg-minh-rv32.S
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* CSR numbers for older assemblers. */
+#define CSR_SISELECT 0x150
+#define CSR_SIREG5 0x156
+#define CSR_MENVCFGH 0x31a
+#define CSR_MCYCLECFGH 0x721
+#define CSR_MINSTRETCFGH 0x722
+
+ .option norvc
+ .option norelax
+
+ .text
+ .global _start
+_start:
+ /*
+ * Failure bits:
+ * 0: delegated cyclecfgh exposes MINH
+ * 1: reading delegated cyclecfgh clears mcyclecfgh.MINH
+ * 2: delegated instretcfgh exposes MINH
+ * 3: reading delegated instretcfgh clears minstretcfgh.MINH
+ */
+ li t4, 0
+ li t0, 1
+ slli t0, t0, 30 /* MINH in the high half */
+ csrw CSR_MCYCLECFGH, t0
+ csrw CSR_MINSTRETCFGH, t0
+ li t1, 1
+ slli t1, t1, 28 /* menvcfgh.CDE */
+ csrw CSR_MENVCFGH, t1
+ li t1, 5 /* Delegate cycle and instret. */
+ csrw mcounteren, t1
+
+ /* Check the delegated view, then the underlying machine register. */
+ li t1, 0x40 /* siselect: cycle */
+ csrw CSR_SISELECT, t1
+ csrr t1, CSR_SIREG5
+ and t1, t1, t0
+ sltu t1, zero, t1
+ or t4, t4, t1
+ csrr t1, CSR_MCYCLECFGH
+ and t1, t1, t0
+ sltu t1, zero, t1
+ xori t1, t1, 1
+ slli t1, t1, 1
+ or t4, t4, t1
+
+ li t1, 0x42 /* siselect: instret */
+ csrw CSR_SISELECT, t1
+ csrr t1, CSR_SIREG5
+ and t1, t1, t0
+ sltu t1, zero, t1
+ slli t1, t1, 2
+ or t4, t4, t1
+ csrr t1, CSR_MINSTRETCFGH
+ and t1, t1, t0
+ sltu t1, zero, t1
+ xori t1, t1, 1
+ slli t1, t1, 3
+ or t4, t4, t1
+
+ lla a1, semiargs
+ li t0, 0x20026 /* ADP_Stopped_ApplicationExit */
+ sw t0, 0(a1)
+ sw t4, 4(a1)
+ li a0, 0x20 /* TARGET_SYS_EXIT_EXTENDED */
+
+ /* Semihosting call sequence. */
+ .balign 16
+ slli zero, zero, 0x1f
+ ebreak
+ srai zero, zero, 0x7
+ j .
+
+ .data
+ .balign 16
+semiargs:
+ .space 8
diff --git a/tests/tcg/riscv32/system/meson.build
b/tests/tcg/riscv32/system/meson.build
index
f8e55ad3d4e6b64dc4a59e048b9cce71fdce120c..09e2c4fc8c6f356dc27ae9299f3231e2e3356891
100644
--- a/tests/tcg/riscv32/system/meson.build
+++ b/tests/tcg/riscv32/system/meson.build
@@ -22,6 +22,13 @@ tests += {
},
}
+tests += {
+ 'smcdeleg-minh-rv32.S': {
+ 'cflags': cflags,
+ 'qemu_args': ['-cpu', 'max', qemu_args],
+ },
+}
+
if 'qemu-system-riscv32' in emulators
tcg_tests += {
'riscv32-softmmu': {
diff --git a/tests/tcg/riscv64/smcdeleg-minh.S
b/tests/tcg/riscv64/smcdeleg-minh.S
new file mode 100644
index
0000000000000000000000000000000000000000..38d3c30f0afaa416a46322f2b892e5969172a60f
--- /dev/null
+++ b/tests/tcg/riscv64/smcdeleg-minh.S
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* CSR numbers for older assemblers. */
+#define CSR_SISELECT 0x150
+#define CSR_SIREG2 0x152
+#define CSR_MENVCFG 0x30a
+#define CSR_MCYCLECFG 0x321
+#define CSR_MINSTRETCFG 0x322
+
+ .option norvc
+ .option norelax
+
+ .text
+ .global _start
+_start:
+ /*
+ * Failure bits:
+ * 0: delegated cyclecfg exposes MINH
+ * 1: reading delegated cyclecfg clears mcyclecfg.MINH
+ * 2: delegated instretcfg exposes MINH
+ * 3: reading delegated instretcfg clears minstretcfg.MINH
+ */
+ li t4, 0
+ li t0, 1
+ slli t0, t0, 62 /* MINH */
+ csrw CSR_MCYCLECFG, t0
+ csrw CSR_MINSTRETCFG, t0
+ li t1, 1
+ slli t1, t1, 60 /* menvcfg.CDE */
+ csrw CSR_MENVCFG, t1
+ li t1, 5 /* Delegate cycle and instret. */
+ csrw mcounteren, t1
+
+ /* Check the delegated view, then the underlying machine register. */
+ li t1, 0x40 /* siselect: cycle */
+ csrw CSR_SISELECT, t1
+ csrr t1, CSR_SIREG2
+ and t1, t1, t0
+ sltu t1, zero, t1
+ or t4, t4, t1
+ csrr t1, CSR_MCYCLECFG
+ and t1, t1, t0
+ sltu t1, zero, t1
+ xori t1, t1, 1
+ slli t1, t1, 1
+ or t4, t4, t1
+
+ li t1, 0x42 /* siselect: instret */
+ csrw CSR_SISELECT, t1
+ csrr t1, CSR_SIREG2
+ and t1, t1, t0
+ sltu t1, zero, t1
+ slli t1, t1, 2
+ or t4, t4, t1
+ csrr t1, CSR_MINSTRETCFG
+ and t1, t1, t0
+ sltu t1, zero, t1
+ xori t1, t1, 1
+ slli t1, t1, 3
+ or t4, t4, t1
+
+ lla a1, semiargs
+ li t0, 0x20026 /* ADP_Stopped_ApplicationExit */
+ sd t0, 0(a1)
+ sd t4, 8(a1)
+ li a0, 0x20 /* TARGET_SYS_EXIT_EXTENDED */
+
+ /* Semihosting call sequence. */
+ .balign 16
+ slli zero, zero, 0x1f
+ ebreak
+ srai zero, zero, 0x7
+ j .
+
+ .data
+ .balign 16
+semiargs:
+ .space 16
diff --git a/tests/tcg/riscv64/system/meson.build
b/tests/tcg/riscv64/system/meson.build
index
3108e6595d4e91e6a941e006206992a41ddbe436..6af497a1a41debe58dfa329060510bd896c88ac7
100644
--- a/tests/tcg/riscv64/system/meson.build
+++ b/tests/tcg/riscv64/system/meson.build
@@ -75,6 +75,13 @@ tests += {
},
}
+tests += {
+ 'smcdeleg-minh.S': {
+ 'cflags': cflags,
+ 'qemu_args': ['-cpu', 'max', qemu_args],
+ },
+}
+
if 'qemu-system-riscv64' in emulators
tcg_tests += {
'riscv64-softmmu': {
--
2.43.0