summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/aarch64/common/cpu.h4
-rw-r--r--libcpu/aarch64/common/exception.c10
-rw-r--r--libcpu/aarch64/common/mmu.c27
-rw-r--r--libcpu/aarch64/common/mmu.h108
-rw-r--r--libcpu/aarch64/common/trap.c82
-rw-r--r--libcpu/aarch64/cortex-a/entry_point.S8
-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
-rw-r--r--libcpu/risc-v/t-head/c906/mmu.c20
-rw-r--r--libcpu/risc-v/t-head/c906/mmu.h4
-rw-r--r--libcpu/risc-v/t-head/c906/riscv_mmu.h70
-rw-r--r--libcpu/risc-v/virt64/mmu.c20
-rw-r--r--libcpu/risc-v/virt64/mmu.h4
-rw-r--r--libcpu/risc-v/virt64/riscv_mmu.h71
15 files changed, 561 insertions, 73 deletions
diff --git a/libcpu/aarch64/common/cpu.h b/libcpu/aarch64/common/cpu.h
index e3efaec485..873207d91b 100644
--- a/libcpu/aarch64/common/cpu.h
+++ b/libcpu/aarch64/common/cpu.h
@@ -13,10 +13,6 @@
#include <rtthread.h>
#include <stdbool.h>
-#ifndef RT_CPUS_NR
-#define RT_CPUS_NR 1
-#endif /* RT_CPUS_NR */
-
#ifdef RT_USING_SMP
struct cpu_ops_t
{
diff --git a/libcpu/aarch64/common/exception.c b/libcpu/aarch64/common/exception.c
index 7da19c0e6e..7582c2a0ce 100644
--- a/libcpu/aarch64/common/exception.c
+++ b/libcpu/aarch64/common/exception.c
@@ -54,6 +54,10 @@ static void data_abort(unsigned long far, unsigned long iss)
rt_kprintf("Translation fault, third level\n");
break;
+ case 0b001000:
+ rt_kprintf("Access flag fault, zeroth level\n");
+ break;
+
case 0b001001:
rt_kprintf("Access flag fault, first level\n");
break;
@@ -66,6 +70,10 @@ static void data_abort(unsigned long far, unsigned long iss)
rt_kprintf("Access flag fault, third level\n");
break;
+ case 0b001100:
+ rt_kprintf("Permission fault, zeroth level\n");
+ break;
+
case 0b001101:
rt_kprintf("Permission fault, first level\n");
break;
@@ -148,7 +156,7 @@ static void data_abort(unsigned long far, unsigned long iss)
}
}
-void process_exception(unsigned long esr, unsigned long epc)
+void print_exception(unsigned long esr, unsigned long epc)
{
rt_uint8_t ec;
rt_uint32_t iss;
diff --git a/libcpu/aarch64/common/mmu.c b/libcpu/aarch64/common/mmu.c
index e8a0bfeefb..1426dc7fef 100644
--- a/libcpu/aarch64/common/mmu.c
+++ b/libcpu/aarch64/common/mmu.c
@@ -204,7 +204,7 @@ static int _kernel_map_2M(unsigned long *lv0_tbl, void *vaddr, void *paddr, unsi
{
return MMU_MAP_ERROR_VANOTALIGN;
}
- if (pa & ARCH_SECTION_MASK)
+ if (pa & ARCH_PAGE_MASK)
{
return MMU_MAP_ERROR_PANOTALIGN;
}
@@ -556,7 +556,7 @@ static int _map_single_page_2M(unsigned long *lv0_tbl, unsigned long va,
{
return MMU_MAP_ERROR_VANOTALIGN;
}
- if (pa & ARCH_SECTION_MASK)
+ if (pa & ARCH_PAGE_MASK)
{
return MMU_MAP_ERROR_PANOTALIGN;
}
@@ -803,8 +803,8 @@ void rt_hw_mem_setup_early(unsigned long *tbl0, unsigned long *tbl1,
#ifdef RT_USING_SMART
unsigned long va = KERNEL_VADDR_START;
#else
- extern unsigned char _start;
- unsigned long va = (unsigned long) &_start;
+ extern unsigned char __start;
+ unsigned long va = (unsigned long) &__start;
va = RT_ALIGN_DOWN(va, 0x200000);
#endif
@@ -826,3 +826,22 @@ void rt_hw_mem_setup_early(unsigned long *tbl0, unsigned long *tbl1,
while (1);
}
}
+
+void *rt_hw_mmu_pgtbl_create(void)
+{
+ size_t *mmu_table;
+ mmu_table = (size_t *)rt_pages_alloc_ext(0, PAGE_ANY_AVAILABLE);
+ if (!mmu_table)
+ {
+ return RT_NULL;
+ }
+
+ memset(mmu_table, 0, ARCH_PAGE_SIZE);
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE);
+ return mmu_table;
+}
+
+void rt_hw_mmu_pgtbl_delete(void *pgtbl)
+{
+ rt_pages_free(pgtbl, 0);
+}
diff --git a/libcpu/aarch64/common/mmu.h b/libcpu/aarch64/common/mmu.h
index d85f79e792..875f925463 100644
--- a/libcpu/aarch64/common/mmu.h
+++ b/libcpu/aarch64/common/mmu.h
@@ -1,11 +1,12 @@
/*
- * Copyright (c) 2006-2018, RT-Thread Development Team
+ * Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-05-12 RT-Thread the first version
+ * 2023-08-15 Shell Support more mapping attribution
*/
#ifndef __MMU_H_
#define __MMU_H_
@@ -29,27 +30,42 @@ struct mem_desc
struct rt_varea varea;
};
+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,
+};
+
#define MMU_AF_SHIFT 10
#define MMU_SHARED_SHIFT 8
#define MMU_AP_SHIFT 6
#define MMU_MA_SHIFT 2
+#define MMU_AP_MASK (0x3 << MMU_AP_SHIFT)
#define MMU_AP_KAUN 0UL /* kernel r/w, user none */
#define MMU_AP_KAUA 1UL /* kernel r/w, user r/w */
#define MMU_AP_KRUN 2UL /* kernel r, user none */
#define MMU_AP_KRUR 3UL /* kernel r, user r */
+#define MMU_ATTR_AF (1ul << MMU_AF_SHIFT) /* the access flag */
+#define MMU_ATTR_DBM (1ul << 51) /* the dirty bit modifier */
#define MMU_MAP_CUSTOM(ap, mtype) \
((0x1UL << MMU_AF_SHIFT) | (0x2UL << MMU_SHARED_SHIFT) | \
((ap) << MMU_AP_SHIFT) | ((mtype) << MMU_MA_SHIFT))
-#define MMU_MAP_K_RO MMU_MAP_CUSTOM(MMU_AP_KRUN, NORMAL_MEM)
-#define MMU_MAP_K_RWCB MMU_MAP_CUSTOM(MMU_AP_KAUN, NORMAL_MEM)
-#define MMU_MAP_K_RW MMU_MAP_CUSTOM(MMU_AP_KAUN, NORMAL_NOCACHE_MEM)
-#define MMU_MAP_K_DEVICE MMU_MAP_CUSTOM(MMU_AP_KAUN, DEVICE_MEM)
-#define MMU_MAP_U_RO MMU_MAP_CUSTOM(MMU_AP_KRUR, NORMAL_NOCACHE_MEM)
-#define MMU_MAP_U_RWCB MMU_MAP_CUSTOM(MMU_AP_KAUA, NORMAL_MEM)
-#define MMU_MAP_U_RW MMU_MAP_CUSTOM(MMU_AP_KAUA, NORMAL_NOCACHE_MEM)
-#define MMU_MAP_U_DEVICE MMU_MAP_CUSTOM(MMU_AP_KAUA, DEVICE_MEM)
+#define MMU_MAP_K_ROCB MMU_MAP_CUSTOM(MMU_AP_KRUN, NORMAL_MEM)
+#define MMU_MAP_K_RO MMU_MAP_CUSTOM(MMU_AP_KRUN, NORMAL_NOCACHE_MEM)
+#define MMU_MAP_K_RWCB MMU_MAP_CUSTOM(MMU_AP_KAUN, NORMAL_MEM)
+#define MMU_MAP_K_RW MMU_MAP_CUSTOM(MMU_AP_KAUN, NORMAL_NOCACHE_MEM)
+#define MMU_MAP_K_DEVICE MMU_MAP_CUSTOM(MMU_AP_KAUN, DEVICE_MEM)
+#define MMU_MAP_U_ROCB MMU_MAP_CUSTOM(MMU_AP_KRUR, NORMAL_MEM)
+#define MMU_MAP_U_RO MMU_MAP_CUSTOM(MMU_AP_KRUR, NORMAL_NOCACHE_MEM)
+#define MMU_MAP_U_RWCB MMU_MAP_CUSTOM(MMU_AP_KAUA, NORMAL_MEM)
+#define MMU_MAP_U_RW MMU_MAP_CUSTOM(MMU_AP_KAUA, NORMAL_NOCACHE_MEM)
+#define MMU_MAP_U_DEVICE MMU_MAP_CUSTOM(MMU_AP_KAUA, DEVICE_MEM)
+#define MMU_MAP_TRACE(attr) ((attr) & ~(MMU_ATTR_AF | MMU_ATTR_DBM))
#define ARCH_SECTION_SHIFT 21
#define ARCH_SECTION_SIZE (1 << ARCH_SECTION_SHIFT)
@@ -88,7 +104,8 @@ void rt_hw_aspace_switch(struct rt_aspace *aspace);
void *rt_hw_mmu_v2p(struct rt_aspace *aspace, void *vaddr);
void rt_hw_mmu_kernel_map_init(struct rt_aspace *aspace, rt_size_t vaddr_start,
rt_size_t size);
-void rt_hw_mmu_ktbl_set(unsigned long tbl);
+void *rt_hw_mmu_pgtbl_create(void);
+void rt_hw_mmu_pgtbl_delete(void *pgtbl);
static inline void *rt_hw_mmu_tbl_get()
{
@@ -101,8 +118,8 @@ static inline void *rt_hw_mmu_kernel_v2p(void *v_addr)
{
rt_ubase_t par;
void *paddr;
- asm volatile("at s1e1w, %0"::"r"(v_addr):"memory");
- asm volatile("mrs %0, par_el1":"=r"(par)::"memory");
+ __asm__ volatile("at s1e1w, %0"::"r"(v_addr):"memory");
+ __asm__ volatile("mrs %0, par_el1":"=r"(par)::"memory");
if (par & 0x1)
{
@@ -118,6 +135,73 @@ static inline void *rt_hw_mmu_kernel_v2p(void *v_addr)
return paddr;
}
+/**
+ * @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)
+ {
+ /* remove write permission for user */
+ case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER:
+ attr = (attr & ~MMU_AP_MASK) | (MMU_AP_KAUA << MMU_AP_SHIFT);
+ break;
+ default:
+ RT_ASSERT(0);
+ }
+ return attr;
+}
+
+/**
+ * @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 & 0x40)
+ attr |= 0x80;
+ 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;
+ switch (prot)
+ {
+ /* test write permission for user */
+ case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER:
+ if ((attr & MMU_AP_MASK) == (MMU_AP_KAUA << MMU_AP_SHIFT))
+ rc = RT_TRUE;
+ else
+ rc = RT_FALSE;
+ break;
+ default:
+ RT_ASSERT(0);
+ }
+ return rc;
+}
int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size,
enum rt_mmu_cntl cmd);
diff --git a/libcpu/aarch64/common/trap.c b/libcpu/aarch64/common/trap.c
index 95adf628d8..487e940600 100644
--- a/libcpu/aarch64/common/trap.c
+++ b/libcpu/aarch64/common/trap.c
@@ -18,6 +18,10 @@
#include <backtrace.h>
+#define DBG_TAG "libcpu.trap"
+#define DBG_LVL DBG_LOG
+#include <rtdbg.h>
+
void rt_unwind(struct rt_hw_exp_stack *regs, int pc_adj)
{
}
@@ -40,7 +44,7 @@ static void _check_fault(struct rt_hw_exp_stack *regs, uint32_t pc_adj, char *in
if ((mode & 0x1f) == 0x00)
{
- rt_kprintf("%s! pc = 0x%08x\n", info, regs->pc - pc_adj);
+ rt_kprintf("%s! pc = 0x%x\n", info, regs->pc - pc_adj);
/* user stack backtrace */
#ifdef RT_USING_LWP
@@ -79,7 +83,7 @@ static void _check_fault(struct rt_hw_exp_stack *regs, uint32_t pc_adj, char *in
}
}
-int _get_type(unsigned long esr)
+rt_inline int _get_type(unsigned long esr)
{
int ret;
int fsc = esr & 0x3f;
@@ -91,19 +95,31 @@ int _get_type(unsigned long esr)
case 0x7:
ret = MM_FAULT_TYPE_PAGE_FAULT;
break;
+ case 0xc:
+ case 0xd:
+ case 0xe:
+ case 0xf:
+ ret = MM_FAULT_TYPE_ACCESS_FAULT;
+ break;
+ case 0x8:
case 0x9:
case 0xa:
case 0xb:
- ret = MM_FAULT_TYPE_ACCESS_FAULT;
- break;
+ /* access flag fault */
default:
ret = MM_FAULT_TYPE_GENERIC;
}
return ret;
}
-int check_user_stack(unsigned long esr, struct rt_hw_exp_stack *regs)
+rt_inline long _irq_is_disable(long cpsr)
{
+ return !!(cpsr & 0x80);
+}
+
+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;
@@ -130,20 +146,24 @@ int check_user_stack(unsigned long esr, struct rt_hw_exp_stack *regs)
break;
}
- if (fault_op)
+ /* page fault exception only allow from user space */
+ lwp = lwp_self();
+ if (lwp && fault_op)
{
- asm volatile("mrs %0, far_el1":"=r"(dfar));
+ __asm__ volatile("mrs %0, far_el1":"=r"(dfar));
struct rt_aspace_fault_msg msg = {
.fault_op = fault_op,
.fault_type = fault_type,
.fault_vaddr = dfar,
};
- lwp = lwp_self();
- RT_ASSERT(lwp);
+
+ lwp_user_setting_save(rt_thread_self());
+ __asm__ volatile("mrs %0, daif\nmsr daifclr, 0x3\nisb\n":"=r"(level));
if (rt_aspace_fault_try_fix(lwp->aspace, &msg))
{
ret = 1;
}
+ __asm__ volatile("msr daif, %0\nisb\n"::"r"(level));
}
return ret;
}
@@ -269,6 +289,12 @@ void rt_hw_trap_irq(void)
#endif
}
+#ifdef RT_USING_SMART
+#define DBG_CHECK_EVENT(regs, esr) dbg_check_event(regs, esr)
+#else
+#define DBG_CHECK_EVENT(regs, esr) (0)
+#endif
+
void rt_hw_trap_fiq(void)
{
void *param;
@@ -292,7 +318,7 @@ void rt_hw_trap_fiq(void)
rt_hw_interrupt_ack(ir);
}
-void process_exception(unsigned long esr, unsigned long epc);
+void print_exception(unsigned long esr, unsigned long epc);
void SVC_Handler(struct rt_hw_exp_stack *regs);
void rt_hw_trap_exception(struct rt_hw_exp_stack *regs)
{
@@ -302,27 +328,43 @@ void rt_hw_trap_exception(struct rt_hw_exp_stack *regs)
asm volatile("mrs %0, esr_el1":"=r"(esr));
ec = (unsigned char)((esr >> 26) & 0x3fU);
-#ifdef RT_USING_LWP
- if (dbg_check_event(regs, esr))
+ if (DBG_CHECK_EVENT(regs, esr))
{
return;
}
- else
-#endif
- if (ec == 0x15) /* is 64bit syscall ? */
+ else if (ec == 0x15) /* is 64bit syscall ? */
{
SVC_Handler(regs);
/* never return here */
}
-#ifdef RT_USING_LWP
- if (check_user_stack(esr, regs))
+
+#ifdef RT_USING_SMART
+ /**
+ * Note: check_user_stack will take lock and it will possibly be a dead-lock
+ * if exception comes from kernel.
+ */
+ if ((regs->cpsr & 0x1f) == 0)
{
- return;
+ if (user_fault_fixable(esr, regs))
+ return;
+ }
+ else
+ {
+ if (_irq_is_disable(regs->cpsr))
+ {
+ LOG_E("Kernel fault from interrupt/critical section");
+ }
+ if (rt_critical_level() != 0)
+ {
+ LOG_E("scheduler is not available");
+ }
+ else if (user_fault_fixable(esr, regs))
+ return;
}
#endif
- process_exception(esr, regs->pc);
+ print_exception(esr, regs->pc);
rt_hw_show_register(regs);
- rt_kprintf("current: %s\n", rt_thread_self()->parent.name);
+ LOG_E("current thread: %s\n", rt_thread_self()->parent.name);
#ifdef RT_USING_FINSH
list_thread();
diff --git a/libcpu/aarch64/cortex-a/entry_point.S b/libcpu/aarch64/cortex-a/entry_point.S
index ee0ec86273..3c79fdebbc 100644
--- a/libcpu/aarch64/cortex-a/entry_point.S
+++ b/libcpu/aarch64/cortex-a/entry_point.S
@@ -38,8 +38,8 @@ boot_arg1 .req x23
boot_arg2 .req x24
stack_top .req x25
- .global _start
-_start:
+.global __start
+__start:
/*
* Boot CPU general-purpose register settings:
* x0 = physical address of device tree blob (dtb) in system RAM.
@@ -165,8 +165,8 @@ _start:
dsb sy
#ifdef RT_USING_SMART
- ldr x2, =_start
- GET_PHY x3, _start
+ ldr x2, =__start
+ GET_PHY x3, __start
sub x3, x3, x2
#else
mov x3,0
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;
}
diff --git a/libcpu/risc-v/t-head/c906/mmu.c b/libcpu/risc-v/t-head/c906/mmu.c
index 75893d65e6..1754e5aaa4 100644
--- a/libcpu/risc-v/t-head/c906/mmu.c
+++ b/libcpu/risc-v/t-head/c906/mmu.c
@@ -7,6 +7,7 @@
* Date Author Notes
* 2021-01-30 lizhirui first version
* 2022-12-13 WangXiaoyao Port to new mm
+ * 2023-10-12 Shell Add permission control API
*/
#include <rtthread.h>
@@ -567,3 +568,22 @@ void rt_hw_mmu_kernel_map_init(rt_aspace_t aspace, rt_size_t vaddr_start, rt_siz
rt_hw_tlb_invalidate_all_local();
}
+
+void *rt_hw_mmu_pgtbl_create(void)
+{
+ size_t *mmu_table;
+ mmu_table = (rt_ubase_t *)rt_pages_alloc_ext(0, PAGE_ANY_AVAILABLE);
+ if (!mmu_table)
+ {
+ return -RT_ENOMEM;
+ }
+ rt_memcpy(mmu_table, rt_kernel_space.page_table, ARCH_PAGE_SIZE);
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE);
+
+ return mmu_table;
+}
+
+void rt_hw_mmu_pgtbl_delete(void *pgtbl)
+{
+ rt_pages_free(pgtbl, 0);
+}
diff --git a/libcpu/risc-v/t-head/c906/mmu.h b/libcpu/risc-v/t-head/c906/mmu.h
index 809e514b82..58229464cd 100644
--- a/libcpu/risc-v/t-head/c906/mmu.h
+++ b/libcpu/risc-v/t-head/c906/mmu.h
@@ -6,6 +6,7 @@
* Change Logs:
* Date Author Notes
* 2021-01-30 lizhirui first version
+ * 2023-10-12 Shell Add permission control API
*/
#ifndef __MMU_H__
@@ -70,4 +71,7 @@ void *rt_hw_mmu_v2p(rt_aspace_t aspace, void *vaddr);
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);
+
#endif
diff --git a/libcpu/risc-v/t-head/c906/riscv_mmu.h b/libcpu/risc-v/t-head/c906/riscv_mmu.h
index 87db683b05..dfb5a8ee48 100644
--- a/libcpu/risc-v/t-head/c906/riscv_mmu.h
+++ b/libcpu/risc-v/t-head/c906/riscv_mmu.h
@@ -7,6 +7,7 @@
* Date Author Notes
* 2021-01-30 lizhirui first version
* 2021-05-03 lizhirui porting to c906
+ * 2023-10-12 Shell Add permission control API
*/
#ifndef __RISCV_MMU_H__
@@ -90,8 +91,10 @@
#define MMU_MAP_K_RWCB PTE_WRAP(PAGE_ATTR_CB | PTE_G | PAGE_ATTR_RWX | PTE_V)
#define MMU_MAP_K_RW PTE_WRAP(PTE_G | PAGE_ATTR_RWX | PTE_V)
#define MMU_MAP_U_RWCB PTE_WRAP(PAGE_ATTR_CB | PTE_U | PAGE_ATTR_RWX | PTE_V)
+#define MMU_MAP_U_ROCB PTE_WRAP(PAGE_ATTR_CB | PTE_U | PAGE_ATTR_READONLY | PTE_V)
#define MMU_MAP_U_RWCB_XN PTE_WRAP(PAGE_ATTR_CB | PTE_U | PAGE_ATTR_XN | PTE_V)
#define MMU_MAP_U_RW PTE_WRAP(PTE_U | PAGE_ATTR_RWX | PTE_V)
+#define MMU_MAP_TRACE(attr) (attr)
#define PTE_XWR_MASK 0xe
@@ -108,4 +111,71 @@ void mmu_set_pagetable(rt_ubase_t addr);
void mmu_enable_user_page_access();
void mmu_disable_user_page_access();
+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,
+};
+
+/**
+ * @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:
+ 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:
+ 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:
+ default:
+ RT_ASSERT(0);
+ }
+ return rc;
+}
+
#endif
diff --git a/libcpu/risc-v/virt64/mmu.c b/libcpu/risc-v/virt64/mmu.c
index 091be5adab..c1a62bfdea 100644
--- a/libcpu/risc-v/virt64/mmu.c
+++ b/libcpu/risc-v/virt64/mmu.c
@@ -7,6 +7,7 @@
* Date Author Notes
* 2021-01-30 lizhirui first version
* 2022-12-13 WangXiaoyao Port to new mm
+ * 2023-10-12 Shell Add permission control API
*/
#include <rtthread.h>
@@ -490,3 +491,22 @@ void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr)
rt_hw_aspace_switch(&rt_kernel_space);
rt_page_cleanup();
}
+
+void *rt_hw_mmu_pgtbl_create(void)
+{
+ size_t *mmu_table;
+ mmu_table = (rt_ubase_t *)rt_pages_alloc_ext(0, PAGE_ANY_AVAILABLE);
+ if (!mmu_table)
+ {
+ return RT_NULL;
+ }
+ rt_memcpy(mmu_table, rt_kernel_space.page_table, ARCH_PAGE_SIZE);
+ rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE);
+
+ return mmu_table;
+}
+
+void rt_hw_mmu_pgtbl_delete(void *pgtbl)
+{
+ rt_pages_free(pgtbl, 0);
+}
diff --git a/libcpu/risc-v/virt64/mmu.h b/libcpu/risc-v/virt64/mmu.h
index 809e514b82..58229464cd 100644
--- a/libcpu/risc-v/virt64/mmu.h
+++ b/libcpu/risc-v/virt64/mmu.h
@@ -6,6 +6,7 @@
* Change Logs:
* Date Author Notes
* 2021-01-30 lizhirui first version
+ * 2023-10-12 Shell Add permission control API
*/
#ifndef __MMU_H__
@@ -70,4 +71,7 @@ void *rt_hw_mmu_v2p(rt_aspace_t aspace, void *vaddr);
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);
+
#endif
diff --git a/libcpu/risc-v/virt64/riscv_mmu.h b/libcpu/risc-v/virt64/riscv_mmu.h
index 2e255263f5..a56492dcab 100644
--- a/libcpu/risc-v/virt64/riscv_mmu.h
+++ b/libcpu/risc-v/virt64/riscv_mmu.h
@@ -6,6 +6,7 @@
* Change Logs:
* Date Author Notes
* 2021-01-30 lizhirui first version
+ * 2023-10-12 Shell Add permission control API
*/
#ifndef __RISCV_MMU_H__
@@ -93,4 +94,74 @@ void mmu_set_pagetable(rt_ubase_t addr);
void mmu_enable_user_page_access();
void mmu_disable_user_page_access();
+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,
+};
+
+/**
+ * @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:
+ attr &= ~PTE_W;
+ 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:
+ attr |= PTE_W;
+ 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 = !!(attr & PTE_W);
+ default:
+ RT_ASSERT(0);
+ }
+ return rc;
+}
+
#endif