scsi: ufs: core: Fix divide by zero in ufshcd_map_queues()
[platform/kernel/linux-starfive.git] / tools / testing / selftests / mincore / mincore_selftest.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * kselftest suite for mincore().
4  *
5  * Copyright (C) 2020 Collabora, Ltd.
6  */
7
8 #define _GNU_SOURCE
9
10 #include <stdio.h>
11 #include <errno.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <sys/mman.h>
15 #include <string.h>
16 #include <fcntl.h>
17
18 #include "../kselftest.h"
19 #include "../kselftest_harness.h"
20
21 /* Default test file size: 4MB */
22 #define MB (1UL << 20)
23 #define FILE_SIZE (4 * MB)
24
25
26 /*
27  * Tests the user interface. This test triggers most of the documented
28  * error conditions in mincore().
29  */
30 TEST(basic_interface)
31 {
32         int retval;
33         int page_size;
34         unsigned char vec[1];
35         char *addr;
36
37         page_size = sysconf(_SC_PAGESIZE);
38
39         /* Query a 0 byte sized range */
40         retval = mincore(0, 0, vec);
41         EXPECT_EQ(0, retval);
42
43         /* Addresses in the specified range are invalid or unmapped */
44         errno = 0;
45         retval = mincore(NULL, page_size, vec);
46         EXPECT_EQ(-1, retval);
47         EXPECT_EQ(ENOMEM, errno);
48
49         errno = 0;
50         addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
51                 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
52         ASSERT_NE(MAP_FAILED, addr) {
53                 TH_LOG("mmap error: %s", strerror(errno));
54         }
55
56         /* <addr> argument is not page-aligned */
57         errno = 0;
58         retval = mincore(addr + 1, page_size, vec);
59         EXPECT_EQ(-1, retval);
60         EXPECT_EQ(EINVAL, errno);
61
62         /* <length> argument is too large */
63         errno = 0;
64         retval = mincore(addr, -1, vec);
65         EXPECT_EQ(-1, retval);
66         EXPECT_EQ(ENOMEM, errno);
67
68         /* <vec> argument points to an illegal address */
69         errno = 0;
70         retval = mincore(addr, page_size, NULL);
71         EXPECT_EQ(-1, retval);
72         EXPECT_EQ(EFAULT, errno);
73         munmap(addr, page_size);
74 }
75
76
77 /*
78  * Test mincore() behavior on a private anonymous page mapping.
79  * Check that the page is not loaded into memory right after the mapping
80  * but after accessing it (on-demand allocation).
81  * Then free the page and check that it's not memory-resident.
82  */
83 TEST(check_anonymous_locked_pages)
84 {
85         unsigned char vec[1];
86         char *addr;
87         int retval;
88         int page_size;
89
90         page_size = sysconf(_SC_PAGESIZE);
91
92         /* Map one page and check it's not memory-resident */
93         errno = 0;
94         addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
95                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
96         ASSERT_NE(MAP_FAILED, addr) {
97                 TH_LOG("mmap error: %s", strerror(errno));
98         }
99         retval = mincore(addr, page_size, vec);
100         ASSERT_EQ(0, retval);
101         ASSERT_EQ(0, vec[0]) {
102                 TH_LOG("Page found in memory before use");
103         }
104
105         /* Touch the page and check again. It should now be in memory */
106         addr[0] = 1;
107         mlock(addr, page_size);
108         retval = mincore(addr, page_size, vec);
109         ASSERT_EQ(0, retval);
110         ASSERT_EQ(1, vec[0]) {
111                 TH_LOG("Page not found in memory after use");
112         }
113
114         /*
115          * It shouldn't be memory-resident after unlocking it and
116          * marking it as unneeded.
117          */
118         munlock(addr, page_size);
119         madvise(addr, page_size, MADV_DONTNEED);
120         retval = mincore(addr, page_size, vec);
121         ASSERT_EQ(0, retval);
122         ASSERT_EQ(0, vec[0]) {
123                 TH_LOG("Page in memory after being zapped");
124         }
125         munmap(addr, page_size);
126 }
127
128
129 /*
130  * Check mincore() behavior on huge pages.
131  * This test will be skipped if the mapping fails (ie. if there are no
132  * huge pages available).
133  *
134  * Make sure the system has at least one free huge page, check
135  * "HugePages_Free" in /proc/meminfo.
136  * Increment /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages if
137  * needed.
138  */
139 TEST(check_huge_pages)
140 {
141         unsigned char vec[1];
142         char *addr;
143         int retval;
144         int page_size;
145
146         page_size = sysconf(_SC_PAGESIZE);
147
148         errno = 0;
149         addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
150                 MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
151                 -1, 0);
152         if (addr == MAP_FAILED) {
153                 if (errno == ENOMEM)
154                         SKIP(return, "No huge pages available.");
155                 else
156                         TH_LOG("mmap error: %s", strerror(errno));
157         }
158         retval = mincore(addr, page_size, vec);
159         ASSERT_EQ(0, retval);
160         ASSERT_EQ(0, vec[0]) {
161                 TH_LOG("Page found in memory before use");
162         }
163
164         addr[0] = 1;
165         mlock(addr, page_size);
166         retval = mincore(addr, page_size, vec);
167         ASSERT_EQ(0, retval);
168         ASSERT_EQ(1, vec[0]) {
169                 TH_LOG("Page not found in memory after use");
170         }
171
172         munlock(addr, page_size);
173         munmap(addr, page_size);
174 }
175
176
177 /*
178  * Test mincore() behavior on a file-backed page.
179  * No pages should be loaded into memory right after the mapping. Then,
180  * accessing any address in the mapping range should load the page
181  * containing the address and a number of subsequent pages (readahead).
182  *
183  * The actual readahead settings depend on the test environment, so we
184  * can't make a lot of assumptions about that. This test covers the most
185  * general cases.
186  */
187 TEST(check_file_mmap)
188 {
189         unsigned char *vec;
190         int vec_size;
191         char *addr;
192         int retval;
193         int page_size;
194         int fd;
195         int i;
196         int ra_pages = 0;
197
198         page_size = sysconf(_SC_PAGESIZE);
199         vec_size = FILE_SIZE / page_size;
200         if (FILE_SIZE % page_size)
201                 vec_size++;
202
203         vec = calloc(vec_size, sizeof(unsigned char));
204         ASSERT_NE(NULL, vec) {
205                 TH_LOG("Can't allocate array");
206         }
207
208         errno = 0;
209         fd = open(".", O_TMPFILE | O_RDWR, 0600);
210         ASSERT_NE(-1, fd) {
211                 TH_LOG("Can't create temporary file: %s",
212                         strerror(errno));
213         }
214         errno = 0;
215         retval = fallocate(fd, 0, 0, FILE_SIZE);
216         ASSERT_EQ(0, retval) {
217                 TH_LOG("Error allocating space for the temporary file: %s",
218                         strerror(errno));
219         }
220
221         /*
222          * Map the whole file, the pages shouldn't be fetched yet.
223          */
224         errno = 0;
225         addr = mmap(NULL, FILE_SIZE, PROT_READ | PROT_WRITE,
226                         MAP_SHARED, fd, 0);
227         ASSERT_NE(MAP_FAILED, addr) {
228                 TH_LOG("mmap error: %s", strerror(errno));
229         }
230         retval = mincore(addr, FILE_SIZE, vec);
231         ASSERT_EQ(0, retval);
232         for (i = 0; i < vec_size; i++) {
233                 ASSERT_EQ(0, vec[i]) {
234                         TH_LOG("Unexpected page in memory");
235                 }
236         }
237
238         /*
239          * Touch a page in the middle of the mapping. We expect the next
240          * few pages (the readahead window) to be populated too.
241          */
242         addr[FILE_SIZE / 2] = 1;
243         retval = mincore(addr, FILE_SIZE, vec);
244         ASSERT_EQ(0, retval);
245         ASSERT_EQ(1, vec[FILE_SIZE / 2 / page_size]) {
246                 TH_LOG("Page not found in memory after use");
247         }
248
249         i = FILE_SIZE / 2 / page_size + 1;
250         while (i < vec_size && vec[i]) {
251                 ra_pages++;
252                 i++;
253         }
254         EXPECT_GT(ra_pages, 0) {
255                 TH_LOG("No read-ahead pages found in memory");
256         }
257
258         EXPECT_LT(i, vec_size) {
259                 TH_LOG("Read-ahead pages reached the end of the file");
260         }
261         /*
262          * End of the readahead window. The rest of the pages shouldn't
263          * be in memory.
264          */
265         if (i < vec_size) {
266                 while (i < vec_size && !vec[i])
267                         i++;
268                 EXPECT_EQ(vec_size, i) {
269                         TH_LOG("Unexpected page in memory beyond readahead window");
270                 }
271         }
272
273         munmap(addr, FILE_SIZE);
274         close(fd);
275         free(vec);
276 }
277
278
279 /*
280  * Test mincore() behavior on a page backed by a tmpfs file.  This test
281  * performs the same steps as the previous one. However, we don't expect
282  * any readahead in this case.
283  */
284 TEST(check_tmpfs_mmap)
285 {
286         unsigned char *vec;
287         int vec_size;
288         char *addr;
289         int retval;
290         int page_size;
291         int fd;
292         int i;
293         int ra_pages = 0;
294
295         page_size = sysconf(_SC_PAGESIZE);
296         vec_size = FILE_SIZE / page_size;
297         if (FILE_SIZE % page_size)
298                 vec_size++;
299
300         vec = calloc(vec_size, sizeof(unsigned char));
301         ASSERT_NE(NULL, vec) {
302                 TH_LOG("Can't allocate array");
303         }
304
305         errno = 0;
306         fd = open("/dev/shm", O_TMPFILE | O_RDWR, 0600);
307         ASSERT_NE(-1, fd) {
308                 TH_LOG("Can't create temporary file: %s",
309                         strerror(errno));
310         }
311         errno = 0;
312         retval = fallocate(fd, 0, 0, FILE_SIZE);
313         ASSERT_EQ(0, retval) {
314                 TH_LOG("Error allocating space for the temporary file: %s",
315                         strerror(errno));
316         }
317
318         /*
319          * Map the whole file, the pages shouldn't be fetched yet.
320          */
321         errno = 0;
322         addr = mmap(NULL, FILE_SIZE, PROT_READ | PROT_WRITE,
323                         MAP_SHARED, fd, 0);
324         ASSERT_NE(MAP_FAILED, addr) {
325                 TH_LOG("mmap error: %s", strerror(errno));
326         }
327         retval = mincore(addr, FILE_SIZE, vec);
328         ASSERT_EQ(0, retval);
329         for (i = 0; i < vec_size; i++) {
330                 ASSERT_EQ(0, vec[i]) {
331                         TH_LOG("Unexpected page in memory");
332                 }
333         }
334
335         /*
336          * Touch a page in the middle of the mapping. We expect only
337          * that page to be fetched into memory.
338          */
339         addr[FILE_SIZE / 2] = 1;
340         retval = mincore(addr, FILE_SIZE, vec);
341         ASSERT_EQ(0, retval);
342         ASSERT_EQ(1, vec[FILE_SIZE / 2 / page_size]) {
343                 TH_LOG("Page not found in memory after use");
344         }
345
346         i = FILE_SIZE / 2 / page_size + 1;
347         while (i < vec_size && vec[i]) {
348                 ra_pages++;
349                 i++;
350         }
351         ASSERT_EQ(ra_pages, 0) {
352                 TH_LOG("Read-ahead pages found in memory");
353         }
354
355         munmap(addr, FILE_SIZE);
356         close(fd);
357         free(vec);
358 }
359
360 TEST_HARNESS_MAIN