| From: John Hubbard <jhubbard@nvidia.com> |
| Subject: selftests/mm: move uffd* routines from vm_util.c to uffd-common.c |
| Date: Fri, 2 Jun 2023 19:15:57 -0700 |
| |
| Move the uffd*() routines to their natural home. Note that |
| ksm_functional_tests.c also depend, intentionally (due to a recent |
| commit [1]), upon uffd-common.[ch]. |
| |
| Link: https://lkml.kernel.org/r/20230603021558.95299-11-jhubbard@nvidia.com |
| Signed-off-by: John Hubbard <jhubbard@nvidia.com> |
| Acked-by: David Hildenbrand <david@redhat.com> |
| Cc: Peter Xu <peterx@redhat.com> |
| Cc: Jonathan Corbet <corbet@lwn.net> |
| Cc: Muhammad Usama Anjum <usama.anjum@collabora.com> |
| Cc: Nathan Chancellor <nathan@kernel.org> |
| Cc: Shuah Khan <shuah@kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| tools/testing/selftests/mm/Makefile | 7 |
| tools/testing/selftests/mm/hugepage-mremap.c | 2 |
| tools/testing/selftests/mm/ksm_functional_tests.c | 2 |
| tools/testing/selftests/mm/uffd-common.c | 105 ++++++++++++ |
| tools/testing/selftests/mm/uffd-common.h | 12 + |
| tools/testing/selftests/mm/vm_util.c | 104 ----------- |
| tools/testing/selftests/mm/vm_util.h | 10 - |
| 7 files changed, 122 insertions(+), 120 deletions(-) |
| |
| --- a/tools/testing/selftests/mm/hugepage-mremap.c~selftests-mm-move-uffd-routines-from-vm_utilc-to-uffd-commonc |
| +++ a/tools/testing/selftests/mm/hugepage-mremap.c |
| @@ -24,7 +24,7 @@ |
| #include <sys/ioctl.h> |
| #include <string.h> |
| #include <stdbool.h> |
| -#include "vm_util.h" |
| +#include "uffd-common.h" |
| |
| #define DEFAULT_LENGTH_MB 10UL |
| #define MB_TO_BYTES(x) (x * 1024 * 1024) |
| --- a/tools/testing/selftests/mm/ksm_functional_tests.c~selftests-mm-move-uffd-routines-from-vm_utilc-to-uffd-commonc |
| +++ a/tools/testing/selftests/mm/ksm_functional_tests.c |
| @@ -22,7 +22,7 @@ |
| #include <linux/userfaultfd.h> |
| |
| #include "../kselftest.h" |
| -#include "vm_util.h" |
| +#include "uffd-common.h" |
| |
| #define KiB 1024u |
| #define MiB (1024 * KiB) |
| --- a/tools/testing/selftests/mm/Makefile~selftests-mm-move-uffd-routines-from-vm_utilc-to-uffd-commonc |
| +++ a/tools/testing/selftests/mm/Makefile |
| @@ -110,8 +110,11 @@ include ../lib.mk |
| |
| $(TEST_GEN_PROGS): vm_util.c |
| |
| -$(OUTPUT)/uffd-stress: uffd-common.c |
| -$(OUTPUT)/uffd-unit-tests: uffd-common.c |
| +$(OUTPUT)/uffd-stress: uffd-common.c |
| +$(OUTPUT)/uffd-unit-tests: uffd-common.c |
| +$(OUTPUT)/hugepage-mremap: uffd-common.c |
| +$(OUTPUT)/write_to_hugetlbfs: uffd-common.c |
| +$(OUTPUT)/ksm_functional_tests: uffd-common.c |
| |
| ifeq ($(MACHINE),x86_64) |
| BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32)) |
| --- a/tools/testing/selftests/mm/uffd-common.c~selftests-mm-move-uffd-routines-from-vm_utilc-to-uffd-commonc |
| +++ a/tools/testing/selftests/mm/uffd-common.c |
| @@ -6,6 +6,7 @@ |
| */ |
| |
| #include "uffd-common.h" |
| +#include "vm_util.h" |
| |
| #define BASE_PMD_ADDR ((void *)(1UL << 30)) |
| |
| @@ -616,3 +617,107 @@ int copy_page(int ufd, unsigned long off |
| { |
| return __copy_page(ufd, offset, false, wp); |
| } |
| + |
| +/* If `ioctls' non-NULL, the allowed ioctls will be returned into the var */ |
| +int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len, |
| + bool miss, bool wp, bool minor, uint64_t *ioctls) |
| +{ |
| + struct uffdio_register uffdio_register = { 0 }; |
| + uint64_t mode = 0; |
| + int ret = 0; |
| + |
| + if (miss) |
| + mode |= UFFDIO_REGISTER_MODE_MISSING; |
| + if (wp) |
| + mode |= UFFDIO_REGISTER_MODE_WP; |
| + if (minor) |
| + mode |= UFFDIO_REGISTER_MODE_MINOR; |
| + |
| + uffdio_register.range.start = (unsigned long)addr; |
| + uffdio_register.range.len = len; |
| + uffdio_register.mode = mode; |
| + |
| + if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1) |
| + ret = -errno; |
| + else if (ioctls) |
| + *ioctls = uffdio_register.ioctls; |
| + |
| + return ret; |
| +} |
| + |
| +int uffd_register(int uffd, void *addr, uint64_t len, |
| + bool miss, bool wp, bool minor) |
| +{ |
| + return uffd_register_with_ioctls(uffd, addr, len, |
| + miss, wp, minor, NULL); |
| +} |
| + |
| +int uffd_unregister(int uffd, void *addr, uint64_t len) |
| +{ |
| + struct uffdio_range range = { .start = (uintptr_t)addr, .len = len }; |
| + int ret = 0; |
| + |
| + if (ioctl(uffd, UFFDIO_UNREGISTER, &range) == -1) |
| + ret = -errno; |
| + |
| + return ret; |
| +} |
| + |
| +int uffd_open_dev(unsigned int flags) |
| +{ |
| + int fd, uffd; |
| + |
| + fd = open("/dev/userfaultfd", O_RDWR | O_CLOEXEC); |
| + if (fd < 0) |
| + return fd; |
| + uffd = ioctl(fd, USERFAULTFD_IOC_NEW, flags); |
| + close(fd); |
| + |
| + return uffd; |
| +} |
| + |
| +int uffd_open_sys(unsigned int flags) |
| +{ |
| +#ifdef __NR_userfaultfd |
| + return syscall(__NR_userfaultfd, flags); |
| +#else |
| + return -1; |
| +#endif |
| +} |
| + |
| +int uffd_open(unsigned int flags) |
| +{ |
| + int uffd = uffd_open_sys(flags); |
| + |
| + if (uffd < 0) |
| + uffd = uffd_open_dev(flags); |
| + |
| + return uffd; |
| +} |
| + |
| +int uffd_get_features(uint64_t *features) |
| +{ |
| + struct uffdio_api uffdio_api = { .api = UFFD_API, .features = 0 }; |
| + /* |
| + * This should by default work in most kernels; the feature list |
| + * will be the same no matter what we pass in here. |
| + */ |
| + int fd = uffd_open(UFFD_USER_MODE_ONLY); |
| + |
| + if (fd < 0) |
| + /* Maybe the kernel is older than user-only mode? */ |
| + fd = uffd_open(0); |
| + |
| + if (fd < 0) |
| + return fd; |
| + |
| + if (ioctl(fd, UFFDIO_API, &uffdio_api)) { |
| + close(fd); |
| + return -errno; |
| + } |
| + |
| + *features = uffdio_api.features; |
| + close(fd); |
| + |
| + return 0; |
| +} |
| --- a/tools/testing/selftests/mm/uffd-common.h~selftests-mm-move-uffd-routines-from-vm_utilc-to-uffd-commonc |
| +++ a/tools/testing/selftests/mm/uffd-common.h |
| @@ -19,8 +19,6 @@ |
| #include <signal.h> |
| #include <poll.h> |
| #include <string.h> |
| -#include <linux/mman.h> |
| -#include <sys/mman.h> |
| #include <sys/syscall.h> |
| #include <sys/ioctl.h> |
| #include <sys/wait.h> |
| @@ -110,6 +108,16 @@ int __copy_page(int ufd, unsigned long o |
| int copy_page(int ufd, unsigned long offset, bool wp); |
| void *uffd_poll_thread(void *arg); |
| |
| +int uffd_register(int uffd, void *addr, uint64_t len, |
| + bool miss, bool wp, bool minor); |
| +int uffd_unregister(int uffd, void *addr, uint64_t len); |
| +int uffd_open_dev(unsigned int flags); |
| +int uffd_open_sys(unsigned int flags); |
| +int uffd_open(unsigned int flags); |
| +int uffd_get_features(uint64_t *features); |
| +int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len, |
| + bool miss, bool wp, bool minor, uint64_t *ioctls); |
| + |
| #define TEST_ANON 1 |
| #define TEST_HUGETLB 2 |
| #define TEST_SHMEM 3 |
| --- a/tools/testing/selftests/mm/vm_util.c~selftests-mm-move-uffd-routines-from-vm_utilc-to-uffd-commonc |
| +++ a/tools/testing/selftests/mm/vm_util.c |
| @@ -225,110 +225,6 @@ int detect_hugetlb_page_sizes(size_t siz |
| return count; |
| } |
| |
| -/* If `ioctls' non-NULL, the allowed ioctls will be returned into the var */ |
| -int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len, |
| - bool miss, bool wp, bool minor, uint64_t *ioctls) |
| -{ |
| - struct uffdio_register uffdio_register = { 0 }; |
| - uint64_t mode = 0; |
| - int ret = 0; |
| - |
| - if (miss) |
| - mode |= UFFDIO_REGISTER_MODE_MISSING; |
| - if (wp) |
| - mode |= UFFDIO_REGISTER_MODE_WP; |
| - if (minor) |
| - mode |= UFFDIO_REGISTER_MODE_MINOR; |
| - |
| - uffdio_register.range.start = (unsigned long)addr; |
| - uffdio_register.range.len = len; |
| - uffdio_register.mode = mode; |
| - |
| - if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1) |
| - ret = -errno; |
| - else if (ioctls) |
| - *ioctls = uffdio_register.ioctls; |
| - |
| - return ret; |
| -} |
| - |
| -int uffd_register(int uffd, void *addr, uint64_t len, |
| - bool miss, bool wp, bool minor) |
| -{ |
| - return uffd_register_with_ioctls(uffd, addr, len, |
| - miss, wp, minor, NULL); |
| -} |
| - |
| -int uffd_unregister(int uffd, void *addr, uint64_t len) |
| -{ |
| - struct uffdio_range range = { .start = (uintptr_t)addr, .len = len }; |
| - int ret = 0; |
| - |
| - if (ioctl(uffd, UFFDIO_UNREGISTER, &range) == -1) |
| - ret = -errno; |
| - |
| - return ret; |
| -} |
| - |
| -int uffd_open_dev(unsigned int flags) |
| -{ |
| - int fd, uffd; |
| - |
| - fd = open("/dev/userfaultfd", O_RDWR | O_CLOEXEC); |
| - if (fd < 0) |
| - return fd; |
| - uffd = ioctl(fd, USERFAULTFD_IOC_NEW, flags); |
| - close(fd); |
| - |
| - return uffd; |
| -} |
| - |
| -int uffd_open_sys(unsigned int flags) |
| -{ |
| -#ifdef __NR_userfaultfd |
| - return syscall(__NR_userfaultfd, flags); |
| -#else |
| - return -1; |
| -#endif |
| -} |
| - |
| -int uffd_open(unsigned int flags) |
| -{ |
| - int uffd = uffd_open_sys(flags); |
| - |
| - if (uffd < 0) |
| - uffd = uffd_open_dev(flags); |
| - |
| - return uffd; |
| -} |
| - |
| -int uffd_get_features(uint64_t *features) |
| -{ |
| - struct uffdio_api uffdio_api = { .api = UFFD_API, .features = 0 }; |
| - /* |
| - * This should by default work in most kernels; the feature list |
| - * will be the same no matter what we pass in here. |
| - */ |
| - int fd = uffd_open(UFFD_USER_MODE_ONLY); |
| - |
| - if (fd < 0) |
| - /* Maybe the kernel is older than user-only mode? */ |
| - fd = uffd_open(0); |
| - |
| - if (fd < 0) |
| - return fd; |
| - |
| - if (ioctl(fd, UFFDIO_API, &uffdio_api)) { |
| - close(fd); |
| - return -errno; |
| - } |
| - |
| - *features = uffdio_api.features; |
| - close(fd); |
| - |
| - return 0; |
| -} |
| - |
| unsigned int psize(void) |
| { |
| if (!__page_size) |
| --- a/tools/testing/selftests/mm/vm_util.h~selftests-mm-move-uffd-routines-from-vm_utilc-to-uffd-commonc |
| +++ a/tools/testing/selftests/mm/vm_util.h |
| @@ -34,16 +34,6 @@ int64_t allocate_transhuge(void *ptr, in |
| unsigned long default_huge_page_size(void); |
| int detect_hugetlb_page_sizes(size_t sizes[], int max); |
| |
| -int uffd_register(int uffd, void *addr, uint64_t len, |
| - bool miss, bool wp, bool minor); |
| -int uffd_unregister(int uffd, void *addr, uint64_t len); |
| -int uffd_open_dev(unsigned int flags); |
| -int uffd_open_sys(unsigned int flags); |
| -int uffd_open(unsigned int flags); |
| -int uffd_get_features(uint64_t *features); |
| -int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len, |
| - bool miss, bool wp, bool minor, uint64_t *ioctls); |
| - |
| /* |
| * On ppc64 this will only work with radix 2M hugepage size |
| */ |
| _ |