From 0bc71ee0b70ba8842cbf919ba4fcfd6a37f8f716 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:17 +0800 Subject: [PATCH 01/18] target/riscv: gdbstub: Check priv spec version before reporting CSR The gdbstub CSR XML is dynamically generated according to the result of the CSR predicate() result. This has been working fine until commit 7100fe6c2441 ("target/riscv: Enable privileged spec version 1.12") introduced the privilege spec version check in riscv_csrrw_check(). When debugging the 'sifive_u' machine whose priv spec is at 1.10, gdbstub reports priv spec 1.12 CSRs like menvcfg in the XML, hence we see "remote failure reply 'E14'" message when examining all CSRs via "info register system" from gdb. Add the priv spec version check in the CSR XML generation logic to fix this issue. Fixes: 7100fe6c2441 ("target/riscv: Enable privileged spec version 1.12") Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-2-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/gdbstub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 6e7bbdbd5e..e57372db38 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -290,6 +290,9 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) g_string_append_printf(s, ""); for (i = 0; i < CSR_TABLE_SIZE; i++) { + if (env->priv_ver < csr_ops[i].min_priv_ver) { + continue; + } predicate = csr_ops[i].predicate; if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) { if (csr_ops[i].name) { From a5e0f68652fe1ed0231311d6c8aaeaf55c631821 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:18 +0800 Subject: [PATCH 02/18] target/riscv: Add some comments to clarify the priority policy of riscv_csrrw_check() The priority policy of riscv_csrrw_check() was once adjusted in commit eacaf4401956 ("target/riscv: Fix priority of csr related check in riscv_csrrw_check") whose commit message says the CSR existence check should come before the access control check, but the code changes did not agree with the commit message, that the predicate() check actually came after the read / write check. In fact this was intentional. Add some comments there so that people won't bother trying to change it without a solid reason. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Message-ID: <20230228104035.1879882-3-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 75a540bfcb..4cc2c6370f 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3776,11 +3776,12 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, int read_only = get_field(csrno, 0xC00) == 3; int csr_min_priv = csr_ops[csrno].min_priv_ver; - /* ensure the CSR extension is enabled. */ + /* ensure the CSR extension is enabled */ if (!cpu->cfg.ext_icsr) { return RISCV_EXCP_ILLEGAL_INST; } + /* privileged spec version check */ if (env->priv_ver < csr_min_priv) { return RISCV_EXCP_ILLEGAL_INST; } @@ -3790,10 +3791,18 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, return RISCV_EXCP_ILLEGAL_INST; } + /* read / write check */ if (write_mask && read_only) { return RISCV_EXCP_ILLEGAL_INST; } + /* + * The predicate() not only does existence check but also does some + * access control check which triggers for example virtual instruction + * exception in some cases. When writing read-only CSRs in those cases + * illegal instruction exception should be triggered instead of virtual + * instruction exception. Hence this comes after the read / write check. + */ RISCVException ret = csr_ops[csrno].predicate(env, csrno); if (ret != RISCV_EXCP_NONE) { return ret; From 0ee342256af9205e7388efdf193a6d8f1ba1a617 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:19 +0800 Subject: [PATCH 03/18] target/riscv: Use g_assert() for the predicate() NULL check At present riscv_csrrw_check() checks the CSR predicate() against NULL and throws RISCV_EXCP_ILLEGAL_INST if it is NULL. But this is a pure software check, and has nothing to do with the emulation of the hardware behavior, thus it is inappropriate to return illegal instruction exception when software forgets to install the hook. Change to use g_assert() instead. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Message-ID: <20230228104035.1879882-4-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 4cc2c6370f..cfd7ffc5c2 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3786,11 +3786,6 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, return RISCV_EXCP_ILLEGAL_INST; } - /* check predicate */ - if (!csr_ops[csrno].predicate) { - return RISCV_EXCP_ILLEGAL_INST; - } - /* read / write check */ if (write_mask && read_only) { return RISCV_EXCP_ILLEGAL_INST; @@ -3803,6 +3798,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, * illegal instruction exception should be triggered instead of virtual * instruction exception. Hence this comes after the read / write check. */ + g_assert(csr_ops[csrno].predicate != NULL); RISCVException ret = csr_ops[csrno].predicate(env, csrno); if (ret != RISCV_EXCP_NONE) { return ret; From 28eb8bee83c6223f5921f95844e381fe01ec9e0f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:20 +0800 Subject: [PATCH 04/18] target/riscv: gdbstub: Minor change for better readability Use a variable 'base_reg' to represent cs->gdb_num_regs so that the call to ricsv_gen_dynamic_vector_xml() can be placed in one single line for better readability. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-5-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/gdbstub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index e57372db38..704f3d6922 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -385,9 +385,9 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) 32, "riscv-32bit-fpu.xml", 0); } if (env->misa_ext & RVV) { + int base_reg = cs->gdb_num_regs; gdb_register_coprocessor(cs, riscv_gdb_get_vector, riscv_gdb_set_vector, - ricsv_gen_dynamic_vector_xml(cs, - cs->gdb_num_regs), + ricsv_gen_dynamic_vector_xml(cs, base_reg), "riscv-vector.xml", 0); } switch (env->misa_mxl_max) { From e17e2c7cb968e519eb1f6c676e5c98e21f016310 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:21 +0800 Subject: [PATCH 05/18] target/riscv: gdbstub: Do not generate CSR XML if Zicsr is disabled There is no need to generate the CSR XML if the Zicsr extension is not enabled. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-6-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/gdbstub.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 704f3d6922..294f0ceb1c 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -406,7 +406,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) g_assert_not_reached(); } - gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, - riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs), - "riscv-csr.xml", 0); + if (cpu->cfg.ext_icsr) { + int base_reg = cs->gdb_num_regs; + gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, + riscv_gen_dynamic_csr_xml(cs, base_reg), + "riscv-csr.xml", 0); + } } From 8c7feddddd9218b407792120bcfda0347ed16205 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:22 +0800 Subject: [PATCH 06/18] target/riscv: Coding style fixes in csr.c Fix various places that violate QEMU coding style: - correct multi-line comment format - indent to opening parenthesis Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-7-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 62 ++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index cfd7ffc5c2..6a82628749 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -963,7 +963,7 @@ static RISCVException sstc_32(CPURISCVState *env, int csrno) } static RISCVException read_vstimecmp(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { *val = env->vstimecmp; @@ -971,7 +971,7 @@ static RISCVException read_vstimecmp(CPURISCVState *env, int csrno, } static RISCVException read_vstimecmph(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { *val = env->vstimecmp >> 32; @@ -979,7 +979,7 @@ static RISCVException read_vstimecmph(CPURISCVState *env, int csrno, } static RISCVException write_vstimecmp(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { RISCVCPU *cpu = env_archcpu(env); @@ -996,7 +996,7 @@ static RISCVException write_vstimecmp(CPURISCVState *env, int csrno, } static RISCVException write_vstimecmph(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { RISCVCPU *cpu = env_archcpu(env); @@ -1020,7 +1020,7 @@ static RISCVException read_stimecmp(CPURISCVState *env, int csrno, } static RISCVException read_stimecmph(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { if (riscv_cpu_virt_enabled(env)) { *val = env->vstimecmp >> 32; @@ -1032,7 +1032,7 @@ static RISCVException read_stimecmph(CPURISCVState *env, int csrno, } static RISCVException write_stimecmp(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { RISCVCPU *cpu = env_archcpu(env); @@ -1055,7 +1055,7 @@ static RISCVException write_stimecmp(CPURISCVState *env, int csrno, } static RISCVException write_stimecmph(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { RISCVCPU *cpu = env_archcpu(env); @@ -1342,7 +1342,8 @@ static RISCVException write_misa(CPURISCVState *env, int csrno, /* 'E' excludes all other extensions */ if (val & RVE) { - /* when we support 'E' we can do "val = RVE;" however + /* + * when we support 'E' we can do "val = RVE;" however * for now we just drop writes if 'E' is present. */ return RISCV_EXCP_NONE; @@ -1361,7 +1362,8 @@ static RISCVException write_misa(CPURISCVState *env, int csrno, val &= ~RVD; } - /* Suppress 'C' if next instruction is not aligned + /* + * Suppress 'C' if next instruction is not aligned * TODO: this should check next_pc */ if ((val & RVC) && (GETPC() & ~3) != 0) { @@ -1830,28 +1832,28 @@ static RISCVException write_mscratch(CPURISCVState *env, int csrno, } static RISCVException read_mepc(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { *val = env->mepc; return RISCV_EXCP_NONE; } static RISCVException write_mepc(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { env->mepc = val; return RISCV_EXCP_NONE; } static RISCVException read_mcause(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { *val = env->mcause; return RISCV_EXCP_NONE; } static RISCVException write_mcause(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { env->mcause = val; return RISCV_EXCP_NONE; @@ -1873,14 +1875,14 @@ static RISCVException write_mtval(CPURISCVState *env, int csrno, /* Execution environment configuration setup */ static RISCVException read_menvcfg(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { *val = env->menvcfg; return RISCV_EXCP_NONE; } static RISCVException write_menvcfg(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE; @@ -1893,14 +1895,14 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno, } static RISCVException read_menvcfgh(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { *val = env->menvcfg >> 32; return RISCV_EXCP_NONE; } static RISCVException write_menvcfgh(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { uint64_t mask = MENVCFG_PBMTE | MENVCFG_STCE; uint64_t valh = (uint64_t)val << 32; @@ -1911,7 +1913,7 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno, } static RISCVException read_senvcfg(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { RISCVException ret; @@ -1925,7 +1927,7 @@ static RISCVException read_senvcfg(CPURISCVState *env, int csrno, } static RISCVException write_senvcfg(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE; RISCVException ret; @@ -1940,7 +1942,7 @@ static RISCVException write_senvcfg(CPURISCVState *env, int csrno, } static RISCVException read_henvcfg(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { RISCVException ret; @@ -1954,7 +1956,7 @@ static RISCVException read_henvcfg(CPURISCVState *env, int csrno, } static RISCVException write_henvcfg(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE; RISCVException ret; @@ -1974,7 +1976,7 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno, } static RISCVException read_henvcfgh(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { RISCVException ret; @@ -1988,7 +1990,7 @@ static RISCVException read_henvcfgh(CPURISCVState *env, int csrno, } static RISCVException write_henvcfgh(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE; uint64_t valh = (uint64_t)val << 32; @@ -2031,13 +2033,13 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno, } static RISCVException write_mstateen_1_3(CPURISCVState *env, int csrno, - target_ulong new_val) + target_ulong new_val) { return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val); } static RISCVException read_mstateenh(CPURISCVState *env, int csrno, - target_ulong *val) + target_ulong *val) { *val = env->mstateen[csrno - CSR_MSTATEEN0H] >> 32; @@ -2058,7 +2060,7 @@ static RISCVException write_mstateenh(CPURISCVState *env, int csrno, } static RISCVException write_mstateen0h(CPURISCVState *env, int csrno, - target_ulong new_val) + target_ulong new_val) { uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG; @@ -2066,7 +2068,7 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno, } static RISCVException write_mstateenh_1_3(CPURISCVState *env, int csrno, - target_ulong new_val) + target_ulong new_val) { return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val); } @@ -2103,7 +2105,7 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno, } static RISCVException write_hstateen_1_3(CPURISCVState *env, int csrno, - target_ulong new_val) + target_ulong new_val) { return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val); } @@ -2142,7 +2144,7 @@ static RISCVException write_hstateen0h(CPURISCVState *env, int csrno, } static RISCVException write_hstateenh_1_3(CPURISCVState *env, int csrno, - target_ulong new_val) + target_ulong new_val) { return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val); } @@ -3335,7 +3337,7 @@ static RISCVException read_mseccfg(CPURISCVState *env, int csrno, } static RISCVException write_mseccfg(CPURISCVState *env, int csrno, - target_ulong val) + target_ulong val) { mseccfg_csr_write(env, val); return RISCV_EXCP_NONE; From a7e407b3f87329be533570351fc1658a7ba7b06f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:23 +0800 Subject: [PATCH 07/18] target/riscv: Use 'bool' type for read_only The read_only variable is currently declared as an 'int', but it should really be a 'bool'. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-8-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 6a82628749..9264db6110 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3775,7 +3775,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, RISCVCPU *cpu) { /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */ - int read_only = get_field(csrno, 0xC00) == 3; + bool read_only = get_field(csrno, 0xC00) == 3; int csr_min_priv = csr_ops[csrno].min_priv_ver; /* ensure the CSR extension is enabled */ From 77ad639cb1269ed19fe726edee7c20487b95f7d3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:24 +0800 Subject: [PATCH 08/18] target/riscv: Simplify {read, write}_pmpcfg() a little bit Use the register index that has already been calculated in the pmpcfg_csr_{read,write} call. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-9-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9264db6110..a3e0e5755c 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3360,7 +3360,7 @@ static RISCVException read_pmpcfg(CPURISCVState *env, int csrno, if (!check_pmp_reg_index(env, reg_index)) { return RISCV_EXCP_ILLEGAL_INST; } - *val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0); + *val = pmpcfg_csr_read(env, reg_index); return RISCV_EXCP_NONE; } @@ -3372,7 +3372,7 @@ static RISCVException write_pmpcfg(CPURISCVState *env, int csrno, if (!check_pmp_reg_index(env, reg_index)) { return RISCV_EXCP_ILLEGAL_INST; } - pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val); + pmpcfg_csr_write(env, reg_index, val); return RISCV_EXCP_NONE; } From 94e297071bc0a5965cc32c497a886f2cf9d32710 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:25 +0800 Subject: [PATCH 09/18] target/riscv: Simplify getting RISCVCPU pointer from env Use env_archcpu() to get RISCVCPU pointer from env directly. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-10-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index a3e0e5755c..8e827362cc 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -46,8 +46,7 @@ static RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit) { bool virt = riscv_cpu_virt_enabled(env); - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) { return RISCV_EXCP_NONE; @@ -90,8 +89,7 @@ static RISCVException fs(CPURISCVState *env, int csrno) static RISCVException vs(CPURISCVState *env, int csrno) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); if (env->misa_ext & RVV || cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) { @@ -108,8 +106,7 @@ static RISCVException vs(CPURISCVState *env, int csrno) static RISCVException ctr(CPURISCVState *env, int csrno) { #if !defined(CONFIG_USER_ONLY) - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); int ctr_index; target_ulong ctr_mask; int base_csrno = CSR_CYCLE; @@ -166,8 +163,7 @@ static RISCVException ctr32(CPURISCVState *env, int csrno) #if !defined(CONFIG_USER_ONLY) static RISCVException mctr(CPURISCVState *env, int csrno) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); int ctr_index; int base_csrno = CSR_MHPMCOUNTER3; @@ -195,8 +191,7 @@ static RISCVException mctr32(CPURISCVState *env, int csrno) static RISCVException sscofpmf(CPURISCVState *env, int csrno) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); if (!cpu->cfg.ext_sscofpmf) { return RISCV_EXCP_ILLEGAL_INST; @@ -321,8 +316,7 @@ static RISCVException umode32(CPURISCVState *env, int csrno) static RISCVException mstateen(CPURISCVState *env, int csrno) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); if (!cpu->cfg.ext_smstateen) { return RISCV_EXCP_ILLEGAL_INST; @@ -333,8 +327,7 @@ static RISCVException mstateen(CPURISCVState *env, int csrno) static RISCVException hstateen_pred(CPURISCVState *env, int csrno, int base) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); if (!cpu->cfg.ext_smstateen) { return RISCV_EXCP_ILLEGAL_INST; @@ -363,8 +356,7 @@ static RISCVException sstateen(CPURISCVState *env, int csrno) { bool virt = riscv_cpu_virt_enabled(env); int index = csrno - CSR_SSTATEEN0; - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); if (!cpu->cfg.ext_smstateen) { return RISCV_EXCP_ILLEGAL_INST; @@ -918,8 +910,7 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno, static RISCVException sstc(CPURISCVState *env, int csrno) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); bool hmode_check = false; if (!cpu->cfg.ext_sstc || !env->rdtime_fn) { @@ -1152,8 +1143,7 @@ static RISCVException write_ignore(CPURISCVState *env, int csrno, static RISCVException read_mvendorid(CPURISCVState *env, int csrno, target_ulong *val) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); *val = cpu->cfg.mvendorid; return RISCV_EXCP_NONE; @@ -1162,8 +1152,7 @@ static RISCVException read_mvendorid(CPURISCVState *env, int csrno, static RISCVException read_marchid(CPURISCVState *env, int csrno, target_ulong *val) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); *val = cpu->cfg.marchid; return RISCV_EXCP_NONE; @@ -1172,8 +1161,7 @@ static RISCVException read_marchid(CPURISCVState *env, int csrno, static RISCVException read_mimpid(CPURISCVState *env, int csrno, target_ulong *val) { - CPUState *cs = env_cpu(env); - RISCVCPU *cpu = RISCV_CPU(cs); + RISCVCPU *cpu = env_archcpu(env); *val = cpu->cfg.mimpid; return RISCV_EXCP_NONE; From 04733fb0916f4b2b240da42342374b05d5dfc389 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:26 +0800 Subject: [PATCH 10/18] target/riscv: Avoid reporting odd-numbered pmpcfgX in the CSR XML for RV64 At present the odd-numbered PMP configuration registers for RV64 are reported in the CSR XML by QEMU gdbstub. However these registers do not exist on RV64 so trying to access them from gdb results in 'E14'. Move the pmpcfgX index check from the actual read/write routine to the PMP CSR predicate() routine, so that non-existent pmpcfgX won't be reported in the CSR XML for RV64. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-11-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 8e827362cc..7284fd8a0d 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -412,6 +412,15 @@ static int aia_hmode32(CPURISCVState *env, int csrno) static RISCVException pmp(CPURISCVState *env, int csrno) { if (riscv_cpu_cfg(env)->pmp) { + if (csrno <= CSR_PMPCFG3) { + uint32_t reg_index = csrno - CSR_PMPCFG0; + + /* TODO: RV128 restriction check */ + if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) { + return RISCV_EXCP_ILLEGAL_INST; + } + } + return RISCV_EXCP_NONE; } @@ -3331,23 +3340,11 @@ static RISCVException write_mseccfg(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static bool check_pmp_reg_index(CPURISCVState *env, uint32_t reg_index) -{ - /* TODO: RV128 restriction check */ - if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) { - return false; - } - return true; -} - static RISCVException read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val) { uint32_t reg_index = csrno - CSR_PMPCFG0; - if (!check_pmp_reg_index(env, reg_index)) { - return RISCV_EXCP_ILLEGAL_INST; - } *val = pmpcfg_csr_read(env, reg_index); return RISCV_EXCP_NONE; } @@ -3357,9 +3354,6 @@ static RISCVException write_pmpcfg(CPURISCVState *env, int csrno, { uint32_t reg_index = csrno - CSR_PMPCFG0; - if (!check_pmp_reg_index(env, reg_index)) { - return RISCV_EXCP_ILLEGAL_INST; - } pmpcfg_csr_write(env, reg_index, val); return RISCV_EXCP_NONE; } From a1f0083c6e3eee2d80e712e8a03abd70b25df097 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 18:40:27 +0800 Subject: [PATCH 11/18] target/riscv: gdbstub: Turn on debugger mode before calling CSR predicate() Since commit 94452ac4cf26 ("target/riscv: remove fflags, frm, and fcsr from riscv-*-fpu.xml") the 3 FPU CSRs are removed from the XML target decription. The original intent of that commit was based on the assumption that the 3 FPU CSRs will show up in the riscv-csr.xml so the ones in riscv-*-fpu.xml are redundant. But unforuantely that is not true. As the FPU CSR predicate() has a run-time check on MSTATUS.FS, at the time when CSR XML is generated MSTATUS.FS is unset, hence no FPU CSRs will be reported. The FPU CSR predicate() already considered such a case of being accessed by a debugger. All we need to do is to turn on debugger mode before calling predicate(). Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-12-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/gdbstub.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 294f0ceb1c..ef52f41460 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -280,6 +280,10 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) int bitsize = 16 << env->misa_mxl_max; int i; +#if !defined(CONFIG_USER_ONLY) + env->debugger = true; +#endif + /* Until gdb knows about 128-bit registers */ if (bitsize > 64) { bitsize = 64; @@ -308,6 +312,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) g_string_append_printf(s, ""); cpu->dyn_csr_xml = g_string_free(s, false); + +#if !defined(CONFIG_USER_ONLY) + env->debugger = false; +#endif + return CSR_TABLE_SIZE; } From 7eac8f4191561492fa9fa1e12c80fe27d9842fc6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 21:45:29 +0800 Subject: [PATCH 12/18] target/riscv: gdbstub: Drop the vector CSRs in riscv-vector.xml It's worth noting that the vector CSR predicate() has a similar run-time check logic to the FPU CSR. With the previous patch our gdbstub can correctly report these vector CSRs via the CSR xml. Commit 719d3561b269 ("target/riscv: gdb: support vector registers for rv64 & rv32") inserted these vector CSRs in an ad-hoc, non-standard way in the riscv-vector.xml. Now we can treat these CSRs no different from other CSRs. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-13-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/gdbstub.c | 75 ------------------------------------------ 1 file changed, 75 deletions(-) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index ef52f41460..6048541606 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -127,40 +127,6 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n) return 0; } -/* - * Convert register index number passed by GDB to the correspond - * vector CSR number. Vector CSRs are defined after vector registers - * in dynamic generated riscv-vector.xml, thus the starting register index - * of vector CSRs is 32. - * Return 0 if register index number is out of range. - */ -static int riscv_gdb_vector_csrno(int num_regs) -{ - /* - * The order of vector CSRs in the switch case - * should match with the order defined in csr_ops[]. - */ - switch (num_regs) { - case 32: - return CSR_VSTART; - case 33: - return CSR_VXSAT; - case 34: - return CSR_VXRM; - case 35: - return CSR_VCSR; - case 36: - return CSR_VL; - case 37: - return CSR_VTYPE; - case 38: - return CSR_VLENB; - default: - /* Unknown register. */ - return 0; - } -} - static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n) { uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3; @@ -174,19 +140,6 @@ static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n) return cnt; } - int csrno = riscv_gdb_vector_csrno(n); - - if (!csrno) { - return 0; - } - - target_ulong val = 0; - int result = riscv_csrrw_debug(env, csrno, &val, 0, 0); - - if (result == RISCV_EXCP_NONE) { - return gdb_get_regl(buf, val); - } - return 0; } @@ -201,19 +154,6 @@ static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t *mem_buf, int n) return vlenb; } - int csrno = riscv_gdb_vector_csrno(n); - - if (!csrno) { - return 0; - } - - target_ulong val = ldtul_p(mem_buf); - int result = riscv_csrrw_debug(env, csrno, NULL, val, -1); - - if (result == RISCV_EXCP_NONE) { - return sizeof(target_ulong); - } - return 0; } @@ -361,21 +301,6 @@ static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg) num_regs++; } - /* Define vector CSRs */ - const char *vector_csrs[7] = { - "vstart", "vxsat", "vxrm", "vcsr", - "vl", "vtype", "vlenb" - }; - - for (i = 0; i < 7; i++) { - g_string_append_printf(s, - "", - vector_csrs[i], TARGET_LONG_BITS, base_reg++); - num_regs++; - } - g_string_append_printf(s, ""); cpu->dyn_vreg_xml = g_string_free(s, false); From fb517fdb150b71d6fad8e2332c9aace82143e45f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 21:45:30 +0800 Subject: [PATCH 13/18] target/riscv: Allow debugger to access user timer and counter CSRs At present user timer and counter CSRs are not reported in the CSR XML hence gdb cannot access them. Fix it by adding a debugger check in their predicate() routine. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-14-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 7284fd8a0d..10ae5df5e6 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -131,6 +131,10 @@ static RISCVException ctr(CPURISCVState *env, int csrno) skip_ext_pmu_check: + if (env->debugger) { + return RISCV_EXCP_NONE; + } + if (env->priv < PRV_M && !get_field(env->mcounteren, ctr_mask)) { return RISCV_EXCP_ILLEGAL_INST; } From ddb10742f1acce17dbb8f3551af01bf5bfc4fa14 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 21:45:31 +0800 Subject: [PATCH 14/18] target/riscv: Allow debugger to access seed CSR At present seed CSR is not reported in the CSR XML hence gdb cannot access it. Fix it by adding a debugger check in its predicate() routine. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Reviewed-by: LIU Zhiwei Message-ID: <20230228104035.1879882-15-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 10ae5df5e6..15b23b9b5a 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -459,6 +459,10 @@ static RISCVException seed(CPURISCVState *env, int csrno) } #if !defined(CONFIG_USER_ONLY) + if (env->debugger) { + return RISCV_EXCP_NONE; + } + /* * With a CSR read-write instruction: * 1) The seed CSR is always available in machine mode as normal. From 0308fc621914ba424705d188dc4a58006edb3472 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 21:45:32 +0800 Subject: [PATCH 15/18] target/riscv: Allow debugger to access {h, s}stateen CSRs At present {h,s}stateen CSRs are not reported in the CSR XML hence gdb cannot access them. Fix it by adjusting their predicate() routine logic so that the static config check comes before the run-time check, as well as adding a debugger check. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Message-ID: <20230228104035.1879882-16-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 15b23b9b5a..a0e70f5ba0 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -337,13 +337,22 @@ static RISCVException hstateen_pred(CPURISCVState *env, int csrno, int base) return RISCV_EXCP_ILLEGAL_INST; } + RISCVException ret = hmode(env, csrno); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + if (env->debugger) { + return RISCV_EXCP_NONE; + } + if (env->priv < PRV_M) { if (!(env->mstateen[csrno - base] & SMSTATEEN_STATEEN)) { return RISCV_EXCP_ILLEGAL_INST; } } - return hmode(env, csrno); + return RISCV_EXCP_NONE; } static RISCVException hstateen(CPURISCVState *env, int csrno) @@ -366,6 +375,15 @@ static RISCVException sstateen(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } + RISCVException ret = smode(env, csrno); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + if (env->debugger) { + return RISCV_EXCP_NONE; + } + if (env->priv < PRV_M) { if (!(env->mstateen[index] & SMSTATEEN_STATEEN)) { return RISCV_EXCP_ILLEGAL_INST; @@ -378,7 +396,7 @@ static RISCVException sstateen(CPURISCVState *env, int csrno) } } - return smode(env, csrno); + return RISCV_EXCP_NONE; } /* Checks if PointerMasking registers could be accessed */ From e4e1f216a1ece6a69d10b22bc6f1cf855e054c95 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 21:45:33 +0800 Subject: [PATCH 16/18] target/riscv: Allow debugger to access sstc CSRs At present with a debugger attached sstc CSRs can only be accssed when CPU is in M-mode, or configured correctly. Fix it by adjusting their predicate() routine logic so that the static config check comes before the run-time check, as well as adding a debugger check. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Message-ID: <20230228104035.1879882-17-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index a0e70f5ba0..020c3f524f 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -952,6 +952,19 @@ static RISCVException sstc(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } + if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) { + hmode_check = true; + } + + RISCVException ret = hmode_check ? hmode(env, csrno) : smode(env, csrno); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + if (env->debugger) { + return RISCV_EXCP_NONE; + } + if (env->priv == PRV_M) { return RISCV_EXCP_NONE; } @@ -972,11 +985,7 @@ static RISCVException sstc(CPURISCVState *env, int csrno) } } - if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) { - hmode_check = true; - } - - return hmode_check ? hmode(env, csrno) : smode(env, csrno); + return RISCV_EXCP_NONE; } static RISCVException sstc_32(CPURISCVState *env, int csrno) From 9e83a35661e76652dcbdd761b8a63649f93a3d38 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 21:45:34 +0800 Subject: [PATCH 17/18] target/riscv: Drop priv level check in mseccfg predicate() riscv_csrrw_check() already does the generic privilege level check hence there is no need to do the specific M-mode access check in the mseccfg predicate(). With this change debugger can access the mseccfg CSR anytime. Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Message-ID: <20230228104035.1879882-18-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 020c3f524f..785f6f4d45 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -451,7 +451,7 @@ static RISCVException pmp(CPURISCVState *env, int csrno) static RISCVException epmp(CPURISCVState *env, int csrno) { - if (env->priv == PRV_M && riscv_cpu_cfg(env)->epmp) { + if (riscv_cpu_cfg(env)->epmp) { return RISCV_EXCP_NONE; } From fb5bd4dcaec42b8373f445be9ab2a05aed29c4db Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 28 Feb 2023 21:45:35 +0800 Subject: [PATCH 18/18] target/riscv: Group all predicate() routines together Move sstc()/sstc32() to where all predicate() routines live, and smstateen_acc_ok() to near {read,write}_xenvcfg(). Signed-off-by: Bin Meng Reviewed-by: Weiwei Li Message-ID: <20230228104035.1879882-19-bmeng@tinylab.org> Signed-off-by: Palmer Dabbelt --- target/riscv/csr.c | 177 ++++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 90 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 785f6f4d45..3a7e0217e2 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -40,42 +40,6 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops) csr_ops[csrno & (CSR_TABLE_SIZE - 1)] = *ops; } -/* Predicates */ -#if !defined(CONFIG_USER_ONLY) -static RISCVException smstateen_acc_ok(CPURISCVState *env, int index, - uint64_t bit) -{ - bool virt = riscv_cpu_virt_enabled(env); - RISCVCPU *cpu = env_archcpu(env); - - if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) { - return RISCV_EXCP_NONE; - } - - if (!(env->mstateen[index] & bit)) { - return RISCV_EXCP_ILLEGAL_INST; - } - - if (virt) { - if (!(env->hstateen[index] & bit)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - - if (env->priv == PRV_U && !(env->sstateen[index] & bit)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - } - - if (env->priv == PRV_U && riscv_has_ext(env, RVS)) { - if (!(env->sstateen[index] & bit)) { - return RISCV_EXCP_ILLEGAL_INST; - } - } - - return RISCV_EXCP_NONE; -} -#endif - static RISCVException fs(CPURISCVState *env, int csrno) { #if !defined(CONFIG_USER_ONLY) @@ -399,6 +363,60 @@ static RISCVException sstateen(CPURISCVState *env, int csrno) return RISCV_EXCP_NONE; } +static RISCVException sstc(CPURISCVState *env, int csrno) +{ + RISCVCPU *cpu = env_archcpu(env); + bool hmode_check = false; + + if (!cpu->cfg.ext_sstc || !env->rdtime_fn) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) { + hmode_check = true; + } + + RISCVException ret = hmode_check ? hmode(env, csrno) : smode(env, csrno); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + if (env->debugger) { + return RISCV_EXCP_NONE; + } + + if (env->priv == PRV_M) { + return RISCV_EXCP_NONE; + } + + /* + * No need of separate function for rv32 as menvcfg stores both menvcfg + * menvcfgh for RV32. + */ + if (!(get_field(env->mcounteren, COUNTEREN_TM) && + get_field(env->menvcfg, MENVCFG_STCE))) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if (riscv_cpu_virt_enabled(env)) { + if (!(get_field(env->hcounteren, COUNTEREN_TM) && + get_field(env->henvcfg, HENVCFG_STCE))) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } + } + + return RISCV_EXCP_NONE; +} + +static RISCVException sstc_32(CPURISCVState *env, int csrno) +{ + if (riscv_cpu_mxl(env) != MXL_RV32) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return sstc(env, csrno); +} + /* Checks if PointerMasking registers could be accessed */ static RISCVException pointer_masking(CPURISCVState *env, int csrno) { @@ -943,60 +961,6 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static RISCVException sstc(CPURISCVState *env, int csrno) -{ - RISCVCPU *cpu = env_archcpu(env); - bool hmode_check = false; - - if (!cpu->cfg.ext_sstc || !env->rdtime_fn) { - return RISCV_EXCP_ILLEGAL_INST; - } - - if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) { - hmode_check = true; - } - - RISCVException ret = hmode_check ? hmode(env, csrno) : smode(env, csrno); - if (ret != RISCV_EXCP_NONE) { - return ret; - } - - if (env->debugger) { - return RISCV_EXCP_NONE; - } - - if (env->priv == PRV_M) { - return RISCV_EXCP_NONE; - } - - /* - * No need of separate function for rv32 as menvcfg stores both menvcfg - * menvcfgh for RV32. - */ - if (!(get_field(env->mcounteren, COUNTEREN_TM) && - get_field(env->menvcfg, MENVCFG_STCE))) { - return RISCV_EXCP_ILLEGAL_INST; - } - - if (riscv_cpu_virt_enabled(env)) { - if (!(get_field(env->hcounteren, COUNTEREN_TM) && - get_field(env->henvcfg, HENVCFG_STCE))) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - } - - return RISCV_EXCP_NONE; -} - -static RISCVException sstc_32(CPURISCVState *env, int csrno) -{ - if (riscv_cpu_mxl(env) != MXL_RV32) { - return RISCV_EXCP_ILLEGAL_INST; - } - - return sstc(env, csrno); -} - static RISCVException read_vstimecmp(CPURISCVState *env, int csrno, target_ulong *val) { @@ -1944,6 +1908,39 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException smstateen_acc_ok(CPURISCVState *env, int index, + uint64_t bit) +{ + bool virt = riscv_cpu_virt_enabled(env); + RISCVCPU *cpu = env_archcpu(env); + + if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) { + return RISCV_EXCP_NONE; + } + + if (!(env->mstateen[index] & bit)) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if (virt) { + if (!(env->hstateen[index] & bit)) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } + + if (env->priv == PRV_U && !(env->sstateen[index] & bit)) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } + } + + if (env->priv == PRV_U && riscv_has_ext(env, RVS)) { + if (!(env->sstateen[index] & bit)) { + return RISCV_EXCP_ILLEGAL_INST; + } + } + + return RISCV_EXCP_NONE; +} + static RISCVException read_senvcfg(CPURISCVState *env, int csrno, target_ulong *val) {