diff options
| author | Shell <[email protected]> | 2024-06-07 21:34:03 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-06-07 21:34:03 +0800 |
| commit | f00db6381a383d85f1c145cbebac22967e7d2eb8 (patch) | |
| tree | 220a6143139c9b1d35d1652fed9fad2721d66788 /libcpu | |
| parent | 479fab77750594aa74c86beada156810fc651407 (diff) | |
[mm] precise & readable mm fault type (#9047)
* [smart] fixup: precise mm fault type
Also, fixup arm64 read access fault
* arm64: using meaningful macro on trap
* fixup: renaming macro
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/aarch64/common/armv8.h | 25 | ||||
| -rw-r--r-- | libcpu/aarch64/common/trap.c | 50 | ||||
| -rw-r--r-- | libcpu/risc-v/t-head/c906/trap.c | 6 | ||||
| -rw-r--r-- | libcpu/risc-v/virt64/riscv_mmu.h | 23 | ||||
| -rw-r--r-- | libcpu/risc-v/virt64/trap.c | 12 |
5 files changed, 78 insertions, 38 deletions
diff --git a/libcpu/aarch64/common/armv8.h b/libcpu/aarch64/common/armv8.h index a6d084f620..5f64f03090 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_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) +#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 60410a316a..3be1578eb4 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_ESR_EXTRACT_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: - ret = MM_FAULT_TYPE_ACCESS_FAULT; + 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,28 +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; - 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_ESR_EXTRACT_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: - fault_op = MM_FAULT_OP_WRITE; + 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; } diff --git a/libcpu/risc-v/t-head/c906/trap.c b/libcpu/risc-v/t-head/c906/trap.c index 025b2d3092..c4ba4bf333 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 3c998beadf..fd4781ec98 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 6af0c0097d..f34f46c9e9 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; |
