[PATCH i-g-t v3 4/8] tests/intel/xe_madvise: Add dontneed-after-mmap subtest

Arvind Yadav
2026-02-17T02:35:49Z

This test verifies that an existing mmap becomes invalid after the BO
is marked as purgeable and purged. The test creates a BO, maps it,
writes data, then marks it DONTNEED and triggers memory pressure.
Accessing the previously valid mapping should now trigger SIGBUS or
SIGSEGV, confirming that existing mappings are correctly invalidated
when the backing store is purged.

Cc: Nishit Sharma <nishit.sharma@intel.com>
Cc: Pravalika Gurram <pravalika.gurram@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Signed-off-by: Arvind Yadav <arvind.yadav@intel.com>
---
tests/intel/xe_madvise.c | 54 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)

diff --git a/tests/intel/xe_madvise.c b/tests/intel/xe_madvise.c
index 7dbe70f42..5c6a24553 100644
--- a/tests/intel/xe_madvise.c
+++ b/tests/intel/xe_madvise.c
@@ -196,6 +196,54 @@ static void test_dontneed_before_mmap(int fd, struct drm_xe_engine_class_instanc
xe_vm_destroy(fd, vm);
}

+/**
+ * SUBTEST: dontneed-after-mmap
+ * Description: Mark BO as DONTNEED after mmap, verify SIGBUS on accessing purged mapping
+ * Test category: functionality test
+ */
+static void test_dontneed_after_mmap(int fd, struct drm_xe_engine_class_instance *hwe)
+{
+ uint32_t bo, vm;
+ uint64_t addr = PURGEABLE_ADDR;
+ size_t bo_size = PURGEABLE_BO_SIZE;
+ void *map;
+
+ purgeable_setup_simple_bo(fd, &vm, &bo, addr, bo_size, true);
+
+ map = xe_bo_map(fd, bo, bo_size);
+ memset(map, 0xAB, bo_size);
+
+ if (!purgeable_mark_and_verify_purged(fd, vm, addr, bo_size))
+ igt_skip("Unable to induce purge on this platform/config");
+
+ /* Access purged mapping - should trigger SIGBUS/SIGSEGV */
+ {
+ sighandler_t old_sigsegv, old_sigbus;
+ char *ptr = (char *)map;
+ int sig;
+
+ old_sigsegv = signal(SIGSEGV, (__sighandler_t)sigtrap);
+ old_sigbus = signal(SIGBUS, (__sighandler_t)sigtrap);
+
+ sig = sigsetjmp(jmp, SIGBUS | SIGSEGV);
+ if (sig == SIGBUS || sig == SIGSEGV) {
+ /* Expected - purged mapping access failed */
+ } else if (sig == 0) {
+ *ptr = 0;
+ igt_assert_f(false, "Access to purged mapping should trigger signal\n");
+ } else {
+ igt_assert_f(false, "unexpected signal %d\n", sig);
+ }
+
+ signal(SIGBUS, old_sigbus);
+ signal(SIGSEGV, old_sigsegv);
+ }
+
+ munmap(map, bo_size);
+ gem_close(fd, bo);
+ xe_vm_destroy(fd, vm);
+}
+
int igt_main()
{
struct drm_xe_engine_class_instance *hwe;
@@ -212,6 +260,12 @@ int igt_main()
break;
}

+ igt_subtest("dontneed-after-mmap")
+ xe_for_each_engine(fd, hwe) {
+ test_dontneed_after_mmap(fd, hwe);
+ break;
+ }
+
igt_fixture() {
xe_device_put(fd);
drm_close_driver(fd);
--
2.43.0