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")
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
60caee32dc0cf5b6a8492e0cf8ff15f71acc2087..57030724f85a897e21e5082b9857411b50f932ac
100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -1607,7 +1607,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 */
@@ -1616,7 +1616,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:
@@ -1642,7 +1642,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 */
@@ -1652,7 +1652,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
16f9a06c9485ed75b3d127d6b9d090f5eaad4486..cfe2d854b729a8dfdbce2373e73b91b470db6b4e
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
668a9a76070b6f16087b08ea84683d883312e951..5d91381c62d77ae7e37c129112d6367f692df660
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