Signed-off-by: Richard Henderson <[email protected]>
---
 target/riscv/tcg/cpu_helper.c | 48 +++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c
index 3318e82ea7..fb1250a4b8 100644
--- a/target/riscv/tcg/cpu_helper.c
+++ b/target/riscv/tcg/cpu_helper.c
@@ -899,12 +899,13 @@ void riscv_cpu_set_mode(CPURISCVState *env, 
privilege_mode_t newpriv,
  *
  * @env: CPURISCVState
  * @prot: The returned protection attributes
- * @addr: The physical address to be checked permission
+ * @first, @last: The physical address range to be permission checked
  * @access_type: The type of MMU access
  * @mode: Indicates current privilege level.
  */
-static int get_physical_address_pmp(CPURISCVState *env, int *prot, hwaddr addr,
-                                    int size, MMUAccessType access_type,
+static int get_physical_address_pmp(CPURISCVState *env, int *prot,
+                                    hwaddr first, hwaddr last,
+                                    MMUAccessType access_type,
                                     privilege_mode_t mode)
 {
     pmp_priv_t pmp_priv;
@@ -915,8 +916,8 @@ static int get_physical_address_pmp(CPURISCVState *env, int 
*prot, hwaddr addr,
         return TRANSLATE_SUCCESS;
     }
 
-    pmp_has_privs = pmp_hart_has_privs(env, addr, size, 1 << access_type,
-                                       &pmp_priv, mode);
+    pmp_has_privs = pmp_hart_has_privs(env, first, last - first + 1,
+                                       1 << access_type, &pmp_priv, mode);
     if (!pmp_has_privs) {
         *prot = 0;
         return TRANSLATE_PMP_FAIL;
@@ -1142,6 +1143,8 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
     base = base_root;
     for (i = 0; i < levels; i++, ptshift -= ptidxbits) {
         target_ulong idx;
+        int pmp_prot, pmp_ret;
+
         if (i == 0) {
             idx = (addr >> (PGSHIFT + ptshift)) &
                            ((1 << (ptidxbits + widened)) - 1);
@@ -1174,10 +1177,9 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
             pte_addr = base + idx * ptesize;
         }
 
-        int pmp_prot;
-        int pmp_ret = get_physical_address_pmp(env, &pmp_prot, pte_addr,
-                                               sxlen_bytes,
-                                               MMU_DATA_LOAD, PRV_S);
+        pmp_ret = get_physical_address_pmp(env, &pmp_prot, pte_addr,
+                                           pte_addr + sxlen_bytes - 1,
+                                           MMU_DATA_LOAD, PRV_S);
         if (pmp_ret != TRANSLATE_SUCCESS) {
             return TRANSLATE_PMP_FAIL;
         }
@@ -1425,7 +1427,8 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
         }
 
         pmp_ret = get_physical_address_pmp(env, &pmp_prot, pte_addr,
-                                           sxlen_bytes, MMU_DATA_STORE, PRV_S);
+                                           pte_addr + sxlen_bytes - 1,
+                                           MMU_DATA_STORE, PRV_S);
         if (pmp_ret != TRANSLATE_SUCCESS) {
             return TRANSLATE_PMP_FAIL;
         }
@@ -1655,8 +1658,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
vaddr first, vaddr last,
 {
     RISCVCPU *cpu = RISCV_CPU(cs);
     CPURISCVState *env = &cpu->env;
-    int size = last - address + 1;
-    vaddr im_address;
     hwaddr pa = 0;
     int prot, prot2, prot_pmp;
     bool pmp_pma_violation = false;
@@ -1676,7 +1677,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
vaddr first, vaddr last,
     pmu_tlb_fill_incr_ctr(cpu, access_type);
     if (two_stage_lookup) {
         /* Two stage lookup */
-        ret = get_physical_address(env, &pa, &prot, address,
+        ret = get_physical_address(env, &pa, &prot, first,
                                    &env->guest_phys_fault_addr, access_type,
                                    mmu_idx, true, true, false, probe);
         /*
@@ -1692,11 +1693,11 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
vaddr first, vaddr last,
         qemu_log_mask(CPU_LOG_MMU,
                       "%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
                       HWADDR_FMT_plx " prot %d\n",
-                      __func__, address, ret, pa, prot);
+                      __func__, first, ret, pa, prot);
 
         if (ret == TRANSLATE_SUCCESS) {
             /* Second stage lookup */
-            im_address = pa;
+            vaddr im_address = pa;
 
             ret = get_physical_address(env, &pa, &prot2, im_address, NULL,
                                        access_type, MMUIdx_U, false, true,
@@ -1711,8 +1712,9 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
vaddr first, vaddr last,
             prot &= prot2;
 
             if (ret == TRANSLATE_SUCCESS) {
-                ret = get_physical_address_pmp(env, &prot_pmp, pa,
-                                               size, access_type, mode);
+                ret = get_physical_address_pmp(env, &prot_pmp,
+                                               pa, pa + (last - first),
+                                               access_type, mode);
                 tlb_size = pmp_get_tlb_size(env, pa);
 
                 qemu_log_mask(CPU_LOG_MMU,
@@ -1736,18 +1738,19 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
vaddr first, vaddr last,
         }
     } else {
         /* Single stage lookup */
-        ret = get_physical_address(env, &pa, &prot, address, NULL,
+        ret = get_physical_address(env, &pa, &prot, first, NULL,
                                    access_type, mmu_idx, true, false, false,
                                    probe);
 
         qemu_log_mask(CPU_LOG_MMU,
                       "%s address=%" VADDR_PRIx " ret %d physical "
                       HWADDR_FMT_plx " prot %d\n",
-                      __func__, address, ret, pa, prot);
+                      __func__, first, ret, pa, prot);
 
         if (ret == TRANSLATE_SUCCESS) {
-            ret = get_physical_address_pmp(env, &prot_pmp, pa,
-                                           size, access_type, mode);
+            ret = get_physical_address_pmp(env, &prot_pmp,
+                                           pa, pa + (last - first),
+                                           access_type, mode);
             tlb_size = pmp_get_tlb_size(env, pa);
 
             qemu_log_mask(CPU_LOG_MMU,
@@ -1764,7 +1767,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
vaddr first, vaddr last,
     }
 
     if (ret == TRANSLATE_SUCCESS) {
-        tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
+        tlb_set_page(cs, address & ~(tlb_size - 1),
+                     (pa + (address - first)) & ~(tlb_size - 1),
                      prot, mmu_idx, tlb_size);
         return true;
     } else if (probe) {
-- 
2.43.0


Reply via email to