Skip to content

Commit e478425

Browse files
Ralph Campbelljgunthorpe
authored andcommitted
mm/hmm: add tests for hmm_pfn_to_map_order()
Add a sanity test for hmm_range_fault() returning the page mapping size order. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ralph Campbell <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 3b50a6e commit e478425

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

lib/test_hmm.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,10 @@ static void dmirror_mkentry(struct dmirror *dmirror, struct hmm_range *range,
766766
*perm |= HMM_DMIRROR_PROT_WRITE;
767767
else
768768
*perm |= HMM_DMIRROR_PROT_READ;
769+
if (hmm_pfn_to_map_order(entry) + PAGE_SHIFT == PMD_SHIFT)
770+
*perm |= HMM_DMIRROR_PROT_PMD;
771+
else if (hmm_pfn_to_map_order(entry) + PAGE_SHIFT == PUD_SHIFT)
772+
*perm |= HMM_DMIRROR_PROT_PUD;
769773
}
770774

771775
static bool dmirror_snapshot_invalidate(struct mmu_interval_notifier *mni,

lib/test_hmm_uapi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ struct hmm_dmirror_cmd {
4040
* HMM_DMIRROR_PROT_NONE: unpopulated PTE or PTE with no access
4141
* HMM_DMIRROR_PROT_READ: read-only PTE
4242
* HMM_DMIRROR_PROT_WRITE: read/write PTE
43+
* HMM_DMIRROR_PROT_PMD: PMD sized page is fully mapped by same permissions
44+
* HMM_DMIRROR_PROT_PUD: PUD sized page is fully mapped by same permissions
4345
* HMM_DMIRROR_PROT_ZERO: special read-only zero page
4446
* HMM_DMIRROR_PROT_DEV_PRIVATE_LOCAL: Migrated device private page on the
4547
* device the ioctl() is made
@@ -51,6 +53,8 @@ enum {
5153
HMM_DMIRROR_PROT_NONE = 0x00,
5254
HMM_DMIRROR_PROT_READ = 0x01,
5355
HMM_DMIRROR_PROT_WRITE = 0x02,
56+
HMM_DMIRROR_PROT_PMD = 0x04,
57+
HMM_DMIRROR_PROT_PUD = 0x08,
5458
HMM_DMIRROR_PROT_ZERO = 0x10,
5559
HMM_DMIRROR_PROT_DEV_PRIVATE_LOCAL = 0x20,
5660
HMM_DMIRROR_PROT_DEV_PRIVATE_REMOTE = 0x30,

tools/testing/selftests/vm/hmm-tests.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,82 @@ TEST_F(hmm2, snapshot)
12911291
hmm_buffer_free(buffer);
12921292
}
12931293

1294+
/*
1295+
* Test the hmm_range_fault() HMM_PFN_PMD flag for large pages that
1296+
* should be mapped by a large page table entry.
1297+
*/
1298+
TEST_F(hmm, compound)
1299+
{
1300+
struct hmm_buffer *buffer;
1301+
unsigned long npages;
1302+
unsigned long size;
1303+
int *ptr;
1304+
unsigned char *m;
1305+
int ret;
1306+
long pagesizes[4];
1307+
int n, idx;
1308+
unsigned long i;
1309+
1310+
/* Skip test if we can't allocate a hugetlbfs page. */
1311+
1312+
n = gethugepagesizes(pagesizes, 4);
1313+
if (n <= 0)
1314+
return;
1315+
for (idx = 0; --n > 0; ) {
1316+
if (pagesizes[n] < pagesizes[idx])
1317+
idx = n;
1318+
}
1319+
size = ALIGN(TWOMEG, pagesizes[idx]);
1320+
npages = size >> self->page_shift;
1321+
1322+
buffer = malloc(sizeof(*buffer));
1323+
ASSERT_NE(buffer, NULL);
1324+
1325+
buffer->ptr = get_hugepage_region(size, GHR_STRICT);
1326+
if (buffer->ptr == NULL) {
1327+
free(buffer);
1328+
return;
1329+
}
1330+
1331+
buffer->size = size;
1332+
buffer->mirror = malloc(npages);
1333+
ASSERT_NE(buffer->mirror, NULL);
1334+
1335+
/* Initialize the pages the device will snapshot in buffer->ptr. */
1336+
for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1337+
ptr[i] = i;
1338+
1339+
/* Simulate a device snapshotting CPU pagetables. */
1340+
ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
1341+
ASSERT_EQ(ret, 0);
1342+
ASSERT_EQ(buffer->cpages, npages);
1343+
1344+
/* Check what the device saw. */
1345+
m = buffer->mirror;
1346+
for (i = 0; i < npages; ++i)
1347+
ASSERT_EQ(m[i], HMM_DMIRROR_PROT_WRITE |
1348+
HMM_DMIRROR_PROT_PMD);
1349+
1350+
/* Make the region read-only. */
1351+
ret = mprotect(buffer->ptr, size, PROT_READ);
1352+
ASSERT_EQ(ret, 0);
1353+
1354+
/* Simulate a device snapshotting CPU pagetables. */
1355+
ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
1356+
ASSERT_EQ(ret, 0);
1357+
ASSERT_EQ(buffer->cpages, npages);
1358+
1359+
/* Check what the device saw. */
1360+
m = buffer->mirror;
1361+
for (i = 0; i < npages; ++i)
1362+
ASSERT_EQ(m[i], HMM_DMIRROR_PROT_READ |
1363+
HMM_DMIRROR_PROT_PMD);
1364+
1365+
free_hugepage_region(buffer->ptr);
1366+
buffer->ptr = NULL;
1367+
hmm_buffer_free(buffer);
1368+
}
1369+
12941370
/*
12951371
* Test two devices reading the same memory (double mapped).
12961372
*/

0 commit comments

Comments
 (0)