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/Makefile.softmmu-target | 22 ++++++++++
 tests/tcg/riscv32/smcdeleg-minh-rv32.S    | 70 +++++++++++++++++++++++++++++++
 tests/tcg/riscv64/Makefile.softmmu-target |  4 ++
 tests/tcg/riscv64/smcdeleg-minh.S         | 70 +++++++++++++++++++++++++++++++
 5 files changed, 170 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/Makefile.softmmu-target 
b/tests/tcg/riscv32/Makefile.softmmu-target
new file mode 100644
index 
0000000000000000000000000000000000000000..67d334974577e14ff36e7c51067ebcab4c1349bd
--- /dev/null
+++ b/tests/tcg/riscv32/Makefile.softmmu-target
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# RISC-V 32-bit system tests
+#
+
+TEST_SRC = $(SRC_PATH)/tests/tcg/riscv32
+VPATH += $(TEST_SRC)
+
+LINK_SCRIPT = $(SRC_PATH)/tests/tcg/riscv64/semihost.ld
+LDFLAGS = -m elf32lriscv -T $(LINK_SCRIPT)
+CFLAGS += -g -Og $(EXTRA_CFLAGS) -march=rv32im_zicsr -mabi=ilp32
+
+%.o: %.S
+       $(CC) $(CFLAGS) $< -Wa,--noexecstack -c -o $@
+%: %.o $(LINK_SCRIPT)
+       $(LD) $(LDFLAGS) $< -o $@
+
+QEMU_OPTS += -M virt -display none -semihosting -device loader,file=
+
+TESTS += smcdeleg-minh-rv32
+run-smcdeleg-minh-rv32: smcdeleg-minh-rv32
+       $(call run-test, $<, $(QEMU) -cpu max $(QEMU_OPTS)$<)
diff --git a/tests/tcg/riscv32/smcdeleg-minh-rv32.S 
b/tests/tcg/riscv32/smcdeleg-minh-rv32.S
new file mode 100644
index 
0000000000000000000000000000000000000000..2e8ee394f5f8a4e01b1c9efc815d21af18de4b3c
--- /dev/null
+++ b/tests/tcg/riscv32/smcdeleg-minh-rv32.S
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+       .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    0x721, t0               /* mcyclecfgh */
+       csrw    0x722, t0               /* minstretcfgh */
+       li      t1, 1
+       slli    t1, t1, 28              /* menvcfgh.CDE */
+       csrw    0x31a, t1
+       li      t1, 5                   /* delegate cycle and instret */
+       csrw    mcounteren, t1
+
+       li      t1, 0x40
+       csrw    0x150, t1               /* siselect: cycle */
+       csrr    t1, 0x156               /* sireg5: cyclecfgh */
+       and     t1, t1, t0
+       sltu    t1, zero, t1
+       or      t4, t4, t1
+       csrr    t1, 0x721
+       and     t1, t1, t0
+       sltu    t1, zero, t1
+       xori    t1, t1, 1
+       slli    t1, t1, 1
+       or      t4, t4, t1
+
+       li      t1, 0x42
+       csrw    0x150, t1               /* siselect: instret */
+       csrr    t1, 0x156               /* sireg5: instretcfgh */
+       and     t1, t1, t0
+       sltu    t1, zero, t1
+       slli    t1, t1, 2
+       or      t4, t4, t1
+       csrr    t1, 0x722
+       and     t1, t1, t0
+       sltu    t1, zero, t1
+       xori    t1, t1, 1
+       slli    t1, t1, 3
+       or      t4, t4, t1
+
+       la      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/riscv64/Makefile.softmmu-target 
b/tests/tcg/riscv64/Makefile.softmmu-target
index 
677244e8b187435b09fc6b7616e269992543587c..af6bc1aad8893726a3b26392da89f34319dd78a8
 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -48,6 +48,10 @@ TESTS += sscofpmf-cycle-overflow
 run-sscofpmf-cycle-overflow: sscofpmf-cycle-overflow
        $(call run-test, $<, $(QEMU) -cpu max -icount shift=3 $(QEMU_OPTS)$<)
 
+TESTS += smcdeleg-minh
+run-smcdeleg-minh: smcdeleg-minh
+       $(call run-test, $<, $(QEMU) -cpu max $(QEMU_OPTS)$<)
+
 EXTRA_RUNS += run-plugin-doubletrap
 run-plugin-doubletrap: doubletrap
        $(call run-test, $<, \
diff --git a/tests/tcg/riscv64/smcdeleg-minh.S 
b/tests/tcg/riscv64/smcdeleg-minh.S
new file mode 100644
index 
0000000000000000000000000000000000000000..41cbb580475b5dcd079d4542631dfe2474536d60
--- /dev/null
+++ b/tests/tcg/riscv64/smcdeleg-minh.S
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+       .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    0x321, t0               /* mcyclecfg */
+       csrw    0x322, t0               /* minstretcfg */
+       li      t1, 1
+       slli    t1, t1, 60              /* menvcfg.CDE */
+       csrw    0x30a, t1
+       li      t1, 5                   /* delegate cycle and instret */
+       csrw    mcounteren, t1
+
+       li      t1, 0x40
+       csrw    0x150, t1               /* siselect: cycle */
+       csrr    t1, 0x152               /* sireg2: cyclecfg */
+       and     t1, t1, t0
+       sltu    t1, zero, t1
+       or      t4, t4, t1
+       csrr    t1, 0x321               /* mcyclecfg: MINH remains set */
+       and     t1, t1, t0
+       sltu    t1, zero, t1
+       xori    t1, t1, 1
+       slli    t1, t1, 1
+       or      t4, t4, t1
+
+       li      t1, 0x42
+       csrw    0x150, t1               /* siselect: instret */
+       csrr    t1, 0x152               /* sireg2: instretcfg */
+       and     t1, t1, t0
+       sltu    t1, zero, t1
+       slli    t1, t1, 2
+       or      t4, t4, t1
+       csrr    t1, 0x322               /* minstretcfg: MINH remains set */
+       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

-- 
2.43.0


Reply via email to