The intention is to test hmm device coherent type under different get
user pages paths. Also, test gup with FOLL_LONGTERM flag set in
device coherent pages. These pages should get migrated back to system
memory.

Signed-off-by: Alex Sierra <alex.sie...@amd.com>
Reviewed-by: Alistair Popple <apop...@nvidia.com>
---
 tools/testing/selftests/vm/hmm-tests.c | 105 +++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/tools/testing/selftests/vm/hmm-tests.c 
b/tools/testing/selftests/vm/hmm-tests.c
index 84ec8c4a1dc7..61a02a6a3dea 100644
--- a/tools/testing/selftests/vm/hmm-tests.c
+++ b/tools/testing/selftests/vm/hmm-tests.c
@@ -36,6 +36,7 @@
  * in the usual include/uapi/... directory.
  */
 #include "../../../../lib/test_hmm_uapi.h"
+#include "../../../../mm/gup_test.h"
 
 struct hmm_buffer {
        void            *ptr;
@@ -60,6 +61,8 @@ enum {
 #define NTIMES         10
 
 #define ALIGN(x, a) (((x) + (a - 1)) & (~((a) - 1)))
+/* Just the flags we need, copied from mm.h: */
+#define FOLL_WRITE     0x01    /* check pte is writable */
 
 FIXTURE(hmm)
 {
@@ -1766,4 +1769,106 @@ TEST_F(hmm, exclusive_cow)
        hmm_buffer_free(buffer);
 }
 
+static int gup_test_exec(int gup_fd, unsigned long addr,
+                        int cmd, int npages, int size)
+{
+       struct gup_test gup = {
+               .nr_pages_per_call      = npages,
+               .addr                   = addr,
+               .gup_flags              = FOLL_WRITE,
+               .size                   = size,
+       };
+
+       if (ioctl(gup_fd, cmd, &gup)) {
+               perror("ioctl on error\n");
+               return errno;
+       }
+
+       return 0;
+}
+
+/*
+ * Test get user device pages through gup_test. Setting PIN_LONGTERM flag.
+ * This should trigger a migration back to system memory for both, private
+ * and coherent type pages.
+ * This test makes use of gup_test module. Make sure GUP_TEST_CONFIG is added
+ * to your configuration before you run it.
+ */
+TEST_F(hmm, hmm_gup_test)
+{
+       struct hmm_buffer *buffer;
+       int gup_fd;
+       unsigned long npages;
+       unsigned long size;
+       unsigned long i;
+       int *ptr;
+       int ret;
+       unsigned char *m;
+
+       gup_fd = open("/sys/kernel/debug/gup_test", O_RDWR);
+       if (gup_fd == -1)
+               SKIP(return, "Skipping test, could not find gup_test driver");
+
+       npages = 3;
+       size = npages << self->page_shift;
+
+       buffer = malloc(sizeof(*buffer));
+       ASSERT_NE(buffer, NULL);
+
+       buffer->fd = -1;
+       buffer->size = size;
+       buffer->mirror = malloc(size);
+       ASSERT_NE(buffer->mirror, NULL);
+
+       buffer->ptr = mmap(NULL, size,
+                          PROT_READ | PROT_WRITE,
+                          MAP_PRIVATE | MAP_ANONYMOUS,
+                          buffer->fd, 0);
+       ASSERT_NE(buffer->ptr, MAP_FAILED);
+
+       /* Initialize buffer in system memory. */
+       for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+               ptr[i] = i;
+
+       /* Migrate memory to device. */
+       ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
+       ASSERT_EQ(ret, 0);
+       ASSERT_EQ(buffer->cpages, npages);
+       /* Check what the device read. */
+       for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
+               ASSERT_EQ(ptr[i], i);
+
+       ASSERT_EQ(gup_test_exec(gup_fd,
+                               (unsigned long)buffer->ptr,
+                               GUP_BASIC_TEST, 1, self->page_size), 0);
+       ASSERT_EQ(gup_test_exec(gup_fd,
+                               (unsigned long)buffer->ptr + 1 * 
self->page_size,
+                               GUP_FAST_BENCHMARK, 1, self->page_size), 0);
+       ASSERT_EQ(gup_test_exec(gup_fd,
+                               (unsigned long)buffer->ptr + 2 * 
self->page_size,
+                               PIN_LONGTERM_BENCHMARK, 1, self->page_size), 0);
+
+       /* Take snapshot to CPU pagetables */
+       ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
+       ASSERT_EQ(ret, 0);
+       ASSERT_EQ(buffer->cpages, npages);
+       m = buffer->mirror;
+       if (hmm_is_coherent_type(variant->device_number)) {
+               ASSERT_EQ(HMM_DMIRROR_PROT_DEV_COHERENT_LOCAL | 
HMM_DMIRROR_PROT_WRITE, m[0]);
+               ASSERT_EQ(HMM_DMIRROR_PROT_DEV_COHERENT_LOCAL | 
HMM_DMIRROR_PROT_WRITE, m[1]);
+       } else {
+               ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[0]);
+               ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[1]);
+       }
+       ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[2]);
+       /*
+        * Check again the content on the pages. Make sure there's no
+        * corrupted data.
+        */
+       for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
+               ASSERT_EQ(ptr[i], i);
+
+       close(gup_fd);
+       hmm_buffer_free(buffer);
+}
 TEST_HARNESS_MAIN
-- 
2.32.0

Reply via email to