@@ -747,7 +747,7 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot,
* @is_debug: Is this access from a debugger or the monitor?
*/
static int get_physical_address(CPURISCVState *env, hwaddr *physical,
- int *prot, vaddr addr,
+ int *ret_prot, vaddr addr,
target_ulong *fault_pte_addr,
int access_type, int mmu_idx,
bool first_stage, bool two_stage,
@@ -779,20 +779,14 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
*physical = addr;
- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return TRANSLATE_SUCCESS;
}
- *prot = 0;
+ *ret_prot = 0;
hwaddr base;
- int levels, ptidxbits, ptesize, vm, sum, mxr, widened;
-
- if (first_stage == true) {
- mxr = get_field(env->mstatus, MSTATUS_MXR);
- } else {
- mxr = get_field(env->vsstatus, MSTATUS_MXR);
- }
+ int levels, ptidxbits, ptesize, vm, sum, widened;
if (first_stage == true) {
if (use_background) {
@@ -835,7 +829,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
levels = 5; ptidxbits = 9; ptesize = 8; break;
case VM_1_10_MBARE:
*physical = addr;
- *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ *ret_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return TRANSLATE_SUCCESS;
default:
g_assert_not_reached();
@@ -970,6 +964,27 @@ restart:
return TRANSLATE_FAIL;
}
+ int prot = 0;
+ if (pte & PTE_R) {
+ prot |= PAGE_READ;
+ }
+ if (pte & PTE_W) {
+ prot |= PAGE_WRITE;
+ }
+ if (pte & PTE_X) {
+ bool mxr;
+
+ if (first_stage == true) {
+ mxr = get_field(env->mstatus, MSTATUS_MXR);
+ } else {
+ mxr = get_field(env->vsstatus, MSTATUS_MXR);
+ }
+ if (mxr) {
+ prot |= PAGE_READ;
+ }
+ prot |= PAGE_EXEC;
+ }
+
if ((pte & PTE_U) &&
((mode != PRV_U) && (!sum || access_type == MMU_INST_FETCH))) {
/*
@@ -982,17 +997,9 @@ restart:
/* Supervisor PTE flags when not S mode */
return TRANSLATE_FAIL;
}
- if (access_type == MMU_DATA_LOAD &&
- !((pte & PTE_R) || ((pte & PTE_X) && mxr))) {
- /* Read access check failed */
- return TRANSLATE_FAIL;
- }
- if (access_type == MMU_DATA_STORE && !(pte & PTE_W)) {
- /* Write access check failed */
- return TRANSLATE_FAIL;
- }
- if (access_type == MMU_INST_FETCH && !(pte & PTE_X)) {
- /* Fetch access check failed */
+
+ if (!((prot >> access_type) & 1)) {
+ /* Access check failed */
return TRANSLATE_FAIL;
}
@@ -1057,20 +1064,16 @@ restart:
(vpn & (((target_ulong)1 << ptshift) - 1))
) << PGSHIFT) | (addr & ~TARGET_PAGE_MASK);
- /* set permissions on the TLB entry */
- if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
- *prot |= PAGE_READ;
- }
- if (pte & PTE_X) {
- *prot |= PAGE_EXEC;
- }
/*
- * Add write permission on stores or if the page is already dirty,
- * so that we TLB miss on later writes to update the dirty bit.
+ * Remove write permission unless this is a store, or the page is
+ * already dirty, so that we TLB miss on later writes to update
+ * the dirty bit.
*/
- if ((pte & PTE_W) && (access_type == MMU_DATA_STORE || (pte & PTE_D))) {
- *prot |= PAGE_WRITE;
+ if (access_type != MMU_DATA_STORE && !(pte & PTE_D)) {
+ prot &= ~PAGE_WRITE;
}
+ *ret_prot = prot;
+
return TRANSLATE_SUCCESS;
}