From fb78a71020a768d6615c8b10802f53bcc2c37c85 Mon Sep 17 00:00:00 2001 From: Shell Date: Wed, 25 Oct 2023 14:59:48 +0800 Subject: [smart] replace varea pgmgr and fixup of dfs mmap (#8184) Signed-off-by: shell Signed-off-by: Shell --- examples/utest/testcases/mm/SConscript | 11 +- examples/utest/testcases/mm/aspace_map_expand.c | 119 ++++++++++++ .../mm/aspace_unmap_range_invalid_param.c | 84 ++++++++ .../utest/testcases/mm/aspace_unmap_range_shrink.c | 75 +++++++ .../utest/testcases/mm/aspace_unmap_range_split.c | 65 +++++++ examples/utest/testcases/mm/common.h | 21 +- examples/utest/testcases/mm/lwp_mmap_expand.c | 109 +++++++++++ examples/utest/testcases/mm/lwp_mmap_fd.c | 140 ++++++++++++++ .../testcases/mm/lwp_mmap_fd_map_fixed_merge.c | 214 ++++++++++++++++++++ .../testcases/mm/lwp_mmap_fd_map_fixed_split.c | 215 +++++++++++++++++++++ examples/utest/testcases/mm/lwp_mmap_fix_private.c | 138 +++++++++++++ examples/utest/testcases/mm/lwp_mmap_map_fixed.c | 117 +++++++++++ examples/utest/testcases/mm/mm_api_tc.c | 6 +- examples/utest/testcases/mm/mm_lwp_tc.c | 5 +- examples/utest/testcases/mm/rt_ioremap.c | 43 +++++ examples/utest/testcases/mm/test_aspace_api.h | 12 +- .../utest/testcases/mm/test_aspace_api_internal.h | 4 +- examples/utest/testcases/mm/test_bst_adpt.h | 6 +- 18 files changed, 1363 insertions(+), 21 deletions(-) create mode 100644 examples/utest/testcases/mm/aspace_map_expand.c create mode 100644 examples/utest/testcases/mm/aspace_unmap_range_invalid_param.c create mode 100644 examples/utest/testcases/mm/aspace_unmap_range_shrink.c create mode 100644 examples/utest/testcases/mm/aspace_unmap_range_split.c create mode 100644 examples/utest/testcases/mm/lwp_mmap_expand.c create mode 100644 examples/utest/testcases/mm/lwp_mmap_fd.c create mode 100644 examples/utest/testcases/mm/lwp_mmap_fd_map_fixed_merge.c create mode 100644 examples/utest/testcases/mm/lwp_mmap_fd_map_fixed_split.c create mode 100644 examples/utest/testcases/mm/lwp_mmap_fix_private.c create mode 100644 examples/utest/testcases/mm/lwp_mmap_map_fixed.c create mode 100644 examples/utest/testcases/mm/rt_ioremap.c (limited to 'examples') diff --git a/examples/utest/testcases/mm/SConscript b/examples/utest/testcases/mm/SConscript index a0ea7402e7..93c0667c0b 100644 --- a/examples/utest/testcases/mm/SConscript +++ b/examples/utest/testcases/mm/SConscript @@ -6,8 +6,15 @@ src = [] CPPPATH = [cwd] if GetDepend(['UTEST_MM_API_TC', 'RT_USING_SMART']): - src += ['mm_api_tc.c', 'mm_libcpu_tc.c'] - if GetDepend(['RT_USING_MEMBLOCK']): + # deprecated test, will be rewrited in the future + # src += ['mm_api_tc.c', 'mm_libcpu_tc.c'] + src += ['rt_ioremap.c'] + src += ['aspace_unmap_range_invalid_param.c', 'aspace_unmap_range_shrink.c'] + src += ['aspace_unmap_range_split.c', 'aspace_map_expand.c'] + src += ['lwp_mmap_expand.c', 'lwp_mmap_map_fixed.c', 'lwp_mmap_fix_private.c'] + src += ['lwp_mmap_fd.c', 'lwp_mmap_fd_map_fixed_merge.c', 'lwp_mmap_fd_map_fixed_split.c'] + +if GetDepend(['UTEST_MM_API_TC', 'RT_USING_MEMBLOCK']): src += ['mm_memblock_tc.c'] if GetDepend(['UTEST_MM_LWP_TC', 'RT_USING_SMART']): diff --git a/examples/utest/testcases/mm/aspace_map_expand.c b/examples/utest/testcases/mm/aspace_map_expand.c new file mode 100644 index 0000000000..2fd70f1da0 --- /dev/null +++ b/examples/utest/testcases/mm/aspace_map_expand.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-22 Shell test case for aspace_map with varea_expand + */ +#include "common.h" +#include "lwp_user_mm.h" +#include + +#include + +static size_t flags = MMF_PREFETCH | MMF_MAP_FIXED; +static size_t attr = MMU_MAP_K_RWCB; +static rt_mem_obj_t mem_obj = &rt_mm_dummy_mapper; + +static char *ex_vaddr = (void *)0x100000000; +static size_t ex_offset = 1024; +static size_t map_size = 0x3000; + +static size_t former_vsz; +static size_t former_vcount; + +static struct rt_lwp *lwp; + +static int _count_vsz(rt_varea_t varea, void *arg) +{ + rt_base_t *pvsz = arg; + *pvsz += 1; + return 0; +} + +static rt_base_t count_vcount(rt_aspace_t aspace) +{ + rt_base_t vcount = 0; + rt_aspace_traversal(aspace, _count_vsz, &vcount); + return vcount; +} + +static void test_map_varea_expand(void) +{ + char *next_va; + size_t next_offset; + + /* create an existed mapping */ + next_va = ex_vaddr; + former_vsz = rt_aspace_count_vsz(lwp->aspace); + former_vcount = count_vcount(lwp->aspace); + utest_int_equal( + RT_EOK, + rt_aspace_map(lwp->aspace, (void *)&ex_vaddr, map_size, attr, flags, mem_obj, ex_offset) + ); + uassert_true(next_va == ex_vaddr); + utest_int_equal(former_vsz + map_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vsz += map_size; + former_vcount += 1; + + /* test the RIGHT side expansion of varea by rt_aspace_map */ + next_va = ex_vaddr + map_size; + next_offset = ex_offset + (map_size >> MM_PAGE_SHIFT); + utest_int_equal( + RT_EOK, + rt_aspace_map(lwp->aspace, (void *)&next_va, map_size, attr, flags, mem_obj, next_offset) + ); + uassert_true(next_va == (char *)ex_vaddr + map_size); + utest_int_equal(former_vsz + map_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount, count_vcount(lwp->aspace)); + former_vsz += map_size; + + /* test the LEFT side expansion of varea by rt_aspace_map */ + next_va = ex_vaddr - map_size; + next_offset = ex_offset - (map_size >> MM_PAGE_SHIFT); + utest_int_equal( + RT_EOK, + rt_aspace_map(lwp->aspace, (void *)&next_va, map_size, attr, flags, mem_obj, next_offset) + ); + uassert_true(next_va == ex_vaddr - map_size); + utest_int_equal(former_vsz + map_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount, count_vcount(lwp->aspace)); + former_vsz += map_size; + + /* test the expand varea routine from rt_aspace_map_static */ + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, next_va, 3 * map_size)); + + /* test the expand varea routine from rt_aspace_map_phy */ + /* test the expand varea routine from rt_aspace_map_phy_static */ + /* these 2 from another file */ +} + +static void aspace_map_tc(void) +{ + CONSIST_HEAP(test_map_varea_expand()); +} + +static rt_err_t utest_tc_init(void) +{ + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(aspace_map_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.mm.aspace_map.varea_expand", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/aspace_unmap_range_invalid_param.c b/examples/utest/testcases/mm/aspace_unmap_range_invalid_param.c new file mode 100644 index 0000000000..1beec1aa8a --- /dev/null +++ b/examples/utest/testcases/mm/aspace_unmap_range_invalid_param.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-17 Shell test case for aspace_unmap_range + */ +#include "common.h" +#include "lwp_user_mm.h" +#include + +#include + +static void *vaddr = (void *)0x100000000; +static size_t existed_size = 0x5000; +static char *unmap_start; +static size_t unmap_size = 0x2000; +static size_t former_vsz; +static struct rt_lwp *lwp; +static size_t flags = MMF_PREFETCH | MMF_MAP_FIXED; + +static void test_unmap_range_invalid_param(void) +{ + rt_mem_obj_t notsupp_object; + + /* create an existed mapping */ + former_vsz = rt_aspace_count_vsz(lwp->aspace); + uassert_true(!rt_aspace_map(lwp->aspace, &vaddr, existed_size, MMU_MAP_K_RWCB, flags, &rt_mm_dummy_mapper, 0)); + utest_int_equal(former_vsz + existed_size, rt_aspace_count_vsz(lwp->aspace)); + former_vsz += existed_size; + + /* test unaligned vaddr start */ + unmap_start = (char *)vaddr - 0x1234; + utest_int_equal(-RT_EINVAL, rt_aspace_unmap_range(lwp->aspace, unmap_start, unmap_size)); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + + /* test unaligned size */ + unmap_size = 0x2000; + unmap_start = (char *)vaddr + existed_size - unmap_size; + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, unmap_start, unmap_size - 0x123)); + utest_int_equal(former_vsz - unmap_size, rt_aspace_count_vsz(lwp->aspace)); + + /* create another mapping binding to mem_obj without proper handler */ + notsupp_object = rt_mem_obj_create(&rt_mm_dummy_mapper); + notsupp_object->on_varea_shrink = RT_NULL; + + utest_int_equal( + RT_EOK, + rt_aspace_map(lwp->aspace, (void *)&unmap_start, unmap_size, MMU_MAP_K_RWCB, flags, notsupp_object, 0) + ); + + utest_int_equal(-RT_EPERM, rt_aspace_unmap_range(lwp->aspace, unmap_start, 0x1000)); + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, vaddr, existed_size)); + rt_free(notsupp_object); +} + +static void aspace_unmap_tc(void) +{ + CONSIST_HEAP(test_unmap_range_invalid_param()); +} + +static rt_err_t utest_tc_init(void) +{ + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(aspace_unmap_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.mm.aspace_unmap_range.invalid_param", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/aspace_unmap_range_shrink.c b/examples/utest/testcases/mm/aspace_unmap_range_shrink.c new file mode 100644 index 0000000000..de52572d52 --- /dev/null +++ b/examples/utest/testcases/mm/aspace_unmap_range_shrink.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-17 Shell test case for aspace_unmap_range + */ +#include "common.h" +#include "lwp_user_mm.h" +#include + +#include + +static void *vaddr = (void *)0x100000000; +static size_t existed_size = 0x5000; +static char *unmap_start; +static char *unmap_end; +static size_t former_vsz; +static size_t unmap_size = 0x2000; +static struct rt_lwp *lwp; + +static void test_unmap_range_shrink(void) +{ + /* create an existed mapping */ + former_vsz = rt_aspace_count_vsz(lwp->aspace); + uassert_true(!rt_aspace_map(lwp->aspace, &vaddr, existed_size, MMU_MAP_K_RWCB, MMF_PREFETCH, &rt_mm_dummy_mapper, 0)); + utest_int_equal(former_vsz + existed_size, rt_aspace_count_vsz(lwp->aspace)); + former_vsz += existed_size; + + /* test the shrink mode of unmap from LEFT side */ + unmap_start = (char *)vaddr - unmap_size/2; + uassert_true(!rt_aspace_unmap_range(lwp->aspace, unmap_start, unmap_size)); + unmap_end = unmap_start + unmap_size; + uassert_true(rt_hw_mmu_v2p(lwp->aspace, unmap_end) != ARCH_MAP_FAILED); + utest_int_equal(former_vsz - (unmap_end - (char *)vaddr), rt_aspace_count_vsz(lwp->aspace)); + former_vsz -= unmap_end - (char *)vaddr; + + /* test the shrink mode of unmap from RIGHT side */ + unmap_start = (char *)vaddr + existed_size - unmap_size / 2; + uassert_true(!rt_aspace_unmap_range(lwp->aspace, unmap_start, unmap_size)); + uassert_true(rt_hw_mmu_v2p(lwp->aspace, unmap_start - 1) != ARCH_MAP_FAILED); + utest_int_equal(former_vsz - (unmap_end - (char *)vaddr), rt_aspace_count_vsz(lwp->aspace)); + former_vsz -= unmap_end - (char *)vaddr; + + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, vaddr, existed_size)); +} + +static void aspace_unmap_tc(void) +{ + CONSIST_HEAP(test_unmap_range_shrink()); +} + +static rt_err_t utest_tc_init(void) +{ + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(aspace_unmap_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.mm.aspace_unmap_range.shrink", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/aspace_unmap_range_split.c b/examples/utest/testcases/mm/aspace_unmap_range_split.c new file mode 100644 index 0000000000..07489df693 --- /dev/null +++ b/examples/utest/testcases/mm/aspace_unmap_range_split.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-17 Shell test case for aspace_unmap_range + */ +#include "common.h" +#include "lwp_user_mm.h" +#include + +#include + +static void *vaddr = (void *)0x100000000; +static size_t existed_size = 0x5000; +static char *unmap_start = (char *)0x100000000 + 0x3000; +static size_t former_vsz; +static size_t unmap_size = 0x1000; +static struct rt_lwp *lwp; + +static void test_unmap_range_split(void) +{ + /* create an existed mapping */ + former_vsz = rt_aspace_count_vsz(lwp->aspace); + uassert_true(!rt_aspace_map(lwp->aspace, &vaddr, existed_size, MMU_MAP_K_RWCB, MMF_PREFETCH, &rt_mm_dummy_mapper, 0)); + utest_int_equal(former_vsz + existed_size, rt_aspace_count_vsz(lwp->aspace)); + former_vsz += existed_size; + + /* test the split mode of unmap */ + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, unmap_start, unmap_size)); + uassert_true(rt_hw_mmu_v2p(lwp->aspace, unmap_start - 1) != ARCH_MAP_FAILED); + uassert_true(rt_hw_mmu_v2p(lwp->aspace, unmap_start + unmap_size) != ARCH_MAP_FAILED); + utest_int_equal(former_vsz - unmap_size, rt_aspace_count_vsz(lwp->aspace)); + + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, vaddr, existed_size)); +} + +static void aspace_unmap_tc(void) +{ + CONSIST_HEAP(test_unmap_range_split()); +} + +static rt_err_t utest_tc_init(void) +{ + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(aspace_unmap_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.mm.aspace_unmap_range.split", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/common.h b/examples/utest/testcases/mm/common.h index da86ba46ff..3255e166ca 100644 --- a/examples/utest/testcases/mm/common.h +++ b/examples/utest/testcases/mm/common.h @@ -35,10 +35,15 @@ extern rt_base_t rt_heap_lock(void); extern void rt_heap_unlock(rt_base_t level); +#define __int_compare(a, b, operator) do{long _a = (long)(a); long _b = (long)(b); __utest_assert((_a) operator (_b), "Assertion Failed: (" #a ") "#operator" (" #b ")"); if (!((_a) operator (_b)))LOG_E("\t"#a"=%ld(0x%lx), "#b"=%ld(0x%lx)", _a, _a, _b, _b);} while (0) +#define utest_int_equal(a, b) __int_compare(a, b, ==) +#define utest_int_less(a, b) __int_compare(a, b, <) +#define utest_int_less_equal(a, b) __int_compare(a, b, <=) + /** * @brief During the operations, is heap still the same; */ -#define CONSIST_HEAP(statement) do { \ +#define CONSIST_HEAP(statement) do { \ rt_size_t total, used, max_used; \ rt_size_t totala, useda, max_useda; \ rt_ubase_t level = rt_heap_lock(); \ @@ -46,11 +51,19 @@ extern void rt_heap_unlock(rt_base_t level); statement; \ rt_memory_info(&totala, &useda, &max_useda); \ rt_heap_unlock(level); \ - uassert_true(total == totala); \ - uassert_true(used == useda); \ - uassert_true(max_used == max_useda); \ + utest_int_equal(total, totala); \ + utest_int_equal(used, useda); \ } while (0) +#ifdef STANDALONE_TC +#define TC_ASSERT(expr) \ + ((expr) \ + ? 0 \ + : rt_kprintf("AssertFault(%d): %s\n", __LINE__, RT_STRINGIFY(expr))) +#else +#define TC_ASSERT(expr) uassert_true(expr) +#endif + rt_inline int memtest(volatile char *buf, int value, size_t buf_sz) { int ret = 0; diff --git a/examples/utest/testcases/mm/lwp_mmap_expand.c b/examples/utest/testcases/mm/lwp_mmap_expand.c new file mode 100644 index 0000000000..ee54f150fa --- /dev/null +++ b/examples/utest/testcases/mm/lwp_mmap_expand.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-22 Shell test case for aspace_map with varea_expand + */ +#include "common.h" +#include "lwp_user_mm.h" +#include + +#include + +static long fd = -1; +static long pgoffset = 0; +static size_t flags = MAP_FIXED | MAP_ANONYMOUS; +static size_t prot1 = PROT_READ | PROT_WRITE; + +static char *ex_vaddr = (void *)0x100000000; +static size_t map_size = 0x3000; + +static size_t former_vsz; +static size_t former_vcount; + +static struct rt_lwp *lwp; + +static int _count_vsz(rt_varea_t varea, void *arg) +{ + rt_base_t *pvsz = arg; + *pvsz += 1; + return 0; +} + +static rt_base_t count_vcount(rt_aspace_t aspace) +{ + rt_base_t vcount = 0; + rt_aspace_traversal(aspace, _count_vsz, &vcount); + return vcount; +} + +static void test_mmap_expand(void) +{ + char *next_va; + + /* map new pages at ex_vaddr to anonymous */ + next_va = ex_vaddr; + former_vsz = rt_aspace_count_vsz(lwp->aspace); + former_vcount = count_vcount(lwp->aspace); + next_va = lwp_mmap2(lwp, next_va, map_size, prot1, flags, fd, pgoffset); + uassert_true(next_va == ex_vaddr); + utest_int_equal(former_vsz + map_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vsz += map_size; + former_vcount += 1; + + /* test the RIGHT side expansion of varea by lwp_mmap2 */ + next_va = ex_vaddr + map_size; + uassert_true( + lwp_mmap2(lwp, next_va, map_size, prot1, flags, fd, pgoffset) + == next_va + ); + utest_int_equal(former_vsz + map_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount, count_vcount(lwp->aspace)); + former_vsz += map_size; + + /* test the LEFT side expansion of varea by rt_aspace_map */ + next_va = ex_vaddr - map_size; + uassert_true( + lwp_mmap2(lwp, next_va, map_size, prot1, flags, fd, pgoffset) + == next_va + ); + utest_int_equal(former_vsz + map_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount, count_vcount(lwp->aspace)); + former_vsz += map_size; + + /* test other prot/offset/flags */ + + /* clear mapping */ + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, next_va, 3 * map_size)); +} + +static void aspace_map_tc(void) +{ + CONSIST_HEAP(test_mmap_expand()); +} + +static rt_err_t utest_tc_init(void) +{ + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(aspace_map_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.lwp.mman.mmap_anon.expand", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/lwp_mmap_fd.c b/examples/utest/testcases/mm/lwp_mmap_fd.c new file mode 100644 index 0000000000..da2e4f8edf --- /dev/null +++ b/examples/utest/testcases/mm/lwp_mmap_fd.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-17 Shell test case for aspace_map(MAP_FIXED) + */ +#include "common.h" +#include "lwp_user_mm.h" +#include "utest_assert.h" +#include + +#include + +#define PAGE_SZ (1 << MM_PAGE_SHIFT) +#define PAGE_COUNT ('z' - 'a' + 1) +#define FILE_PATH "/test_mmap" +#define FILE_SZ (PAGE_COUNT * PAGE_SZ) + +static struct rt_lwp *lwp; +static size_t former_vsz; +static size_t former_vcount; +static char page_sz_buf[PAGE_SZ]; + +static void *vaddr = (void *)0x100000000; +static long pgoffset = 0; +static size_t ex_prot = PROT_NONE; +static size_t ex_flags = MAP_PRIVATE | MAP_ANONYMOUS; + +static int _count_vsz(rt_varea_t varea, void *arg) +{ + rt_base_t *pvsz = arg; + *pvsz += 1; + return 0; +} + +static rt_base_t count_vcount(rt_aspace_t aspace) +{ + rt_base_t vcount = 0; + rt_aspace_traversal(aspace, _count_vsz, &vcount); + return vcount; +} + +static rt_err_t _lwp_get_user(struct rt_lwp *lwp, char *vaddr, char *buffer) +{ + rt_varea_t varea = _aspace_bst_search(lwp->aspace, vaddr); + if (varea && varea->mem_obj && varea->mem_obj->page_read) + { + struct rt_aspace_io_msg io_msg; + rt_mm_io_msg_init(&io_msg, MM_PA_TO_OFF(vaddr), vaddr, buffer); + varea->mem_obj->page_read(varea, &io_msg); + } + return RT_EOK; +} + +static void _verify_file_content(const char *mmap_buf) +{ + char ch = 'a'; + for (char *read_va = (char *)mmap_buf; read_va < mmap_buf + FILE_SZ; read_va += PAGE_SZ, ch++) + { + _lwp_get_user(lwp, read_va, page_sz_buf); + utest_int_equal(RT_EOK, memtest(page_sz_buf, ch, PAGE_SZ)); + } +} + +static void test_mmap_fd(void) +{ + former_vsz = rt_aspace_count_vsz(lwp->aspace); + former_vcount = count_vcount(lwp->aspace); + + /* create an existed mapping */ + long temp_fd; + temp_fd = open(FILE_PATH, O_RDONLY); + LOG_D("New fd=%ld path=%s", temp_fd, FILE_PATH); + uassert_true(temp_fd >= 0); + utest_int_equal( + lwp_mmap2(lwp, vaddr, FILE_SZ, ex_prot, ex_flags, temp_fd, pgoffset), + vaddr); + close(temp_fd); + + utest_int_equal(former_vsz + FILE_SZ, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + + _verify_file_content(vaddr); + + /* create an override mapping */ + + /* close */ + + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, vaddr, FILE_SZ)); +} + +static void testcase_main(void) +{ + test_mmap_fd(); +} + +static void _setup_file_content(long fd) +{ + char ch = 'a'; + + for (size_t i = 0; i < PAGE_COUNT; i++, ch++) + { + memset(page_sz_buf, ch, PAGE_SZ); + write(fd, page_sz_buf, PAGE_SZ); + } +} + +static rt_err_t utest_tc_init(void) +{ + /* setup file */ + long temp_file_des; + temp_file_des = open(FILE_PATH, O_RDWR | O_CREAT, 0777); + LOG_D("New fd=%ld path=%s", temp_file_des, FILE_PATH); + if (temp_file_des < 0) + return -RT_ERROR; + _setup_file_content(temp_file_des); + close(temp_file_des); + + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(testcase_main); +} +UTEST_TC_EXPORT(testcase, "testcases.lwp.mman.mmap_fd.basic", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/lwp_mmap_fd_map_fixed_merge.c b/examples/utest/testcases/mm/lwp_mmap_fd_map_fixed_merge.c new file mode 100644 index 0000000000..b33606618e --- /dev/null +++ b/examples/utest/testcases/mm/lwp_mmap_fd_map_fixed_merge.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-17 Shell test case for aspace_map(MAP_FIXED) + */ +#include "common.h" +#include "lwp_user_mm.h" +#include "utest_assert.h" +#include + +#include + +#define PAGE_SZ (1 << MM_PAGE_SHIFT) +#define PAGE_COUNT ('z' - 'a' + 1) +#define FILE_PATH "/test_mmap" +#define FILE_SZ (PAGE_COUNT * PAGE_SZ) + +static struct rt_lwp *lwp; +static size_t former_vsz; +static size_t former_vcount; +static char page_sz_buf[PAGE_SZ]; + +static void *ex_start = (void *)0x100000000; +static size_t ex_size = 0x5000; +static long pgoffset = 0; +static size_t ex_prot = PROT_NONE; +static size_t ex_flags = MAP_PRIVATE | MAP_ANONYMOUS; + +static char *private0 = (char *)0x100000000; +static char *private1 = (char *)0x100000000 + 0x1000; +static char *private2 = (char *)0x100000000 + 0x2000; +static char *private3 = (char *)0x100000000 + 0x3000; +static char *private4 = (char *)0x100000000 + 0x4000; +static size_t or_size = 0x1000; +static size_t or_prot = PROT_READ | PROT_WRITE; +static size_t or_flags = MAP_ANON | MAP_FIXED; + +static long anon_fd = -1; + +static int _count_vsz(rt_varea_t varea, void *arg) +{ + rt_base_t *pvsz = arg; + *pvsz += 1; + return 0; +} + +static rt_base_t count_vcount(rt_aspace_t aspace) +{ + rt_base_t vcount = 0; + rt_aspace_traversal(aspace, _count_vsz, &vcount); + return vcount; +} + +static rt_err_t _lwp_get_user(struct rt_lwp *lwp, char *vaddr, char *buffer) +{ + rt_varea_t varea = _aspace_bst_search(lwp->aspace, vaddr); + if (varea && varea->mem_obj && varea->mem_obj->page_read) + { + struct rt_aspace_io_msg io_msg; + rt_mm_io_msg_init(&io_msg, MM_PA_TO_OFF(vaddr), vaddr, buffer); + varea->mem_obj->page_read(varea, &io_msg); + } + return RT_EOK; +} + +static void _verify_file_content(struct rt_lwp *lwp, const char *mmap_buf, int ch) +{ + _lwp_get_user(lwp, (char *)mmap_buf, page_sz_buf); + utest_int_equal(RT_EOK, memtest(page_sz_buf, ch, PAGE_SZ)); +} + +static void test_mmap_fd_fixed(void) +{ + former_vsz = rt_aspace_count_vsz(lwp->aspace); + former_vcount = count_vcount(lwp->aspace); + + /* create an existed mapping */ + long temp_fd; + temp_fd = open(FILE_PATH, O_RDONLY); + LOG_D("New fd=%ld path=%s", temp_fd, FILE_PATH); + uassert_true(temp_fd >= 0); + utest_int_equal( + lwp_mmap2(lwp, ex_start, ex_size, ex_prot, ex_flags, anon_fd, pgoffset), + ex_start); + utest_int_equal(former_vsz + ex_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vsz += ex_size; + former_vcount += 1; + _verify_file_content(lwp, private0, 0); + _verify_file_content(lwp, private1, 0); + _verify_file_content(lwp, private2, 0); + _verify_file_content(lwp, private3, 0); + _verify_file_content(lwp, private4, 0); + + /* create an override mapping */ + utest_int_equal( + lwp_mmap2(lwp, private2, or_size, or_prot, or_flags, temp_fd, 2), + private2); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 2, count_vcount(lwp->aspace)); + former_vcount += 2; + _verify_file_content(lwp, private0, 0); + _verify_file_content(lwp, private1, 0); + _verify_file_content(lwp, private2, 'c'); + _verify_file_content(lwp, private3, 0); + _verify_file_content(lwp, private4, 0); + + /* fix private from left most */ + utest_int_equal( + lwp_mmap2(lwp, private0, or_size, or_prot, or_flags, temp_fd, 0), + private0); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vcount += 1; + _verify_file_content(lwp, private0, 'a'); + _verify_file_content(lwp, private1, 0); + _verify_file_content(lwp, private2, 'c'); + _verify_file_content(lwp, private3, 0); + _verify_file_content(lwp, private4, 0); + + /* fix private from right most */ + utest_int_equal( + lwp_mmap2(lwp, private4, or_size, or_prot, or_flags, temp_fd, 4), + private4); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vcount += 1; + _verify_file_content(lwp, private0, 'a'); + _verify_file_content(lwp, private1, 0); + _verify_file_content(lwp, private2, 'c'); + _verify_file_content(lwp, private3, 0); + _verify_file_content(lwp, private4, 'e'); + + /* fix private from left-middle */ + utest_int_equal( + lwp_mmap2(lwp, private1, or_size, or_prot, or_flags, temp_fd, 1), + private1); + rt_aspace_print_all(lwp->aspace); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount - 1, count_vcount(lwp->aspace)); + former_vcount -= 1; + _verify_file_content(lwp, private0, 'a'); + _verify_file_content(lwp, private1, 'b'); + _verify_file_content(lwp, private2, 'c'); + _verify_file_content(lwp, private3, 0); + _verify_file_content(lwp, private4, 'e'); + + /* fix private from right-middle */ + utest_int_equal( + lwp_mmap2(lwp, private3, or_size, or_prot, or_flags, temp_fd, 3), + private3); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount - 1, count_vcount(lwp->aspace)); + former_vcount -= 1; + _verify_file_content(lwp, private0, 'a'); + _verify_file_content(lwp, private1, 'b'); + _verify_file_content(lwp, private2, 'c'); + _verify_file_content(lwp, private3, 'd'); + _verify_file_content(lwp, private4, 'e'); + + /* close */ + close(temp_fd); + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, ex_start, FILE_SZ)); +} + +static void testcase_main(void) +{ + test_mmap_fd_fixed(); +} + +static void _setup_file_content(long fd) +{ + char ch = 'a'; + for (size_t i = 0; i < PAGE_COUNT; i++, ch++) + { + memset(page_sz_buf, ch, PAGE_SZ); + write(fd, page_sz_buf, PAGE_SZ); + } +} + +static rt_err_t utest_tc_init(void) +{ + /* setup file */ + long temp_file_des; + temp_file_des = open(FILE_PATH, O_RDWR | O_CREAT, 0777); + LOG_D("New fd=%ld path=%s", temp_file_des, FILE_PATH); + if (temp_file_des < 0) + return -RT_ERROR; + _setup_file_content(temp_file_des); + close(temp_file_des); + + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(testcase_main); +} +UTEST_TC_EXPORT(testcase, "testcases.lwp.mman.mmap_fd.map_fixed_merge", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/lwp_mmap_fd_map_fixed_split.c b/examples/utest/testcases/mm/lwp_mmap_fd_map_fixed_split.c new file mode 100644 index 0000000000..7f7ef23b30 --- /dev/null +++ b/examples/utest/testcases/mm/lwp_mmap_fd_map_fixed_split.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-17 Shell test case for aspace_map(MAP_FIXED) + */ +#include "common.h" +#include "lwp_user_mm.h" +#include "utest_assert.h" +#include + +#include + +#define PAGE_SZ (1 << MM_PAGE_SHIFT) +#define PAGE_COUNT ('z' - 'a' + 1) +#define FILE_PATH "/test_mmap" +#define FILE_SZ (PAGE_COUNT * PAGE_SZ) + +static struct rt_lwp *lwp; +static size_t former_vsz; +static size_t former_vcount; +static char page_sz_buf[PAGE_SZ]; + +static void *ex_start = (void *)0x100000000; +static size_t ex_size = 0x5000; +static long pgoffset = 0; +static size_t ex_prot = PROT_NONE; +static size_t ex_flags = MAP_PRIVATE | MAP_ANONYMOUS; + +static char *private0 = (char *)0x100000000; +static char *private1 = (char *)0x100000000 + 0x1000; +static char *private2 = (char *)0x100000000 + 0x2000; +static char *private3 = (char *)0x100000000 + 0x3000; +static char *private4 = (char *)0x100000000 + 0x4000; +static size_t or_size = 0x1000; +static size_t or_prot = PROT_READ | PROT_WRITE; +static size_t or_flags = MAP_ANON | MAP_FIXED; + +static long anon_fd = -1; + +static int _count_vsz(rt_varea_t varea, void *arg) +{ + rt_base_t *pvsz = arg; + *pvsz += 1; + return 0; +} + +static rt_base_t count_vcount(rt_aspace_t aspace) +{ + rt_base_t vcount = 0; + rt_aspace_traversal(aspace, _count_vsz, &vcount); + return vcount; +} + +static rt_err_t _lwp_get_user(struct rt_lwp *lwp, char *vaddr, char *buffer) +{ + rt_varea_t varea = _aspace_bst_search(lwp->aspace, vaddr); + if (varea && varea->mem_obj && varea->mem_obj->page_read) + { + struct rt_aspace_io_msg io_msg; + rt_mm_io_msg_init(&io_msg, MM_PA_TO_OFF(vaddr), vaddr, buffer); + varea->mem_obj->page_read(varea, &io_msg); + } + else + return -RT_ERROR; + return RT_EOK; +} + +static void _verify_file_content(struct rt_lwp *lwp, const char *mmap_buf, int ch) +{ + utest_int_equal(RT_EOK, _lwp_get_user(lwp, (char *)mmap_buf, page_sz_buf)); + utest_int_equal(RT_EOK, memtest(page_sz_buf, ch, PAGE_SZ)); +} + +static void test_mmap_fd_fixed(void) +{ + former_vsz = rt_aspace_count_vsz(lwp->aspace); + former_vcount = count_vcount(lwp->aspace); + + /* create an existed mapping */ + long temp_fd; + temp_fd = open(FILE_PATH, O_RDONLY); + LOG_D("New fd=%ld path=%s", temp_fd, FILE_PATH); + uassert_true(temp_fd >= 0); + utest_int_equal( + lwp_mmap2(lwp, ex_start, ex_size, ex_prot, ex_flags, temp_fd, pgoffset), + ex_start); + utest_int_equal(former_vsz + ex_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + _verify_file_content(lwp, private0, 'a'); + _verify_file_content(lwp, private1, 'b'); + _verify_file_content(lwp, private2, 'c'); + _verify_file_content(lwp, private3, 'd'); + _verify_file_content(lwp, private4, 'e'); + former_vsz += ex_size; + former_vcount += 1; + + /* create an override mapping */ + utest_int_equal( + lwp_mmap2(lwp, private2, or_size, or_prot, or_flags, anon_fd, pgoffset), + private2); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 2, count_vcount(lwp->aspace)); + former_vcount += 2; + _verify_file_content(lwp, private0, 'a'); + _verify_file_content(lwp, private1, 'b'); + _verify_file_content(lwp, private2, 0); + _verify_file_content(lwp, private3, 'd'); + _verify_file_content(lwp, private4, 'e'); + + /* fix private from left most */ + utest_int_equal( + lwp_mmap2(lwp, private0, or_size, or_prot, or_flags, anon_fd, pgoffset), + private0); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vcount += 1; + _verify_file_content(lwp, private0, 0); + _verify_file_content(lwp, private1, 'b'); + _verify_file_content(lwp, private2, 0); + _verify_file_content(lwp, private3, 'd'); + _verify_file_content(lwp, private4, 'e'); + + /* fix private from right most */ + utest_int_equal( + lwp_mmap2(lwp, private4, or_size, or_prot, or_flags, anon_fd, pgoffset), + private4); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vcount += 1; + _verify_file_content(lwp, private0, 0); + _verify_file_content(lwp, private1, 'b'); + _verify_file_content(lwp, private2, 0); + _verify_file_content(lwp, private3, 'd'); + _verify_file_content(lwp, private4, 0); + + /* fix private from left-middle */ + utest_int_equal( + lwp_mmap2(lwp, private1, or_size, or_prot, or_flags, anon_fd, pgoffset), + private1); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount - 1, count_vcount(lwp->aspace)); + former_vcount -= 1; + _verify_file_content(lwp, private0, 0); + _verify_file_content(lwp, private1, 0); + _verify_file_content(lwp, private2, 0); + _verify_file_content(lwp, private3, 'd'); + _verify_file_content(lwp, private4, 0); + + /* fix private from right-middle */ + utest_int_equal( + lwp_mmap2(lwp, private3, or_size, or_prot, or_flags, anon_fd, pgoffset), + private3); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount - 1, count_vcount(lwp->aspace)); + former_vcount -= 1; + _verify_file_content(lwp, private0, 0); + _verify_file_content(lwp, private1, 0); + _verify_file_content(lwp, private2, 0); + _verify_file_content(lwp, private3, 0); + _verify_file_content(lwp, private4, 0); + + /* close */ + close(temp_fd); + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, ex_start, FILE_SZ)); +} + +static void testcase_main(void) +{ + test_mmap_fd_fixed(); +} + +static void _setup_file_content(long fd) +{ + char ch = 'a'; + for (size_t i = 0; i < PAGE_COUNT; i++, ch++) + { + memset(page_sz_buf, ch, PAGE_SZ); + write(fd, page_sz_buf, PAGE_SZ); + } +} + +static rt_err_t utest_tc_init(void) +{ + /* setup file */ + long temp_file_des; + temp_file_des = open(FILE_PATH, O_RDWR | O_CREAT, 0777); + LOG_D("New fd=%ld path=%s", temp_file_des, FILE_PATH); + if (temp_file_des < 0) + return -RT_ERROR; + _setup_file_content(temp_file_des); + close(temp_file_des); + + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(testcase_main); +} +UTEST_TC_EXPORT(testcase, "testcases.lwp.mman.mmap_fd.map_fixed_split", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/lwp_mmap_fix_private.c b/examples/utest/testcases/mm/lwp_mmap_fix_private.c new file mode 100644 index 0000000000..71570bb4dc --- /dev/null +++ b/examples/utest/testcases/mm/lwp_mmap_fix_private.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-22 Shell test case for aspace_map with varea_expand + */ +#include "common.h" +#include "lwp_user_mm.h" +#include "mm_fault.h" +#include + +#include + +static long fd = -1; +static long pgoffset = 0; +static size_t flags = MAP_FIXED | MAP_ANONYMOUS; +static size_t prot = PROT_READ | PROT_WRITE; + +static char *ex_vaddr = (char *)0x100000000; +static size_t ex_size = 0x5000; +static char *private0 = (char *)0x100000000; +static char *private1 = (char *)0x100000000 + 0x1000; +static char *private2 = (char *)0x100000000 + 0x2000; +static char *private3 = (char *)0x100000000 + 0x3000; +static char *private4 = (char *)0x100000000 + 0x4000; + +/** + * todo: suppoprt prefetch pages, so more than 1 page can install to private at a time + * static size_t priv_size = 0x1000; + */ + +static size_t former_vsz; +static size_t former_vcount; + +static struct rt_lwp *lwp; + +static int _count_vsz(rt_varea_t varea, void *arg) +{ + rt_base_t *pvsz = arg; + *pvsz += 1; + return 0; +} + +static rt_base_t count_vcount(rt_aspace_t aspace) +{ + rt_base_t vcount = 0; + rt_aspace_traversal(aspace, _count_vsz, &vcount); + return vcount; +} + +static void test_mmap_fix_private(void) +{ + char *next_va; + struct rt_aspace_fault_msg msg; + msg.fault_op = MM_FAULT_OP_WRITE; + msg.fault_type = MM_FAULT_TYPE_ACCESS_FAULT; + + /* map new pages at ex_vaddr to anonymous */ + next_va = ex_vaddr; + former_vsz = rt_aspace_count_vsz(lwp->aspace); + former_vcount = count_vcount(lwp->aspace); + next_va = lwp_mmap2(lwp, next_va, ex_size, prot, flags, fd, pgoffset); + uassert_true(next_va == ex_vaddr); + utest_int_equal(former_vsz + ex_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vsz += ex_size; + former_vcount += 1; + + /* fix private in the middle */ + msg.fault_vaddr = private2; + utest_int_equal(MM_FAULT_FIXABLE_TRUE, rt_aspace_fault_try_fix(lwp->aspace, &msg)); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 2, count_vcount(lwp->aspace)); + former_vcount += 2; + + /* fix private from left most */ + msg.fault_vaddr = private0; + utest_int_equal(MM_FAULT_FIXABLE_TRUE, rt_aspace_fault_try_fix(lwp->aspace, &msg)); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vcount += 1; + + /* fix private from right most */ + msg.fault_vaddr = private4; + utest_int_equal(MM_FAULT_FIXABLE_TRUE, rt_aspace_fault_try_fix(lwp->aspace, &msg)); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vcount += 1; + + /* fix private from left-middle */ + msg.fault_vaddr = private1; + utest_int_equal(MM_FAULT_FIXABLE_TRUE, rt_aspace_fault_try_fix(lwp->aspace, &msg)); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount - 1, count_vcount(lwp->aspace)); + former_vcount -= 1; + + /* fix private from right-middle */ + msg.fault_vaddr = private3; + utest_int_equal(MM_FAULT_FIXABLE_TRUE, rt_aspace_fault_try_fix(lwp->aspace, &msg)); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount - 1, count_vcount(lwp->aspace)); + former_vcount -= 1; + + /* clear mapping */ + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, ex_vaddr, ex_size)); + rt_free(lwp->aspace->private_object); + lwp->aspace->private_object = RT_NULL; +} + +static void testcase_main(void) +{ + CONSIST_HEAP(test_mmap_fix_private()); +} + +static rt_err_t utest_tc_init(void) +{ + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(testcase_main); +} +UTEST_TC_EXPORT(testcase, "testcases.lwp.mman.mmap_anon.fix_private", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/lwp_mmap_map_fixed.c b/examples/utest/testcases/mm/lwp_mmap_map_fixed.c new file mode 100644 index 0000000000..affc514037 --- /dev/null +++ b/examples/utest/testcases/mm/lwp_mmap_map_fixed.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-08-17 Shell test case for aspace_map(MAP_FIXED) + */ +#include "common.h" +#include "lwp_user_mm.h" +#include "utest_assert.h" +#include + +#include + +static struct rt_lwp *lwp; +static size_t former_vsz; +static size_t former_vcount; + +static void *vaddr = (void *)0x100000000; +static size_t ex_size = 0x5000; +static char *override_start; +static size_t override_size = 0x2000; +static long fd = -1; +static long pgoffset = 0; +static size_t ex_prot = PROT_NONE; +static size_t ex_flags = MAP_PRIVATE | MAP_ANONYMOUS; +static size_t override_prot = PROT_READ | PROT_WRITE; +static size_t override_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED; + +static int _count_vsz(rt_varea_t varea, void *arg) +{ + rt_base_t *pvsz = arg; + *pvsz += 1; + return 0; +} + +static rt_base_t count_vcount(rt_aspace_t aspace) +{ + rt_base_t vcount = 0; + rt_aspace_traversal(aspace, _count_vsz, &vcount); + return vcount; +} + +static char put_data[] = "hello,world"; + +static void test_map_fixed(void) +{ + void *effect_override; + + former_vsz = rt_aspace_count_vsz(lwp->aspace); + former_vcount = count_vcount(lwp->aspace); + + /* create an existed mapping */ + vaddr = lwp_mmap2(lwp, vaddr, ex_size, ex_prot, ex_flags, fd, pgoffset); + uassert_true((long)vaddr > 0); + utest_int_equal(former_vsz + ex_size, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace)); + former_vsz += ex_size; + former_vcount += 1; + + /* fix private in the middle */ + override_start = (char *)vaddr + 0x1000; + effect_override = lwp_mmap2(lwp, override_start, override_size, override_prot, override_flags, fd, pgoffset); + uassert_true(effect_override == override_start); + utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace)); + utest_int_equal(former_vcount + 2, count_vcount(lwp->aspace)); + utest_int_equal( + lwp_data_put(lwp, effect_override, put_data, sizeof(put_data)), + sizeof(put_data) + ); + + utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, vaddr, ex_size)); +} + +static void aspace_unmap_tc(void) +{ + test_map_fixed(); +} + +static rt_size_t total, used, max_used; +static rt_size_t totala, useda, max_useda; +static rt_ubase_t level; +static rt_err_t utest_tc_init(void) +{ + lwp = lwp_create(0); + if (lwp) + lwp_user_space_init(lwp, 1); + else + return -RT_ENOMEM; + + /* stats */ + level = rt_heap_lock(); + rt_memory_info(&total, &used, &max_used); + + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + lwp_ref_dec(lwp); + + /* check */ + rt_memory_info(&totala, &useda, &max_useda); + rt_heap_unlock(level); + utest_int_equal(total, totala); + utest_int_less_equal(useda, used); + + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(aspace_unmap_tc); +} +UTEST_TC_EXPORT(testcase, "testcases.lwp.mman.mmap_anon.fix_private", utest_tc_init, utest_tc_cleanup, 10); diff --git a/examples/utest/testcases/mm/mm_api_tc.c b/examples/utest/testcases/mm/mm_api_tc.c index e7c3127064..6ddb39189d 100644 --- a/examples/utest/testcases/mm/mm_api_tc.c +++ b/examples/utest/testcases/mm/mm_api_tc.c @@ -40,9 +40,9 @@ static rt_err_t utest_tc_cleanup(void) static void testcase(void) { - UTEST_UNIT_RUN(aspace_tc); - UTEST_UNIT_RUN(ioremap_tc); - UTEST_UNIT_RUN(flag_tc); + aspace_tc(); + ioremap_tc(); + flag_tc(); } UTEST_TC_EXPORT(testcase, "testcases.mm.api_tc", utest_tc_init, utest_tc_cleanup, 20); diff --git a/examples/utest/testcases/mm/mm_lwp_tc.c b/examples/utest/testcases/mm/mm_lwp_tc.c index b0e82085bf..76fc0c8c92 100644 --- a/examples/utest/testcases/mm/mm_lwp_tc.c +++ b/examples/utest/testcases/mm/mm_lwp_tc.c @@ -13,6 +13,7 @@ #include "lwp_arch.h" #include "lwp_user_mm.h" #include "mm_aspace.h" +#include "mm_flag.h" #include "mmu.h" /** @@ -62,7 +63,7 @@ static void test_user_map_varea(void) uassert_true(varea->attr == (MMU_MAP_U_RWCB)); uassert_true(varea->size == buf_sz); uassert_true(varea->aspace == lwp->aspace); - uassert_true(varea->flag == 0); + uassert_true(varea->flag == MMF_MAP_PRIVATE); uassert_true(varea->start != 0); uassert_true(varea->start >= (void *)USER_VADDR_START && varea->start < (void *)USER_VADDR_TOP); @@ -86,7 +87,7 @@ static void test_user_map_varea_ext(void) uassert_true(varea->attr == (MMU_MAP_U_RW)); uassert_true(varea->size == buf_sz); uassert_true(varea->aspace == lwp->aspace); - uassert_true(varea->flag == 0); + uassert_true(varea->flag == MMF_MAP_PRIVATE); uassert_true(varea->start != 0); uassert_true(varea->start >= (void *)USER_VADDR_START && varea->start < (void *)USER_VADDR_TOP); diff --git a/examples/utest/testcases/mm/rt_ioremap.c b/examples/utest/testcases/mm/rt_ioremap.c new file mode 100644 index 0000000000..ca7f172b8e --- /dev/null +++ b/examples/utest/testcases/mm/rt_ioremap.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-14 WangXiaoyao the first version + * 2023-03-20 WangXiaoyao Format & add more testcases for API under mm_aspace.h + */ + +#include "common.h" + +void ioremap_tc(void) +{ + const size_t bufsz = 0x1000; + void *paddr = (void *)rt_pages_alloc(rt_page_bits(bufsz)) + PV_OFFSET; + int *vaddr; + vaddr = rt_ioremap_cached(paddr, bufsz); + if (vaddr) + { + TC_ASSERT(*vaddr == *(int *)(paddr - PV_OFFSET)); + + rt_iounmap(vaddr); + rt_pages_free(paddr - PV_OFFSET, 0); + } +} + +static rt_err_t utest_tc_init(void) +{ + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + return RT_EOK; +} + +static void test_main(void) +{ + CONSIST_HEAP(ioremap_tc()); +} +UTEST_TC_EXPORT(test_main, "testcases.mm.ioremap", utest_tc_init, utest_tc_cleanup, 20); diff --git a/examples/utest/testcases/mm/test_aspace_api.h b/examples/utest/testcases/mm/test_aspace_api.h index 47f2bac670..2213888c28 100644 --- a/examples/utest/testcases/mm/test_aspace_api.h +++ b/examples/utest/testcases/mm/test_aspace_api.h @@ -11,6 +11,8 @@ #define __TEST_ASPACE_API_H__ #include "common.h" +#include "mm_aspace.h" +#include "mm_flag.h" #include "test_aspace_api_internal.h" #include "test_synchronization.h" @@ -122,11 +124,11 @@ static void aspace_map_tc(void) * in _rt_aspace_map:_varea_install * not covering an existed varea if a named mapping is mandatory */ - vaddr = (void *)((rt_ubase_t)aspace_map_tc & ~ARCH_PAGE_MASK); - CONSIST_HEAP( - uassert_true( - rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_MAP_FIXED, &rt_mm_dummy_mapper, 0))); - uassert_true(vaddr == RT_NULL); + // vaddr = (void *)((rt_ubase_t)aspace_map_tc & ~ARCH_PAGE_MASK); + // CONSIST_HEAP( + // uassert_true( + // rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, 0, &rt_mm_dummy_mapper, 0))); + // uassert_true(vaddr == RT_NULL); /** * @brief Requirement: diff --git a/examples/utest/testcases/mm/test_aspace_api_internal.h b/examples/utest/testcases/mm/test_aspace_api_internal.h index f8e9d63e91..953424f07c 100644 --- a/examples/utest/testcases/mm/test_aspace_api_internal.h +++ b/examples/utest/testcases/mm/test_aspace_api_internal.h @@ -36,8 +36,8 @@ static void test_find_free(void) uassert_true(!rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_MAP_FIXED, &rt_mm_dummy_mapper, 0)); uassert_true(vaddr == top_page); /* type 1, on failure */ - uassert_true(rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_MAP_FIXED, &rt_mm_dummy_mapper, 0)); - uassert_true(!vaddr); + // uassert_true(rt_aspace_map(&rt_kernel_space, &vaddr, 0x1000, MMU_MAP_K_RWCB, MMF_MAP_FIXED, &rt_mm_dummy_mapper, 0)); + // uassert_true(!vaddr); /* type 2, on success */ vaddr = top_page; diff --git a/examples/utest/testcases/mm/test_bst_adpt.h b/examples/utest/testcases/mm/test_bst_adpt.h index 1a1b55de43..e081a754bb 100644 --- a/examples/utest/testcases/mm/test_bst_adpt.h +++ b/examples/utest/testcases/mm/test_bst_adpt.h @@ -35,7 +35,7 @@ void test_bst_adpt(void) uassert_true(!!lwp); uassert_true(!lwp_user_space_init(lwp, 0)); aspace = lwp->aspace; - mem_obj = &lwp->lwp_obj->mem_obj; + mem_obj = &rt_mm_dummy_mapper; uassert_true(!!aspace); uassert_true(!!mem_obj); @@ -46,9 +46,9 @@ void test_bst_adpt(void) !rt_aspace_map(aspace, &target_va, map_size, MMU_MAP_K_RWCB, flags, mem_obj, 0)); /* 2 wrappers */ uassert_true( - !rt_aspace_map(aspace, &prev_va, map_size - 1, MMU_MAP_K_RWCB, flags, mem_obj, 0)); + !rt_aspace_map(aspace, &prev_va, map_size, MMU_MAP_K_RWCB, flags, mem_obj, 0)); uassert_true( - !rt_aspace_map(aspace, &next_va, map_size - 1, MMU_MAP_K_RWCB, flags, mem_obj, 0)); + !rt_aspace_map(aspace, &next_va, map_size, MMU_MAP_K_RWCB, flags, mem_obj, 0)); /* _aspace_bst_search */ uassert_true(!!_aspace_bst_search(aspace, target_va)); -- cgit v1.3.1