qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] target/riscv: Adjust privilege level for HLV(X)/HSV instructions
@ 2021-03-11 10:30 Georg Kotheimer
  2021-03-16 20:16 ` Alistair Francis
  2021-03-18 20:33 ` Alistair Francis
  0 siblings, 2 replies; 7+ messages in thread
From: Georg Kotheimer @ 2021-03-11 10:30 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: Alistair Francis, Georg Kotheimer

According to the specification the "field SPVP of hstatus controls the
privilege level of the access" for the hypervisor virtual-machine load
and store instructions HLV, HLVX and HSV.

Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
---
 target/riscv/cpu_helper.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 2f43939fb6..d0577b1e08 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -325,7 +325,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         use_background = true;
     }
 
-    if (mode == PRV_M && access_type != MMU_INST_FETCH) {
+    /* MPRV does not affect the virtual-machine load/store
+       instructions, HLV, HLVX, and HSV. */
+    if (riscv_cpu_two_stage_lookup(mmu_idx)) {
+        mode = get_field(env->hstatus, HSTATUS_SPVP);
+    } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
         if (get_field(env->mstatus, MSTATUS_MPRV)) {
             mode = get_field(env->mstatus, MSTATUS_MPP);
         }
@@ -695,19 +699,18 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
                   __func__, address, access_type, mmu_idx);
 
