diff options
| author | geniusgogo <[email protected]> | 2023-10-17 13:07:59 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-17 13:07:59 +0800 |
| commit | ecd29fda6005ef19c625f194f9311259ba907a78 (patch) | |
| tree | d0e272f5783ac4a3048238e14a37bcd88b5dc3e6 /libcpu/arm/cortex-a | |
| parent | 7d64cdcf58969b1b2b7e9cfb3aac9e46cb456ae3 (diff) | |
Sync dfs lwp (#8123)
Diffstat (limited to 'libcpu/arm/cortex-a')
| -rw-r--r-- | libcpu/arm/cortex-a/mmu.c | 25 | ||||
| -rw-r--r-- | libcpu/arm/cortex-a/mmu.h | 119 | ||||
| -rw-r--r-- | libcpu/arm/cortex-a/trap.c | 62 |
3 files changed, 178 insertions, 28 deletions
diff --git a/libcpu/arm/cortex-a/mmu.c b/libcpu/arm/cortex-a/mmu.c index c573611616..0e1b50ab22 100644 --- a/libcpu/arm/cortex-a/mmu.c +++ b/libcpu/arm/cortex-a/mmu.c @@ -1,11 +1,12 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2012-01-10 bernard porting to AM1808 + * 2023-10-10 Shell Add permission control API */ #include <rthw.h> @@ -440,3 +441,25 @@ int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size, { return -RT_ENOSYS; } + +#define KPTE_START (KERNEL_VADDR_START >> ARCH_SECTION_SHIFT) + +void *rt_hw_mmu_pgtbl_create(void) +{ + size_t *mmu_table; + mmu_table = (size_t *)rt_pages_alloc_ext(2, PAGE_ANY_AVAILABLE); + if (!mmu_table) + { + return RT_NULL; + } + rt_memcpy(mmu_table + KPTE_START, (size_t *)rt_kernel_space.page_table + KPTE_START, ARCH_PAGE_SIZE); + rt_memset(mmu_table, 0, 3 * ARCH_PAGE_SIZE); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, 4 * ARCH_PAGE_SIZE); + + return mmu_table; +} + +void rt_hw_mmu_pgtbl_delete(void *pgtbl) +{ + rt_pages_free(pgtbl, 2); +} diff --git a/libcpu/arm/cortex-a/mmu.h b/libcpu/arm/cortex-a/mmu.h index 61b47a9402..bd016b835d 100644 --- a/libcpu/arm/cortex-a/mmu.h +++ b/libcpu/arm/cortex-a/mmu.h @@ -1,11 +1,12 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-03-25 quanzhao the first version + * 2023-10-10 Shell Add permission control API */ #ifndef __MMU_H_ #define __MMU_H_ @@ -25,7 +26,7 @@ #define AP_RO ((1<<10) |(1 << 15)) /* supervisor=RW, user=No */ #else #define AP_RW (3<<10) /* supervisor=RW, user=RW */ -#define AP_RO ((2<<10) /* supervisor=RW, user=RO */ +#define AP_RO (2<<10) /* supervisor=RW, user=RO */ #endif #define SHARED (1<<16) /* shareable */ @@ -65,14 +66,17 @@ struct mem_desc #define MMU_MAP_MTBL_SHARE (1<<10) #define MMU_MAP_MTBL_NG(x) (x<<11) -#define MMU_MAP_K_RO (MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE) -#define MMU_MAP_K_RWCB (MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE) -#define MMU_MAP_K_RW (MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE) -#define MMU_MAP_K_DEVICE (MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE) -#define MMU_MAP_U_RO (MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(2)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE) -#define MMU_MAP_U_RWCB (MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE) -#define MMU_MAP_U_RW (MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE) -#define MMU_MAP_U_DEVICE (MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE) +#define MMU_MAP_K_ROCB ((MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_K_RO ((MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(1)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_K_RWCB ((MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_K_RW ((MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_K_DEVICE ((MMU_MAP_MTBL_NG(0))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(1)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_U_ROCB ((MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(2)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_U_RO ((MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(2)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_U_RWCB ((MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_C|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_U_RW ((MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_U_DEVICE ((MMU_MAP_MTBL_NG(1))|(MMU_MAP_MTBL_A|MMU_MAP_MTBL_AP2(0)|MMU_MAP_MTBL_AP01(3)|MMU_MAP_MTBL_TEX(0)|MMU_MAP_MTBL_B|MMU_MAP_MTBL_SHARE)) +#define MMU_MAP_TRACE(attr) (attr) #define ARCH_SECTION_SHIFT 20 #define ARCH_SECTION_SIZE (1 << ARCH_SECTION_SHIFT) @@ -97,6 +101,15 @@ struct mem_desc */ #define ARCH_MAP_FAILED ((void *)-1) +enum rt_hw_mmu_prot_t { + RT_HW_MMU_PROT_READ, + RT_HW_MMU_PROT_WRITE, + RT_HW_MMU_PROT_EXECUTE, + RT_HW_MMU_PROT_KERNEL, + RT_HW_MMU_PROT_USER, + RT_HW_MMU_PROT_CACHE, +}; + int rt_hw_mmu_ioremap_init(struct rt_aspace *aspace, void *v_address, size_t size); void rt_hw_init_mmu_table(struct mem_desc *mdesc, rt_uint32_t size); @@ -115,4 +128,90 @@ void *rt_hw_mmu_tbl_get(); int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size, enum rt_mmu_cntl cmd); +void *rt_hw_mmu_pgtbl_create(void); +void rt_hw_mmu_pgtbl_delete(void *pgtbl); + +#define AP_APX_MASK (MMU_MAP_MTBL_AP2(0x1) | MMU_MAP_MTBL_AP01(0x3)) +#define AP_APX_URW_KRW (MMU_MAP_MTBL_AP2(0x0) | MMU_MAP_MTBL_AP01(0x3)) +#define AP_APX_URO_KRO (MMU_MAP_MTBL_AP2(0x1) | MMU_MAP_MTBL_AP01(0x2)) + +/** + * @brief Remove permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be removed + * @return size_t returned attribution + */ +rt_inline size_t rt_hw_mmu_attr_rm_perm(size_t attr, enum rt_hw_mmu_prot_t prot) +{ + switch (prot) + { + /* remove write permission for user */ + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: + if ((attr & AP_APX_MASK) == AP_APX_URW_KRW) + attr &= ~MMU_MAP_MTBL_AP01(0x1); + break; + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: + switch (attr & AP_APX_MASK) + { + case MMU_MAP_MTBL_AP01(0): + break; + case MMU_MAP_MTBL_AP01(3): + attr = (attr & AP_APX_MASK) | AP_APX_URO_KRO; + default: + attr |= MMU_MAP_MTBL_AP2(0x1); + break; + } + break; + default: + RT_ASSERT(0); + } + return attr; +} + +/** + * @brief Add permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be added + * @return size_t returned attribution + */ +rt_inline size_t rt_hw_mmu_attr_add_perm(size_t attr, enum rt_hw_mmu_prot_t prot) +{ + switch (prot) + { + /* add write permission for user */ + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: + attr |= MMU_MAP_MTBL_AP01(0x3); + attr &= ~MMU_MAP_MTBL_AP2(0x1); + break; + default: + RT_ASSERT(0); + } + return attr; +} + +/** + * @brief Test permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be test + * @return rt_bool_t RT_TRUE if the prot is allowed, otherwise RT_FALSE + */ +rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, enum rt_hw_mmu_prot_t prot) +{ + rt_bool_t rc = 0; + switch (prot) + { + /* test write permission for user */ + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: + rc = (AP_APX_MASK & attr) == (AP_APX_URW_KRW); + break; + default: + RT_ASSERT(0); + } + return rc; +} + #endif diff --git a/libcpu/arm/cortex-a/trap.c b/libcpu/arm/cortex-a/trap.c index 800e145b64..f2d051f8a1 100644 --- a/libcpu/arm/cortex-a/trap.c +++ b/libcpu/arm/cortex-a/trap.c @@ -8,14 +8,16 @@ * 2013-07-20 Bernard first version */ -#include <backtrace.h> -#include <board.h> #include <rthw.h> #include <rtthread.h> +#include <board.h> +#include <backtrace.h> #include "interrupt.h" #include "mm_fault.h" +#include <rtdbg.h> + #ifdef RT_USING_FINSH extern long list_thread(void); #endif @@ -42,25 +44,47 @@ void check_user_fault(struct rt_hw_exp_stack *regs, uint32_t pc_adj, char *info) } } -int check_user_stack(struct rt_hw_exp_stack *regs) +int check_data_abort(struct rt_hw_exp_stack *regs) { + struct rt_lwp *lwp; void *dfar = RT_NULL; + rt_base_t dfsr = RT_NULL; + __asm__ volatile("mrc p15, 0, %0, c6, c0, 0" : "=r"(dfar)); + __asm__ volatile("mrc p15, 0, %0, c5, c0, 0" : "=r"(dfsr)); + + struct rt_aspace_fault_msg msg = { + .fault_op = MM_FAULT_OP_WRITE, + .fault_type = MM_FAULT_TYPE_PAGE_FAULT, + .fault_vaddr = dfar, + }; + lwp = lwp_self(); + if (lwp && rt_aspace_fault_try_fix(lwp->aspace, &msg)) + { + regs->pc -= 8; + return 1; + } + + return 0; +} + +int check_prefetch_abort(struct rt_hw_exp_stack *regs) +{ struct rt_lwp *lwp; - asm volatile("MRC p15, 0, %0, c6, c0, 0" : "=r"(dfar)); + void *ifar = RT_NULL; + rt_base_t ifsr = RT_NULL; + __asm__ volatile("mrc p15, 0, %0, c6, c0, 2" : "=r"(ifar)); + __asm__ volatile("mrc p15, 0, %0, c5, c0, 1" : "=r"(ifsr)); - if ((dfar >= (void *)USER_STACK_VSTART) && (dfar < (void *)USER_STACK_VEND)) + struct rt_aspace_fault_msg msg = { + .fault_op = MM_FAULT_OP_READ, + .fault_type = MM_FAULT_TYPE_PAGE_FAULT, + .fault_vaddr = ifar, + }; + lwp = lwp_self(); + if (lwp && rt_aspace_fault_try_fix(lwp->aspace, &msg)) { - struct rt_aspace_fault_msg msg = { - .fault_op = MM_FAULT_OP_WRITE, - .fault_type = MM_FAULT_TYPE_PAGE_FAULT, - .fault_vaddr = dfar, - }; - lwp = lwp_self(); - if (lwp && rt_aspace_fault_try_fix(lwp->aspace, &msg)) - { - regs->pc -= 8; - return 1; - } + regs->pc -= 4; + return 1; } return 0; @@ -185,6 +209,10 @@ void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs) { return; } + if (check_prefetch_abort(regs)) + { + return; + } check_user_fault(regs, 4, "User prefetch abort"); #endif rt_unwind(regs, 4); @@ -211,7 +239,7 @@ void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs) { return; } - if (check_user_stack(regs)) + if (check_data_abort(regs)) { return; } |
