mpu缺页模拟支持
This commit is contained in:
@@ -124,3 +124,6 @@ CONFIG_THREAD_IPC_MSG_LEN=96
|
||||
CONFIG_THREAD_MAP_BUF_LEN=16
|
||||
CONFIG_MSG_BUF_VADDR=0xE0000000
|
||||
CONFIG_BOOT_FS_VADDR=0xE0001000
|
||||
CONFIG_MPU_PAGE_FAULT_SUPPORT=y
|
||||
CONFIG_MPU_PAGE_NUM=64
|
||||
CONFIG_MPU_PAGE_FAULT_REGIONS_NUM=2
|
||||
|
||||
@@ -111,4 +111,7 @@ CONFIG_CPU_TYPE="stm32f4"
|
||||
CONFIG_RTT_DIR="./"
|
||||
CONFIG_ARCH="cortex-m4"
|
||||
CONFIG_FLOAT_TYPE="hard"
|
||||
CONFIG_BOARD_NAME="STM32F407VET6"
|
||||
CONFIG_BOARD_NAME="STM32F407VET6"
|
||||
CONFIG_MPU_PAGE_FAULT_SUPPORT=y
|
||||
CONFIG_MPU_PAGE_NUM=64
|
||||
CONFIG_MPU_PAGE_FAULT_REGIONS_NUM=2
|
||||
|
||||
@@ -95,6 +95,15 @@ if MK_MPU_CFG
|
||||
config MPU_VERSION
|
||||
int "mpu version"
|
||||
default 1
|
||||
config MPU_PAGE_FAULT_SUPPORT
|
||||
bool "mpu page falut sim support."
|
||||
default 0
|
||||
config MPU_PAGE_NUM
|
||||
int "mpu page num."
|
||||
default 32
|
||||
config MPU_PAGE_FAULT_REGIONS_NUM
|
||||
int "mpu page fualt regions num."
|
||||
default 2
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "thread.h"
|
||||
#include "map.h"
|
||||
#include "thread_knl.h"
|
||||
#include "vma.h"
|
||||
/** @addtogroup Template_Project
|
||||
* @{
|
||||
*/
|
||||
@@ -137,8 +138,12 @@ void MemManage_Handler(void)
|
||||
}
|
||||
|
||||
end:
|
||||
printk("task:0x%x, semgement fault.\n", thread_get_current_task());
|
||||
task_knl_kill(thread_get_current(), is_knl);
|
||||
if (task_vma_page_fault(&(thread_get_current_task()->mm_space.mem_vma),
|
||||
ALIGN_DOWN(fault_addr, PAGE_SIZE), NULL) < 0)
|
||||
{
|
||||
printk("task:0x%x, semgement fault.\n", thread_get_current_task());
|
||||
task_knl_kill(thread_get_current(), is_knl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,8 +75,12 @@ void MemManage_Handler(void)
|
||||
}
|
||||
|
||||
end:
|
||||
printk("task:0x%x, semgement fault.\n", thread_get_current_task());
|
||||
task_knl_kill(thread_get_current(), is_knl);
|
||||
if (task_vma_page_fault(&(thread_get_current_task()->mm_space.mem_vma),
|
||||
ALIGN_DOWN(fault_addr, PAGE_SIZE), NULL) < 0)
|
||||
{
|
||||
printk("task:0x%x, semgement fault.\n", thread_get_current_task());
|
||||
task_knl_kill(thread_get_current(), is_knl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -134,8 +134,12 @@ void MemManage_Handler(void)
|
||||
}
|
||||
|
||||
end:
|
||||
printk("task:0x%x, semgement fault.\n", thread_get_current_task());
|
||||
task_knl_kill(thread_get_current(), is_knl);
|
||||
if (task_vma_page_fault(&(thread_get_current_task()->mm_space.mem_vma),
|
||||
ALIGN_DOWN(fault_addr, PAGE_SIZE), NULL) < 0)
|
||||
{
|
||||
printk("task:0x%x, semgement fault.\n", thread_get_current_task());
|
||||
task_knl_kill(thread_get_current(), is_knl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <util.h>
|
||||
#include <arch.h>
|
||||
#include <mmu/rbtree_mm.h>
|
||||
#include <spinlock.h>
|
||||
|
||||
enum vpage_prot_attrs
|
||||
{
|
||||
@@ -17,10 +18,8 @@ enum vpage_prot_attrs
|
||||
VPAGE_PROT_IN_KNL = 0x20, //!< 内核中使用
|
||||
};
|
||||
|
||||
#define VMA_ADDR_RESV 0x1 //!< 保留内存
|
||||
// #define VMA_ADDR_UNCACHE 0x2 //!< uncache内存
|
||||
|
||||
#define VMA_USED_NODE 0x1 //!< 该vma节点被使用,非空闲
|
||||
#define VMA_ADDR_RESV 0x1 //!< flags 保留内存
|
||||
#define VMA_ADDR_PAGE_FAULT_SIM 0x2 //!< page fault模拟
|
||||
|
||||
typedef union vma_addr
|
||||
{
|
||||
@@ -92,6 +91,7 @@ typedef struct vma
|
||||
};
|
||||
};
|
||||
} vma_t;
|
||||
#define VMA_USED_NODE 0x1 //!< 该vma节点被使用,非空闲
|
||||
|
||||
static inline paddr_t vma_node_get_paddr(vma_t *data)
|
||||
{
|
||||
@@ -134,9 +134,24 @@ typedef struct region_info
|
||||
#endif
|
||||
int16_t region_inx; //!< 区域索引
|
||||
} region_info_t;
|
||||
|
||||
#define MPU_PAGE_FAULT_SUPPORT CONFIG_MPU_PAGE_FAULT_SUPPORT
|
||||
#define MPU_PAGE_NUM CONFIG_MPU_PAGE_NUM
|
||||
#define MPU_PAGE_FAULT_REGIONS_NUM CONFIG_MPU_PAGE_FAULT_REGIONS_NUM
|
||||
|
||||
typedef struct task_vma
|
||||
{
|
||||
region_info_t pt_regions[CONFIG_REGION_NUM]; //!< mpu内存保护块
|
||||
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT)
|
||||
void *mem_pages[MPU_PAGE_NUM]; //!< 模拟内存缺页
|
||||
size_t mem_pages_alloc_size[MPU_PAGE_NUM]; //!< 红黑树优化支持
|
||||
uint8_t mem_pages_attrs[MPU_PAGE_NUM]; //!< 内存页的属性
|
||||
region_info_t *mem_pages_pt_regions[MPU_PAGE_FAULT_REGIONS_NUM]; //!< 用多少个regions模拟缺页
|
||||
int pt_regions_sel; //!< 用于确定下次选用那个region进行映射
|
||||
#endif
|
||||
|
||||
spinlock_t lock;
|
||||
} task_vma_t;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -11,24 +11,27 @@
|
||||
#include <task.h>
|
||||
#include <thread.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <spinlock.h>
|
||||
static region_info_t *vma_alloc_pt_region(task_vma_t *vma)
|
||||
{
|
||||
assert(vma != NULL);
|
||||
/*TODO:加锁*/
|
||||
mword_t status = spinlock_lock(&vma->lock);
|
||||
for (int i = 0; i < CONFIG_REGION_NUM; i++)
|
||||
{
|
||||
if (vma->pt_regions[i].region_inx < 0)
|
||||
{
|
||||
vma->pt_regions[i].region_inx = (int16_t)i;
|
||||
spinlock_set(&vma->lock, status);
|
||||
return &vma->pt_regions[i];
|
||||
}
|
||||
}
|
||||
spinlock_set(&vma->lock, status);
|
||||
return NULL;
|
||||
}
|
||||
static region_info_t *vma_find_pt_region(task_vma_t *vma, addr_t addr, size_t size)
|
||||
{
|
||||
assert(vma);
|
||||
mword_t status = spinlock_lock(&vma->lock);
|
||||
for (int i = 0; i < CONFIG_REGION_NUM; i++)
|
||||
{
|
||||
if (vma->pt_regions[i].region_inx < 0)
|
||||
@@ -37,15 +40,19 @@ static region_info_t *vma_find_pt_region(task_vma_t *vma, addr_t addr, size_t si
|
||||
}
|
||||
if (vma->pt_regions[i].start_addr == addr && vma->pt_regions[i].size == size)
|
||||
{
|
||||
spinlock_set(&vma->lock, status);
|
||||
return vma->pt_regions + i;
|
||||
}
|
||||
}
|
||||
spinlock_set(&vma->lock, status);
|
||||
return NULL;
|
||||
}
|
||||
static void vma_free_pt_region(task_vma_t *vma, region_info_t *ri)
|
||||
{
|
||||
mword_t status = spinlock_lock(&vma->lock);
|
||||
memset(ri, 0, sizeof(*ri));
|
||||
ri->region_inx = -1;
|
||||
spinlock_set(&vma->lock, status);
|
||||
}
|
||||
/**
|
||||
* @brief 初始化vma
|
||||
@@ -57,14 +64,28 @@ int task_vma_init(task_vma_t *vma)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_MK_MPU_CFG)
|
||||
assert(vma != NULL);
|
||||
|
||||
spinlock_init(&vma->lock);
|
||||
for (int i = 0; i < CONFIG_REGION_NUM; i++)
|
||||
{
|
||||
vma->pt_regions[i].region_inx = -1;
|
||||
}
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT)
|
||||
for (int i = 0; i < MPU_PAGE_FAULT_REGIONS_NUM; i++)
|
||||
{
|
||||
vma->mem_pages_pt_regions[i] = vma_alloc_pt_region(vma);
|
||||
if (vma->mem_pages_pt_regions[i] == NULL)
|
||||
{
|
||||
printk("pt regions alloc is failed.\n");
|
||||
assert(vma->mem_pages_pt_regions[i]);
|
||||
}
|
||||
}
|
||||
// vma->mem_pages_bitamp = 0;
|
||||
memset(vma->mem_pages, 0, sizeof(vma->mem_pages));
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 为task增加内存,需要用到mpu的region
|
||||
*
|
||||
@@ -81,6 +102,8 @@ int task_vma_alloc(task_vma_t *task_vma, vma_addr_t vaddr, size_t size,
|
||||
addr_t vma_addr;
|
||||
task_t *pt_task;
|
||||
int ret = 0;
|
||||
size_t mem_align_size;
|
||||
bool_t is_alloc_mem = FALSE;
|
||||
|
||||
pt_task = container_of(
|
||||
container_of(task_vma, mm_space_t, mem_vma),
|
||||
@@ -90,100 +113,127 @@ int task_vma_alloc(task_vma_t *task_vma, vma_addr_t vaddr, size_t size,
|
||||
assert(task_vma != NULL);
|
||||
#if IS_ENABLED(CONFIG_MK_MPU_CFG)
|
||||
#if CONFIG_MPU_VERSION == 1
|
||||
if (!is_power_of_2(size))
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT) //!< 缺页模拟
|
||||
if (vma_addr_get_flags(vaddr) & VMA_ADDR_PAGE_FAULT_SIM)
|
||||
{
|
||||
// 不是2的幂
|
||||
return -EINVAL;
|
||||
mem_align_size = PAGE_SIZE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
mem_align_size = size;
|
||||
}
|
||||
#elif CONFIG_MPU_VERSION == 2
|
||||
if (size & (MPU_ALIGN_SIZE - 1))
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT) //!< 缺页模拟
|
||||
if (vma_addr_get_flags(vaddr) & VMA_ADDR_PAGE_FAULT_SIM)
|
||||
{
|
||||
mem_align_size = PAGE_SIZE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
mem_align_size = MPU_ALIGN_SIZE;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
mem_align_size = sizeof(void *) * 2;
|
||||
#endif
|
||||
if (size & (mem_align_size - 1))
|
||||
{
|
||||
// 不是MPU_ALIGN_SIZE字节对齐的
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
vma_addr = vma_addr_get_addr(vaddr);
|
||||
if (vma_addr != 0)
|
||||
{
|
||||
// 必须让内核自己分配地址
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_end;
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_MK_MPU_CFG)
|
||||
#if CONFIG_MPU_VERSION == 1
|
||||
|
||||
if (paddr == 0)
|
||||
{
|
||||
// 未设置物理内存,则自动申请一个
|
||||
vma_addr = (addr_t)mm_limit_alloc_align(pt_task->lim, size, size);
|
||||
vma_addr = (addr_t)mm_limit_alloc_align(pt_task->lim, size, mem_align_size);
|
||||
assert(((vma_addr & (mem_align_size - 1))) == 0);
|
||||
is_alloc_mem = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 设置了物理内存,就用设置的物理内存
|
||||
vma_addr = paddr;
|
||||
if ((vma_addr & (mem_align_size - 1)) != 0)
|
||||
{
|
||||
// 不是对齐的
|
||||
ret = -EINVAL;
|
||||
goto err_end;
|
||||
}
|
||||
}
|
||||
if (vma_addr == 0)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
if ((vma_addr & (size - 1)) != 0)
|
||||
{
|
||||
// 不是对齐的
|
||||
ret = -EINVAL;
|
||||
goto err_end;
|
||||
}
|
||||
#elif CONFIG_MPU_VERSION == 2
|
||||
vma_addr = (addr_t)mm_limit_alloc_align(pt_task->lim, size, MPU_ALIGN_SIZE);
|
||||
if (vma_addr == 0)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (vma_addr & (MPU_ALIGN_SIZE - 1))
|
||||
{
|
||||
// 不是对齐的
|
||||
ret = -EINVAL;
|
||||
goto err_end;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
vma_addr = (addr_t)mm_limit_alloc_align(pt_task->lim, size, sizeof(void *) * 2);
|
||||
if (vma_addr == 0)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (vma_addr & (sizeof(void *) * 2 - 1))
|
||||
{
|
||||
// 不是对齐的
|
||||
ret = -EINVAL;
|
||||
goto err_end;
|
||||
}
|
||||
#endif
|
||||
// 找到一个合适的区域
|
||||
region_info_t *ri = NULL;
|
||||
|
||||
ri = vma_find_pt_region(task_vma, vma_addr, size);
|
||||
if (ri)
|
||||
{
|
||||
// 已经存在
|
||||
ret = -EEXIST;
|
||||
goto err_end;
|
||||
}
|
||||
|
||||
ri = vma_alloc_pt_region(task_vma);
|
||||
if (!ri)
|
||||
{
|
||||
// 没有找到合适的区域
|
||||
ret = -ENOMEM;
|
||||
goto err_end;
|
||||
}
|
||||
mpu_calc_regs(ri, vma_addr, size,
|
||||
vpage_attrs_to_page_attrs(vma_addr_get_prot(vaddr)),
|
||||
0 /*TODO:支持每一个region bit位*/);
|
||||
ri->start_addr = vma_addr;
|
||||
ri->size = size;
|
||||
if (pt_task == thread_get_current_task())
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT) //!< 缺页模拟
|
||||
if (vma_addr_get_flags(vaddr) & VMA_ADDR_PAGE_FAULT_SIM)
|
||||
{
|
||||
// 只有是当前线程的时候发生切换
|
||||
mpu_switch_to_task(pt_task);
|
||||
size_t alloc_cn = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MPU_PAGE_NUM; i++)
|
||||
{
|
||||
if (task_vma->mem_pages[i] == NULL) //!< 放到内存页中保存
|
||||
{
|
||||
task_vma->mem_pages[i] = (void *)(vma_addr + alloc_cn * PAGE_SIZE);
|
||||
task_vma->mem_pages_attrs[i] = vma_addr_get_prot(vaddr);
|
||||
if (alloc_cn == 0)
|
||||
{
|
||||
task_vma->mem_pages_alloc_size[i] = size;
|
||||
}
|
||||
alloc_cn++;
|
||||
if (alloc_cn * PAGE_SIZE >= size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == MPU_PAGE_NUM)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto err_end;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// 找到一个合适的区域
|
||||
region_info_t *ri = NULL;
|
||||
|
||||
ri = vma_find_pt_region(task_vma, vma_addr, size);
|
||||
if (ri)
|
||||
{
|
||||
// 已经存在
|
||||
ret = -EEXIST;
|
||||
goto err_end;
|
||||
}
|
||||
|
||||
ri = vma_alloc_pt_region(task_vma);
|
||||
if (!ri)
|
||||
{
|
||||
// 没有找到合适的区域
|
||||
ret = -ENOMEM;
|
||||
goto err_end;
|
||||
}
|
||||
mpu_calc_regs(ri, vma_addr, size,
|
||||
vpage_attrs_to_page_attrs(vma_addr_get_prot(vaddr)),
|
||||
0 /*TODO:支持每一个region bit位*/);
|
||||
ri->start_addr = vma_addr;
|
||||
ri->size = size;
|
||||
if (pt_task == thread_get_current_task())
|
||||
{
|
||||
// 只有是当前线程的时候发生切换
|
||||
mpu_switch_to_task(pt_task);
|
||||
}
|
||||
}
|
||||
if (ret_vaddr)
|
||||
{
|
||||
@@ -191,15 +241,10 @@ int task_vma_alloc(task_vma_t *task_vma, vma_addr_t vaddr, size_t size,
|
||||
}
|
||||
goto end;
|
||||
err_end:
|
||||
#if IS_ENABLED(CONFIG_MK_MPU_CFG)
|
||||
#if CONFIG_MPU_VERSION == 1
|
||||
mm_limit_free_align(pt_task->lim, (void *)vma_addr, size);
|
||||
#elif CONFIG_MPU_VERSION == 2
|
||||
mm_limit_free_align(pt_task->lim, (void *)vma_addr, MPU_ALIGN_SIZE);
|
||||
#endif
|
||||
#else
|
||||
mm_limit_free_align(pt_task->lim, (void *)vma_addr, sizeof(void *) * 2);
|
||||
#endif
|
||||
if (is_alloc_mem)
|
||||
{
|
||||
mm_limit_free_align(pt_task->lim, (void *)vma_addr, mem_align_size);
|
||||
}
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
@@ -225,16 +270,62 @@ static int task_vma_free_inner(task_vma_t *task_vma, vaddr_t vaddr, size_t size,
|
||||
region_info_t *ri = NULL;
|
||||
addr_t vma_addr;
|
||||
task_t *pt_task;
|
||||
|
||||
assert(task_vma);
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT) //!< 缺页模拟
|
||||
if (vaddr & (PAGE_SIZE - 1))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((size & (PAGE_SIZE - 1)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
pt_task = container_of(
|
||||
container_of(task_vma, mm_space_t, mem_vma),
|
||||
task_t,
|
||||
mm_space);
|
||||
assert(task_vma);
|
||||
vma_addr = vaddr; // vma_addr_get_addr(vaddr);
|
||||
vma_addr = vaddr;
|
||||
ri = vma_find_pt_region(task_vma, vma_addr, size);
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT) //!< 缺页模拟
|
||||
for (int i = 0; i < MPU_PAGE_FAULT_REGIONS_NUM; i++)
|
||||
{
|
||||
if (ri == task_vma->mem_pages_pt_regions[i])
|
||||
{
|
||||
ri = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!ri)
|
||||
{
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT) //!< 缺页模拟
|
||||
size_t mem_cn = 0;
|
||||
for (int i = 0; i < MPU_PAGE_NUM; i++)
|
||||
{
|
||||
if (task_vma->mem_pages[i] == (void *)(vaddr + mem_cn * PAGE_SIZE))
|
||||
{
|
||||
if (task_vma->mem_pages_alloc_size[i] != 0)
|
||||
{
|
||||
// 是头部,则释放内存
|
||||
mm_limit_free_align(pt_task->lim, (void *)vma_addr, PAGE_SIZE);
|
||||
task_vma->mem_pages_alloc_size[i] = 0;
|
||||
}
|
||||
task_vma->mem_pages[i] = NULL;
|
||||
ri = vma_find_pt_region(task_vma, (addr_t)(vaddr + mem_cn * PAGE_SIZE), PAGE_SIZE);
|
||||
if (ri)
|
||||
{
|
||||
ri->rbar = 0;
|
||||
ri->rasr = 0;
|
||||
}
|
||||
}
|
||||
mem_cn++;
|
||||
if (mem_cn * PAGE_SIZE >= size)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return -ENOENT;
|
||||
}
|
||||
vma_free_pt_region(task_vma, ri);
|
||||
@@ -250,6 +341,7 @@ static int task_vma_free_inner(task_vma_t *task_vma, vaddr_t vaddr, size_t size,
|
||||
mm_limit_free_align(pt_task->lim, (void *)vma_addr, sizeof(void *) * 2);
|
||||
#endif
|
||||
}
|
||||
end:
|
||||
if (pt_task == thread_get_current_task())
|
||||
{
|
||||
mpu_switch_to_task(pt_task);
|
||||
@@ -295,7 +387,43 @@ int task_vma_free_pmem(task_vma_t *task_vma, vaddr_t addr, size_t size, bool_t i
|
||||
*/
|
||||
int task_vma_page_fault(task_vma_t *task_vma, vaddr_t addr, void *paddr)
|
||||
{
|
||||
assert(task_vma);
|
||||
assert((addr & (PAGE_SIZE - 1)) == 0);
|
||||
task_t *pt_task;
|
||||
assert(task_vma);
|
||||
|
||||
pt_task = container_of(
|
||||
container_of(task_vma, mm_space_t, mem_vma),
|
||||
task_t,
|
||||
mm_space);
|
||||
#if IS_ENABLED(MPU_PAGE_FAULT_SUPPORT) //!< 缺页模拟
|
||||
for (int i = 0; i < MPU_PAGE_NUM; i++)
|
||||
{
|
||||
if (task_vma->mem_pages[i] == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((umword_t)(task_vma->mem_pages[i]) == addr)
|
||||
{
|
||||
int sel_region = task_vma->pt_regions_sel % MPU_PAGE_FAULT_REGIONS_NUM;
|
||||
|
||||
mpu_calc_regs(task_vma->mem_pages_pt_regions[sel_region], (umword_t)(task_vma->mem_pages[i]), PAGE_SIZE,
|
||||
vpage_attrs_to_page_attrs(task_vma->mem_pages_attrs[i]),
|
||||
0 /*TODO:支持每一个region bit位*/);
|
||||
task_vma->mem_pages_pt_regions[sel_region]->start_addr = addr;
|
||||
task_vma->mem_pages_pt_regions[sel_region]->size = PAGE_SIZE;
|
||||
task_vma->pt_regions_sel++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pt_task == thread_get_current_task())
|
||||
{
|
||||
mpu_switch_to_task(pt_task);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
# export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp
|
||||
# export TOOLCHAIN=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/
|
||||
# export TOOLCHAIN_LIB=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp
|
||||
export TOOLCHAIN=/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/bin/
|
||||
export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/lib/gcc/arm-none-eabi/5.4.1/armv7-m/
|
||||
# export TOOLCHAIN=/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/bin/
|
||||
# export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/lib/gcc/arm-none-eabi/5.4.1/armv7-m/
|
||||
export TOOLCHAIN=/home/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/
|
||||
export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp
|
||||
export BOARD=STM32F103ZET6
|
||||
export CROSS_COMPILE_NAME=arm-none-eabi-
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# if [ -z "$1"]; then
|
||||
# echo "usage: ./debug.sh [tcp port]"
|
||||
# exit
|
||||
# fi
|
||||
if [ -z "$1" ]; then
|
||||
echo "usage: ./debug.sh [tcp port]"
|
||||
exit
|
||||
fi
|
||||
|
||||
qemu-system-arm -machine\
|
||||
netduinoplus2 -cpu cortex-m4 \
|
||||
|
||||
@@ -15,8 +15,8 @@ enum vpage_prot_attrs
|
||||
VPAGE_PROT_IN_KNL = 0x20, //!< 内核中使用
|
||||
};
|
||||
|
||||
#define VMA_ADDR_RESV 0x1 //!< 保留内存
|
||||
// #define VMA_ADDR_UNCACHE 0x2 //!< uncache内存
|
||||
#define VMA_ADDR_RESV 0x1 //!< flags 保留内存
|
||||
#define VMA_ADDR_PAGE_FAULT_SIM 0x2 //!< page fault模拟
|
||||
|
||||
typedef union vma_addr
|
||||
{
|
||||
|
||||
@@ -53,7 +53,8 @@ static void vmm_press_block_test(CuTest *cu)
|
||||
for (i = 0; i < TEST_MEM_CN; i++)
|
||||
{
|
||||
tag = u_vmam_alloc(VMA_PROT, vma_addr_create(VPAGE_PROT_RWX, 0, 0), TEST_MM_SIZE, 0, &addr);
|
||||
if (msg_tag_get_val(tag) < 0) {
|
||||
if (msg_tag_get_val(tag) < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
memset((void *)addr, 0x55, TEST_MM_SIZE);
|
||||
@@ -77,6 +78,53 @@ static void vmm_press_block_test(CuTest *cu)
|
||||
#undef TEST_MM_SIZE
|
||||
#undef TEST_MEM_CN
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_MPU_PAGE_FAULT_SUPPORT)
|
||||
#define TEST_MEM_CN 30
|
||||
static void vmm_press_block_sim_page_fault_test(CuTest *cu)
|
||||
{
|
||||
int i;
|
||||
int m;
|
||||
addr_t addr;
|
||||
msg_tag_t tag;
|
||||
|
||||
memset(test_main, 0, sizeof(test_main));
|
||||
#define TEST_MM_SIZE (PAGE_SIZE)
|
||||
for (i = 0; i < TEST_MEM_CN; i++)
|
||||
{
|
||||
tag = u_vmam_alloc(VMA_PROT, vma_addr_create(VPAGE_PROT_RWX, VMA_ADDR_PAGE_FAULT_SIM, 0), TEST_MM_SIZE, 0, &addr);
|
||||
if (msg_tag_get_val(tag) < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
memset((void *)addr, 0x55, TEST_MM_SIZE);
|
||||
// printf("alloc umem:0x%lx\n", addr);
|
||||
test_main[i] = (void *)addr;
|
||||
}
|
||||
uint8_t *mem0 = test_main[0];
|
||||
uint8_t *mem1 = test_main[1];
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
*mem0 = *mem1;
|
||||
*mem1 = *mem0;
|
||||
}
|
||||
for (m = 0; m < i; m++)
|
||||
{
|
||||
for (int j = 0; j < TEST_MM_SIZE; j++)
|
||||
{
|
||||
uint8_t *tmp_mm = test_main[m];
|
||||
if (tmp_mm[j] != 0x55)
|
||||
{
|
||||
printf("mem test fail. i:%d j:%d\n", m, j);
|
||||
}
|
||||
assert(tmp_mm[j] == 0x55);
|
||||
}
|
||||
u_vmam_free(VMA_PROT, (addr_t)(test_main[m]), TEST_MM_SIZE);
|
||||
}
|
||||
|
||||
#undef TEST_MM_SIZE
|
||||
#undef TEST_MEM_CN
|
||||
}
|
||||
#endif
|
||||
static CuSuite suite;
|
||||
CuSuite *vmm_test_suite(void)
|
||||
{
|
||||
@@ -87,6 +135,8 @@ CuSuite *vmm_test_suite(void)
|
||||
#endif
|
||||
SUITE_ADD_TEST(&suite, vmm_small_block_test);
|
||||
SUITE_ADD_TEST(&suite, vmm_press_block_test);
|
||||
|
||||
#if IS_ENABLED(CONFIG_MPU_PAGE_FAULT_SUPPORT)
|
||||
SUITE_ADD_TEST(&suite, vmm_press_block_sim_page_fault_test);
|
||||
#endif
|
||||
return &suite;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user