-    if (mode == PRV_M && access_type != MMU_INST_FETCH) {
-        if (get_field(env->mstatus, MSTATUS_MPRV)) {
-            mode = get_field(env->mstatus, MSTATUS_MPP);
+    /* MPRV does not affect the virtual-machine load/store
+       instructions, HLV, HLVX, and HSV. */
+    if (riscv_cpu_two_stage_lookup(mmu_idx)) {
+        mode = get_field(env->hstatus, HSTATUS_SPVP);
+    } else if (mode == PRV_M && access_type != MMU_INST_FETCH &&
+               get_field(env->mstatus, MSTATUS_MPRV)) {
+        mode = get_field(env->mstatus, MSTATUS_MPP);
+        if (riscv_has_ext(env, RVH) && get_field(env->mstatus, MSTATUS_MPV)) {
+            two_stage_lookup = true;
         }
     }
 
-    if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
-        access_type != MMU_INST_FETCH &&
-        get_field(env->mstatus, MSTATUS_MPRV) &&
-        get_field(env->mstatus, MSTATUS_MPV)) {
-        two_stage_lookup = true;
-    }
-
     if (riscv_cpu_virt_enabled(env) ||
         ((riscv_cpu_two_stage_lookup(mmu_idx) || two_stage_lookup) &&
          access_type != MMU_INST_FETCH)) {
-- 
2.30.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread
* [PATCH] target/riscv: Adjust privilege level for HLV(X)/HSV instructions
@ 2020-10-18 12:03 Georg Kotheimer
  2020-10-18 15:57 ` Richard Henderson
  0 siblings, 1 reply; 7+ messages in thread
From: Georg Kotheimer @ 2020-10-18 12:03 UTC (permalink / raw)
  To: qemu-devel, qemu-riscv; +Cc: Georg Kotheimer

According to the specification the "field SPVP of hstatus controls the
privilege level of the access" for the hypervisor virtual-machine load
and store instructions HLV, HLVX and HSV.

We introduce the new virtualization register field HS_HYP_LD_ST,
similar to HS_TWO_STAGE, which tracks whether we are currently
executing a hypervisor virtual-macine load or store instruction.

Signed-off-by: Georg Kotheimer <georg.kotheimer@kernkonzept.com>
---
 target/riscv/cpu.h        |  2 ++
 target/riscv/cpu_bits.h   |  1 +
 target/riscv/cpu_helper.c | 60 ++++++++++++++++++++++++++++++---------
 target/riscv/op_helper.c  |  7 +++++
 4 files changed, 56 insertions(+), 14 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index de275782e6..a39674a84d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -323,6 +323,8 @@ bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
 void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
 bool riscv_cpu_two_stage_lookup(CPURISCVState *env);
 void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable);
+bool riscv_cpu_hyp_load_store_inst(CPURISCVState *env);
+void riscv_cpu_set_hyp_load_store_inst(CPURISCVState *env, bool enable);
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index bd36062877..0983ec6471 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -481,6 +481,7 @@
  */
 #define FORCE_HS_EXCEP      2
 #define HS_TWO_STAGE        4
+#define HS_HYP_LD_ST        8
 
 /* RV32 satp CSR field masks */
 #define SATP32_MODE         0x80000000
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 904899054d..58d1fa2675 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -238,6 +238,24 @@ void riscv_cpu_set_two_stage_lookup(CPURISCVState *env, bool enable)
     env->virt = set_field(env->virt, HS_TWO_STAGE, enable);
 }
 
+bool riscv_cpu_hyp_load_store_inst(CPURISCVState *env)
+{
+    if (!riscv_has_ext(env, RVH)) {
+        return false;
+    }
+
+    return get_field(env->virt, HS_HYP_LD_ST);
+}
+
+void riscv_cpu_set_hyp_load_store_inst(CPURISCVState *env, bool enable)
+{
+    if (!riscv_has_ext(env, RVH)) {
+        return;
+    }
+
+    env->virt = set_field(env->virt, HS_HYP_LD_ST, enable);
+}
+
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
 {
     CPURISCVState *env = &cpu->env;
@@ -346,7 +364,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
         use_background = true;
     }
 
-    if (mode == PRV_M && access_type != MMU_INST_FETCH) {
+    /* MPRV does not affect the virtual-machine load/store
+       instructions, HLV, HLVX, and HSV. */
+    if (riscv_cpu_hyp_load_store_inst(env)) {
+        mode = get_field(env->hstatus, HSTATUS_SPVP);
+    } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
         if (get_field(env->mstatus, MSTATUS_MPRV)) {
             mode = get_field(env->mstatus, MSTATUS_MPP);
         }
@@ -711,17 +733,21 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
     qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
                   __func__, address, access_type, mmu_idx);
 
-    if (mode == PRV_M && access_type != MMU_INST_FETCH) {
+    /* MPRV does not affect the virtual-machine load/store
+       instructions, HLV, HLVX, and HSV. */
+    if (riscv_cpu_hyp_load_store_inst(env)) {
+        mode = get_field(env->hstatus, HSTATUS_SPVP);
+    } else if (mode == PRV_M && access_type != MMU_INST_FETCH) {
         if (get_field(env->mstatus, MSTATUS_MPRV)) {
             mode = get_field(env->mstatus, MSTATUS_MPP);
         }
-    }
 
-    if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
-        access_type != MMU_INST_FETCH &&
-        get_field(env->mstatus, MSTATUS_MPRV) &&
-        MSTATUS_MPV_ISSET(env)) {
-        riscv_cpu_set_two_stage_lookup(env, true);
+        if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
+            access_type != MMU_INST_FETCH &&
+            get_field(env->mstatus, MSTATUS_MPRV) &&
+            MSTATUS_MPV_ISSET(env)) {
+            riscv_cpu_set_two_stage_lookup(env, true);
+        }
     }
 
     if (riscv_cpu_virt_enabled(env) ||
@@ -777,12 +803,16 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
                       __func__, address, ret, pa, prot);
     }
 
-    /* We did the two stage lookup based on MPRV, unset the lookup */
-    if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
-        access_type != MMU_INST_FETCH &&
-        get_field(env->mstatus, MSTATUS_MPRV) &&
-        MSTATUS_MPV_ISSET(env)) {
-        riscv_cpu_set_two_stage_lookup(env, false);
+    /* MPRV does not affect the virtual-machine load/store
+       instructions, HLV, HLVX, and HSV. */
+    if (!riscv_cpu_hyp_load_store_inst(env)) {
+        /* We did the two stage lookup based on MPRV, unset the lookup */
+        if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
+            access_type != MMU_INST_FETCH &&
+            get_field(env->mstatus, MSTATUS_MPRV) &&
+            MSTATUS_MPV_ISSET(env)) {
+            riscv_cpu_set_two_stage_lookup(env, false);
+        }
     }
 
     if (riscv_feature(env, RISCV_FEATURE_PMP) &&
@@ -949,6 +979,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
                 riscv_cpu_set_two_stage_lookup(env, false);
                 htval = env->guest_phys_fault_addr;
             }
+
+            riscv_cpu_set_hyp_load_store_inst(env, false);
         }
 
         s = env->mstatus;
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 9b9ada45a9..905a924255 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -240,6 +240,7 @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address,
             get_field(env->hstatus, HSTATUS_HU))) {
         target_ulong pte;
 
+        riscv_cpu_set_hyp_load_store_inst(env, true);
         riscv_cpu_set_two_stage_lookup(env, true);
 
         switch (memop) {
@@ -269,6 +270,7 @@ target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address,
         }
 
         riscv_cpu_set_two_stage_lookup(env, false);
+        riscv_cpu_set_hyp_load_store_inst(env, false);
 
         return pte;
     }
@@ -288,6 +290,8 @@ void helper_hyp_store(CPURISCVState *env, target_ulong address,
         (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
         (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
             get_field(env->hstatus, HSTATUS_HU))) {
+
+        riscv_cpu_set_hyp_load_store_inst(env, true);
         riscv_cpu_set_two_stage_lookup(env, true);
 
         switch (memop) {
@@ -311,6 +315,7 @@ void helper_hyp_store(CPURISCVState *env, target_ulong address,
         }
 
         riscv_cpu_set_two_stage_lookup(env, false);
+        riscv_cpu_set_hyp_load_store_inst(env, false);
 
         return;
     }
@@ -331,6 +336,7 @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
             get_field(env->hstatus, HSTATUS_HU))) {
         target_ulong pte;
 
+        riscv_cpu_set_hyp_load_store_inst(env, true);
         riscv_cpu_set_two_stage_lookup(env, true);
 
         switch (memop) {
@@ -345,6 +351,7 @@ target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
         }
 
         riscv_cpu_set_two_stage_lookup(env, false);
+        riscv_cpu_set_hyp_load_store_inst(env, false);
 
         return pte;
     }
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-03-18 20:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-11 10:30 [PATCH] target/riscv: Adjust privilege level for HLV(X)/HSV instructions Georg Kotheimer
2021-03-16 20:16 ` Alistair Francis
2021-03-18 20:33 ` Alistair Francis
  -- strict thread matches above, loose matches on Subject: below --
2020-10-18 12:03 Georg Kotheimer
2020-10-18 15:57 ` Richard Henderson
2020-10-21 19:21   ` Alistair Francis
2020-10-22 15:21     ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).