if (private)
flags |= MAP_PRIVATE; else
flags |= MAP_SHARED;
/* * For THP, we must explicitly enable the THP size, allocate twice the * required space then manually align.
*/ if (thp) { struct thp_settings settings = *thp_current_settings();
if (private)
settings.hugepages[sz2ord(size)].enabled = THP_ALWAYS; else
settings.shmem_hugepages[sz2ord(size)].enabled = SHMEM_ALWAYS;
thp_push_settings(&settings);
mem = mmap_aligned(size, prot, flags);
} else { if (hugetlb) {
flags |= MAP_HUGETLB;
flags |= __builtin_ctzll(size) << MAP_HUGE_SHIFT;
}
mem = mmap(NULL, size, prot, flags, -1, 0);
}
if (mem == MAP_FAILED) {
mem = NULL; goto out;
}
assert(((uintptr_t)mem & (size - 1)) == 0);
/* * Populate the folio by writing the first byte and check that all pages * are populated. Finally set the whole thing to non-zero data to avoid * kernel from mapping it back to the zero page.
*/
mem[0] = 1; for (addr = mem; addr < mem + size; addr += pagesize) { if (!pagemap_is_populated(pagemap_fd, addr)) {
munmap(mem, size);
mem = NULL; goto out;
}
}
memset(mem, 1, size);
out: if (thp)
thp_pop_settings();
/* Allocate a folio of required size and type. */
mem = alloc_one_folio(size, private, hugetlb); if (!mem) {
ksft_test_result_fail("alloc_one_folio() failed\n"); goto out;
}
/* Register range for uffd-wp. */ if (userfaultfd_open(&features)) { if (errno == ENOENT)
ksft_test_result_skip("userfaultfd not available\n"); else
ksft_test_result_fail("userfaultfd_open() failed\n"); goto out;
} if (uffd_register(uffd, mem, size, false, true, false)) {
ksft_test_result_fail("uffd_register() failed\n"); goto out;
}
wp_prms.mode = UFFDIO_WRITEPROTECT_MODE_WP;
wp_prms.range.start = (uintptr_t)mem;
wp_prms.range.len = size; if (ioctl(uffd, UFFDIO_WRITEPROTECT, &wp_prms)) {
ksft_test_result_fail("ioctl(UFFDIO_WRITEPROTECT) failed\n"); goto out;
}
if (swapout) {
madvise(mem, size, MADV_PAGEOUT); if (!range_is_swapped(mem, size)) {
ksft_test_result_skip("MADV_PAGEOUT did not work, is swap enabled?\n"); goto out;
}
}
/* Check that uffd-wp is set for all PTEs in range. */ if (!check_uffd_wp_state(mem, size, true)) goto out;
/* * Move the mapping to a new, aligned location. Since * UFFD_FEATURE_EVENT_REMAP is not set, we expect the uffd-wp bit for * each PTE to be cleared in the new mapping.
*/
addr = mmap_aligned(size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS); if (addr == MAP_FAILED) {
ksft_test_result_fail("mmap_aligned() failed\n"); goto out;
} if (mremap(mem, size, size, MREMAP_FIXED | MREMAP_MAYMOVE, addr) == MAP_FAILED) {
ksft_test_result_fail("mremap() failed\n");
munmap(addr, size); goto out;
}
mem = addr;
/* Check that uffd-wp is cleared for all PTEs in range. */ if (!check_uffd_wp_state(mem, size, false)) goto out;
/* If THP is supported, save THP settings and initially disable THP. */ if (nr_thpsizes) {
thp_save_settings();
thp_read_settings(&settings); for (i = 0; i < NR_ORDERS; i++) {
settings.hugepages[i].enabled = THP_NEVER;
settings.shmem_hugepages[i].enabled = SHMEM_NEVER;
}
thp_push_settings(&settings);
}
for (i = 0; i < ARRAY_SIZE(testcases); i++)
plan += *testcases[i].nr_sizes;
ksft_set_plan(plan);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.