xref: /openbmc/linux/tools/testing/selftests/mm/uffd-common.h (revision 5f8b7d4b2e9604d03ae06f1a2dd5a1f34c33e533)
133be4e89SPeter Xu // SPDX-License-Identifier: GPL-2.0-only
233be4e89SPeter Xu /*
333be4e89SPeter Xu  * Userfaultfd tests common header
433be4e89SPeter Xu  *
533be4e89SPeter Xu  * Copyright (C) 2015-2023  Red Hat, Inc.
633be4e89SPeter Xu  */
733be4e89SPeter Xu #ifndef __UFFD_COMMON_H__
833be4e89SPeter Xu #define __UFFD_COMMON_H__
933be4e89SPeter Xu 
1033be4e89SPeter Xu #define _GNU_SOURCE
1176697523SMichael Ellerman #define __SANE_USERSPACE_TYPES__ // Use ll64
1233be4e89SPeter Xu #include <stdio.h>
1333be4e89SPeter Xu #include <errno.h>
1433be4e89SPeter Xu #include <unistd.h>
1533be4e89SPeter Xu #include <stdlib.h>
1633be4e89SPeter Xu #include <sys/types.h>
1733be4e89SPeter Xu #include <sys/stat.h>
1833be4e89SPeter Xu #include <fcntl.h>
1933be4e89SPeter Xu #include <time.h>
2033be4e89SPeter Xu #include <signal.h>
2133be4e89SPeter Xu #include <poll.h>
2233be4e89SPeter Xu #include <string.h>
2333be4e89SPeter Xu #include <linux/mman.h>
2433be4e89SPeter Xu #include <sys/mman.h>
2533be4e89SPeter Xu #include <sys/syscall.h>
2633be4e89SPeter Xu #include <sys/ioctl.h>
2733be4e89SPeter Xu #include <sys/wait.h>
2833be4e89SPeter Xu #include <pthread.h>
2933be4e89SPeter Xu #include <linux/userfaultfd.h>
3033be4e89SPeter Xu #include <setjmp.h>
3133be4e89SPeter Xu #include <stdbool.h>
3233be4e89SPeter Xu #include <assert.h>
3333be4e89SPeter Xu #include <inttypes.h>
3433be4e89SPeter Xu #include <stdint.h>
3533be4e89SPeter Xu #include <sys/random.h>
36*0b9be246SEdward Liaw #include <stdatomic.h>
3733be4e89SPeter Xu 
3833be4e89SPeter Xu #include "../kselftest.h"
3933be4e89SPeter Xu #include "vm_util.h"
4033be4e89SPeter Xu 
4133be4e89SPeter Xu #define UFFD_FLAGS	(O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY)
4233be4e89SPeter Xu 
4333be4e89SPeter Xu #define _err(fmt, ...)						\
4433be4e89SPeter Xu 	do {							\
4533be4e89SPeter Xu 		int ret = errno;				\
4633be4e89SPeter Xu 		fprintf(stderr, "ERROR: " fmt, ##__VA_ARGS__);	\
4733be4e89SPeter Xu 		fprintf(stderr, " (errno=%d, @%s:%d)\n",	\
4833be4e89SPeter Xu 			ret, __FILE__, __LINE__);		\
4933be4e89SPeter Xu 	} while (0)
5033be4e89SPeter Xu 
5133be4e89SPeter Xu #define errexit(exitcode, fmt, ...)		\
5233be4e89SPeter Xu 	do {					\
5333be4e89SPeter Xu 		_err(fmt, ##__VA_ARGS__);	\
5433be4e89SPeter Xu 		exit(exitcode);			\
5533be4e89SPeter Xu 	} while (0)
5633be4e89SPeter Xu 
5733be4e89SPeter Xu #define err(fmt, ...) errexit(1, fmt, ##__VA_ARGS__)
5833be4e89SPeter Xu 
5933be4e89SPeter Xu /* pthread_mutex_t starts at page offset 0 */
6033be4e89SPeter Xu #define area_mutex(___area, ___nr)					\
6133be4e89SPeter Xu 	((pthread_mutex_t *) ((___area) + (___nr)*page_size))
6233be4e89SPeter Xu /*
6333be4e89SPeter Xu  * count is placed in the page after pthread_mutex_t naturally aligned
6433be4e89SPeter Xu  * to avoid non alignment faults on non-x86 archs.
6533be4e89SPeter Xu  */
6633be4e89SPeter Xu #define area_count(___area, ___nr)					\
6733be4e89SPeter Xu 	((volatile unsigned long long *) ((unsigned long)		\
6833be4e89SPeter Xu 				 ((___area) + (___nr)*page_size +	\
6933be4e89SPeter Xu 				  sizeof(pthread_mutex_t) +		\
7033be4e89SPeter Xu 				  sizeof(unsigned long long) - 1) &	\
7133be4e89SPeter Xu 				 ~(unsigned long)(sizeof(unsigned long long) \
7233be4e89SPeter Xu 						  -  1)))
7333be4e89SPeter Xu 
7433be4e89SPeter Xu /* Userfaultfd test statistics */
7550834084SPeter Xu struct uffd_args {
7633be4e89SPeter Xu 	int cpu;
770210c43eSPeter Xu 	/* Whether apply wr-protects when installing pages */
780210c43eSPeter Xu 	bool apply_wp;
7933be4e89SPeter Xu 	unsigned long missing_faults;
8033be4e89SPeter Xu 	unsigned long wp_faults;
8133be4e89SPeter Xu 	unsigned long minor_faults;
827cf0f9e8SAxel Rasmussen 
837cf0f9e8SAxel Rasmussen 	/* A custom fault handler; defaults to uffd_handle_page_fault. */
847cf0f9e8SAxel Rasmussen 	void (*handle_fault)(struct uffd_msg *msg, struct uffd_args *args);
8533be4e89SPeter Xu };
8633be4e89SPeter Xu 
8733be4e89SPeter Xu struct uffd_test_ops {
88be39fec4SPeter Xu 	int (*allocate_area)(void **alloc_area, bool is_src);
8933be4e89SPeter Xu 	void (*release_pages)(char *rel_area);
9033be4e89SPeter Xu 	void (*alias_mapping)(__u64 *start, size_t len, unsigned long offset);
9133be4e89SPeter Xu 	void (*check_pmd_mapping)(void *p, int expect_nr_hpages);
9233be4e89SPeter Xu };
9333be4e89SPeter Xu typedef struct uffd_test_ops uffd_test_ops_t;
9433be4e89SPeter Xu 
95265818efSPeter Xu extern unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
9633be4e89SPeter Xu extern char *area_src, *area_src_alias, *area_dst, *area_dst_alias, *area_remap;
97c5cb9036SPeter Xu extern int uffd, uffd_flags, finished, *pipefd, test_type;
98111fd29bSPeter Xu extern bool map_shared;
9962515b5fSPeter Xu extern bool test_uffdio_wp;
10033be4e89SPeter Xu extern unsigned long long *count_verify;
10133be4e89SPeter Xu extern volatile bool test_uffdio_copy_eexist;
102*0b9be246SEdward Liaw extern atomic_bool ready_for_fork;
10333be4e89SPeter Xu 
10433be4e89SPeter Xu extern uffd_test_ops_t anon_uffd_test_ops;
10533be4e89SPeter Xu extern uffd_test_ops_t shmem_uffd_test_ops;
10633be4e89SPeter Xu extern uffd_test_ops_t hugetlb_uffd_test_ops;
10733be4e89SPeter Xu extern uffd_test_ops_t *uffd_test_ops;
10833be4e89SPeter Xu 
10950834084SPeter Xu void uffd_stats_report(struct uffd_args *args, int n_cpus);
110f9da2426SPeter Xu int uffd_test_ctx_init(uint64_t features, const char **errmsg);
111f9da2426SPeter Xu int userfaultfd_open(uint64_t *features);
11233be4e89SPeter Xu int uffd_read_msg(int ufd, struct uffd_msg *msg);
11333be4e89SPeter Xu void wp_range(int ufd, __u64 start, __u64 len, bool wp);
11450834084SPeter Xu void uffd_handle_page_fault(struct uffd_msg *msg, struct uffd_args *args);
1150210c43eSPeter Xu int __copy_page(int ufd, unsigned long offset, bool retry, bool wp);
1160210c43eSPeter Xu int copy_page(int ufd, unsigned long offset, bool wp);
11733be4e89SPeter Xu void *uffd_poll_thread(void *arg);
11833be4e89SPeter Xu 
11956d2afffSJohn Hubbard int uffd_open_dev(unsigned int flags);
12056d2afffSJohn Hubbard int uffd_open_sys(unsigned int flags);
12156d2afffSJohn Hubbard int uffd_open(unsigned int flags);
12256d2afffSJohn Hubbard int uffd_get_features(uint64_t *features);
12356d2afffSJohn Hubbard 
12433be4e89SPeter Xu #define TEST_ANON	1
12533be4e89SPeter Xu #define TEST_HUGETLB	2
12633be4e89SPeter Xu #define TEST_SHMEM	3
12733be4e89SPeter Xu 
12833be4e89SPeter Xu #endif
129