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