summaryrefslogtreecommitdiff
path: root/libcpu/arm
diff options
context:
space:
mode:
authorgeniusgogo <[email protected]>2023-10-17 13:07:59 +0800
committerGitHub <[email protected]>2023-10-17 13:07:59 +0800
commitecd29fda6005ef19c625f194f9311259ba907a78 (patch)
treed0e272f5783ac4a3048238e14a37bcd88b5dc3e6 /libcpu/arm
parent7d64cdcf58969b1b2b7e9cfb3aac9e46cb456ae3 (diff)
Sync dfs lwp (#8123)
Diffstat (limited to 'libcpu/arm')
-rw-r--r--libcpu/arm/cortex-a/mmu.c25
-rw-r--r--libcpu/arm/cortex-a/mmu.h119
-rw-r--r--libcpu/arm/cortex-a/trap.c62
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;
}