From: "Dr. David Alan Gilbert" <dgilb...@redhat.com>

* tests/userfaultfd.c: Add test
* tests/userfaultfd.test: Call test
---
 tests/userfaultfd.c    | 179 ++++++++++++++++++++++++++++++++++++++++++++++++-
 tests/userfaultfd.test |   2 +-
 2 files changed, 177 insertions(+), 4 deletions(-)

diff --git a/tests/userfaultfd.c b/tests/userfaultfd.c
index 5747a2a..9410fe4 100644
--- a/tests/userfaultfd.c
+++ b/tests/userfaultfd.c
@@ -26,7 +26,11 @@
  */
 
 #include "tests.h"
+#include <assert.h>
 #include <fcntl.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
 #include <sys/syscall.h>
 
 #if defined __NR_userfaultfd && defined O_CLOEXEC
@@ -34,12 +38,181 @@
 # include <stdio.h>
 # include <unistd.h>
 
+#ifdef HAVE_LINUX_USERFAULTFD_H
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <linux/ioctl.h>
+#include <linux/userfaultfd.h>
+#endif
+
+void
+ioctl_test(int fd)
+{
+#ifdef HAVE_LINUX_USERFAULTFD_H
+       int rc;
+       size_t pagesize = getpagesize();
+
+       /* ---- API ---- */
+       struct uffdio_api api_struct;
+       /* With a bad fd */
+       memset(&api_struct, 0, sizeof(api_struct));
+       rc = ioctl(-1, UFFDIO_API, &api_struct);
+       printf("ioctl(-1, UFFDIO_API, {api=0, features=0, "
+               "features.out=0, ioctls=0"
+               "}) = %d %s (%m)\n", rc, errno2name());
+       /* With a bad pointer */
+       rc = ioctl(fd, UFFDIO_API, NULL);
+       printf("ioctl(%d, UFFDIO_API, NULL) = %d %s (%m)\n",
+               fd, rc, errno2name());
+       /* Normal call */
+       api_struct.api = UFFD_API;
+       api_struct.features = 0;
+       rc = ioctl(fd, UFFDIO_API, &api_struct);
+       printf("ioctl(%d, UFFDIO_API, {api=0xaa, features=0, "
+               "features.out=%#" PRIx64 ", " "ioctls=1<<_UFFDIO_REGISTER|"
+               "1<<_UFFDIO_UNREGISTER|1<<_UFFDIO_API",
+               fd, (uint64_t)api_struct.features);
+       api_struct.ioctls &= ~(1ull<<_UFFDIO_REGISTER|
+                               1ull<<_UFFDIO_UNREGISTER|
+                               1ull<<_UFFDIO_API);
+       if (api_struct.ioctls)
+               printf("|%#" PRIx64, (uint64_t)api_struct.ioctls);
+       printf("}) = %d\n", rc);
+
+       /* For the rest of the tests we need some anonymous memory */
+       void *area1 = mmap(NULL, pagesize, PROT_READ|PROT_WRITE,
+                               MAP_PRIVATE|MAP_ANONYMOUS,
+                               -1, 0);
+       assert(area1);
+       void *area2 = mmap(NULL, pagesize, PROT_READ|PROT_WRITE,
+                               MAP_PRIVATE|MAP_ANONYMOUS,
+                               -1, 0);
+       assert(area2);
+       madvise(area2, pagesize, MADV_DONTNEED);
+       *(char *)area1 = 42;
+
+       /* ---- REGISTER ---- */
+       struct uffdio_register register_struct;
+       memset(&register_struct, 0, sizeof(register_struct));
+
+       rc = ioctl(-1, UFFDIO_REGISTER, &register_struct);
+       printf("ioctl(-1, UFFDIO_REGISTER, {range={start=0, len=0}, "
+               "mode=0, ioctls=0}) = %d %s (%m)\n",
+                rc, errno2name());
+
+       rc = ioctl(fd, UFFDIO_REGISTER, NULL);
+       printf("ioctl(%d, UFFDIO_REGISTER, NULL) = %d %s (%m)\n",
+                fd, rc, errno2name());
+
+       register_struct.range.start = (uint64_t)(uintptr_t)area2;
+       register_struct.range.len = pagesize;
+       register_struct.mode = UFFDIO_REGISTER_MODE_MISSING;
+       rc = ioctl(fd, UFFDIO_REGISTER, &register_struct);
+       printf("ioctl(%d, UFFDIO_REGISTER, {range={start=%p, len=%#zx}, "
+               "mode=UFFDIO_REGISTER_MODE_MISSING, ioctls="
+               "1<<_UFFDIO_WAKE|1<<_UFFDIO_COPY|1<<_UFFDIO_ZEROPAGE",
+               fd, area2, pagesize);
+       register_struct.ioctls &= ~(1ull<<_UFFDIO_WAKE|
+                               1ull<<_UFFDIO_COPY|
+                               1ull<<_UFFDIO_ZEROPAGE);
+       if (register_struct.ioctls)
+               printf("|%#" PRIx64, (uint64_t)register_struct.ioctls);
+       printf("}) = %d\n", rc);
+
+       /* With area2 registered we can now do the atomic copies onto it
+        * but be careful not to access it in any other way otherwise
+        * userfaultfd will cause us to stall.
+        */
+       /* ---- COPY ---- */
+       struct uffdio_copy copy_struct;
+
+       memset(&copy_struct, 0, sizeof(copy_struct));
+       rc = ioctl(-1, UFFDIO_COPY, &copy_struct);
+       printf("ioctl(-1, UFFDIO_COPY, {dst=0, src=0, len=0, mode=0"
+               ", copy=0}) = %d %s (%m)\n",
+               rc, errno2name());
+
+       rc = ioctl(fd, UFFDIO_COPY, NULL);
+       printf("ioctl(%d, UFFDIO_COPY, NULL) = %d %s (%m)\n",
+               fd, rc, errno2name());
+
+       copy_struct.dst = (uint64_t)(uintptr_t)area2;
+       copy_struct.src = (uint64_t)(uintptr_t)area1;
+       copy_struct.len = pagesize;
+       copy_struct.mode = UFFDIO_COPY_MODE_DONTWAKE;
+       rc = ioctl(fd, UFFDIO_COPY, &copy_struct);
+       printf("ioctl(%d, UFFDIO_COPY, {dst=%p, src=%p, len=%#zx,"
+               " mode=UFFDIO_COPY_MODE_DONTWAKE, copy=%#zx}) = %d\n",
+               fd, area2, area1, pagesize, pagesize, rc);
+
+       /* ---- ZEROPAGE ---- */
+       struct uffdio_zeropage zero_struct;
+       madvise(area2, pagesize, MADV_DONTNEED);
+
+       memset(&zero_struct, 0, sizeof(zero_struct));
+       rc = ioctl(-1, UFFDIO_ZEROPAGE, &zero_struct);
+       printf("ioctl(-1, UFFDIO_ZEROPAGE, {range={start=0, len=0}, mode=0"
+               ", zeropage=0}) = %d %s (%m)\n",
+               rc, errno2name());
+
+       rc = ioctl(fd, UFFDIO_ZEROPAGE, NULL);
+       printf("ioctl(%d, UFFDIO_ZEROPAGE, NULL) = %d %s (%m)\n",
+               fd, rc, errno2name());
+
+       zero_struct.range.start = (uint64_t)(uintptr_t)area2;
+       zero_struct.range.len = pagesize;
+       zero_struct.mode = UFFDIO_ZEROPAGE_MODE_DONTWAKE;
+       rc = ioctl(fd, UFFDIO_ZEROPAGE, &zero_struct);
+       printf("ioctl(%d, UFFDIO_ZEROPAGE, {range={start=%p, len=%#zx},"
+               " mode=UFFDIO_ZEROPAGE_MODE_DONTWAKE, zeropage=%#zx}) = %d\n",
+               fd, area2, pagesize, pagesize, rc);
+
+       /* ---- WAKE ---- */
+       struct uffdio_range range_struct;
+       memset(&range_struct, 0, sizeof(range_struct));
+
+       rc = ioctl(-1, UFFDIO_WAKE, &range_struct);
+       printf("ioctl(-1, UFFDIO_WAKE, {start=0, len=0}) = %d %s (%m)\n",
+               rc, errno2name());
+
+       rc = ioctl(fd, UFFDIO_WAKE, NULL);
+       printf("ioctl(%d, UFFDIO_WAKE, NULL) = %d %s (%m)\n",
+               fd, rc, errno2name());
+
+       range_struct.start = (uint64_t)(uintptr_t)area2;
+       range_struct.len = pagesize;
+       rc = ioctl(fd, UFFDIO_WAKE, &range_struct);
+       printf("ioctl(%d, UFFDIO_WAKE, {start=%p, len=%#zx}) = %d\n",
+               fd, area2, pagesize, rc);
+
+       /* ---- UNREGISTER ---- */
+       memset(&range_struct, 0, sizeof(range_struct));
+
+       rc = ioctl(-1, UFFDIO_UNREGISTER, &range_struct);
+       printf("ioctl(-1, UFFDIO_UNREGISTER, {start=0, len=0}) = %d %s (%m)\n",
+               rc, errno2name());
+
+       rc = ioctl(fd, UFFDIO_UNREGISTER, NULL);
+       printf("ioctl(%d, UFFDIO_UNREGISTER, NULL) = %d %s (%m)\n",
+               fd, rc, errno2name());
+
+       range_struct.start = (uint64_t)(uintptr_t)area2;
+       range_struct.len = pagesize;
+       rc = ioctl(fd, UFFDIO_UNREGISTER, &range_struct);
+       printf("ioctl(%d, UFFDIO_UNREGISTER, {start=%p, len=%#zx}) = %d\n",
+               fd, area2, pagesize, rc);
+
+#endif
+}
+
 int
 main(void)
 {
-       long rc = syscall(__NR_userfaultfd, 1 | O_NONBLOCK | O_CLOEXEC);
-       printf("userfaultfd(O_NONBLOCK|O_CLOEXEC|0x1) = %ld %s (%m)\n",
-              rc, errno2name());
+       int fd = syscall(__NR_userfaultfd, O_NONBLOCK | O_CLOEXEC);
+       printf("userfaultfd(O_NONBLOCK|O_CLOEXEC) = %d\n",
+              fd);
+       if (fd != -1)
+               ioctl_test(fd);
        puts("+++ exited with 0 +++");
        return 0;
 }
diff --git a/tests/userfaultfd.test b/tests/userfaultfd.test
index af8b6fb..ccf4e44 100755
--- a/tests/userfaultfd.test
+++ b/tests/userfaultfd.test
@@ -3,4 +3,4 @@
 # Check userfaultfd syscall decoding.
 
 . "${srcdir=.}/init.sh"
-run_strace_match_diff -a38
+run_strace_match_diff -a1 -e trace=ioctl,userfaultfd
-- 
2.5.5


------------------------------------------------------------------------------
Find and fix application performance issues faster with Applications Manager
Applications Manager provides deep performance insights into multiple tiers of
your business applications. It resolves application problems quickly and
reduces your MTTR. Get your free trial!
https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to