Revert "BACKPORT: FROMGIT: userfaultfd/selftests: add test exercising minor fault handling"

This reverts commit 2b2f7d6a04d65c2ebd53f9e5d3de6b55635d57b6 so that it
can be re-applied once dependcies are brought in.

Signed-off-by: Lokesh Gidra <lokeshgidra@google.com>
Bug: 187930641
Change-Id: Ib24c94e1d8ec6c46004d35f58e48d9d35eeb8312
This commit is contained in:
Lokesh Gidra 2021-05-21 03:52:12 -07:00 • committed by Michael Bestas
commit 9ade127571

View file

@ -77,8 +77,6 @@ static int test_type;
#define ALARM_INTERVAL_SECS 10
static volatile bool test_uffdio_copy_eexist = true;
static volatile bool test_uffdio_zeropage_eexist = true;
/* Whether to test uffd minor faults */
static bool test_uffdio_minor = false;
static bool map_shared;
static int huge_fd;
@ -269,7 +267,7 @@ static struct uffd_test_ops shmem_uffd_test_ops = {
};
static struct uffd_test_ops hugetlb_uffd_test_ops = {
.expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC & ~(1 << _UFFDIO_CONTINUE),
.expected_ioctls = UFFD_API_RANGE_IOCTLS_BASIC,
.allocate_area = hugetlb_allocate_area,
.release_pages = hugetlb_release_pages,
.alias_mapping = hugetlb_alias_mapping,
@ -286,22 +284,6 @@ static int my_bcmp(char *str1, char *str2, size_t n)
return 0;
}
static void continue_range(int ufd, __u64 start, __u64 len)
{
struct uffdio_continue req;
req.range.start = start;
req.range.len = len;
req.mode = 0;
if (ioctl(ufd, UFFDIO_CONTINUE, &req)) {
fprintf(stderr,
"UFFDIO_CONTINUE failed for address 0x%" PRIx64 "\n",
(uint64_t)start);
exit(1);
}
}
static void *locking_thread(void *arg)
{
unsigned long cpu = (unsigned long) arg;
@ -440,41 +422,13 @@ static int uffd_handle_page_fault(struct uffd_msg *msg)
fprintf(stderr, "unexpected msg event %u\n",
msg->event), exit(1);
if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_MINOR) {
uint8_t *area;
int b;
if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
fprintf(stderr, "unexpected write fault\n"), exit(1);
/*
* Minor page faults
*
* To prove we can modify the original range for testing
* purposes, we're going to bit flip this range before
* continuing.
*
* Note that this requires all minor page fault tests operate on
* area_dst (non-UFFD-registered) and area_dst_alias
* (UFFD-registered).
*/
offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
offset &= ~(page_size-1);
area = (uint8_t *)(area_dst +
((char *)msg->arg.pagefault.address -
area_dst_alias));
for (b = 0; b < page_size; ++b)
area[b] = ~area[b];
continue_range(uffd, msg->arg.pagefault.address, page_size);
return 1;
} else {
/* Missing page faults */
if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE) {
fprintf(stderr, "unexpected write fault\n");
exit(1);
}
offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
offset &= ~(page_size-1);
return copy_page(uffd, offset);
}
return copy_page(uffd, offset);
}
static void *uffd_poll_thread(void *arg)
@ -641,7 +595,7 @@ static int stress(unsigned long *userfaults)
return 0;
}
static int userfaultfd_open_ext(uint64_t *features)
static int userfaultfd_open(int features)
{
struct uffdio_api uffdio_api;
@ -654,7 +608,7 @@ static int userfaultfd_open_ext(uint64_t *features)
uffd_flags = fcntl(uffd, F_GETFD, NULL);
uffdio_api.api = UFFD_API;
uffdio_api.features = *features;
uffdio_api.features = features;
if (ioctl(uffd, UFFDIO_API, &uffdio_api)) {
fprintf(stderr, "UFFDIO_API\n");
return 1;
@ -664,15 +618,9 @@ static int userfaultfd_open_ext(uint64_t *features)
return 1;
}
*features = uffdio_api.features;
return 0;
}
static int userfaultfd_open(uint64_t features)
{
return userfaultfd_open_ext(&features);
}
sigjmp_buf jbuf, *sigbuf;
static void sighndl(int sig, siginfo_t *siginfo, void *ptr)
@ -944,7 +892,7 @@ static int userfaultfd_events_test(void)
perror("fork"), exit(1);
if (!pid)
exit(faulting_process(0));
return faulting_process(0);
waitpid(pid, &err, 0);
if (err)
@ -1027,101 +975,6 @@ static int userfaultfd_sig_test(void)
close(uffd);
return userfaults != 0;
}
static int userfaultfd_minor_test(void)
{
struct uffdio_register uffdio_register;
unsigned long expected_ioctls;
unsigned long userfaults;
unsigned long p;
pthread_t uffd_mon;
uint8_t expected_byte;
void *expected_page;
char c;
uint64_t features = UFFD_FEATURE_MINOR_HUGETLBFS;
if (!test_uffdio_minor)
return 0;
printf("testing minor faults: ");
fflush(stdout);
if (uffd_test_ops->release_pages(area_dst))
return 1;
if (userfaultfd_open_ext(&features))
return 1;
/* If kernel reports the feature isn't supported, skip the test. */
if (!(features & UFFD_FEATURE_MINOR_HUGETLBFS)) {
printf("skipping test due to lack of feature support\n");
fflush(stdout);
return 0;
}
uffdio_register.range.start = (unsigned long)area_dst_alias;
uffdio_register.range.len = nr_pages * page_size;
uffdio_register.mode = UFFDIO_REGISTER_MODE_MINOR;
if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register)) {
fprintf(stderr, "register failure\n");
exit(1);
}
expected_ioctls = uffd_test_ops->expected_ioctls;
expected_ioctls |= 1 << _UFFDIO_CONTINUE;
if ((uffdio_register.ioctls & expected_ioctls) != expected_ioctls) {
fprintf(stderr, "unexpected missing ioctl(s)\n");
exit(1);
}
/*
* After registering with UFFD, populate the non-UFFD-registered side of
* the shared mapping. This should *not* trigger any UFFD minor faults.
*/
for (p = 0; p < nr_pages; ++p) {
memset(area_dst + (p * page_size), p % ((uint8_t)-1),
page_size);
}
if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL)) {
perror("uffd_poll_thread create");
exit(1);
}
/*
* Read each of the pages back using the UFFD-registered mapping. We
* expect that the first time we touch a page, it will result in a minor
* fault. uffd_poll_thread will resolve the fault by bit-flipping the
* page's contents, and then issuing a CONTINUE ioctl.
*/
if (posix_memalign(&expected_page, page_size, page_size)) {
fprintf(stderr, "out of memory\n");
return 1;
}
for (p = 0; p < nr_pages; ++p) {
expected_byte = ~((uint8_t)(p % ((uint8_t)-1)));
memset(expected_page, expected_byte, page_size);
if (my_bcmp(expected_page, area_dst_alias + (p * page_size),
page_size)) {
fprintf(stderr,
"unexpected page contents after minor fault\n");
exit(1);
}
}
if (write(pipefd[1], &c, sizeof(c)) != sizeof(c)) {
perror("pipe write");
exit(1);
}
if (pthread_join(uffd_mon, (void **)&userfaults))
return 1;
printf("userfaults: %ld\n", userfaults);
close(uffd);
return userfaults != nr_pages;
}
static int userfaultfd_stress(void)
{
void *area;
@ -1312,7 +1165,7 @@ static int userfaultfd_stress(void)
close(uffd);
return userfaultfd_zeropage_test() || userfaultfd_sig_test()
|| userfaultfd_events_test() || userfaultfd_minor_test();
|| userfaultfd_events_test();
}
/*
@ -1351,8 +1204,6 @@ static void set_test_type(const char *type)
map_shared = true;
test_type = TEST_HUGETLB;
uffd_test_ops = &hugetlb_uffd_test_ops;
/* Minor faults require shared hugetlb; only enable here. */
test_uffdio_minor = true;
} else if (!strcmp(type, "shmem")) {
map_shared = true;
test_type = TEST_SHMEM;