aboutsummaryrefslogtreecommitdiff
path: root/target/arm/ptw.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-06-08 19:38:49 +0100
committerPeter Maydell <peter.maydell@linaro.org>2022-06-08 19:38:49 +0100
commit9a12fb366d442751603dc91ab5c5f9b7c828c783 (patch)
tree899bcebf4e9601547e5a82749e0505f11c97d519 /target/arm/ptw.c
parent53c038efb7a634dd5b6ede8eb034791c0dc83f43 (diff)
target/arm: Move get_phys_addr_pmsav5 to ptw.c
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220604040607.269301-6-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/ptw.c')
-rw-r--r--target/arm/ptw.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 6a1f4b549d..5c32648a16 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -289,6 +289,91 @@ do_fault:
return true;
}
+static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
+ hwaddr *phys_ptr, int *prot,
+ ARMMMUFaultInfo *fi)
+{
+ int n;
+ uint32_t mask;
+ uint32_t base;
+ bool is_user = regime_is_user(env, mmu_idx);
+
+ if (regime_translation_disabled(env, mmu_idx)) {
+ /* MPU disabled. */
+ *phys_ptr = address;
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ return false;
+ }
+
+ *phys_ptr = address;
+ for (n = 7; n >= 0; n--) {
+ base = env->cp15.c6_region[n];
+ if ((base & 1) == 0) {
+ continue;
+ }
+ mask = 1 << ((base >> 1) & 0x1f);
+ /* Keep this shift separate from the above to avoid an
+ (undefined) << 32. */
+ mask = (mask << 1) - 1;
+ if (((base ^ address) & ~mask) == 0) {
+ break;
+ }
+ }
+ if (n < 0) {
+ fi->type = ARMFault_Background;
+ return true;
+ }
+
+ if (access_type == MMU_INST_FETCH) {
+ mask = env->cp15.pmsav5_insn_ap;
+ } else {
+ mask = env->cp15.pmsav5_data_ap;
+ }
+ mask = (mask >> (n * 4)) & 0xf;
+ switch (mask) {
+ case 0:
+ fi->type = ARMFault_Permission;
+ fi->level = 1;
+ return true;
+ case 1:
+ if (is_user) {
+ fi->type = ARMFault_Permission;
+ fi->level = 1;
+ return true;
+ }
+ *prot = PAGE_READ | PAGE_WRITE;
+ break;
+ case 2:
+ *prot = PAGE_READ;
+ if (!is_user) {
+ *prot |= PAGE_WRITE;
+ }
+ break;
+ case 3:
+ *prot = PAGE_READ | PAGE_WRITE;
+ break;
+ case 5:
+ if (is_user) {
+ fi->type = ARMFault_Permission;
+ fi->level = 1;
+ return true;
+ }
+ *prot = PAGE_READ;
+ break;
+ case 6:
+ *prot = PAGE_READ;
+ break;
+ default:
+ /* Bad permission. */
+ fi->type = ARMFault_Permission;
+ fi->level = 1;
+ return true;
+ }
+ *prot |= PAGE_EXEC;
+ return false;
+}
+
/**
* get_phys_addr - get the physical address for this virtual address
*