Skip to content

Commit

Permalink
tools: add hmm gup tests for device coherent type
Browse files Browse the repository at this point in the history
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.

Link: https://lkml.kernel.org/r/20220715150521.18165-14-alex.sierra@amd.com
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
Reviewed-by: Alistair Popple <apopple@nvidia.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: David Hildenbrand <david@redhat.com>
Cc: Felix Kuehling <Felix.Kuehling@amd.com>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Ralph Campbell <rcampbell@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
  • Loading branch information
Alex Sierra authored and akpm committed Jul 18, 2022
1 parent e6474b1 commit 9e09b70
Showing 1 changed file with 110 additions and 0 deletions.
110 changes: 110 additions & 0 deletions tools/testing/selftests/vm/hmm-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -59,6 +60,9 @@ 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 */
#define FOLL_LONGTERM 0x10000 /* mapping lifetime is indefinite */

FIXTURE(hmm)
{
Expand Down Expand Up @@ -1764,4 +1768,110 @@ 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, int flags)
{
struct gup_test gup = {
.nr_pages_per_call = npages,
.addr = addr,
.gup_flags = FOLL_WRITE | flags,
.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 = 4;
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), 0);
ASSERT_EQ(gup_test_exec(gup_fd,
(unsigned long)buffer->ptr + 1 * self->page_size,
GUP_FAST_BENCHMARK, 1, self->page_size, 0), 0);
ASSERT_EQ(gup_test_exec(gup_fd,
(unsigned long)buffer->ptr + 2 * self->page_size,
PIN_FAST_BENCHMARK, 1, self->page_size, FOLL_LONGTERM), 0);
ASSERT_EQ(gup_test_exec(gup_fd,
(unsigned long)buffer->ptr + 3 * self->page_size,
PIN_LONGTERM_BENCHMARK, 1, self->page_size, 0), 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]);
ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[3]);
/*
* 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

0 comments on commit 9e09b70

Please sign in to comment.