mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-21 10:36:04 +08:00
Sync dfs lwp (#8123)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
+109
-10
@@ -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
|
||||
|
||||
+46
-18
@@ -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)
|
||||
{
|
||||
void *dfar = RT_NULL;
|
||||
struct rt_lwp *lwp;
|
||||
asm volatile("MRC p15, 0, %0, c6, c0, 0" : "=r"(dfar));
|
||||
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));
|
||||
|
||||
if ((dfar >= (void *)USER_STACK_VSTART) && (dfar < (void *)USER_STACK_VEND))
|
||||
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))
|
||||
{
|
||||
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 -= 8;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_prefetch_abort(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
struct rt_lwp *lwp;
|
||||
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));
|
||||
|
||||
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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user