162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Userfaultfd tests common header 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2015-2023 Red Hat, Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#ifndef __UFFD_COMMON_H__ 862306a36Sopenharmony_ci#define __UFFD_COMMON_H__ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define _GNU_SOURCE 1162306a36Sopenharmony_ci#include <stdio.h> 1262306a36Sopenharmony_ci#include <errno.h> 1362306a36Sopenharmony_ci#include <unistd.h> 1462306a36Sopenharmony_ci#include <stdlib.h> 1562306a36Sopenharmony_ci#include <sys/types.h> 1662306a36Sopenharmony_ci#include <sys/stat.h> 1762306a36Sopenharmony_ci#include <fcntl.h> 1862306a36Sopenharmony_ci#include <time.h> 1962306a36Sopenharmony_ci#include <signal.h> 2062306a36Sopenharmony_ci#include <poll.h> 2162306a36Sopenharmony_ci#include <string.h> 2262306a36Sopenharmony_ci#include <linux/mman.h> 2362306a36Sopenharmony_ci#include <sys/mman.h> 2462306a36Sopenharmony_ci#include <sys/syscall.h> 2562306a36Sopenharmony_ci#include <sys/ioctl.h> 2662306a36Sopenharmony_ci#include <sys/wait.h> 2762306a36Sopenharmony_ci#include <pthread.h> 2862306a36Sopenharmony_ci#include <linux/userfaultfd.h> 2962306a36Sopenharmony_ci#include <setjmp.h> 3062306a36Sopenharmony_ci#include <stdbool.h> 3162306a36Sopenharmony_ci#include <assert.h> 3262306a36Sopenharmony_ci#include <inttypes.h> 3362306a36Sopenharmony_ci#include <stdint.h> 3462306a36Sopenharmony_ci#include <sys/random.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include "../kselftest.h" 3762306a36Sopenharmony_ci#include "vm_util.h" 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define UFFD_FLAGS (O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define _err(fmt, ...) \ 4262306a36Sopenharmony_ci do { \ 4362306a36Sopenharmony_ci int ret = errno; \ 4462306a36Sopenharmony_ci fprintf(stderr, "ERROR: " fmt, ##__VA_ARGS__); \ 4562306a36Sopenharmony_ci fprintf(stderr, " (errno=%d, @%s:%d)\n", \ 4662306a36Sopenharmony_ci ret, __FILE__, __LINE__); \ 4762306a36Sopenharmony_ci } while (0) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define errexit(exitcode, fmt, ...) \ 5062306a36Sopenharmony_ci do { \ 5162306a36Sopenharmony_ci _err(fmt, ##__VA_ARGS__); \ 5262306a36Sopenharmony_ci exit(exitcode); \ 5362306a36Sopenharmony_ci } while (0) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define err(fmt, ...) errexit(1, fmt, ##__VA_ARGS__) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* pthread_mutex_t starts at page offset 0 */ 5862306a36Sopenharmony_ci#define area_mutex(___area, ___nr) \ 5962306a36Sopenharmony_ci ((pthread_mutex_t *) ((___area) + (___nr)*page_size)) 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * count is placed in the page after pthread_mutex_t naturally aligned 6262306a36Sopenharmony_ci * to avoid non alignment faults on non-x86 archs. 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ci#define area_count(___area, ___nr) \ 6562306a36Sopenharmony_ci ((volatile unsigned long long *) ((unsigned long) \ 6662306a36Sopenharmony_ci ((___area) + (___nr)*page_size + \ 6762306a36Sopenharmony_ci sizeof(pthread_mutex_t) + \ 6862306a36Sopenharmony_ci sizeof(unsigned long long) - 1) & \ 6962306a36Sopenharmony_ci ~(unsigned long)(sizeof(unsigned long long) \ 7062306a36Sopenharmony_ci - 1))) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* Userfaultfd test statistics */ 7362306a36Sopenharmony_cistruct uffd_args { 7462306a36Sopenharmony_ci int cpu; 7562306a36Sopenharmony_ci /* Whether apply wr-protects when installing pages */ 7662306a36Sopenharmony_ci bool apply_wp; 7762306a36Sopenharmony_ci unsigned long missing_faults; 7862306a36Sopenharmony_ci unsigned long wp_faults; 7962306a36Sopenharmony_ci unsigned long minor_faults; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* A custom fault handler; defaults to uffd_handle_page_fault. */ 8262306a36Sopenharmony_ci void (*handle_fault)(struct uffd_msg *msg, struct uffd_args *args); 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistruct uffd_test_ops { 8662306a36Sopenharmony_ci int (*allocate_area)(void **alloc_area, bool is_src); 8762306a36Sopenharmony_ci void (*release_pages)(char *rel_area); 8862306a36Sopenharmony_ci void (*alias_mapping)(__u64 *start, size_t len, unsigned long offset); 8962306a36Sopenharmony_ci void (*check_pmd_mapping)(void *p, int expect_nr_hpages); 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_citypedef struct uffd_test_ops uffd_test_ops_t; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciextern unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size; 9462306a36Sopenharmony_ciextern char *area_src, *area_src_alias, *area_dst, *area_dst_alias, *area_remap; 9562306a36Sopenharmony_ciextern int uffd, uffd_flags, finished, *pipefd, test_type; 9662306a36Sopenharmony_ciextern bool map_shared; 9762306a36Sopenharmony_ciextern bool test_uffdio_wp; 9862306a36Sopenharmony_ciextern unsigned long long *count_verify; 9962306a36Sopenharmony_ciextern volatile bool test_uffdio_copy_eexist; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciextern uffd_test_ops_t anon_uffd_test_ops; 10262306a36Sopenharmony_ciextern uffd_test_ops_t shmem_uffd_test_ops; 10362306a36Sopenharmony_ciextern uffd_test_ops_t hugetlb_uffd_test_ops; 10462306a36Sopenharmony_ciextern uffd_test_ops_t *uffd_test_ops; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_civoid uffd_stats_report(struct uffd_args *args, int n_cpus); 10762306a36Sopenharmony_ciint uffd_test_ctx_init(uint64_t features, const char **errmsg); 10862306a36Sopenharmony_ciint userfaultfd_open(uint64_t *features); 10962306a36Sopenharmony_ciint uffd_read_msg(int ufd, struct uffd_msg *msg); 11062306a36Sopenharmony_civoid wp_range(int ufd, __u64 start, __u64 len, bool wp); 11162306a36Sopenharmony_civoid uffd_handle_page_fault(struct uffd_msg *msg, struct uffd_args *args); 11262306a36Sopenharmony_ciint __copy_page(int ufd, unsigned long offset, bool retry, bool wp); 11362306a36Sopenharmony_ciint copy_page(int ufd, unsigned long offset, bool wp); 11462306a36Sopenharmony_civoid *uffd_poll_thread(void *arg); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciint uffd_open_dev(unsigned int flags); 11762306a36Sopenharmony_ciint uffd_open_sys(unsigned int flags); 11862306a36Sopenharmony_ciint uffd_open(unsigned int flags); 11962306a36Sopenharmony_ciint uffd_get_features(uint64_t *features); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#define TEST_ANON 1 12262306a36Sopenharmony_ci#define TEST_HUGETLB 2 12362306a36Sopenharmony_ci#define TEST_SHMEM 3 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#endif 126