From f56827b1f6f752bce2623df467e438371443fde0 Mon Sep 17 00:00:00 2001 From: Shell Date: Fri, 7 Jun 2024 03:15:10 +0800 Subject: [PATCH 1/3] [smart] fixup: precise mm fault type Also, fixup arm64 read access fault --- components/lwp/lwp_user_mm.h | 8 ++-- components/mm/mm_aspace.c | 2 +- components/mm/mm_fault.c | 42 ++++++++++++++++++- components/mm/mm_fault.h | 13 +++++- components/mm/mm_private.h | 2 + .../utest/testcases/mm/lwp_mmap_fix_private.c | 2 +- libcpu/aarch64/common/trap.c | 5 ++- libcpu/risc-v/t-head/c906/trap.c | 6 +-- libcpu/risc-v/virt64/riscv_mmu.h | 23 ++++++++-- libcpu/risc-v/virt64/trap.c | 12 +++--- 10 files changed, 91 insertions(+), 24 deletions(-) diff --git a/components/lwp/lwp_user_mm.h b/components/lwp/lwp_user_mm.h index 7155804a441..f38c855f94d 100644 --- a/components/lwp/lwp_user_mm.h +++ b/components/lwp/lwp_user_mm.h @@ -206,13 +206,16 @@ rt_inline rt_size_t lwp_user_mm_flag_to_kernel(int flags) return k_flags; } +#ifndef MMU_MAP_U_ROCB +#define MMU_MAP_U_ROCB MMU_MAP_U_RWCB +#endif /* MMU_MAP_U_ROCB */ + rt_inline rt_size_t lwp_user_mm_attr_to_kernel(int prot) { RT_UNUSED(prot); rt_size_t k_attr = 0; -#ifdef IMPL_MPROTECT if ((prot & PROT_EXEC) || (prot & PROT_WRITE) || ((prot & PROT_READ) && (prot & PROT_WRITE))) k_attr = MMU_MAP_U_RWCB; @@ -220,9 +223,6 @@ rt_inline rt_size_t lwp_user_mm_attr_to_kernel(int prot) k_attr = MMU_MAP_K_RWCB; else k_attr = MMU_MAP_U_ROCB; -#else - k_attr = MMU_MAP_U_RWCB; -#endif /* IMPL_MPROTECT */ return k_attr; } diff --git a/components/mm/mm_aspace.c b/components/mm/mm_aspace.c index acea6cc0807..38abc9002fc 100644 --- a/components/mm/mm_aspace.c +++ b/components/mm/mm_aspace.c @@ -1743,7 +1743,7 @@ rt_err_t rt_aspace_page_put(rt_aspace_t aspace, void *page_va, void *buffer) RDWR_LOCK(aspace); struct rt_aspace_fault_msg msg; msg.fault_op = MM_FAULT_OP_WRITE; - msg.fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + msg.fault_type = MM_FAULT_TYPE_GENERIC_MMU; msg.fault_vaddr = page_va; rc = rt_varea_fix_private_locked(varea, rt_hw_mmu_v2p(aspace, page_va), &msg, RT_TRUE); diff --git a/components/mm/mm_fault.c b/components/mm/mm_fault.c index 4dcef168a52..40af11d4c46 100644 --- a/components/mm/mm_fault.c +++ b/components/mm/mm_fault.c @@ -60,7 +60,7 @@ static int _write_fault(rt_varea_t varea, void *pa, struct rt_aspace_fault_msg * if (rt_varea_is_private_locked(varea)) { if (VAREA_IS_WRITABLE(varea) && ( - msg->fault_type == MM_FAULT_TYPE_ACCESS_FAULT || + msg->fault_type == MM_FAULT_TYPE_RWX_PERM || msg->fault_type == MM_FAULT_TYPE_PAGE_FAULT)) { RDWR_LOCK(aspace); @@ -102,6 +102,44 @@ static int _exec_fault(rt_varea_t varea, void *pa, struct rt_aspace_fault_msg *m return err; } +static void _determine_precise_fault_type(struct rt_aspace_fault_msg *msg, rt_ubase_t pa, rt_varea_t varea) +{ + if (msg->fault_type == MM_FAULT_TYPE_GENERIC_MMU) + { + rt_base_t requesting_perm; + switch (msg->fault_op) + { + case MM_FAULT_OP_READ: + requesting_perm = RT_HW_MMU_PROT_READ | RT_HW_MMU_PROT_USER; + break; + case MM_FAULT_OP_WRITE: + requesting_perm = RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER; + break; + case MM_FAULT_OP_EXECUTE: + requesting_perm = RT_HW_MMU_PROT_EXECUTE | RT_HW_MMU_PROT_USER; + break; + } + + /** + * always checking the user privileges since dynamic permission is not + * supported in kernel. So those faults are never fixable. Hence, adding + * permission check never changes the result of checking. In other + * words, { 0 && (expr) } is always false. + */ + if (rt_hw_mmu_attr_test_perm(varea->attr, requesting_perm)) + { + if (pa == (rt_ubase_t)ARCH_MAP_FAILED) + { + msg->fault_type = MM_FAULT_TYPE_PAGE_FAULT; + } + else + { + msg->fault_type = MM_FAULT_TYPE_RWX_PERM; + } + } + } +} + int rt_aspace_fault_try_fix(rt_aspace_t aspace, struct rt_aspace_fault_msg *msg) { int err = MM_FAULT_FIXABLE_FALSE; @@ -121,6 +159,8 @@ int rt_aspace_fault_try_fix(rt_aspace_t aspace, struct rt_aspace_fault_msg *msg) if (varea) { void *pa = rt_hw_mmu_v2p(aspace, msg->fault_vaddr); + _determine_precise_fault_type(msg, (rt_ubase_t)pa, varea); + if (pa != ARCH_MAP_FAILED && msg->fault_type == MM_FAULT_TYPE_PAGE_FAULT) { LOG_D("%s(fault=%p) has already fixed", __func__, msg->fault_vaddr); diff --git a/components/mm/mm_fault.h b/components/mm/mm_fault.h index 28671aef748..9749e999185 100644 --- a/components/mm/mm_fault.h +++ b/components/mm/mm_fault.h @@ -34,9 +34,12 @@ enum rt_mm_fault_type { /** * Occurs when an instruction attempts to access a memory address that it - * does not have permission to access + * does not have R/W/X permission to access */ - MM_FAULT_TYPE_ACCESS_FAULT, + MM_FAULT_TYPE_RWX_PERM, + + /* Without privileges to access (e.g. user accessing kernel) */ + MM_FAULT_TYPE_NO_PRIVILEGES, /** * Occurs when a load or store instruction accesses a virtual memory @@ -49,6 +52,12 @@ enum rt_mm_fault_type */ MM_FAULT_TYPE_BUS_ERROR, + /** + * Occurs when page table walk failed, permission failed, writings on + * non-dirty page. + */ + MM_FAULT_TYPE_GENERIC_MMU, + MM_FAULT_TYPE_GENERIC, __PRIVATE_PAGE_INSERT, }; diff --git a/components/mm/mm_private.h b/components/mm/mm_private.h index 2a5666e1878..7431cc35a2f 100644 --- a/components/mm/mm_private.h +++ b/components/mm/mm_private.h @@ -38,6 +38,8 @@ ((!varea->mem_obj || !varea->mem_obj->get_name) \ ? "unknow" \ : varea->mem_obj->get_name(varea)) + +/* only user address use COW technique, so user permission is always checked */ #define VAREA_IS_WRITABLE(varea) \ (rt_hw_mmu_attr_test_perm(varea->attr, \ RT_HW_MMU_PROT_USER | RT_HW_MMU_PROT_WRITE)) diff --git a/examples/utest/testcases/mm/lwp_mmap_fix_private.c b/examples/utest/testcases/mm/lwp_mmap_fix_private.c index 71570bb4dce..22261e4b4f7 100644 --- a/examples/utest/testcases/mm/lwp_mmap_fix_private.c +++ b/examples/utest/testcases/mm/lwp_mmap_fix_private.c @@ -56,7 +56,7 @@ static void test_mmap_fix_private(void) char *next_va; struct rt_aspace_fault_msg msg; msg.fault_op = MM_FAULT_OP_WRITE; - msg.fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + msg.fault_type = MM_FAULT_TYPE_RWX_PERM; /* map new pages at ex_vaddr to anonymous */ next_va = ex_vaddr; diff --git a/libcpu/aarch64/common/trap.c b/libcpu/aarch64/common/trap.c index 60410a316a1..d53dd502285 100644 --- a/libcpu/aarch64/common/trap.c +++ b/libcpu/aarch64/common/trap.c @@ -75,7 +75,7 @@ rt_inline int _get_type(unsigned long esr) case 0xd: case 0xe: case 0xf: - ret = MM_FAULT_TYPE_ACCESS_FAULT; + ret = MM_FAULT_TYPE_RWX_PERM; break; case 0x8: case 0x9: @@ -96,6 +96,7 @@ rt_inline long _irq_is_disable(long cpsr) static int user_fault_fixable(unsigned long esr, struct rt_hw_exp_stack *regs) { rt_ubase_t level; + rt_bool_t is_write = esr & 0x40; unsigned char ec; void *dfar; int ret = 0; @@ -114,7 +115,7 @@ static int user_fault_fixable(unsigned long esr, struct rt_hw_exp_stack *regs) case 0x21: case 0x24: case 0x25: - fault_op = MM_FAULT_OP_WRITE; + fault_op = is_write ? MM_FAULT_OP_WRITE : MM_FAULT_OP_READ; fault_type = _get_type(esr); break; default: diff --git a/libcpu/risc-v/t-head/c906/trap.c b/libcpu/risc-v/t-head/c906/trap.c index 025b2d3092b..c4ba4bf3335 100644 --- a/libcpu/risc-v/t-head/c906/trap.c +++ b/libcpu/risc-v/t-head/c906/trap.c @@ -169,7 +169,7 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw break; case EP_LOAD_ACCESS_FAULT: fault_op = MM_FAULT_OP_READ; - fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + fault_type = MM_FAULT_TYPE_GENERIC; break; case EP_LOAD_ADDRESS_MISALIGNED: fault_op = MM_FAULT_OP_READ; @@ -181,7 +181,7 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw break; case EP_STORE_ACCESS_FAULT: fault_op = MM_FAULT_OP_WRITE; - fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + fault_type = MM_FAULT_TYPE_GENERIC; break; case EP_STORE_ADDRESS_MISALIGNED: fault_op = MM_FAULT_OP_WRITE; @@ -193,7 +193,7 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw break; case EP_INSTRUCTION_ACCESS_FAULT: fault_op = MM_FAULT_OP_EXECUTE; - fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + fault_type = MM_FAULT_TYPE_GENERIC; break; case EP_INSTRUCTION_ADDRESS_MISALIGNED: fault_op = MM_FAULT_OP_EXECUTE; diff --git a/libcpu/risc-v/virt64/riscv_mmu.h b/libcpu/risc-v/virt64/riscv_mmu.h index 3c998beadfb..fd4781ec98b 100644 --- a/libcpu/risc-v/virt64/riscv_mmu.h +++ b/libcpu/risc-v/virt64/riscv_mmu.h @@ -116,6 +116,10 @@ rt_inline size_t rt_hw_mmu_attr_rm_perm(size_t attr, rt_base_t prot) case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: attr &= ~PTE_W; break; + /* remove write permission for kernel */ + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: + attr &= ~PTE_W; + break; default: RT_ASSERT(0); } @@ -135,7 +139,7 @@ rt_inline size_t rt_hw_mmu_attr_add_perm(size_t attr, rt_base_t prot) { /* add write permission for user */ case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: - attr |= PTE_W; + attr |= (PTE_R | PTE_W | PTE_U); break; default: RT_ASSERT(0); @@ -153,15 +157,26 @@ rt_inline size_t rt_hw_mmu_attr_add_perm(size_t attr, rt_base_t prot) rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot) { rt_bool_t rc = 0; - switch (prot) + switch (prot & ~RT_HW_MMU_PROT_USER) { /* test write permission for user */ - case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: - rc = !!(attr & PTE_W); + case RT_HW_MMU_PROT_WRITE: + rc = ((attr & PTE_W) && (attr & PTE_R)); + break; + case RT_HW_MMU_PROT_READ: + rc = !!(attr & PTE_R); + break; + case RT_HW_MMU_PROT_EXECUTE: + rc = !!(attr & PTE_X); break; default: RT_ASSERT(0); } + + if (rc && (prot & RT_HW_MMU_PROT_USER)) + { + rc = !!(attr & PTE_U); + } return rc; } diff --git a/libcpu/risc-v/virt64/trap.c b/libcpu/risc-v/virt64/trap.c index 6af0c0097db..f34f46c9e98 100644 --- a/libcpu/risc-v/virt64/trap.c +++ b/libcpu/risc-v/virt64/trap.c @@ -162,11 +162,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw { case EP_LOAD_PAGE_FAULT: fault_op = MM_FAULT_OP_READ; - fault_type = MM_FAULT_TYPE_PAGE_FAULT; + fault_type = MM_FAULT_TYPE_GENERIC_MMU; break; case EP_LOAD_ACCESS_FAULT: fault_op = MM_FAULT_OP_READ; - fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + fault_type = MM_FAULT_TYPE_BUS_ERROR; break; case EP_LOAD_ADDRESS_MISALIGNED: fault_op = MM_FAULT_OP_READ; @@ -174,11 +174,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw break; case EP_STORE_PAGE_FAULT: fault_op = MM_FAULT_OP_WRITE; - fault_type = MM_FAULT_TYPE_PAGE_FAULT; + fault_type = MM_FAULT_TYPE_GENERIC_MMU; break; case EP_STORE_ACCESS_FAULT: fault_op = MM_FAULT_OP_WRITE; - fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + fault_type = MM_FAULT_TYPE_BUS_ERROR; break; case EP_STORE_ADDRESS_MISALIGNED: fault_op = MM_FAULT_OP_WRITE; @@ -186,11 +186,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw break; case EP_INSTRUCTION_PAGE_FAULT: fault_op = MM_FAULT_OP_EXECUTE; - fault_type = MM_FAULT_TYPE_PAGE_FAULT; + fault_type = MM_FAULT_TYPE_GENERIC_MMU; break; case EP_INSTRUCTION_ACCESS_FAULT: fault_op = MM_FAULT_OP_EXECUTE; - fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + fault_type = MM_FAULT_TYPE_BUS_ERROR; break; case EP_INSTRUCTION_ADDRESS_MISALIGNED: fault_op = MM_FAULT_OP_EXECUTE; From ac620ba6d086eb28a9603715e729bcdbe536e0bd Mon Sep 17 00:00:00 2001 From: Shell Date: Fri, 7 Jun 2024 10:23:22 +0800 Subject: [PATCH 2/3] arm64: using meaningful macro on trap --- libcpu/aarch64/common/armv8.h | 25 +++++++++++++++++++ libcpu/aarch64/common/trap.c | 47 +++++++++++++++++------------------ 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/libcpu/aarch64/common/armv8.h b/libcpu/aarch64/common/armv8.h index a6d084f620c..25df4612f72 100644 --- a/libcpu/aarch64/common/armv8.h +++ b/libcpu/aarch64/common/armv8.h @@ -149,6 +149,31 @@ rt_ubase_t rt_hw_get_current_el(void); void rt_hw_set_elx_env(void); void rt_hw_set_current_vbar(rt_ubase_t addr); +/* ESR:generic */ +#define ARM64_ABORT_WNR(esr) ((esr) & 0x40) +#define ARM64_ABORT_FETCH_EC(esr) ((unsigned char)(((esr) >> 26) & 0x3fU)) +#define ARM64_ABORT_FETCH_FSC(esr) ((esr) & 0x3f) + +/* ESR:EC */ +#define ARM64_EC_INST_ABORT_FROM_LO_EXCEPTION (0b100000) +#define ARM64_EC_INST_ABORT_WITHOUT_A_CHANGE (0b100001) +#define ARM64_EC_DATA_ABORT_FROM_LO_EXCEPTION (0b100100) +#define ARM64_EC_DATA_ABORT_WITHOUT_A_CHANGE (0b100101) + +/* ESR:FSC */ +#define ARM64_FSC_TRANSLATION_FAULT_LEVEL_0 (0b000100) +#define ARM64_FSC_TRANSLATION_FAULT_LEVEL_1 (0b000101) +#define ARM64_FSC_TRANSLATION_FAULT_LEVEL_2 (0b000110) +#define ARM64_FSC_TRANSLATION_FAULT_LEVEL_3 (0b000111) +#define ARM64_FSC_PERMISSION_FAULT_LEVEL_0 (0b001100) +#define ARM64_FSC_PERMISSION_FAULT_LEVEL_1 (0b001101) +#define ARM64_FSC_PERMISSION_FAULT_LEVEL_2 (0b001110) +#define ARM64_FSC_PERMISSION_FAULT_LEVEL_3 (0b001111) +#define ARM64_FSC_ACCESS_FLAG_FAULT_LEVEL_0 (0b001000) +#define ARM64_FSC_ACCESS_FLAG_FAULT_LEVEL_1 (0b001001) +#define ARM64_FSC_ACCESS_FLAG_FAULT_LEVEL_2 (0b001010) +#define ARM64_FSC_ACCESS_FLAG_FAULT_LEVEL_3 (0b001011) + #endif /* __ASSEMBLY__ */ #endif diff --git a/libcpu/aarch64/common/trap.c b/libcpu/aarch64/common/trap.c index d53dd502285..fac54a3289e 100644 --- a/libcpu/aarch64/common/trap.c +++ b/libcpu/aarch64/common/trap.c @@ -62,26 +62,26 @@ static void _check_fault(struct rt_hw_exp_stack *regs, uint32_t pc_adj, char *in rt_inline int _get_type(unsigned long esr) { int ret; - int fsc = esr & 0x3f; + int fsc = ARM64_ABORT_FETCH_FSC(esr); switch (fsc) { - case 0x4: - case 0x5: - case 0x6: - case 0x7: + case ARM64_FSC_TRANSLATION_FAULT_LEVEL_0: + case ARM64_FSC_TRANSLATION_FAULT_LEVEL_1: + case ARM64_FSC_TRANSLATION_FAULT_LEVEL_2: + case ARM64_FSC_TRANSLATION_FAULT_LEVEL_3: ret = MM_FAULT_TYPE_PAGE_FAULT; break; - case 0xc: - case 0xd: - case 0xe: - case 0xf: + case ARM64_FSC_PERMISSION_FAULT_LEVEL_0: + case ARM64_FSC_PERMISSION_FAULT_LEVEL_1: + case ARM64_FSC_PERMISSION_FAULT_LEVEL_2: + case ARM64_FSC_PERMISSION_FAULT_LEVEL_3: ret = MM_FAULT_TYPE_RWX_PERM; break; - case 0x8: - case 0x9: - case 0xa: - case 0xb: - /* access flag fault */ + case ARM64_FSC_ACCESS_FLAG_FAULT_LEVEL_0: + case ARM64_FSC_ACCESS_FLAG_FAULT_LEVEL_1: + case ARM64_FSC_ACCESS_FLAG_FAULT_LEVEL_2: + case ARM64_FSC_ACCESS_FLAG_FAULT_LEVEL_3: + /* access flag fault, not handle currently */ default: ret = MM_FAULT_TYPE_GENERIC; } @@ -96,29 +96,28 @@ rt_inline long _irq_is_disable(long cpsr) static int user_fault_fixable(unsigned long esr, struct rt_hw_exp_stack *regs) { rt_ubase_t level; - rt_bool_t is_write = esr & 0x40; - unsigned char ec; - void *dfar; - int ret = 0; - - ec = (unsigned char)((esr >> 26) & 0x3fU); enum rt_mm_fault_op fault_op; enum rt_mm_fault_type fault_type; struct rt_lwp *lwp; + void *dfar; + int ret = 0; + unsigned char ec = ARM64_ABORT_FETCH_EC(esr); + rt_bool_t is_write = ARM64_ABORT_WNR(esr); switch (ec) { - case 0x20: + case ARM64_EC_INST_ABORT_FROM_LO_EXCEPTION: fault_op = MM_FAULT_OP_EXECUTE; fault_type = _get_type(esr); break; - case 0x21: - case 0x24: - case 0x25: + case ARM64_EC_INST_ABORT_WITHOUT_A_CHANGE: + case ARM64_EC_DATA_ABORT_FROM_LO_EXCEPTION: + case ARM64_EC_DATA_ABORT_WITHOUT_A_CHANGE: fault_op = is_write ? MM_FAULT_OP_WRITE : MM_FAULT_OP_READ; fault_type = _get_type(esr); break; default: + /* non-fixable */ fault_op = 0; break; } From e4615386709ba0f1d8e4177edc66604e2fc07786 Mon Sep 17 00:00:00 2001 From: Shell Date: Fri, 7 Jun 2024 10:36:26 +0800 Subject: [PATCH 3/3] fixup: renaming macro --- libcpu/aarch64/common/armv8.h | 6 +++--- libcpu/aarch64/common/trap.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libcpu/aarch64/common/armv8.h b/libcpu/aarch64/common/armv8.h index 25df4612f72..5f64f03090d 100644 --- a/libcpu/aarch64/common/armv8.h +++ b/libcpu/aarch64/common/armv8.h @@ -150,9 +150,9 @@ void rt_hw_set_elx_env(void); void rt_hw_set_current_vbar(rt_ubase_t addr); /* ESR:generic */ -#define ARM64_ABORT_WNR(esr) ((esr) & 0x40) -#define ARM64_ABORT_FETCH_EC(esr) ((unsigned char)(((esr) >> 26) & 0x3fU)) -#define ARM64_ABORT_FETCH_FSC(esr) ((esr) & 0x3f) +#define ARM64_ABORT_WNR(esr) ((esr) & 0x40) +#define ARM64_ESR_EXTRACT_EC(esr) ((((esr) >> 26) & 0x3fU)) +#define ARM64_ESR_EXTRACT_FSC(esr) ((esr) & 0x3f) /* ESR:EC */ #define ARM64_EC_INST_ABORT_FROM_LO_EXCEPTION (0b100000) diff --git a/libcpu/aarch64/common/trap.c b/libcpu/aarch64/common/trap.c index fac54a3289e..3be1578eb4b 100644 --- a/libcpu/aarch64/common/trap.c +++ b/libcpu/aarch64/common/trap.c @@ -62,7 +62,7 @@ static void _check_fault(struct rt_hw_exp_stack *regs, uint32_t pc_adj, char *in rt_inline int _get_type(unsigned long esr) { int ret; - int fsc = ARM64_ABORT_FETCH_FSC(esr); + int fsc = ARM64_ESR_EXTRACT_FSC(esr); switch (fsc) { case ARM64_FSC_TRANSLATION_FAULT_LEVEL_0: @@ -101,7 +101,7 @@ static int user_fault_fixable(unsigned long esr, struct rt_hw_exp_stack *regs) struct rt_lwp *lwp; void *dfar; int ret = 0; - unsigned char ec = ARM64_ABORT_FETCH_EC(esr); + unsigned char ec = ARM64_ESR_EXTRACT_EC(esr); rt_bool_t is_write = ARM64_ABORT_WNR(esr); switch (ec)