^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Stress userfaultfd syscall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015 Red Hat, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This test allocates two virtual areas and bounces the physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * memory across the two virtual areas (from area_src to area_dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * using userfaultfd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * There are three threads running per CPU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 1) one per-CPU thread takes a per-page pthread_mutex in a random
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * page of the area_dst (while the physical page may still be in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * area_src), and increments a per-page counter in the same page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * and checks its value against a verification region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * 2) another per-CPU thread handles the userfaults generated by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * thread 1 above. userfaultfd blocking reads or poll() modes are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * exercised interleaved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * 3) one last per-CPU thread transfers the memory in the background
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * at maximum bandwidth (if not already transferred by thread
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 2). Each cpu thread takes cares of transferring a portion of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * When all threads of type 3 completed the transfer, one bounce is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * complete. area_src and area_dst are then swapped. All threads are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * respawned and so the bounce is immediately restarted in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * opposite direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * per-CPU threads 1 by triggering userfaults inside
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * pthread_mutex_lock will also verify the atomicity of the memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * transfer (UFFDIO_COPY).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define _GNU_SOURCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <sys/syscall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <sys/ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <sys/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <pthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/userfaultfd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <setjmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include "../kselftest.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #ifdef __NR_userfaultfd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define BOUNCE_RANDOM (1<<0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define BOUNCE_RACINGFAULTS (1<<1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define BOUNCE_VERIFY (1<<2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define BOUNCE_POLL (1<<3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int bounces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define TEST_ANON 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define TEST_HUGETLB 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define TEST_SHMEM 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int test_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* exercise the test_uffdio_*_eexist every ALARM_INTERVAL_SECS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define ALARM_INTERVAL_SECS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static volatile bool test_uffdio_copy_eexist = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static volatile bool test_uffdio_zeropage_eexist = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Whether to test uffd write-protection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static bool test_uffdio_wp = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* Whether to test uffd minor faults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static bool test_uffdio_minor = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static bool map_shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int shm_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int huge_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static char *huge_fd_off0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static unsigned long long *count_verify;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int uffd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int uffd_flags, finished, *pipefd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static char *area_src, *area_src_alias, *area_dst, *area_dst_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static char *zeropage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) pthread_attr_t attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Userfaultfd test statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct uffd_stats {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned long missing_faults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long wp_faults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned long minor_faults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* pthread_mutex_t starts at page offset 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define area_mutex(___area, ___nr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ((pthread_mutex_t *) ((___area) + (___nr)*page_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * count is placed in the page after pthread_mutex_t naturally aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * to avoid non alignment faults on non-x86 archs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define area_count(___area, ___nr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ((volatile unsigned long long *) ((unsigned long) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ((___area) + (___nr)*page_size + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) sizeof(pthread_mutex_t) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) sizeof(unsigned long long) - 1) & \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ~(unsigned long)(sizeof(unsigned long long) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) - 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) const char *examples =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) "# Run anonymous memory test on 100MiB region with 99999 bounces:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) "./userfaultfd anon 100 99999\n\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) "# Run share memory test on 1GiB region with 99 bounces:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) "./userfaultfd shmem 1000 99\n\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "# Run hugetlb memory test on 256MiB region with 50 bounces (using /dev/hugepages/hugefile):\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "./userfaultfd hugetlb 256 50 /dev/hugepages/hugefile\n\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) "# Run the same hugetlb test but using shmem:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) "./userfaultfd hugetlb_shared 256 50 /dev/hugepages/hugefile\n\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "# 10MiB-~6GiB 999 bounces anonymous test, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) "continue forever unless an error triggers\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) "while ./userfaultfd anon $[RANDOM % 6000 + 10] 999; do true; done\n\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void usage(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) fprintf(stderr, "\nUsage: ./userfaultfd <test type> <MiB> <bounces> "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) "[hugetlbfs_file]\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) fprintf(stderr, "Supported <test type>: anon, hugetlb, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) "hugetlb_shared, shmem\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) fprintf(stderr, "Examples:\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) fprintf(stderr, "%s", examples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define _err(fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int ret = errno; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) fprintf(stderr, "ERROR: " fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) fprintf(stderr, " (errno=%d, line=%d)\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ret, __LINE__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define err(fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) _err(fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) exit(1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void uffd_stats_reset(struct uffd_stats *uffd_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned long n_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) for (i = 0; i < n_cpus; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) uffd_stats[i].cpu = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) uffd_stats[i].missing_faults = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) uffd_stats[i].wp_faults = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) uffd_stats[i].minor_faults = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static void uffd_stats_report(struct uffd_stats *stats, int n_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) unsigned long long miss_total = 0, wp_total = 0, minor_total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) for (i = 0; i < n_cpus; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) miss_total += stats[i].missing_faults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) wp_total += stats[i].wp_faults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) minor_total += stats[i].minor_faults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) printf("userfaults: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (miss_total) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) printf("%llu missing (", miss_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) for (i = 0; i < n_cpus; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) printf("%lu+", stats[i].missing_faults);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) printf("\b) ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (wp_total) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) printf("%llu wp (", wp_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) for (i = 0; i < n_cpus; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) printf("%lu+", stats[i].wp_faults);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) printf("\b) ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (minor_total) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) printf("%llu minor (", minor_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (i = 0; i < n_cpus; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) printf("%lu+", stats[i].minor_faults);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) printf("\b)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static void anon_release_pages(char *rel_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (madvise(rel_area, nr_pages * page_size, MADV_DONTNEED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) err("madvise(MADV_DONTNEED) failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void anon_allocate_area(void **alloc_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (*alloc_area == MAP_FAILED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) err("posix_memalign() failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static void hugetlb_release_pages(char *rel_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (fallocate(huge_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) rel_area == huge_fd_off0 ? 0 : nr_pages * page_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) nr_pages * page_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) err("fallocate() failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static void hugetlb_allocate_area(void **alloc_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) void *area_alias = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) char **alloc_area_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) (map_shared ? MAP_SHARED : MAP_PRIVATE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) MAP_HUGETLB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) huge_fd, *alloc_area == area_src ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) nr_pages * page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (*alloc_area == MAP_FAILED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) err("mmap of hugetlbfs file failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (map_shared) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) MAP_SHARED | MAP_HUGETLB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) huge_fd, *alloc_area == area_src ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) nr_pages * page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (area_alias == MAP_FAILED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) err("mmap of hugetlb file alias failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (*alloc_area == area_src) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) huge_fd_off0 = *alloc_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) alloc_area_alias = &area_src_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) alloc_area_alias = &area_dst_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (area_alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *alloc_area_alias = area_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static void hugetlb_alias_mapping(__u64 *start, size_t len, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!map_shared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * We can't zap just the pagetable with hugetlbfs because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * MADV_DONTEED won't work. So exercise -EEXIST on a alias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * mapping where the pagetables are not established initially,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * this way we'll exercise the -EEXEC at the fs level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) *start = (unsigned long) area_dst_alias + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static void shmem_release_pages(char *rel_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (madvise(rel_area, nr_pages * page_size, MADV_REMOVE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) err("madvise(MADV_REMOVE) failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static void shmem_allocate_area(void **alloc_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) void *area_alias = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) bool is_src = alloc_area == (void **)&area_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) unsigned long offset = is_src ? 0 : nr_pages * page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) MAP_SHARED, shm_fd, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (*alloc_area == MAP_FAILED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) err("mmap of memfd failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) MAP_SHARED, shm_fd, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (area_alias == MAP_FAILED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) err("mmap of memfd alias failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (is_src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) area_src_alias = area_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) area_dst_alias = area_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static void shmem_alias_mapping(__u64 *start, size_t len, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *start = (unsigned long)area_dst_alias + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct uffd_test_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned long expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) void (*allocate_area)(void **alloc_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) void (*release_pages)(char *rel_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) void (*alias_mapping)(__u64 *start, size_t len, unsigned long offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) #define SHMEM_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) (1 << _UFFDIO_COPY) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) (1 << _UFFDIO_ZEROPAGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) #define ANON_EXPECTED_IOCTLS ((1 << _UFFDIO_WAKE) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) (1 << _UFFDIO_COPY) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) (1 << _UFFDIO_ZEROPAGE) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) (1 << _UFFDIO_WRITEPROTECT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static struct uffd_test_ops anon_uffd_test_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .expected_ioctls = ANON_EXPECTED_IOCTLS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .allocate_area = anon_allocate_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .release_pages = anon_release_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .alias_mapping = noop_alias_mapping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static struct uffd_test_ops shmem_uffd_test_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .expected_ioctls = SHMEM_EXPECTED_IOCTLS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .allocate_area = shmem_allocate_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .release_pages = shmem_release_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .alias_mapping = shmem_alias_mapping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) static struct uffd_test_ops hugetlb_uffd_test_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC & ~(1 << _UFFDIO_CONTINUE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .allocate_area = hugetlb_allocate_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .release_pages = hugetlb_release_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .alias_mapping = hugetlb_alias_mapping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static struct uffd_test_ops *uffd_test_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static void userfaultfd_open(uint64_t *features)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct uffdio_api uffdio_api;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (uffd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) err("userfaultfd syscall not available in this kernel");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) uffd_flags = fcntl(uffd, F_GETFD, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) uffdio_api.api = UFFD_API;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) uffdio_api.features = *features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (ioctl(uffd, UFFDIO_API, &uffdio_api))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) err("UFFDIO_API failed.\nPlease make sure to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) "run with either root or ptrace capability.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (uffdio_api.api != UFFD_API)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) err("UFFDIO_API error: %" PRIu64, (uint64_t)uffdio_api.api);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) *features = uffdio_api.features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static inline void munmap_area(void **area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (*area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (munmap(*area, nr_pages * page_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) err("munmap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) *area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static void uffd_test_ctx_clear(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (pipefd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) for (i = 0; i < nr_cpus * 2; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (close(pipefd[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) err("close pipefd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) free(pipefd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) pipefd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (count_verify) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) free(count_verify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) count_verify = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (uffd != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (close(uffd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) err("close uffd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) uffd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) huge_fd_off0 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) munmap_area((void **)&area_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) munmap_area((void **)&area_src_alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) munmap_area((void **)&area_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) munmap_area((void **)&area_dst_alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static void uffd_test_ctx_init_ext(uint64_t *features)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) unsigned long nr, cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) uffd_test_ctx_clear();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) uffd_test_ops->allocate_area((void **)&area_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) uffd_test_ops->allocate_area((void **)&area_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) userfaultfd_open(features);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) count_verify = malloc(nr_pages * sizeof(unsigned long long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (!count_verify)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) err("count_verify");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) for (nr = 0; nr < nr_pages; nr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) *area_mutex(area_src, nr) =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) count_verify[nr] = *area_count(area_src, nr) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * In the transition between 255 to 256, powerpc will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * read out of order in my_bcmp and see both bytes as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * zero, so leave a placeholder below always non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * after the count, to avoid my_bcmp to trigger false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * positives.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) *(area_count(area_src, nr) + 1) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * After initialization of area_src, we must explicitly release pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * for area_dst to make sure it's fully empty. Otherwise we could have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * some area_dst pages be errornously initialized with zero pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * hence we could hit memory corruption later in the test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * One example is when THP is globally enabled, above allocate_area()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * calls could have the two areas merged into a single VMA (as they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * will have the same VMA flags so they're mergeable). When we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * initialize the area_src above, it's possible that some part of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * area_dst could have been faulted in via one huge THP that will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * shared between area_src and area_dst. It could cause some of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * area_dst won't be trapped by missing userfaults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * This release_pages() will guarantee even if that happened, we'll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * proactively split the thp and drop any accidentally initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * pages within area_dst.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) uffd_test_ops->release_pages(area_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) pipefd = malloc(sizeof(int) * nr_cpus * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!pipefd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) err("pipefd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) for (cpu = 0; cpu < nr_cpus; cpu++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (pipe2(&pipefd[cpu * 2], O_CLOEXEC | O_NONBLOCK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) err("pipe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static inline void uffd_test_ctx_init(uint64_t features)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) uffd_test_ctx_init_ext(&features);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static int my_bcmp(char *str1, char *str2, size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) for (i = 0; i < n; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (str1[i] != str2[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static void wp_range(int ufd, __u64 start, __u64 len, bool wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct uffdio_writeprotect prms = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* Write protection page faults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) prms.range.start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) prms.range.len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* Undo write-protect, do wakeup after that */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) prms.mode = wp ? UFFDIO_WRITEPROTECT_MODE_WP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (ioctl(ufd, UFFDIO_WRITEPROTECT, &prms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) err("clear WP failed: address=0x%"PRIx64, (uint64_t)start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static void continue_range(int ufd, __u64 start, __u64 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct uffdio_continue req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) req.range.start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) req.range.len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) req.mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (ioctl(ufd, UFFDIO_CONTINUE, &req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) err("UFFDIO_CONTINUE failed for address 0x%" PRIx64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) (uint64_t)start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * Error handling within the kernel for continue is subtly different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * from copy or zeropage, so it may be a source of bugs. Trigger an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * error (-EEXIST) on purpose, to verify doing so doesn't cause a BUG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) req.mapped = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) ret = ioctl(ufd, UFFDIO_CONTINUE, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (ret >= 0 || req.mapped != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) err("failed to exercise UFFDIO_CONTINUE error handling, ret=%d, mapped=%" PRId64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ret, (int64_t) req.mapped);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static void *locking_thread(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) unsigned long cpu = (unsigned long) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct random_data rand;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) unsigned long page_nr = *(&(page_nr)); /* uninitialized warning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) int32_t rand_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) unsigned long long count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) char randstate[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) unsigned int seed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (bounces & BOUNCE_RANDOM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) seed = (unsigned int) time(NULL) - bounces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (!(bounces & BOUNCE_RACINGFAULTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) seed += cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) bzero(&rand, sizeof(rand));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) bzero(&randstate, sizeof(randstate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (initstate_r(seed, randstate, sizeof(randstate), &rand))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) err("initstate_r failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) page_nr = -bounces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!(bounces & BOUNCE_RACINGFAULTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) page_nr += cpu * nr_pages_per_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) while (!finished) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (bounces & BOUNCE_RANDOM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (random_r(&rand, &rand_nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) err("random_r failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) page_nr = rand_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (sizeof(page_nr) > sizeof(rand_nr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (random_r(&rand, &rand_nr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) err("random_r failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) page_nr |= (((unsigned long) rand_nr) << 16) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) page_nr += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) page_nr %= nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) pthread_mutex_lock(area_mutex(area_dst, page_nr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) count = *area_count(area_dst, page_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (count != count_verify[page_nr])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) err("page_nr %lu memory corruption %llu %llu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) page_nr, count, count_verify[page_nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) *area_count(area_dst, page_nr) = count_verify[page_nr] = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) pthread_mutex_unlock(area_mutex(area_dst, page_nr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static void retry_copy_page(int ufd, struct uffdio_copy *uffdio_copy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) uffd_test_ops->alias_mapping(&uffdio_copy->dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) uffdio_copy->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (ioctl(ufd, UFFDIO_COPY, uffdio_copy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* real retval in ufdio_copy.copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (uffdio_copy->copy != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) err("UFFDIO_COPY retry error: %"PRId64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) (int64_t)uffdio_copy->copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) err("UFFDIO_COPY retry unexpected: %"PRId64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) (int64_t)uffdio_copy->copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static int __copy_page(int ufd, unsigned long offset, bool retry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct uffdio_copy uffdio_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (offset >= nr_pages * page_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) err("unexpected offset %lu\n", offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) uffdio_copy.dst = (unsigned long) area_dst + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) uffdio_copy.src = (unsigned long) area_src + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) uffdio_copy.len = page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (test_uffdio_wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) uffdio_copy.mode = UFFDIO_COPY_MODE_WP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) uffdio_copy.mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) uffdio_copy.copy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (ioctl(ufd, UFFDIO_COPY, &uffdio_copy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* real retval in ufdio_copy.copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (uffdio_copy.copy != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) err("UFFDIO_COPY error: %"PRId64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) (int64_t)uffdio_copy.copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else if (uffdio_copy.copy != page_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) err("UFFDIO_COPY error: %"PRId64, (int64_t)uffdio_copy.copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (test_uffdio_copy_eexist && retry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) test_uffdio_copy_eexist = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) retry_copy_page(ufd, &uffdio_copy, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static int copy_page_retry(int ufd, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return __copy_page(ufd, offset, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) static int copy_page(int ufd, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return __copy_page(ufd, offset, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) static int uffd_read_msg(int ufd, struct uffd_msg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) int ret = read(uffd, msg, sizeof(*msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (ret != sizeof(*msg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (errno == EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) err("blocking read error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) err("short read");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) static void uffd_handle_page_fault(struct uffd_msg *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct uffd_stats *stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (msg->event != UFFD_EVENT_PAGEFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) err("unexpected msg event %u", msg->event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* Write protect page faults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) wp_range(uffd, msg->arg.pagefault.address, page_size, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) stats->wp_faults++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) } else if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_MINOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) uint8_t *area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * Minor page faults
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * To prove we can modify the original range for testing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * purposes, we're going to bit flip this range before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * continuing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * Note that this requires all minor page fault tests operate on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * area_dst (non-UFFD-registered) and area_dst_alias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * (UFFD-registered).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) area = (uint8_t *)(area_dst +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ((char *)msg->arg.pagefault.address -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) area_dst_alias));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) for (b = 0; b < page_size; ++b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) area[b] = ~area[b];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) continue_range(uffd, msg->arg.pagefault.address, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) stats->minor_faults++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* Missing page faults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) err("unexpected write fault");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) offset &= ~(page_size-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (copy_page(uffd, offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) stats->missing_faults++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static void *uffd_poll_thread(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct uffd_stats *stats = (struct uffd_stats *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) unsigned long cpu = stats->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct pollfd pollfd[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct uffd_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct uffdio_register uffd_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) char tmp_chr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) pollfd[0].fd = uffd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) pollfd[0].events = POLLIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) pollfd[1].fd = pipefd[cpu*2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) pollfd[1].events = POLLIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ret = poll(pollfd, 2, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) err("poll error: %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (pollfd[1].revents & POLLIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (read(pollfd[1].fd, &tmp_chr, 1) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) err("read pipefd error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (!(pollfd[0].revents & POLLIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) err("pollfd[0].revents %d", pollfd[0].revents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if (uffd_read_msg(uffd, &msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) switch (msg.event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) err("unexpected msg event %u\n", msg.event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) case UFFD_EVENT_PAGEFAULT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) uffd_handle_page_fault(&msg, stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) case UFFD_EVENT_FORK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) close(uffd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) uffd = msg.arg.fork.ufd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) pollfd[0].fd = uffd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) case UFFD_EVENT_REMOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) uffd_reg.range.start = msg.arg.remove.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) uffd_reg.range.len = msg.arg.remove.end -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) msg.arg.remove.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (ioctl(uffd, UFFDIO_UNREGISTER, &uffd_reg.range))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) err("remove failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) case UFFD_EVENT_REMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) area_dst = (char *)(unsigned long)msg.arg.remap.to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) pthread_mutex_t uffd_read_mutex = PTHREAD_MUTEX_INITIALIZER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static void *uffd_read_thread(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct uffd_stats *stats = (struct uffd_stats *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct uffd_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) pthread_mutex_unlock(&uffd_read_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) /* from here cancellation is ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (uffd_read_msg(uffd, &msg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) uffd_handle_page_fault(&msg, stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static void *background_thread(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) unsigned long cpu = (unsigned long) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) unsigned long page_nr, start_nr, mid_nr, end_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) start_nr = cpu * nr_pages_per_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) end_nr = (cpu+1) * nr_pages_per_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) mid_nr = (start_nr + end_nr) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) /* Copy the first half of the pages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) for (page_nr = start_nr; page_nr < mid_nr; page_nr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) copy_page_retry(uffd, page_nr * page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * If we need to test uffd-wp, set it up now. Then we'll have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * at least the first half of the pages mapped already which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * can be write-protected for testing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (test_uffdio_wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) wp_range(uffd, (unsigned long)area_dst + start_nr * page_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) nr_pages_per_cpu * page_size, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * Continue the 2nd half of the page copying, handling write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * protection faults if any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) for (page_nr = mid_nr; page_nr < end_nr; page_nr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) copy_page_retry(uffd, page_nr * page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static int stress(struct uffd_stats *uffd_stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) unsigned long cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) pthread_t locking_threads[nr_cpus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) pthread_t uffd_threads[nr_cpus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) pthread_t background_threads[nr_cpus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) finished = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) for (cpu = 0; cpu < nr_cpus; cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (pthread_create(&locking_threads[cpu], &attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) locking_thread, (void *)cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (bounces & BOUNCE_POLL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (pthread_create(&uffd_threads[cpu], &attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) uffd_poll_thread,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) (void *)&uffd_stats[cpu]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (pthread_create(&uffd_threads[cpu], &attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) uffd_read_thread,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) (void *)&uffd_stats[cpu]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) pthread_mutex_lock(&uffd_read_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (pthread_create(&background_threads[cpu], &attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) background_thread, (void *)cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) for (cpu = 0; cpu < nr_cpus; cpu++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (pthread_join(background_threads[cpu], NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * Be strict and immediately zap area_src, the whole area has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * been transferred already by the background treads. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * area_src could then be faulted in in a racy way by still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * running uffdio_threads reading zeropages after we zapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * area_src (but they're guaranteed to get -EEXIST from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * UFFDIO_COPY without writing zero pages into area_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * because the background threads already completed).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) uffd_test_ops->release_pages(area_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) finished = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) for (cpu = 0; cpu < nr_cpus; cpu++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (pthread_join(locking_threads[cpu], NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) for (cpu = 0; cpu < nr_cpus; cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (bounces & BOUNCE_POLL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (write(pipefd[cpu*2+1], &c, 1) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) err("pipefd write error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (pthread_join(uffd_threads[cpu],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) (void *)&uffd_stats[cpu]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (pthread_cancel(uffd_threads[cpu]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (pthread_join(uffd_threads[cpu], NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) sigjmp_buf jbuf, *sigbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) static void sighndl(int sig, siginfo_t *siginfo, void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (sig == SIGBUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (sigbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) siglongjmp(*sigbuf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) abort();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * For non-cooperative userfaultfd test we fork() a process that will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * generate pagefaults, will mremap the area monitored by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * userfaultfd and at last this process will release the monitored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * For the anonymous and shared memory the area is divided into two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * parts, the first part is accessed before mremap, and the second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * part is accessed after mremap. Since hugetlbfs does not support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) * mremap, the entire monitored area is accessed in a single pass for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * HUGETLB_TEST.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * The release of the pages currently generates event for shmem and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * for hugetlb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * monitored area, generate pagefaults and test that signal is delivered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) * test robustness use case - we release monitored area, fork a process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * that will generate pagefaults and verify signal is generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * feature. Using monitor thread, verify no userfault events are generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static int faulting_process(int signal_test)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) unsigned long nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) unsigned long long count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) unsigned long split_nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) unsigned long lastnr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct sigaction act;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) unsigned long signalled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (test_type != TEST_HUGETLB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) split_nr_pages = (nr_pages + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) split_nr_pages = nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (signal_test) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) sigbuf = &jbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) memset(&act, 0, sizeof(act));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) act.sa_sigaction = sighndl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) act.sa_flags = SA_SIGINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (sigaction(SIGBUS, &act, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) err("sigaction");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) lastnr = (unsigned long)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) for (nr = 0; nr < split_nr_pages; nr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) int steps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) unsigned long offset = nr * page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (signal_test) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (sigsetjmp(*sigbuf, 1) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (steps == 1 && nr == lastnr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) err("Signal repeated");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) lastnr = nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (signal_test == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (steps == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) /* This is a MISSING request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) steps++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (copy_page(uffd, offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) signalled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* This is a WP request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) assert(steps == 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) wp_range(uffd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) (__u64)area_dst +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) page_size, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) signalled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) count = *area_count(area_dst, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (count != count_verify[nr])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) err("nr %lu memory corruption %llu %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) nr, count, count_verify[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * Trigger write protection if there is by writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) * the same value back.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) *area_count(area_dst, nr) = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (signal_test)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return signalled != split_nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (test_type == TEST_HUGETLB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) area_dst = mremap(area_dst, nr_pages * page_size, nr_pages * page_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) MREMAP_MAYMOVE | MREMAP_FIXED, area_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (area_dst == MAP_FAILED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) err("mremap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) /* Reset area_src since we just clobbered it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) area_src = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) for (; nr < nr_pages; nr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) count = *area_count(area_dst, nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (count != count_verify[nr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) err("nr %lu memory corruption %llu %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) nr, count, count_verify[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) * Trigger write protection if there is by writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * the same value back.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) *area_count(area_dst, nr) = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) uffd_test_ops->release_pages(area_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) for (nr = 0; nr < nr_pages; nr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (my_bcmp(area_dst + nr * page_size, zeropage, page_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) err("nr %lu is not zero", nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) static void retry_uffdio_zeropage(int ufd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) struct uffdio_zeropage *uffdio_zeropage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) uffd_test_ops->alias_mapping(&uffdio_zeropage->range.start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) uffdio_zeropage->range.len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (ioctl(ufd, UFFDIO_ZEROPAGE, uffdio_zeropage)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (uffdio_zeropage->zeropage != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) err("UFFDIO_ZEROPAGE error: %"PRId64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) (int64_t)uffdio_zeropage->zeropage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) err("UFFDIO_ZEROPAGE error: %"PRId64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) (int64_t)uffdio_zeropage->zeropage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) static int __uffdio_zeropage(int ufd, unsigned long offset, bool retry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) struct uffdio_zeropage uffdio_zeropage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) unsigned long has_zeropage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) __s64 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) has_zeropage = uffd_test_ops->expected_ioctls & (1 << _UFFDIO_ZEROPAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (offset >= nr_pages * page_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) err("unexpected offset %lu", offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) uffdio_zeropage.range.start = (unsigned long) area_dst + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) uffdio_zeropage.range.len = page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) uffdio_zeropage.mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) ret = ioctl(ufd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) res = uffdio_zeropage.zeropage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) /* real retval in ufdio_zeropage.zeropage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (has_zeropage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) err("UFFDIO_ZEROPAGE error: %"PRId64, (int64_t)res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) else if (res != -EINVAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) err("UFFDIO_ZEROPAGE not -EINVAL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) } else if (has_zeropage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (res != page_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) err("UFFDIO_ZEROPAGE unexpected size");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (test_uffdio_zeropage_eexist && retry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) test_uffdio_zeropage_eexist = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) retry_uffdio_zeropage(ufd, &uffdio_zeropage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) err("UFFDIO_ZEROPAGE succeeded");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) static int uffdio_zeropage(int ufd, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return __uffdio_zeropage(ufd, offset, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* exercise UFFDIO_ZEROPAGE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static int userfaultfd_zeropage_test(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct uffdio_register uffdio_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) unsigned long expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) printf("testing UFFDIO_ZEROPAGE: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) uffd_test_ctx_init(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) uffdio_register.range.start = (unsigned long) area_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) uffdio_register.range.len = nr_pages * page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (test_uffdio_wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) err("register failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) expected_ioctls = uffd_test_ops->expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) err("unexpected missing ioctl for anon memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (uffdio_zeropage(uffd, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (my_bcmp(area_dst, zeropage, page_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) err("zeropage is not zero");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) printf("done.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) static int userfaultfd_events_test(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) struct uffdio_register uffdio_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) unsigned long expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) pthread_t uffd_mon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) int err, features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) pid_t pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) struct uffd_stats stats = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) printf("testing events (fork, remap, remove): ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) features = UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) UFFD_FEATURE_EVENT_REMOVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) uffd_test_ctx_init(features);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) uffdio_register.range.start = (unsigned long) area_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) uffdio_register.range.len = nr_pages * page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (test_uffdio_wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) err("register failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) expected_ioctls = uffd_test_ops->expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) err("unexpected missing ioctl for anon memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) err("uffd_poll_thread create");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) pid = fork();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (pid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) err("fork");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (!pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) exit(faulting_process(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) waitpid(pid, &err, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) err("faulting process failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) err("pipe write");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) if (pthread_join(uffd_mon, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) uffd_stats_report(&stats, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return stats.missing_faults != nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) static int userfaultfd_sig_test(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) struct uffdio_register uffdio_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) unsigned long expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) unsigned long userfaults;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) pthread_t uffd_mon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) int err, features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) pid_t pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) struct uffd_stats stats = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) printf("testing signal delivery: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) features = UFFD_FEATURE_EVENT_FORK|UFFD_FEATURE_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) uffd_test_ctx_init(features);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) uffdio_register.range.start = (unsigned long) area_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) uffdio_register.range.len = nr_pages * page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (test_uffdio_wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) err("register failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) expected_ioctls = uffd_test_ops->expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) err("unexpected missing ioctl for anon memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (faulting_process(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) err("faulting process failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) uffd_test_ops->release_pages(area_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) err("uffd_poll_thread create");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) pid = fork();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) if (pid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) err("fork");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (!pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) exit(faulting_process(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) waitpid(pid, &err, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) err("faulting process failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) err("pipe write");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (pthread_join(uffd_mon, (void **)&userfaults))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) printf("done.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (userfaults)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) err("Signal test failed, userfaults: %ld", userfaults);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return userfaults != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) static int userfaultfd_minor_test(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) struct uffdio_register uffdio_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) unsigned long expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) unsigned long p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) pthread_t uffd_mon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) uint8_t expected_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) void *expected_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) struct uffd_stats stats = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) uint64_t req_features, features_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (!test_uffdio_minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) printf("testing minor faults: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (test_type == TEST_HUGETLB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) req_features = UFFD_FEATURE_MINOR_HUGETLBFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) else if (test_type == TEST_SHMEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) req_features = UFFD_FEATURE_MINOR_SHMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) features_out = req_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) uffd_test_ctx_init_ext(&features_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) /* If kernel reports required features aren't supported, skip test. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if ((features_out & req_features) != req_features) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) printf("skipping test due to lack of feature support\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) uffdio_register.range.start = (unsigned long)area_dst_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) uffdio_register.range.len = nr_pages * page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) uffdio_register.mode = UFFDIO_REGISTER_MODE_MINOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) err("register failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) expected_ioctls = uffd_test_ops->expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) expected_ioctls |= 1 << _UFFDIO_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) err("unexpected missing ioctl(s)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) * After registering with UFFD, populate the non-UFFD-registered side of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) * the shared mapping. This should *not* trigger any UFFD minor faults.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) for (p = 0; p < nr_pages; ++p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) memset(area_dst + (p * page_size), p % ((uint8_t)-1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) err("uffd_poll_thread create");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * Read each of the pages back using the UFFD-registered mapping. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * expect that the first time we touch a page, it will result in a minor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * fault. uffd_poll_thread will resolve the fault by bit-flipping the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) * page's contents, and then issuing a CONTINUE ioctl.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (posix_memalign(&expected_page, page_size, page_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) err("out of memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) for (p = 0; p < nr_pages; ++p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) expected_byte = ~((uint8_t)(p % ((uint8_t)-1)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) memset(expected_page, expected_byte, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if (my_bcmp(expected_page, area_dst_alias + (p * page_size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) page_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) err("unexpected page contents after minor fault");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) err("pipe write");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (pthread_join(uffd_mon, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) uffd_stats_report(&stats, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) return stats.missing_faults != 0 || stats.minor_faults != nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) static int userfaultfd_stress(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) void *area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) char *tmp_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) unsigned long nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) struct uffdio_register uffdio_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) struct uffd_stats uffd_stats[nr_cpus];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) uffd_test_ctx_init(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (posix_memalign(&area, page_size, page_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) err("out of memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) zeropage = area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) bzero(zeropage, page_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) pthread_mutex_lock(&uffd_read_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) pthread_attr_init(&attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) pthread_attr_setstacksize(&attr, 16*1024*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) while (bounces--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) unsigned long expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) printf("bounces: %d, mode:", bounces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (bounces & BOUNCE_RANDOM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) printf(" rnd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (bounces & BOUNCE_RACINGFAULTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) printf(" racing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (bounces & BOUNCE_VERIFY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) printf(" ver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (bounces & BOUNCE_POLL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) printf(" poll");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) printf(", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (bounces & BOUNCE_POLL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) fcntl(uffd, F_SETFL, uffd_flags & ~O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) /* register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) uffdio_register.range.start = (unsigned long) area_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) uffdio_register.range.len = nr_pages * page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (test_uffdio_wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) uffdio_register.mode |= UFFDIO_REGISTER_MODE_WP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) err("register failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) expected_ioctls = uffd_test_ops->expected_ioctls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) if ((uffdio_register.ioctls & expected_ioctls) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) expected_ioctls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) err("unexpected missing ioctl for anon memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) if (area_dst_alias) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) uffdio_register.range.start = (unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) area_dst_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) err("register failure alias");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) * The madvise done previously isn't enough: some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) * uffd_thread could have read userfaults (one of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) * those already resolved by the background thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) * and it may be in the process of calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) * UFFDIO_COPY. UFFDIO_COPY will read the zapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) * area_src and it would map a zero page in it (of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) * course such a UFFDIO_COPY is perfectly safe as it'd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * return -EEXIST). The problem comes at the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * bounce though: that racing UFFDIO_COPY would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) * generate zeropages in the area_src, so invalidating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) * the previous MADV_DONTNEED. Without this additional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) * MADV_DONTNEED those zeropages leftovers in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) * area_src would lead to -EEXIST failure during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) * next bounce, effectively leaving a zeropage in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) * area_dst.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) * Try to comment this out madvise to see the memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) * corruption being caught pretty quick.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * khugepaged is also inhibited to collapse THP after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * MADV_DONTNEED only after the UFFDIO_REGISTER, so it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) * required to MADV_DONTNEED here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) uffd_test_ops->release_pages(area_dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) uffd_stats_reset(uffd_stats, nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) /* bounce pass */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) if (stress(uffd_stats))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) /* Clear all the write protections if there is any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (test_uffdio_wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) wp_range(uffd, (unsigned long)area_dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) nr_pages * page_size, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) /* unregister */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) err("unregister failure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if (area_dst_alias) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) uffdio_register.range.start = (unsigned long) area_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if (ioctl(uffd, UFFDIO_UNREGISTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) &uffdio_register.range))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) err("unregister failure alias");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) /* verification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (bounces & BOUNCE_VERIFY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) for (nr = 0; nr < nr_pages; nr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) if (*area_count(area_dst, nr) != count_verify[nr])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) err("error area_count %llu %llu %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) *area_count(area_src, nr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) count_verify[nr], nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) /* prepare next bounce */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) tmp_area = area_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) area_src = area_dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) area_dst = tmp_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) tmp_area = area_src_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) area_src_alias = area_dst_alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) area_dst_alias = tmp_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) uffd_stats_report(uffd_stats, nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return userfaultfd_zeropage_test() || userfaultfd_sig_test()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) || userfaultfd_events_test() || userfaultfd_minor_test();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) * Copied from mlock2-tests.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) unsigned long default_huge_page_size(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) unsigned long hps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) char *line = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) size_t linelen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) FILE *f = fopen("/proc/meminfo", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) if (!f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) while (getline(&line, &linelen, f) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (sscanf(line, "Hugepagesize: %lu kB", &hps) == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) hps <<= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) free(line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) return hps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) static void set_test_type(const char *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) if (!strcmp(type, "anon")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) test_type = TEST_ANON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) uffd_test_ops = &anon_uffd_test_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) /* Only enable write-protect test for anonymous test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) test_uffdio_wp = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) } else if (!strcmp(type, "hugetlb")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) test_type = TEST_HUGETLB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) uffd_test_ops = &hugetlb_uffd_test_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) } else if (!strcmp(type, "hugetlb_shared")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) map_shared = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) test_type = TEST_HUGETLB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) uffd_test_ops = &hugetlb_uffd_test_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) /* Minor faults require shared hugetlb; only enable here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) test_uffdio_minor = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) } else if (!strcmp(type, "shmem")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) map_shared = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) test_type = TEST_SHMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) uffd_test_ops = &shmem_uffd_test_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) test_uffdio_minor = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) err("Unknown test type: %s", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (test_type == TEST_HUGETLB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) page_size = default_huge_page_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) page_size = sysconf(_SC_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) if (!page_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) err("Unable to determine page size");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) * 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) > page_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) err("Impossible to run this test");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) static void sigalrm(int sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (sig != SIGALRM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) abort();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) test_uffdio_copy_eexist = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) test_uffdio_zeropage_eexist = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) alarm(ALARM_INTERVAL_SECS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (argc < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (signal(SIGALRM, sigalrm) == SIG_ERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) err("failed to arm SIGALRM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) alarm(ALARM_INTERVAL_SECS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) set_test_type(argv[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) nr_pages_per_cpu = atol(argv[2]) * 1024*1024 / page_size /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) nr_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) if (!nr_pages_per_cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) _err("invalid MiB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) bounces = atoi(argv[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) if (bounces <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) _err("invalid bounces");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) nr_pages = nr_pages_per_cpu * nr_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (test_type == TEST_HUGETLB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) if (argc < 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) huge_fd = open(argv[4], O_CREAT | O_RDWR, 0755);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) if (huge_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) err("Open of %s failed", argv[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (ftruncate(huge_fd, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) err("ftruncate %s to size 0 failed", argv[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) } else if (test_type == TEST_SHMEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) shm_fd = memfd_create(argv[0], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) if (shm_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) err("memfd_create");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (ftruncate(shm_fd, nr_pages * page_size * 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) err("ftruncate");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) if (fallocate(shm_fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) nr_pages * page_size * 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) err("fallocate");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) nr_pages, nr_pages_per_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) return userfaultfd_stress();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) #else /* __NR_userfaultfd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) #warning "missing __NR_userfaultfd definition"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) int main(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) printf("skip: Skipping userfaultfd test (missing __NR_userfaultfd)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) return KSFT_SKIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) #endif /* __NR_userfaultfd */