[PATCH i-g-t v6 5/9] tests/intel/xe_madvise: Add dontneed-after-mmap subtest

Arvind Yadav
2026-03-25T12:45:46Z

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.

v4:
- Added proper resource cleanup before calling igt_skip(). (Nishit)
- Added assertion for xe_bo_map. (Nishit)

v6:
- Fix sigsetjmp(jmp, SIGBUS | SIGSEGV) to sigsetjmp(jmp, 1). The
second argument is a plain boolean savemask, not a signal set.

Cc: Nishit Sharma <nishit.sharma@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>
Cc: Pravalika Gurram <pravalika.gurram@intel.com>
Signed-off-by: Arvind Yadav <arvind.yadav@intel.com>
---
tests/intel/xe_madvise.c | 64 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)

diff --git a/tests/intel/xe_madvise.c b/tests/intel/xe_madvise.c
index 81e05b6d4..9a157de1d 100644
--- a/tests/intel/xe_madvise.c
+++ b/tests/intel/xe_madvise.c
@@ -244,6 +244,64 @@ static void test_dontneed_before_mmap(int fd)
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)
+{
+ 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);
+ igt_assert(map != MAP_FAILED);
+ memset(map, 0xAB, bo_size);
+
+ if (!purgeable_mark_and_verify_purged(fd, vm, addr, bo_size)) {
+ munmap(map, bo_size);
+ gem_close(fd, bo);
+ xe_vm_destroy(fd, vm);
+ 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, 1); /* savemask=1: save/restore signal mask */
+ switch (sig) {
+ case SIGBUS:
+ case SIGSEGV:
+ /* Expected - purged mapping access failed */
+ break;
+ case 0:
+ *ptr = 0;
+ default:
+ igt_assert_f(false,
+ "Access to purged mapping should trigger SIGBUS, got sig=%d\n",
+ sig);
+ break;
+ }
+
+ 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;
@@ -268,6 +326,12 @@ int igt_main()
break;
}

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