12
12
#define KSM_SCAN_LIMIT_SEC_DEFAULT 120
13
13
#define KSM_PAGE_COUNT_DEFAULT 10l
14
14
#define KSM_PROT_STR_DEFAULT "rw"
15
+ #define KSM_USE_ZERO_PAGES_DEFAULT false
15
16
16
17
struct ksm_sysfs {
17
18
unsigned long max_page_sharing ;
@@ -25,7 +26,8 @@ struct ksm_sysfs {
25
26
26
27
enum ksm_test_name {
27
28
CHECK_KSM_MERGE ,
28
- CHECK_KSM_UNMERGE
29
+ CHECK_KSM_UNMERGE ,
30
+ CHECK_KSM_ZERO_PAGE_MERGE
29
31
};
30
32
31
33
static int ksm_write_sysfs (const char * file_path , unsigned long val )
@@ -80,10 +82,12 @@ static int str_to_prot(char *prot_str)
80
82
81
83
static void print_help (void )
82
84
{
83
- printf ("usage: ksm_tests [-h] <test type> [-a prot] [-p page_count] [-l timeout]\n" );
85
+ printf ("usage: ksm_tests [-h] <test type> [-a prot] [-p page_count] [-l timeout]\n"
86
+ "[-z use_zero_pages]\n" );
84
87
85
88
printf ("Supported <test type>:\n"
86
89
" -M (page merging)\n"
90
+ " -Z (zero pages merging)\n"
87
91
" -U (page unmerging)\n\n" );
88
92
89
93
printf (" -a: specify the access protections of pages.\n"
@@ -93,6 +97,8 @@ static void print_help(void)
93
97
" Default: %ld\n" , KSM_PAGE_COUNT_DEFAULT );
94
98
printf (" -l: limit the maximum running time (in seconds) for a test.\n"
95
99
" Default: %d seconds\n" , KSM_SCAN_LIMIT_SEC_DEFAULT );
100
+ printf (" -z: change use_zero_pages tunable\n"
101
+ " Default: %d\n" , KSM_USE_ZERO_PAGES_DEFAULT );
96
102
97
103
exit (0 );
98
104
}
@@ -289,6 +295,50 @@ static int check_ksm_unmerge(int mapping, int prot, int timeout, size_t page_siz
289
295
return KSFT_FAIL ;
290
296
}
291
297
298
+ static int check_ksm_zero_page_merge (int mapping , int prot , long page_count , int timeout ,
299
+ bool use_zero_pages , size_t page_size )
300
+ {
301
+ void * map_ptr ;
302
+ struct timespec start_time ;
303
+
304
+ if (clock_gettime (CLOCK_MONOTONIC_RAW , & start_time )) {
305
+ perror ("clock_gettime" );
306
+ return KSFT_FAIL ;
307
+ }
308
+
309
+ if (ksm_write_sysfs (KSM_FP ("use_zero_pages" ), use_zero_pages ))
310
+ return KSFT_FAIL ;
311
+
312
+ /* fill pages with zero and try to merge them */
313
+ map_ptr = allocate_memory (NULL , prot , mapping , 0 , page_size * page_count );
314
+ if (!map_ptr )
315
+ return KSFT_FAIL ;
316
+
317
+ if (ksm_merge_pages (map_ptr , page_size * page_count , start_time , timeout ))
318
+ goto err_out ;
319
+
320
+ /*
321
+ * verify that the right number of pages are merged:
322
+ * 1) if use_zero_pages is set to 1, empty pages are merged
323
+ * with the kernel zero page instead of with each other;
324
+ * 2) if use_zero_pages is set to 0, empty pages are not treated specially
325
+ * and merged as usual.
326
+ */
327
+ if (use_zero_pages && !assert_ksm_pages_count (0 ))
328
+ goto err_out ;
329
+ else if (!use_zero_pages && !assert_ksm_pages_count (page_count ))
330
+ goto err_out ;
331
+
332
+ printf ("OK\n" );
333
+ munmap (map_ptr , page_size * page_count );
334
+ return KSFT_PASS ;
335
+
336
+ err_out :
337
+ printf ("Not OK\n" );
338
+ munmap (map_ptr , page_size * page_count );
339
+ return KSFT_FAIL ;
340
+ }
341
+
292
342
int main (int argc , char * argv [])
293
343
{
294
344
int ret , opt ;
@@ -298,8 +348,9 @@ int main(int argc, char *argv[])
298
348
size_t page_size = sysconf (_SC_PAGESIZE );
299
349
struct ksm_sysfs ksm_sysfs_old ;
300
350
int test_name = CHECK_KSM_MERGE ;
351
+ bool use_zero_pages = KSM_USE_ZERO_PAGES_DEFAULT ;
301
352
302
- while ((opt = getopt (argc , argv , "ha:p:l:MU " )) != -1 ) {
353
+ while ((opt = getopt (argc , argv , "ha:p:l:z:MUZ " )) != -1 ) {
303
354
switch (opt ) {
304
355
case 'a' :
305
356
prot = str_to_prot (optarg );
@@ -321,11 +372,20 @@ int main(int argc, char *argv[])
321
372
case 'h' :
322
373
print_help ();
323
374
break ;
375
+ case 'z' :
376
+ if (strcmp (optarg , "0" ) == 0 )
377
+ use_zero_pages = 0 ;
378
+ else
379
+ use_zero_pages = 1 ;
380
+ break ;
324
381
case 'M' :
325
382
break ;
326
383
case 'U' :
327
384
test_name = CHECK_KSM_UNMERGE ;
328
385
break ;
386
+ case 'Z' :
387
+ test_name = CHECK_KSM_ZERO_PAGE_MERGE ;
388
+ break ;
329
389
default :
330
390
return KSFT_FAIL ;
331
391
}
@@ -359,6 +419,10 @@ int main(int argc, char *argv[])
359
419
ret = check_ksm_unmerge (MAP_PRIVATE | MAP_ANONYMOUS , prot , ksm_scan_limit_sec ,
360
420
page_size );
361
421
break ;
422
+ case CHECK_KSM_ZERO_PAGE_MERGE :
423
+ ret = check_ksm_zero_page_merge (MAP_PRIVATE | MAP_ANONYMOUS , prot , page_count ,
424
+ ksm_scan_limit_sec , use_zero_pages , page_size );
425
+ break ;
362
426
}
363
427
364
428
if (ksm_restore (& ksm_sysfs_old )) {
0 commit comments