Add a test that changes permissions on a portion of a PUD THP using
mprotect. Since different parts now have different permissions, the
PUD must be split. The test verifies correct behavior after the
permission change.
Signed-off-by: Usama Arif <usamaarif642@gmail.com>
---
tools/testing/selftests/mm/pud_thp_test.c | 26 +++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/tools/testing/selftests/mm/pud_thp_test.c b/tools/testing/selftests/mm/pud_thp_test.c
index 8d4cb0e60f7f7..b59eb470adbba 100644
--- a/tools/testing/selftests/mm/pud_thp_test.c
+++ b/tools/testing/selftests/mm/pud_thp_test.c
@@ -256,4 +256,30 @@ TEST_F(pud_thp, partial_munmap)
self->split_before, split_after);
}
+/*
+ * Test: mprotect triggers split
+ * Verifies that changing protection on part of a PUD THP splits it
+ */
+TEST_F(pud_thp, mprotect_split)
+{
+ volatile unsigned char *p = (unsigned char *)self->aligned;
+ unsigned long split_after;
+ int ret;
+
+ /* Touch memory to allocate PUD THP */
+ memset(self->aligned, 0xEE, PUD_SIZE);
+
+ /* Change protection on a 2MB region - should trigger PUD split */
+ ret = mprotect((char *)self->aligned + PMD_SIZE, PMD_SIZE, PROT_READ);
+ ASSERT_EQ(ret, 0);
+
+ split_after = read_vmstat("thp_split_pud");
+
+ /* Verify memory still readable */
+ ASSERT_EQ(*p, 0xEE);
+
+ TH_LOG("mprotect split completed (thp_split_pud: %lu -> %lu)",
+ self->split_before, split_after);
+}
+
TEST_HARNESS_MAIN
--
2.47.3