1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-08-17 Shell test case for aspace_map(MAP_FIXED)
9 */
10 #include "common.h"
11 #include "lwp_user_mm.h"
12 #include "utest_assert.h"
13 #include <mm_private.h>
14
15 #include <rtthread.h>
16
17 #define PAGE_SZ (1 << MM_PAGE_SHIFT)
18 #define PAGE_COUNT ('z' - 'a' + 1)
19 #define FILE_PATH "/test_mmap"
20 #define FILE_SZ (PAGE_COUNT * PAGE_SZ)
21
22 static struct rt_lwp *lwp;
23 static size_t former_vsz;
24 static size_t former_vcount;
25 static char page_sz_buf[PAGE_SZ];
26
27 static void *ex_start = (void *)0x100000000;
28 static size_t ex_size = 0x5000;
29 static long pgoffset = 0;
30 static size_t ex_prot = PROT_NONE;
31 static size_t ex_flags = MAP_PRIVATE | MAP_ANONYMOUS;
32
33 static char *private0 = (char *)0x100000000;
34 static char *private1 = (char *)0x100000000 + 0x1000;
35 static char *private2 = (char *)0x100000000 + 0x2000;
36 static char *private3 = (char *)0x100000000 + 0x3000;
37 static char *private4 = (char *)0x100000000 + 0x4000;
38 static size_t or_size = 0x1000;
39 static size_t or_prot = PROT_READ | PROT_WRITE;
40 static size_t or_flags = MAP_ANON | MAP_FIXED;
41
42 static long anon_fd = -1;
43
_count_vsz(rt_varea_t varea,void * arg)44 static int _count_vsz(rt_varea_t varea, void *arg)
45 {
46 rt_base_t *pvsz = arg;
47 *pvsz += 1;
48 return 0;
49 }
50
count_vcount(rt_aspace_t aspace)51 static rt_base_t count_vcount(rt_aspace_t aspace)
52 {
53 rt_base_t vcount = 0;
54 rt_aspace_traversal(aspace, _count_vsz, &vcount);
55 return vcount;
56 }
57
_lwp_get_user(struct rt_lwp * lwp,char * vaddr,char * buffer)58 static rt_err_t _lwp_get_user(struct rt_lwp *lwp, char *vaddr, char *buffer)
59 {
60 rt_varea_t varea = _aspace_bst_search(lwp->aspace, vaddr);
61 if (varea && varea->mem_obj && varea->mem_obj->page_read)
62 {
63 struct rt_aspace_io_msg io_msg;
64 rt_mm_io_msg_init(&io_msg, MM_PA_TO_OFF(vaddr), vaddr, buffer);
65 varea->mem_obj->page_read(varea, &io_msg);
66 }
67 else
68 return -RT_ERROR;
69 return RT_EOK;
70 }
71
_verify_file_content(struct rt_lwp * lwp,const char * mmap_buf,int ch)72 static void _verify_file_content(struct rt_lwp *lwp, const char *mmap_buf, int ch)
73 {
74 utest_int_equal(RT_EOK, _lwp_get_user(lwp, (char *)mmap_buf, page_sz_buf));
75 utest_int_equal(RT_EOK, memtest(page_sz_buf, ch, PAGE_SZ));
76 }
77
test_mmap_fd_fixed(void)78 static void test_mmap_fd_fixed(void)
79 {
80 former_vsz = rt_aspace_count_vsz(lwp->aspace);
81 former_vcount = count_vcount(lwp->aspace);
82
83 /* create an existed mapping */
84 long temp_fd;
85 temp_fd = open(FILE_PATH, O_RDONLY);
86 LOG_D("New fd=%ld path=%s", temp_fd, FILE_PATH);
87 uassert_true(temp_fd >= 0);
88 utest_int_equal(
89 lwp_mmap2(lwp, ex_start, ex_size, ex_prot, ex_flags, temp_fd, pgoffset),
90 ex_start);
91 utest_int_equal(former_vsz + ex_size, rt_aspace_count_vsz(lwp->aspace));
92 utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace));
93 _verify_file_content(lwp, private0, 'a');
94 _verify_file_content(lwp, private1, 'b');
95 _verify_file_content(lwp, private2, 'c');
96 _verify_file_content(lwp, private3, 'd');
97 _verify_file_content(lwp, private4, 'e');
98 former_vsz += ex_size;
99 former_vcount += 1;
100
101 /* create an override mapping */
102 utest_int_equal(
103 lwp_mmap2(lwp, private2, or_size, or_prot, or_flags, anon_fd, pgoffset),
104 private2);
105 utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace));
106 utest_int_equal(former_vcount + 2, count_vcount(lwp->aspace));
107 former_vcount += 2;
108 _verify_file_content(lwp, private0, 'a');
109 _verify_file_content(lwp, private1, 'b');
110 _verify_file_content(lwp, private2, 0);
111 _verify_file_content(lwp, private3, 'd');
112 _verify_file_content(lwp, private4, 'e');
113
114 /* fix private from left most */
115 utest_int_equal(
116 lwp_mmap2(lwp, private0, or_size, or_prot, or_flags, anon_fd, pgoffset),
117 private0);
118 utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace));
119 utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace));
120 former_vcount += 1;
121 _verify_file_content(lwp, private0, 0);
122 _verify_file_content(lwp, private1, 'b');
123 _verify_file_content(lwp, private2, 0);
124 _verify_file_content(lwp, private3, 'd');
125 _verify_file_content(lwp, private4, 'e');
126
127 /* fix private from right most */
128 utest_int_equal(
129 lwp_mmap2(lwp, private4, or_size, or_prot, or_flags, anon_fd, pgoffset),
130 private4);
131 utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace));
132 utest_int_equal(former_vcount + 1, count_vcount(lwp->aspace));
133 former_vcount += 1;
134 _verify_file_content(lwp, private0, 0);
135 _verify_file_content(lwp, private1, 'b');
136 _verify_file_content(lwp, private2, 0);
137 _verify_file_content(lwp, private3, 'd');
138 _verify_file_content(lwp, private4, 0);
139
140 /* fix private from left-middle */
141 utest_int_equal(
142 lwp_mmap2(lwp, private1, or_size, or_prot, or_flags, anon_fd, pgoffset),
143 private1);
144 utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace));
145 utest_int_equal(former_vcount - 1, count_vcount(lwp->aspace));
146 former_vcount -= 1;
147 _verify_file_content(lwp, private0, 0);
148 _verify_file_content(lwp, private1, 0);
149 _verify_file_content(lwp, private2, 0);
150 _verify_file_content(lwp, private3, 'd');
151 _verify_file_content(lwp, private4, 0);
152
153 /* fix private from right-middle */
154 utest_int_equal(
155 lwp_mmap2(lwp, private3, or_size, or_prot, or_flags, anon_fd, pgoffset),
156 private3);
157 utest_int_equal(former_vsz, rt_aspace_count_vsz(lwp->aspace));
158 utest_int_equal(former_vcount - 1, count_vcount(lwp->aspace));
159 former_vcount -= 1;
160 _verify_file_content(lwp, private0, 0);
161 _verify_file_content(lwp, private1, 0);
162 _verify_file_content(lwp, private2, 0);
163 _verify_file_content(lwp, private3, 0);
164 _verify_file_content(lwp, private4, 0);
165
166 /* close */
167 close(temp_fd);
168 utest_int_equal(RT_EOK, rt_aspace_unmap_range(lwp->aspace, ex_start, FILE_SZ));
169 }
170
testcase_main(void)171 static void testcase_main(void)
172 {
173 test_mmap_fd_fixed();
174 }
175
_setup_file_content(long fd)176 static void _setup_file_content(long fd)
177 {
178 char ch = 'a';
179 for (size_t i = 0; i < PAGE_COUNT; i++, ch++)
180 {
181 memset(page_sz_buf, ch, PAGE_SZ);
182 write(fd, page_sz_buf, PAGE_SZ);
183 }
184 }
185
utest_tc_init(void)186 static rt_err_t utest_tc_init(void)
187 {
188 /* setup file */
189 long temp_file_des;
190 temp_file_des = open(FILE_PATH, O_RDWR | O_CREAT, 0777);
191 LOG_D("New fd=%ld path=%s", temp_file_des, FILE_PATH);
192 if (temp_file_des < 0)
193 return -RT_ERROR;
194 _setup_file_content(temp_file_des);
195 close(temp_file_des);
196
197 lwp = lwp_create(0);
198 if (lwp)
199 lwp_user_space_init(lwp, 1);
200 else
201 return -RT_ENOMEM;
202 return RT_EOK;
203 }
204
utest_tc_cleanup(void)205 static rt_err_t utest_tc_cleanup(void)
206 {
207 lwp_ref_dec(lwp);
208 return RT_EOK;
209 }
210
testcase(void)211 static void testcase(void)
212 {
213 UTEST_UNIT_RUN(testcase_main);
214 }
215 UTEST_TC_EXPORT(testcase, "testcases.lwp.mman.mmap_fd.map_fixed_split", utest_tc_init, utest_tc_cleanup, 10);
216