diff --git a/mkrtos_configs/STM32F205_defconfig b/mkrtos_configs/STM32F205_defconfig index abbf519d1..5cb6aaa48 100644 --- a/mkrtos_configs/STM32F205_defconfig +++ b/mkrtos_configs/STM32F205_defconfig @@ -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 diff --git a/mkrtos_configs/STM32F407VET6_defconfig b/mkrtos_configs/STM32F407VET6_defconfig index 83d466f3d..52b2c474b 100644 --- a/mkrtos_configs/STM32F407VET6_defconfig +++ b/mkrtos_configs/STM32F407VET6_defconfig @@ -111,4 +111,7 @@ CONFIG_CPU_TYPE="stm32f4" CONFIG_RTT_DIR="./" CONFIG_ARCH="cortex-m4" CONFIG_FLOAT_TYPE="hard" -CONFIG_BOARD_NAME="STM32F407VET6" \ No newline at end of file +CONFIG_BOARD_NAME="STM32F407VET6" +CONFIG_MPU_PAGE_FAULT_SUPPORT=y +CONFIG_MPU_PAGE_NUM=64 +CONFIG_MPU_PAGE_FAULT_REGIONS_NUM=2 diff --git a/mkrtos_knl/Kconfig b/mkrtos_knl/Kconfig index bec5b8f09..1ad6f562c 100644 --- a/mkrtos_knl/Kconfig +++ b/mkrtos_knl/Kconfig @@ -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 diff --git a/mkrtos_knl/arch/cortex-m3/core_it.c b/mkrtos_knl/arch/cortex-m3/core_it.c index c22e1c3cd..bedfea5d2 100755 --- a/mkrtos_knl/arch/cortex-m3/core_it.c +++ b/mkrtos_knl/arch/cortex-m3/core_it.c @@ -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); + } } /** diff --git a/mkrtos_knl/arch/cortex-m33/core_it.c b/mkrtos_knl/arch/cortex-m33/core_it.c index 429994eee..5744f05b7 100755 --- a/mkrtos_knl/arch/cortex-m33/core_it.c +++ b/mkrtos_knl/arch/cortex-m33/core_it.c @@ -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); + } } /** diff --git a/mkrtos_knl/arch/cortex-m4/core_it.c b/mkrtos_knl/arch/cortex-m4/core_it.c index 9c1155052..a433ef546 100755 --- a/mkrtos_knl/arch/cortex-m4/core_it.c +++ b/mkrtos_knl/arch/cortex-m4/core_it.c @@ -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); + } } /** diff --git a/mkrtos_knl/inc/knl/vma.h b/mkrtos_knl/inc/knl/vma.h index 656bc4277..c6a7d9336 100644 --- a/mkrtos_knl/inc/knl/vma.h +++ b/mkrtos_knl/inc/knl/vma.h @@ -3,6 +3,7 @@ #include #include #include +#include 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 diff --git a/mkrtos_knl/knl/mm/mpu/vma.c b/mkrtos_knl/knl/mm/mpu/vma.c index 3a33ce474..b781e22f1 100644 --- a/mkrtos_knl/knl/mm/mpu/vma.c +++ b/mkrtos_knl/knl/mm/mpu/vma.c @@ -11,24 +11,27 @@ #include #include #include - +#include 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 } /** diff --git a/mkrtos_script/build_f1.sh b/mkrtos_script/build_f1.sh index 82e849320..b9d84f25a 100755 --- a/mkrtos_script/build_f1.sh +++ b/mkrtos_script/build_f1.sh @@ -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- diff --git a/mkrtos_script/debug_m4.sh b/mkrtos_script/debug_m4.sh index 6a68cfbd0..9860bd818 100755 --- a/mkrtos_script/debug_m4.sh +++ b/mkrtos_script/debug_m4.sh @@ -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 \ diff --git a/mkrtos_user/lib/sys/inc/u_vmam.h b/mkrtos_user/lib/sys/inc/u_vmam.h index 67dc927c0..8967ad5cf 100644 --- a/mkrtos_user/lib/sys/inc/u_vmam.h +++ b/mkrtos_user/lib/sys/inc/u_vmam.h @@ -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 { diff --git a/mkrtos_user/server/init/src/test/vmam_test.c b/mkrtos_user/server/init/src/test/vmam_test.c index 308c02f6e..6d0c576f1 100644 --- a/mkrtos_user/server/init/src/test/vmam_test.c +++ b/mkrtos_user/server/init/src/test/vmam_test.c @@ -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; }