summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
authorShell <[email protected]>2024-06-07 21:34:03 +0800
committerGitHub <[email protected]>2024-06-07 21:34:03 +0800
commitf00db6381a383d85f1c145cbebac22967e7d2eb8 (patch)
tree220a6143139c9b1d35d1652fed9fad2721d66788 /libcpu
parent479fab77750594aa74c86beada156810fc651407 (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.h25
-rw-r--r--libcpu/aarch64/common/trap.c50
-rw-r--r--libcpu/risc-v/t-head/c906/trap.c6
-rw-r--r--libcpu/risc-v/virt64/riscv_mmu.h23
-rw-r--r--libcpu/risc-v/virt64/trap.c12
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;