diff options
author | Lokesh Gidra <lokeshgidra@google.com> | 2021-07-30 00:27:40 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-07-30 00:27:40 +0000 |
commit | 47966bd9bc3a5e741dce1ecb23f69758af3f456f (patch) | |
tree | 8e86b563e6812d922e32c7a64f2ab07626393a2d | |
parent | 282f09ba266daf77bf41d9d0ca6fa8eb1d7ec3fe (diff) | |
parent | 9b11d1b6ab483cb451b102a30d996dc180330161 (diff) | |
download | linux-kselftest-android-s-beta-5.tar.gz |
Merge "Fix ARM related issues in userfaultfd selftest"android-s-beta-5android-s-beta-5
-rw-r--r-- | android/patches/0019-userfaultfd.patch | 103 | ||||
-rw-r--r-- | tools/testing/selftests/vm/userfaultfd.c | 29 |
2 files changed, 115 insertions, 17 deletions
diff --git a/android/patches/0019-userfaultfd.patch b/android/patches/0019-userfaultfd.patch index b0cc72bb01e6..9c070185b63a 100644 --- a/android/patches/0019-userfaultfd.patch +++ b/android/patches/0019-userfaultfd.patch @@ -1,8 +1,11 @@ -diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c -index d3362777a425..d8119de2a342 100644 ---- a/tools/testing/selftests/vm/userfaultfd.c +diff -u b/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c +--- b/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c -@@ -85,6 +85,7 @@ static int uffd, uffd_flags, finished, *pipefd; +@@ -82,9 +82,11 @@ + static char *huge_fd_off0; + static unsigned long long *count_verify; + static int uffd, uffd_flags, finished, *pipefd; ++static volatile bool ready_for_fork; static char *area_src, *area_src_alias, *area_dst, *area_dst_alias; static char *zeropage; pthread_attr_t attr; @@ -10,7 +13,21 @@ index d3362777a425..d8119de2a342 100644 /* pthread_mutex_t starts at page offset 0 */ #define area_mutex(___area, ___nr) \ -@@ -284,23 +285,11 @@ static int my_bcmp(char *str1, char *str2, size_t n) +@@ -139,8 +141,11 @@ + + static void anon_allocate_area(void **alloc_area) + { +- if (posix_memalign(alloc_area, page_size, nr_pages * page_size)) { +- fprintf(stderr, "out of memory\n"); ++ // We can't use posix_memalign due to pointer-tagging used in bionic. ++ *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (*alloc_area == MAP_FAILED) { ++ fprintf(stderr, "anon memory mmap failed\n"); + *alloc_area = NULL; + } + } +@@ -284,23 +289,11 @@ static void *locking_thread(void *arg) { unsigned long cpu = (unsigned long) arg; @@ -35,7 +52,7 @@ index d3362777a425..d8119de2a342 100644 page_nr = -bounces; if (!(bounces & BOUNCE_RACINGFAULTS)) page_nr += cpu * nr_pages_per_cpu; -@@ -308,13 +297,9 @@ static void *locking_thread(void *arg) +@@ -308,13 +301,9 @@ while (!finished) { if (bounces & BOUNCE_RANDOM) { @@ -52,7 +69,17 @@ index d3362777a425..d8119de2a342 100644 16; } } else -@@ -548,18 +533,31 @@ static void *uffd_poll_thread(void *arg) +@@ -501,6 +490,9 @@ + pollfd[1].fd = pipefd[cpu*2]; + pollfd[1].events = POLLIN; + ++ // Notify the main thread that it can now fork. ++ ready_for_fork = true; ++ + for (;;) { + ret = poll(pollfd, 2, -1); + if (!ret) +@@ -548,18 +540,31 @@ pthread_mutex_t uffd_read_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -86,7 +113,7 @@ index d3362777a425..d8119de2a342 100644 if (uffd_read_msg(uffd, &msg)) continue; (*this_cpu_userfaults) += uffd_handle_page_fault(&msg); -@@ -608,6 +606,7 @@ static int stress(unsigned long *userfaults) +@@ -608,6 +613,7 @@ background_thread, (void *)cpu)) return 1; } @@ -94,7 +121,7 @@ index d3362777a425..d8119de2a342 100644 for (cpu = 0; cpu < nr_cpus; cpu++) if (pthread_join(background_threads[cpu], NULL)) return 1; -@@ -640,7 +639,7 @@ static int stress(unsigned long *userfaults) +@@ -640,7 +646,7 @@ if (pthread_join(uffd_threads[cpu], &_userfaults[cpu])) return 1; } else { @@ -103,7 +130,7 @@ index d3362777a425..d8119de2a342 100644 return 1; if (pthread_join(uffd_threads[cpu], NULL)) return 1; -@@ -654,7 +653,7 @@ static int userfaultfd_open(int features) +@@ -654,7 +660,7 @@ { struct uffdio_api uffdio_api; @@ -112,7 +139,53 @@ index d3362777a425..d8119de2a342 100644 if (uffd < 0) { fprintf(stderr, "userfaultfd syscall not available in this kernel\n"); -@@ -1036,6 +1035,7 @@ static int userfaultfd_stress(void) +@@ -914,6 +920,10 @@ + pid_t pid; + char c; + ++ // All the syscalls below up to pthread_create will ensure that this ++ // write is completed before, the uffd_thread sets it to true. ++ ready_for_fork = false; ++ + printf("testing events (fork, remap, remove): "); + fflush(stdout); + +@@ -942,6 +952,11 @@ + if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL)) + perror("uffd_poll_thread create"), exit(1); + ++ // Wait for the poll_thread to start executing before forking. This is ++ // required to avoid a deadlock, which can happen if poll_thread doesn't ++ // start getting executed by the time fork is invoked. ++ while (!ready_for_fork); ++ + pid = fork(); + if (pid < 0) + perror("fork"), exit(1); +@@ -974,6 +989,10 @@ + pid_t pid; + char c; + ++ // All the syscalls below up to pthread_create will ensure that this ++ // write is completed before, the uffd_thread sets it to true. ++ ready_for_fork = false; ++ + printf("testing signal delivery: "); + fflush(stdout); + +@@ -1007,6 +1026,11 @@ + if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL)) + perror("uffd_poll_thread create"), exit(1); + ++ // Wait for the poll_thread to start executing before forking. This is ++ // required to avoid a deadlock, which can happen if poll_thread doesn't ++ // start getting executed by the time fork is invoked. ++ while (!ready_for_fork); ++ + pid = fork(); + if (pid < 0) + perror("fork"), exit(1); +@@ -1036,6 +1060,7 @@ char *tmp_area; unsigned long nr; struct uffdio_register uffdio_register; @@ -120,7 +193,7 @@ index d3362777a425..d8119de2a342 100644 unsigned long cpu; int err; unsigned long userfaults[nr_cpus]; -@@ -1094,6 +1094,17 @@ static int userfaultfd_stress(void) +@@ -1094,6 +1119,17 @@ pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 16*1024*1024); @@ -138,7 +211,7 @@ index d3362777a425..d8119de2a342 100644 err = 0; while (bounces--) { unsigned long expected_ioctls; -@@ -1215,6 +1226,8 @@ static int userfaultfd_stress(void) +@@ -1215,6 +1251,8 @@ printf("\n"); } @@ -147,7 +220,7 @@ index d3362777a425..d8119de2a342 100644 if (err) return err; -@@ -1291,6 +1304,9 @@ static void sigalrm(int sig) +@@ -1291,6 +1329,9 @@ int main(int argc, char **argv) { @@ -157,7 +230,7 @@ index d3362777a425..d8119de2a342 100644 if (argc < 4) usage(); -@@ -1332,6 +1348,12 @@ int main(int argc, char **argv) +@@ -1332,6 +1373,12 @@ } printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n", nr_pages, nr_pages_per_cpu); diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c index d8119de2a342..3e25afd96a71 100644 --- a/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c @@ -82,6 +82,7 @@ static int huge_fd; static char *huge_fd_off0; static unsigned long long *count_verify; static int uffd, uffd_flags, finished, *pipefd; +static volatile bool ready_for_fork; static char *area_src, *area_src_alias, *area_dst, *area_dst_alias; static char *zeropage; pthread_attr_t attr; @@ -140,8 +141,11 @@ static int anon_release_pages(char *rel_area) static void anon_allocate_area(void **alloc_area) { - if (posix_memalign(alloc_area, page_size, nr_pages * page_size)) { - fprintf(stderr, "out of memory\n"); + // We can't use posix_memalign due to pointer-tagging used in bionic. + *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (*alloc_area == MAP_FAILED) { + fprintf(stderr, "anon memory mmap failed\n"); *alloc_area = NULL; } } @@ -486,6 +490,9 @@ static void *uffd_poll_thread(void *arg) pollfd[1].fd = pipefd[cpu*2]; pollfd[1].events = POLLIN; + // Notify the main thread that it can now fork. + ready_for_fork = true; + for (;;) { ret = poll(pollfd, 2, -1); if (!ret) @@ -913,6 +920,10 @@ static int userfaultfd_events_test(void) pid_t pid; char c; + // All the syscalls below up to pthread_create will ensure that this + // write is completed before, the uffd_thread sets it to true. + ready_for_fork = false; + printf("testing events (fork, remap, remove): "); fflush(stdout); @@ -941,6 +952,11 @@ static int userfaultfd_events_test(void) if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL)) perror("uffd_poll_thread create"), exit(1); + // Wait for the poll_thread to start executing before forking. This is + // required to avoid a deadlock, which can happen if poll_thread doesn't + // start getting executed by the time fork is invoked. + while (!ready_for_fork); + pid = fork(); if (pid < 0) perror("fork"), exit(1); @@ -973,6 +989,10 @@ static int userfaultfd_sig_test(void) pid_t pid; char c; + // All the syscalls below up to pthread_create will ensure that this + // write is completed before, the uffd_thread sets it to true. + ready_for_fork = false; + printf("testing signal delivery: "); fflush(stdout); @@ -1006,6 +1026,11 @@ static int userfaultfd_sig_test(void) if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL)) perror("uffd_poll_thread create"), exit(1); + // Wait for the poll_thread to start executing before forking. This is + // required to avoid a deadlock, which can happen if poll_thread doesn't + // start getting executed by the time fork is invoked. + while (!ready_for_fork); + pid = fork(); if (pid < 0) perror("fork"), exit(1); |