]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - tools/testing/selftests/vm/userfaultfd.c
userfaultfd: selftest: return an error if BOUNCE_VERIFY fails
[karo-tx-linux.git] / tools / testing / selftests / vm / userfaultfd.c
index 76071b14cb93857a01a3e4e97324702e4227633d..174f2fc8d2577d93ff85b626fe6cf49d7f1b0597 100644 (file)
 #include <sys/syscall.h>
 #include <sys/ioctl.h>
 #include <pthread.h>
-#include "../../../../include/uapi/linux/userfaultfd.h"
-
-#ifdef __x86_64__
-#define __NR_userfaultfd 323
-#elif defined(__i386__)
-#define __NR_userfaultfd 374
-#elif defined(__powewrpc__)
-#define __NR_userfaultfd 364
-#else
-#error "missing __NR_userfaultfd definition"
-#endif
+#include <linux/userfaultfd.h>
+
+#ifdef __NR_userfaultfd
 
 static unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
 
@@ -147,7 +139,8 @@ static void *locking_thread(void *arg)
                        if (sizeof(page_nr) > sizeof(rand_nr)) {
                                if (random_r(&rand, &rand_nr))
                                        fprintf(stderr, "random_r 2 error\n"), exit(1);
-                               page_nr |= ((unsigned long) rand_nr) << 32;
+                               page_nr |= (((unsigned long) rand_nr) << 16) <<
+                                          16;
                        }
                } else
                        page_nr += 1;
@@ -290,7 +283,8 @@ static void *uffd_poll_thread(void *arg)
                                msg.event), exit(1);
                if (msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
                        fprintf(stderr, "unexpected write fault\n"), exit(1);
-               offset = (char *)msg.arg.pagefault.address - area_dst;
+               offset = (char *)(unsigned long)msg.arg.pagefault.address -
+                        area_dst;
                offset &= ~(page_size-1);
                if (copy_page(offset))
                        userfaults++;
@@ -327,7 +321,8 @@ static void *uffd_read_thread(void *arg)
                if (bounces & BOUNCE_VERIFY &&
                    msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
                        fprintf(stderr, "unexpected write fault\n"), exit(1);
-               offset = (char *)msg.arg.pagefault.address - area_dst;
+               offset = (char *)(unsigned long)msg.arg.pagefault.address -
+                        area_dst;
                offset &= ~(page_size-1);
                if (copy_page(offset))
                        (*this_cpu_userfaults)++;
@@ -427,7 +422,7 @@ static int userfaultfd_stress(void)
        struct uffdio_register uffdio_register;
        struct uffdio_api uffdio_api;
        unsigned long cpu;
-       int uffd_flags;
+       int uffd_flags, err;
        unsigned long userfaults[nr_cpus];
 
        if (posix_memalign(&area, page_size, nr_pages * page_size)) {
@@ -470,6 +465,14 @@ static int userfaultfd_stress(void)
                *area_mutex(area_src, nr) = (pthread_mutex_t)
                        PTHREAD_MUTEX_INITIALIZER;
                count_verify[nr] = *area_count(area_src, nr) = 1;
+               /*
+                * In the transition between 255 to 256, powerpc will
+                * read out of order in my_bcmp and see both bytes as
+                * zero, so leave a placeholder below always non-zero
+                * after the count, to avoid my_bcmp to trigger false
+                * positives.
+                */
+               *(area_count(area_src, nr) + 1) = 1;
        }
 
        pipefd = malloc(sizeof(int) * nr_cpus * 2);
@@ -496,6 +499,7 @@ static int userfaultfd_stress(void)
        pthread_attr_init(&attr);
        pthread_attr_setstacksize(&attr, 16*1024*1024);
 
+       err = 0;
        while (bounces--) {
                unsigned long expected_ioctls;
 
@@ -580,8 +584,9 @@ static int userfaultfd_stress(void)
                                            area_dst + nr * page_size,
                                            sizeof(pthread_mutex_t))) {
                                        fprintf(stderr,
-                                               "error mutex %lu\n",
+                                               "error mutex %lu\n",
                                                nr);
+                                       err = 1;
                                        bounces = 0;
                                }
                                if (*area_count(area_dst, nr) != count_verify[nr]) {
@@ -590,6 +595,7 @@ static int userfaultfd_stress(void)
                                                *area_count(area_src, nr),
                                                count_verify[nr],
                                                nr);
+                                       err = 1;
                                        bounces = 0;
                                }
                        }
@@ -606,7 +612,7 @@ static int userfaultfd_stress(void)
                printf("\n");
        }
 
-       return 0;
+       return err;
 }
 
 int main(int argc, char **argv)
@@ -615,8 +621,8 @@ int main(int argc, char **argv)
                fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
        nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
        page_size = sysconf(_SC_PAGE_SIZE);
-       if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) >
-           page_size)
+       if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) * 2
+           page_size)
                fprintf(stderr, "Impossible to run this test\n"), exit(2);
        nr_pages_per_cpu = atol(argv[1]) * 1024*1024 / page_size /
                nr_cpus;
@@ -634,3 +640,15 @@ int main(int argc, char **argv)
               nr_pages, nr_pages_per_cpu);
        return userfaultfd_stress();
 }
+
+#else /* __NR_userfaultfd */
+
+#warning "missing __NR_userfaultfd definition"
+
+int main(void)
+{
+       printf("skip: Skipping userfaultfd test (missing __NR_userfaultfd)\n");
+       return 0;
+}
+
+#endif /* __NR_userfaultfd */