target/riscv/csr.c | 56 +++++++++++++++++++++++++--------------- target/riscv/op_helper.c | 12 ++++----- 2 files changed, 41 insertions(+), 27 deletions(-)
- Trap satp/hgatp accesses from HS-mode when MSTATUS.TVM is enabled.
- Trap satp accesses from VS-mode when HSTATUS.VTVM is enabled.
- Raise RISCV_EXCP_ILLEGAL_INST when U-mode executes SFENCE.VMA/SINVAL.VMA.
- Raise RISCV_EXCP_VIRT_INSTRUCTION_FAULT when VU-mode executes
SFENCE.VMA/SINVAL.VMA or VS-mode executes SFENCE.VMA/SINVAL.VMA with
HSTATUS.VTVM enabled.
- Raise RISCV_EXCP_VIRT_INSTRUCTION_FAULT when VU-mode executes
HFENCE.GVMA/HFENCE.VVMA/HINVAL.GVMA/HINVAL.VVMA.
Signed-off-by: Yi Chen <chenyi2000@zju.edu.cn>
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
---
Rebase the patch on https://github.com/alistair23/qemu/tree/riscv-to-apply.next
Add "Reviewed-by: LIU Zhiwei"
target/riscv/csr.c | 56 +++++++++++++++++++++++++---------------
target/riscv/op_helper.c | 12 ++++-----
2 files changed, 41 insertions(+), 27 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index e0b871f6dc..d6669d8524 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -449,6 +449,30 @@ static RISCVException sstc_32(CPURISCVState *env, int csrno)
return sstc(env, csrno);
}
+static RISCVException satp(CPURISCVState *env, int csrno)
+{
+ if (env->priv == PRV_S && !env->virt_enabled &&
+ get_field(env->mstatus, MSTATUS_TVM)) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+ if (env->priv == PRV_S && env->virt_enabled &&
+ get_field(env->hstatus, HSTATUS_VTVM)) {
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+
+ return smode(env, csrno);
+}
+
+static RISCVException hgatp(CPURISCVState *env, int csrno)
+{
+ if (env->priv == PRV_S && !env->virt_enabled &&
+ get_field(env->mstatus, MSTATUS_TVM)) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return hmode(env, csrno);
+}
+
/* Checks if PointerMasking registers could be accessed */
static RISCVException pointer_masking(CPURISCVState *env, int csrno)
{
@@ -2647,13 +2671,7 @@ static RISCVException read_satp(CPURISCVState *env, int csrno,
*val = 0;
return RISCV_EXCP_NONE;
}
-
- if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
- return RISCV_EXCP_ILLEGAL_INST;
- } else {
- *val = env->satp;
- }
-
+ *val = env->satp;
return RISCV_EXCP_NONE;
}
@@ -2676,18 +2694,14 @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
}
if (vm && mask) {
- if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
- return RISCV_EXCP_ILLEGAL_INST;
- } else {
- /*
- * The ISA defines SATP.MODE=Bare as "no translation", but we still
- * pass these through QEMU's TLB emulation as it improves
- * performance. Flushing the TLB on SATP writes with paging
- * enabled avoids leaking those invalid cached mappings.
- */
- tlb_flush(env_cpu(env));
- env->satp = val;
- }
+ /*
+ * The ISA defines SATP.MODE=Bare as "no translation", but we still
+ * pass these through QEMU's TLB emulation as it improves
+ * performance. Flushing the TLB on SATP writes with paging
+ * enabled avoids leaking those invalid cached mappings.
+ */
+ tlb_flush(env_cpu(env));
+ env->satp = val;
}
return RISCV_EXCP_NONE;
}
@@ -4183,7 +4197,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
.min_priv_ver = PRIV_VERSION_1_12_0 },
/* Supervisor Protection and Translation */
- [CSR_SATP] = { "satp", smode, read_satp, write_satp },
+ [CSR_SATP] = { "satp", satp, read_satp, write_satp },
/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
[CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect },
@@ -4220,7 +4234,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
.min_priv_ver = PRIV_VERSION_1_12_0 },
[CSR_HGEIP] = { "hgeip", hmode, read_hgeip,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp,
+ [CSR_HGATP] = { "hgatp", hgatp, read_hgatp, write_hgatp,
.min_priv_ver = PRIV_VERSION_1_12_0 },
[CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta,
write_htimedelta,
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index ec9a384772..7cbe13db3f 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -380,12 +380,12 @@ void helper_wfi(CPURISCVState *env)
void helper_tlb_flush(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
- if (!(env->priv >= PRV_S) ||
- (env->priv == PRV_S &&
- get_field(env->mstatus, MSTATUS_TVM))) {
+ if (!env->virt_enabled &&
+ (env->priv == PRV_U ||
+ (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)))) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
- } else if (riscv_has_ext(env, RVH) && env->virt_enabled &&
- get_field(env->hstatus, HSTATUS_VTVM)) {
+ } else if (env->virt_enabled &&
+ (env->priv == PRV_U || get_field(env->hstatus, HSTATUS_VTVM))) {
riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
} else {
tlb_flush(cs);
@@ -402,7 +402,7 @@ void helper_hyp_tlb_flush(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
- if (env->priv == PRV_S && env->virt_enabled) {
+ if (env->virt_enabled) {
riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
}
--
2.40.0
On Thu, Apr 6, 2023 at 8:17 PM Yi Chen <chenyi2000@zju.edu.cn> wrote: > > - Trap satp/hgatp accesses from HS-mode when MSTATUS.TVM is enabled. > - Trap satp accesses from VS-mode when HSTATUS.VTVM is enabled. > - Raise RISCV_EXCP_ILLEGAL_INST when U-mode executes SFENCE.VMA/SINVAL.VMA. > - Raise RISCV_EXCP_VIRT_INSTRUCTION_FAULT when VU-mode executes > SFENCE.VMA/SINVAL.VMA or VS-mode executes SFENCE.VMA/SINVAL.VMA with > HSTATUS.VTVM enabled. > - Raise RISCV_EXCP_VIRT_INSTRUCTION_FAULT when VU-mode executes > HFENCE.GVMA/HFENCE.VVMA/HINVAL.GVMA/HINVAL.VVMA. > > Signed-off-by: Yi Chen <chenyi2000@zju.edu.cn> > Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn> > Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Thanks! Applied to riscv-to-apply.next Alistair > --- > Rebase the patch on https://github.com/alistair23/qemu/tree/riscv-to-apply.next > Add "Reviewed-by: LIU Zhiwei" > target/riscv/csr.c | 56 +++++++++++++++++++++++++--------------- > target/riscv/op_helper.c | 12 ++++----- > 2 files changed, 41 insertions(+), 27 deletions(-) > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index e0b871f6dc..d6669d8524 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -449,6 +449,30 @@ static RISCVException sstc_32(CPURISCVState *env, int csrno) > return sstc(env, csrno); > } > > +static RISCVException satp(CPURISCVState *env, int csrno) > +{ > + if (env->priv == PRV_S && !env->virt_enabled && > + get_field(env->mstatus, MSTATUS_TVM)) { > + return RISCV_EXCP_ILLEGAL_INST; > + } > + if (env->priv == PRV_S && env->virt_enabled && > + get_field(env->hstatus, HSTATUS_VTVM)) { > + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; > + } > + > + return smode(env, csrno); > +} > + > +static RISCVException hgatp(CPURISCVState *env, int csrno) > +{ > + if (env->priv == PRV_S && !env->virt_enabled && > + get_field(env->mstatus, MSTATUS_TVM)) { > + return RISCV_EXCP_ILLEGAL_INST; > + } > + > + return hmode(env, csrno); > +} > + > /* Checks if PointerMasking registers could be accessed */ > static RISCVException pointer_masking(CPURISCVState *env, int csrno) > { > @@ -2647,13 +2671,7 @@ static RISCVException read_satp(CPURISCVState *env, int csrno, > *val = 0; > return RISCV_EXCP_NONE; > } > - > - if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { > - return RISCV_EXCP_ILLEGAL_INST; > - } else { > - *val = env->satp; > - } > - > + *val = env->satp; > return RISCV_EXCP_NONE; > } > > @@ -2676,18 +2694,14 @@ static RISCVException write_satp(CPURISCVState *env, int csrno, > } > > if (vm && mask) { > - if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { > - return RISCV_EXCP_ILLEGAL_INST; > - } else { > - /* > - * The ISA defines SATP.MODE=Bare as "no translation", but we still > - * pass these through QEMU's TLB emulation as it improves > - * performance. Flushing the TLB on SATP writes with paging > - * enabled avoids leaking those invalid cached mappings. > - */ > - tlb_flush(env_cpu(env)); > - env->satp = val; > - } > + /* > + * The ISA defines SATP.MODE=Bare as "no translation", but we still > + * pass these through QEMU's TLB emulation as it improves > + * performance. Flushing the TLB on SATP writes with paging > + * enabled avoids leaking those invalid cached mappings. > + */ > + tlb_flush(env_cpu(env)); > + env->satp = val; > } > return RISCV_EXCP_NONE; > } > @@ -4183,7 +4197,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > .min_priv_ver = PRIV_VERSION_1_12_0 }, > > /* Supervisor Protection and Translation */ > - [CSR_SATP] = { "satp", smode, read_satp, write_satp }, > + [CSR_SATP] = { "satp", satp, read_satp, write_satp }, > > /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */ > [CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect }, > @@ -4220,7 +4234,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > .min_priv_ver = PRIV_VERSION_1_12_0 }, > [CSR_HGEIP] = { "hgeip", hmode, read_hgeip, > .min_priv_ver = PRIV_VERSION_1_12_0 }, > - [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp, > + [CSR_HGATP] = { "hgatp", hgatp, read_hgatp, write_hgatp, > .min_priv_ver = PRIV_VERSION_1_12_0 }, > [CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, > write_htimedelta, > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c > index ec9a384772..7cbe13db3f 100644 > --- a/target/riscv/op_helper.c > +++ b/target/riscv/op_helper.c > @@ -380,12 +380,12 @@ void helper_wfi(CPURISCVState *env) > void helper_tlb_flush(CPURISCVState *env) > { > CPUState *cs = env_cpu(env); > - if (!(env->priv >= PRV_S) || > - (env->priv == PRV_S && > - get_field(env->mstatus, MSTATUS_TVM))) { > + if (!env->virt_enabled && > + (env->priv == PRV_U || > + (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)))) { > riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); > - } else if (riscv_has_ext(env, RVH) && env->virt_enabled && > - get_field(env->hstatus, HSTATUS_VTVM)) { > + } else if (env->virt_enabled && > + (env->priv == PRV_U || get_field(env->hstatus, HSTATUS_VTVM))) { > riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); > } else { > tlb_flush(cs); > @@ -402,7 +402,7 @@ void helper_hyp_tlb_flush(CPURISCVState *env) > { > CPUState *cs = env_cpu(env); > > - if (env->priv == PRV_S && env->virt_enabled) { > + if (env->virt_enabled) { > riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); > } > > -- > 2.40.0 > >
On Thu, Apr 6, 2023 at 8:17 PM Yi Chen <chenyi2000@zju.edu.cn> wrote: > > - Trap satp/hgatp accesses from HS-mode when MSTATUS.TVM is enabled. > - Trap satp accesses from VS-mode when HSTATUS.VTVM is enabled. > - Raise RISCV_EXCP_ILLEGAL_INST when U-mode executes SFENCE.VMA/SINVAL.VMA. > - Raise RISCV_EXCP_VIRT_INSTRUCTION_FAULT when VU-mode executes > SFENCE.VMA/SINVAL.VMA or VS-mode executes SFENCE.VMA/SINVAL.VMA with > HSTATUS.VTVM enabled. > - Raise RISCV_EXCP_VIRT_INSTRUCTION_FAULT when VU-mode executes > HFENCE.GVMA/HFENCE.VVMA/HINVAL.GVMA/HINVAL.VVMA. > > Signed-off-by: Yi Chen <chenyi2000@zju.edu.cn> > Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn> > Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > Rebase the patch on https://github.com/alistair23/qemu/tree/riscv-to-apply.next > Add "Reviewed-by: LIU Zhiwei" > target/riscv/csr.c | 56 +++++++++++++++++++++++++--------------- > target/riscv/op_helper.c | 12 ++++----- > 2 files changed, 41 insertions(+), 27 deletions(-) > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index e0b871f6dc..d6669d8524 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -449,6 +449,30 @@ static RISCVException sstc_32(CPURISCVState *env, int csrno) > return sstc(env, csrno); > } > > +static RISCVException satp(CPURISCVState *env, int csrno) > +{ > + if (env->priv == PRV_S && !env->virt_enabled && > + get_field(env->mstatus, MSTATUS_TVM)) { > + return RISCV_EXCP_ILLEGAL_INST; > + } > + if (env->priv == PRV_S && env->virt_enabled && > + get_field(env->hstatus, HSTATUS_VTVM)) { > + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; > + } > + > + return smode(env, csrno); > +} > + > +static RISCVException hgatp(CPURISCVState *env, int csrno) > +{ > + if (env->priv == PRV_S && !env->virt_enabled && > + get_field(env->mstatus, MSTATUS_TVM)) { > + return RISCV_EXCP_ILLEGAL_INST; > + } > + > + return hmode(env, csrno); > +} > + > /* Checks if PointerMasking registers could be accessed */ > static RISCVException pointer_masking(CPURISCVState *env, int csrno) > { > @@ -2647,13 +2671,7 @@ static RISCVException read_satp(CPURISCVState *env, int csrno, > *val = 0; > return RISCV_EXCP_NONE; > } > - > - if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { > - return RISCV_EXCP_ILLEGAL_INST; > - } else { > - *val = env->satp; > - } > - > + *val = env->satp; > return RISCV_EXCP_NONE; > } > > @@ -2676,18 +2694,14 @@ static RISCVException write_satp(CPURISCVState *env, int csrno, > } > > if (vm && mask) { > - if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) { > - return RISCV_EXCP_ILLEGAL_INST; > - } else { > - /* > - * The ISA defines SATP.MODE=Bare as "no translation", but we still > - * pass these through QEMU's TLB emulation as it improves > - * performance. Flushing the TLB on SATP writes with paging > - * enabled avoids leaking those invalid cached mappings. > - */ > - tlb_flush(env_cpu(env)); > - env->satp = val; > - } > + /* > + * The ISA defines SATP.MODE=Bare as "no translation", but we still > + * pass these through QEMU's TLB emulation as it improves > + * performance. Flushing the TLB on SATP writes with paging > + * enabled avoids leaking those invalid cached mappings. > + */ > + tlb_flush(env_cpu(env)); > + env->satp = val; > } > return RISCV_EXCP_NONE; > } > @@ -4183,7 +4197,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > .min_priv_ver = PRIV_VERSION_1_12_0 }, > > /* Supervisor Protection and Translation */ > - [CSR_SATP] = { "satp", smode, read_satp, write_satp }, > + [CSR_SATP] = { "satp", satp, read_satp, write_satp }, > > /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */ > [CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect }, > @@ -4220,7 +4234,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > .min_priv_ver = PRIV_VERSION_1_12_0 }, > [CSR_HGEIP] = { "hgeip", hmode, read_hgeip, > .min_priv_ver = PRIV_VERSION_1_12_0 }, > - [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp, > + [CSR_HGATP] = { "hgatp", hgatp, read_hgatp, write_hgatp, > .min_priv_ver = PRIV_VERSION_1_12_0 }, > [CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, > write_htimedelta, > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c > index ec9a384772..7cbe13db3f 100644 > --- a/target/riscv/op_helper.c > +++ b/target/riscv/op_helper.c > @@ -380,12 +380,12 @@ void helper_wfi(CPURISCVState *env) > void helper_tlb_flush(CPURISCVState *env) > { > CPUState *cs = env_cpu(env); > - if (!(env->priv >= PRV_S) || > - (env->priv == PRV_S && > - get_field(env->mstatus, MSTATUS_TVM))) { > + if (!env->virt_enabled && > + (env->priv == PRV_U || > + (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)))) { > riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); > - } else if (riscv_has_ext(env, RVH) && env->virt_enabled && > - get_field(env->hstatus, HSTATUS_VTVM)) { > + } else if (env->virt_enabled && > + (env->priv == PRV_U || get_field(env->hstatus, HSTATUS_VTVM))) { > riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); > } else { > tlb_flush(cs); > @@ -402,7 +402,7 @@ void helper_hyp_tlb_flush(CPURISCVState *env) > { > CPUState *cs = env_cpu(env); > > - if (env->priv == PRV_S && env->virt_enabled) { > + if (env->virt_enabled) { > riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); > } > > -- > 2.40.0 > >
© 2016 - 2024 Red Hat, Inc.