Skip to content

Commit

Permalink
tools: add selftests to hmm for COW in device memory
Browse files Browse the repository at this point in the history
The objective is to test device migration mechanism in pages marked as
COW, for private and coherent device type.  In case of writing to COW
private page(s), a page fault will migrate pages back to system memory
first.  Then, these pages will be duplicated.  In case of COW device
coherent type, pages are duplicated directly from device memory.

Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Alex Sierra <[email protected]>
Acked-by: Felix Kuehling <[email protected]>
Cc: Alistair Popple <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: David Hildenbrand <[email protected]>
Cc: Jason Gunthorpe <[email protected]>
Cc: Jerome Glisse <[email protected]>
Cc: Matthew Wilcox <[email protected]>
Cc: Ralph Campbell <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
  • Loading branch information
alexsierrag authored and akpm00 committed Jul 18, 2022
1 parent 9e09b70 commit 96c0657
Showing 1 changed file with 80 additions and 0 deletions.
80 changes: 80 additions & 0 deletions tools/testing/selftests/vm/hmm-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -1874,4 +1874,84 @@ TEST_F(hmm, hmm_gup_test)
close(gup_fd);
hmm_buffer_free(buffer);
}

/*
* Test copy-on-write in device pages.
* In case of writing to COW private page(s), a page fault will migrate pages
* back to system memory first. Then, these pages will be duplicated. In case
* of COW device coherent type, pages are duplicated directly from device
* memory.
*/
TEST_F(hmm, hmm_cow_in_device)
{
struct hmm_buffer *buffer;
unsigned long npages;
unsigned long size;
unsigned long i;
int *ptr;
int ret;
unsigned char *m;
pid_t pid;
int status;

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);

pid = fork();
if (pid == -1)
ASSERT_EQ(pid, 0);
if (!pid) {
/* Child process waitd for SIGTERM from the parent. */
while (1) {
}
perror("Should not reach this\n");
exit(0);
}
/* Parent process writes to COW pages(s) and gets a
* new copy in system. In case of device private pages,
* this write causes a migration to system mem first.
*/
for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
ptr[i] = i;

/* Terminate child and wait */
EXPECT_EQ(0, kill(pid, SIGTERM));
EXPECT_EQ(pid, waitpid(pid, &status, 0));
EXPECT_NE(0, WIFSIGNALED(status));
EXPECT_EQ(SIGTERM, WTERMSIG(status));

/* 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;
for (i = 0; i < npages; i++)
ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[i]);

hmm_buffer_free(buffer);
}
TEST_HARNESS_MAIN

0 comments on commit 96c0657

Please sign in to comment.