From abb63b2e807c9961c63e6073c60a95196a52ae14 Mon Sep 17 00:00:00 2001 From: zhangzheng <1358745329@qq.com> Date: Tue, 17 Sep 2024 22:08:15 +0800 Subject: [PATCH] =?UTF-8?q?vma=E6=8F=90=E4=BE=9Bmpu=E6=94=AF=E6=8C=81(?= =?UTF-8?q?=E6=9C=AA=E5=AE=8C=E6=88=90)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mkrtos_knl/arch/cortex-m3/mm_space.c | 71 ------ mkrtos_knl/arch/cortex-m3/stm32f2/mpu.c | 10 +- mkrtos_knl/inc/knl/mm_space.h | 63 +----- mkrtos_knl/inc/knl/mpu.h | 14 ++ mkrtos_knl/inc/knl/vma.h | 26 +++ mkrtos_knl/knl/mm/mpu/vma.c | 278 ++++++++++++++++++++++++ mkrtos_script/build_f2.sh | 12 +- mkrtos_script/build_qemu_aarch64.sh | 8 +- mkrtos_user/server/uvmm/src/main.c | 4 +- 9 files changed, 344 insertions(+), 142 deletions(-) create mode 100644 mkrtos_knl/knl/mm/mpu/vma.c diff --git a/mkrtos_knl/arch/cortex-m3/mm_space.c b/mkrtos_knl/arch/cortex-m3/mm_space.c index 4d66e786d..5b2287e21 100644 --- a/mkrtos_knl/arch/cortex-m3/mm_space.c +++ b/mkrtos_knl/arch/cortex-m3/mm_space.c @@ -13,74 +13,3 @@ #include "mm_space.h" #include "mpu.h" #include "assert.h" -#if IS_ENABLED(CONFIG_MK_MPU_CFG) -int mm_space_init(mm_space_t *mm_space, int is_knl) -{ - for (int i = 0; i < CONFIG_REGION_NUM; i++) - { - mm_space->pt_regions[i].region_inx = -1; - } - return 0; -} -region_info_t *mm_space_alloc_pt_region(mm_space_t *m_space) -{ - for (int i = 0; i < CONFIG_REGION_NUM; i++) - { - /*TODO:原子操作*/ - if (m_space->pt_regions[i].region_inx < 0) - { - m_space->pt_regions[i].region_inx = (int16_t)i; - return &m_space->pt_regions[i]; - } - } - return NULL; -} -void mm_space_free_pt_region(mm_space_t *m_space, region_info_t *ri) -{ - ri->region_inx = -1; -} - -bool_t mm_space_add(mm_space_t *m_space, - umword_t addr, - umword_t size, - uint8_t attrs) -{ - region_info_t *ri = mm_space_alloc_pt_region(m_space); - - if (!ri) - { - return FALSE; - } -#if CONFIG_MPU_VERSION == 1 - if (!is_power_of_2(size) || (addr & (!(size - 1))) != 0) - { - //!< 申请的大小必须是2的整数倍,而且地址也必须是2的整数倍 - mm_space_free_pt_region(m_space, ri); - return FALSE; - } -#elif CONFIG_MPU_VERSION == 2 - if ((size & (MPU_ALIGN_SIZE - 1)) == 0 && (addr & (MPU_ALIGN_SIZE - 1)) == 0) - { - mm_space_free_pt_region(m_space, ri); - return FALSE; - } -#endif - mpu_calc_regs(ri, addr, size, attrs, 0); - ri->start_addr = addr; - ri->size = size; - return TRUE; -} -void mm_space_del(mm_space_t *m_space, umword_t addr) -{ - for (int i = 0; i < CONFIG_REGION_NUM; i++) - { - if (m_space->pt_regions[i].region_inx >= 0 && - m_space->pt_regions[i].start_addr == addr) - { - m_space->pt_regions[i].region_inx = -1; - m_space->pt_regions[i].start_addr = 0; - break; - } - } -} -#endif diff --git a/mkrtos_knl/arch/cortex-m3/stm32f2/mpu.c b/mkrtos_knl/arch/cortex-m3/stm32f2/mpu.c index a4bb48417..5f5185d57 100755 --- a/mkrtos_knl/arch/cortex-m3/stm32f2/mpu.c +++ b/mkrtos_knl/arch/cortex-m3/stm32f2/mpu.c @@ -25,11 +25,11 @@ void mpu_enable(void) { ARM_MPU_Enable(4); } -void mpu_calc_regs(region_info_t *region, umword_t addr, umword_t ffs_val, uint8_t attrs, uint8_t regions_bits) +void mpu_calc_regs(region_info_t *region, umword_t addr, umword_t size, uint8_t attrs, uint8_t regions_bits) { region->rbar = ARM_MPU_RBAR(region->region_inx, addr); region->rasr = ARM_MPU_RASR(0, attrs, 0UL, 0UL, - 1UL, 1UL, regions_bits, ffs(ffs_val) - 1); + 1UL, 1UL, regions_bits, ffs(size) - 1); } void mpu_region_set(int inx, umword_t rbar, umword_t rasr) { @@ -46,10 +46,10 @@ void mpu_switch_to_task(struct task *tk) mpu_disable(); for (int i = 0; i < CONFIG_REGION_NUM; i++) { - if (tk->mm_space.pt_regions[i].region_inx >= 0) + region_info_t *ri = &tk->mm_space.mem_vma.pt_regions[i]; + if (ri->region_inx >= 0) { - ARM_MPU_SetRegionEx(tk->mm_space.pt_regions[i].region_inx, tk->mm_space.pt_regions[i].rbar, - tk->mm_space.pt_regions[i].rasr); + ARM_MPU_SetRegionEx(ri->region_inx, ri->rbar, ri->rasr); } else { diff --git a/mkrtos_knl/inc/knl/mm_space.h b/mkrtos_knl/inc/knl/mm_space.h index b790e46c3..2e3d21d75 100644 --- a/mkrtos_knl/inc/knl/mm_space.h +++ b/mkrtos_knl/inc/knl/mm_space.h @@ -4,38 +4,22 @@ // #include #include #include -#if IS_ENABLED(CONFIG_MMU) #include #include -#endif -#if !IS_ENABLED(CONFIG_MMU) -typedef struct region_info -{ -#if CONFIG_MK_MPU_CFG - umword_t start_addr; //!< 内存申请的开始地址 - umword_t block_start_addr; //!< 块申请的开始地址 - umword_t block_size; //!< 保护的块大小 - umword_t size; //!< 实际申请的内存大小 - umword_t rbar; //!< mpu保护寄存器信息 - umword_t rasr; //!< mpu保护寄存器信息 - int16_t region_inx; - uint8_t region; //!< 区域禁止信息 -#endif -} region_info_t; -#endif +/** + * @brief 内存空间 + * + */ typedef struct mm_space { #if IS_ENABLED(CONFIG_MMU) page_entry_t mem_dir; //!< MMU根映射表,存放映射信息 - task_vma_t mem_vma; - umword_t asid; + umword_t asid; //!< 进程的ASID #else void *mm_block; //!< task 的私有内存块 size_t mm_block_size; //!< 私有内存块的大小 -#if IS_ENABLED(CONFIG_MK_MPU_CFG) - region_info_t pt_regions[CONFIG_REGION_NUM]; //!< mpu内存保护块 -#endif #endif + task_vma_t mem_vma; //!< 虚拟内存区域 } mm_space_t; enum region_rights @@ -44,36 +28,6 @@ enum region_rights REGION_RO = 2, REGION_RWX = 3, }; -#if IS_ENABLED(CONFIG_MK_MPU_CFG) -region_info_t *mm_space_alloc_pt_region(mm_space_t *m_space); -void mm_space_free_pt_region(mm_space_t *m_space, region_info_t *ri); - -int mm_space_init(mm_space_t *mm_space, int is_knl); -bool_t mm_space_add(mm_space_t *m_space, umword_t addr, umword_t size, uint8_t attrs); -void mm_space_del(mm_space_t *m_space, umword_t addr); -#else -#if !IS_ENABLED(CONFIG_MMU) -static inline int mm_space_init(mm_space_t *mm_space, int is_knl) -{ -} -static inline bool_t mm_space_add(mm_space_t *m_space, umword_t addr, umword_t size, uint8_t attrs) -{ - return TRUE; -} -static inline void mm_space_del(mm_space_t *m_space, umword_t addr) -{ -} -#else -int mm_space_init(mm_space_t *mm_space, int is_knl); -bool_t mm_space_add(mm_space_t *m_space, umword_t addr, umword_t size, uint8_t attrs); -void mm_space_del(mm_space_t *m_space, umword_t addr); - -static inline page_entry_t *mm_space_get_pdir(mm_space_t *sp) -{ - return &sp->mem_dir; -} -#endif -#endif #if !IS_ENABLED(CONFIG_MMU) static inline void mm_space_set_ram_block(mm_space_t *mm_space, void *mem, size_t size) @@ -88,4 +42,9 @@ static inline void mm_space_get_ram_block(mm_space_t *mm_space, void **mem, size *mem = mm_space->mm_block; *size = mm_space->mm_block_size; } +#else +static inline page_entry_t *mm_space_get_pdir(mm_space_t *sp) +{ + return &sp->mem_dir; +} #endif diff --git a/mkrtos_knl/inc/knl/mpu.h b/mkrtos_knl/inc/knl/mpu.h index b6e8f546a..55ae7a553 100644 --- a/mkrtos_knl/inc/knl/mpu.h +++ b/mkrtos_knl/inc/knl/mpu.h @@ -16,6 +16,20 @@ void mpu_calc_regs(region_info_t *region, umword_t addr, umword_t ffs_val, uint8_t attrs, uint8_t regions_bits); void mpu_switch_to(void); void mpu_switch_to_task(struct task *tk); +static inline umword_t vpage_attrs_to_page_attrs(enum vpage_prot_attrs attrs) +{ + umword_t to_attrs = 0; + + if (attrs & VPAGE_PROT_RO) + { + to_attrs == REGION_RO; + } + else if ((attrs & VPAGE_PROT_RWX) == VPAGE_PROT_RWX) + { + to_attrs = REGION_RWX; + } + return to_attrs; +} #else #if !IS_ENABLED(CONFIG_MMU) static inline void mpu_init(void) diff --git a/mkrtos_knl/inc/knl/vma.h b/mkrtos_knl/inc/knl/vma.h index 180199be6..46127cb53 100644 --- a/mkrtos_knl/inc/knl/vma.h +++ b/mkrtos_knl/inc/knl/vma.h @@ -109,12 +109,38 @@ static inline void vma_node_set_unused(vma_t *data) data->flags &= ~(VMA_USED_NODE); } +#if IS_ENABLED(CONFIG_MMU) typedef struct task_vma { mln_rbtree_t idle_tree; mln_rbtree_t alloc_tree; } task_vma_t; +#else +typedef struct region_info +{ + umword_t start_addr; //!< 内存申请的开始地址 + umword_t block_start_addr; //!< 块申请的开始地址 + umword_t block_size; //!< 保护的块大小 + umword_t size; //!< 实际申请的内存大小 + umword_t rbar; //!< mpu保护寄存器信息 + umword_t rasr; //!< mpu保护寄存器信息 + int16_t region_inx; //!< 区域索引 + uint8_t region; //!< 区域禁止信息 +} region_info_t; +typedef struct task_vma +{ +#if IS_ENABLED(CONFIG_MK_MPU_CFG) + region_info_t pt_regions[CONFIG_REGION_NUM]; //!< mpu内存保护块 +#endif +} task_vma_t; +#endif +/** + * @brief 初始化task_vma + * + * @param vma + * @return int + */ int task_vma_init(task_vma_t *vma); /** diff --git a/mkrtos_knl/knl/mm/mpu/vma.c b/mkrtos_knl/knl/mm/mpu/vma.c new file mode 100644 index 000000000..dfae36c90 --- /dev/null +++ b/mkrtos_knl/knl/mm/mpu/vma.c @@ -0,0 +1,278 @@ + + +#include +#include +#include +#include +#include +#include +static region_info_t *vma_alloc_pt_region(task_vma_t *vma) +{ + assert(vma != NULL); + /*TODO:加锁*/ + 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; + return &vma->pt_regions[i]; + } + } + return NULL; +} +static region_info_t *vma_find_pt_region(task_vma_t *vma, addr_t addr, size_t size) +{ + assert(vma); + for (int i = 0; i < CONFIG_REGION_NUM; i++) + { + if (vma->pt_regions[i].region_inx < 0) + { + continue; + } + if (vma->pt_regions[i].start_addr == addr && vma->pt_regions[i].size == size) + { + return vma->pt_regions + i; + } + } + return NULL; +} +static void vma_free_pt_region(task_vma_t *vma, region_info_t *ri) +{ + ri->region_inx = -1; +} + +/** + * @brief 初始化vma + * + * @param vma vma结构体 + * @return int 0表示成功 <0表示失败 + */ +int task_vma_init(task_vma_t *vma) +{ + assert(vma != NULL); + for (int i = 0; i < CONFIG_REGION_NUM; i++) + { + vma->pt_regions[i].region_inx = -1; + } + return 0; +} + +/** + * @brief 为task增加内存,需要用到mpu的region + * + * @param task_vma + * @param vaddr + * @param size + * @param paddr + * @param ret_vaddr + * @return int + */ +int task_vma_alloc(task_vma_t *task_vma, vma_addr_t vaddr, size_t size, + paddr_t paddr, vaddr_t *ret_vaddr) +{ + addr_t vma_addr; + task_t *pt_task; + int ret = 0; + + pt_task = container_of( + container_of(task_vma, mm_space_t, mem_vma), + task_t, + mm_space); + + assert(task_vma != NULL); + if (!ret_vaddr) + { + return -EINVAL; + } +#if CONFIG_MPU_VERSION == 1 + if (!is_power_of_2(size)) + { + // 不是2的幂 + return -EINVAL; + } +#elif CONFIG_MPU_VERSION == 2 + if (size & (MPU_ALIGN_SIZE - 1)) + { + // 不是MPU_ALIGN_SIZE字节对齐的 + return -EINVAL; + } +#endif + vma_addr = vma_addr_get_addr(vaddr); + if (vma_addr != 0) + { + // 必须让内核自己分配地址 + return -EINVAL; + } + +#if CONFIG_MPU_VERSION == 1 + vma_addr = (addr_t)mm_limit_alloc_align(pt_task, size, size); + 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, size, MPU_ALIGN_SIZE); + if (vma_addr == 0) + { + return -ENOMEM; + } + if (vma_addr & (MPU_ALIGN_SIZE - 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; + mpu_switch_to_task( + pt_task); +err_end: +#if CONFIG_MPU_VERSION == 1 + mm_limit_free_align(pt_task, vma_addr, size); +#elif CONFIG_MPU_VERSION == 2 + mm_limit_free_align(pt_task, vma_addr, MPU_ALIGN_SIZE); +#endif + return ret; +} +/** + * @brief 将一个task的内存转移给另一个task + * 1.查找源中是否存在 + * 2.查找目的中是否存在 + * 3.虚拟地址节点从源中删除,插入到目的 + * 4.物理地址从源中解除映射,并从树中删除,插入到目的,并映射到目的端。 + * @param src_task_vma + * @param dst_task_vma + * @param src_addr + * @param size + * @return int + */ +int task_vma_grant(task_vma_t *src_task_vma, task_vma_t *dst_task_vma, + vaddr_t src_addr, vaddr_t dst_addr, size_t size) +{ + return -ENOSYS; +} +/** + * @brief 释放申请的虚拟内存,并释放已经申请的物理内存 + * 1.从分配树中找到需要的节点 + * 2.迭代释放物理内存 + * 3.设置节点为空闲节点,并与周围的合并 + * @param task_vma + * @param addr + * @param size + * @return int + */ +int task_vma_free(task_vma_t *task_vma, vaddr_t vaddr, size_t size) +{ + region_info_t *ri = NULL; + addr_t vma_addr; + task_t *pt_task; + + pt_task = container_of( + container_of(task_vma, mm_space_t, mem_vma), + task_t, + mm_space); + assert(task_vma); + vma_addr = vma_addr_get_addr(vaddr); + ri = vma_find_pt_region(task_vma, vma_addr, size); + if (!ri) + { + return -ENOENT; + } + vma_free_pt_region(task_vma, ri); +#if CONFIG_MPU_VERSION == 1 + mm_limit_free_align(pt_task, vma_addr, size); +#elif CONFIG_MPU_VERSION == 2 + mm_limit_free_align(pt_task, vma_addr, MPU_ALIGN_SIZE); +#endif + mpu_switch_to_task( + container_of( + container_of(task_vma, mm_space_t, mem_vma), + task_t, + mm_space)); + + return 0; +} + +/** + * @brief 释放掉已经申请的物理内存,但是不释放虚拟内存 + * + * @param task_vma + * @param addr + * @param size 释放的大小 + * @param is_free_mem 是否释放内存 + * @return int + */ +int task_vma_free_pmem(task_vma_t *task_vma, vaddr_t addr, size_t size, bool_t is_free_mem) +{ + return -ENOSYS; +} +/** + * @brief 缺页的处理流程 + * 1.查找已经分配的表中是否存在 + * 2.分配物理内存 + * 3.插入到已分配树中去 + * @param task_vma + * @param addr + * @return int + */ +int task_vma_page_fault(task_vma_t *task_vma, vaddr_t addr, void *paddr) +{ + return -ENOSYS; +} + +/** + * @brief 释放task_vma + * + * @param task_vma + * @return int + */ +int task_vma_clean(task_vma_t *task_vma) +{ + task_t *pt_task; + + pt_task = container_of( + container_of(task_vma, mm_space_t, mem_vma), + task_t, + mm_space); + for (int i = 0; i < CONFIG_REGION_NUM; i++) + { + if (task_vma->pt_regions[i].region_inx >= 0) + { + task_vma->pt_regions[i].region_inx = -1; +#if CONFIG_MPU_VERSION == 1 + mm_limit_free_align(pt_task, task_vma->pt_regions[i].start_addr, task_vma->pt_regions[i].size); +#elif CONFIG_MPU_VERSION == 2 + mm_limit_free_align(pt_task, task_vma->pt_regions[i].start_addr, MPU_ALIGN_SIZE); +#endif + } + } + return 0; +} diff --git a/mkrtos_script/build_f2.sh b/mkrtos_script/build_f2.sh index f82ca7dec..81c1479a1 100755 --- a/mkrtos_script/build_f2.sh +++ b/mkrtos_script/build_f2.sh @@ -1,13 +1,9 @@ #!/bin/bash -# export TOOLCHAIN=/home/zhangzheng/mkrtos-tools/gcc/gcc-arm-none-eabi-5_4-2016q3/bin/ -# export TOOLCHAIN_LIB=/home/zhangzheng/mkrtos-tools/gcc/gcc-arm-none-eabi-5_4-2016q3/lib/gcc/arm-none-eabi/5.4.1/armv7-m/ -# 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/gcc-arm-none-eabi-10.3-2021.10/bin/ -# 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=/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=/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 BOARD=STM32F205 export CROSS_COMPILE_NAME=arm-none-eabi- diff --git a/mkrtos_script/build_qemu_aarch64.sh b/mkrtos_script/build_qemu_aarch64.sh index 3080ab545..dfe5e7979 100755 --- a/mkrtos_script/build_qemu_aarch64.sh +++ b/mkrtos_script/build_qemu_aarch64.sh @@ -1,9 +1,9 @@ #!/bin/bash -# export TOOLCHAIN=/Applications/ArmGNUToolchain/11.3.rel1/aarch64-none-elf/bin/ -# export TOOLCHAIN_LIB=/Applications/ArmGNUToolchain/11.3.rel1/aarch64-none-elf/lib/gcc/aarch64-none-elf/11.3.1 -export TOOLCHAIN=/home/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/ -export TOOLCHAIN_LIB=/home/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.3.1 +export TOOLCHAIN=/Applications/ArmGNUToolchain/11.3.rel1/aarch64-none-elf/bin/ +export TOOLCHAIN_LIB=/Applications/ArmGNUToolchain/11.3.rel1/aarch64-none-elf/lib/gcc/aarch64-none-elf/11.3.1 +# export TOOLCHAIN=/home/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/ +# export TOOLCHAIN_LIB=/home/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.3.1 export BOARD=aarch64_qemu export CROSS_COMPILE_NAME=aarch64-none-elf- if [ -z "$1" ]; then diff --git a/mkrtos_user/server/uvmm/src/main.c b/mkrtos_user/server/uvmm/src/main.c index 31a57323b..5959c6604 100644 --- a/mkrtos_user/server/uvmm/src/main.c +++ b/mkrtos_user/server/uvmm/src/main.c @@ -47,5 +47,5 @@ int main(int argc, char *args[]) } -IMPORT_BIN(".rodata", "/home/mkrtos-real/mkrtos_user/server/uvmm/src/benos.bin", benos_bin); -IMPORT_BIN(".rodata", "/home/mkrtos-real/mkrtos_user/server/uvmm/src/vm_benos.json", benos_json); +IMPORT_BIN(".rodata", "/Users/zhangzheng/mkrtos-real/mkrtos_user/server/uvmm/src/benos.bin", benos_bin); +IMPORT_BIN(".rodata", "/Users/zhangzheng/mkrtos-real/mkrtos_user/server/uvmm/src/vm_benos.json", benos_json);