forked from Minki/linux
tools: add selftests to hmm for COW in device memory
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/20220715150521.18165-15-alex.sierra@amd.com Signed-off-by: Alex Sierra <alex.sierra@amd.com> Acked-by: Felix Kuehling <Felix.Kuehling@amd.com> Cc: Alistair Popple <apopple@nvidia.com> Cc: Christoph Hellwig <hch@lst.de> Cc: David Hildenbrand <david@redhat.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>
This commit is contained in:
parent
9e09b705fd
commit
96c0657383
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user