From: nishit.sharma@intel.com
To: jonathan.cavitt@intel.com, igt-dev@lists.freedesktop.org,
nishit.sharma@intel.com
Subject: [PATCH] tests/intel/xe_compute: Add VM page fault property reporting test
Date: Wed, 3 Dec 2025 09:48:20 +0000 [thread overview]
Message-ID: <20251203094820.14800-1-nishit.sharma@intel.com> (raw)
From: Nishit Sharma <nishit.sharma@intel.com>
Add new subtest 'vm-get-property-pagefault-reporting' to validate the
DRM_IOCTL_XE_VM_GET_PROPERTY ioctl for querying VM page fault information.
This test exercises the kernel's page fault tracking mechanism for VMs
created with fault-mode enabled. It verifies:
- Initial page fault count is zero for newly created VMs
- Page faults are correctly tracked and reported after triggering
- Reported fault count respects the maximum limit (≤50 faults)
- All reported faults maintain consistent fault address, access type,
and fault type
- VM isolation is maintained (faults in VM1 don't affect VM2)
Signed-off-by: Nishit Sharma <nishit.sharma@intel.com>
---
tests/intel/xe_compute.c | 171 +++++++++++++++++++++++++++++++++++++++
1 file changed, 171 insertions(+)
diff --git a/tests/intel/xe_compute.c b/tests/intel/xe_compute.c
index 108235637..48c6e032a 100644
--- a/tests/intel/xe_compute.c
+++ b/tests/intel/xe_compute.c
@@ -16,6 +16,7 @@
#include "igt.h"
#include "igt_sysfs.h"
#include "intel_compute.h"
+#include "xe_drm.h"
#include "xe/xe_ioctl.h"
#include "xe/xe_query.h"
@@ -510,6 +511,173 @@ test_compute_square(int fd)
"GPU not supported\n");
}
+static void print_pf(struct xe_vm_fault *fault)
+{
+ igt_debug("FAULT:\n");
+ igt_debug("address = 0x%08x%08x\n",
+ upper_32_bits(fault->address),
+ lower_32_bits(fault->address));
+ igt_debug("address precision = %u\n", fault->address_precision);
+ igt_debug("access type = %u\n", fault->access_type);
+ igt_debug("fault type = %u\n", fault->fault_type);
+ igt_debug("fault level = %u\n", fault->fault_level);
+ igt_debug("\n");
+}
+
+/**
+ * SUBTEST: vm-get-property-pagefault-reporting
+ * Description: Test VM page fault reporting via xe_vm_get_property ioctl
+ * Functionality: VM page fault isolation and query
+ * Test category: functionality test
+ */
+static void test_vm_pagefault_reporting(void)
+{
+ struct drm_xe_engine_class_instance *hwe;
+ struct drm_xe_vm_get_property property = {0};
+ struct xe_vm_fault *faults_1, f0, f;
+ uint32_t vm1, vm2;
+ uint32_t exec_queue1;
+ uint64_t addr = 0x1a0000;
+ struct drm_xe_sync sync = {
+ .type = DRM_XE_SYNC_TYPE_USER_FENCE,
+ .flags = DRM_XE_SYNC_FLAG_SIGNAL,
+ };
+ struct drm_xe_exec exec = {};
+ uint64_t *sync_val;
+ int ret;
+ int fd, fault_count, final_fault_count, check_count;
+ uint32_t bo;
+ bool found_compute = false;
+
+ fd = drm_open_driver(DRIVER_XE);
+ xe_device_get(fd);
+
+ igt_require(xe_has_vram(fd)); /* Fault mode typically needs VRAM */
+
+ /* Create fault-mode VM1 */
+ vm1 = xe_vm_create(fd, DRM_XE_VM_CREATE_FLAG_LR_MODE |
+ DRM_XE_VM_CREATE_FLAG_FAULT_MODE, 0);
+ igt_assert(vm1);
+
+ /* Step 1: Query initial pagefault count (should be 0) */
+ property.vm_id = vm1;
+ property.property = DRM_XE_VM_GET_PROPERTY_FAULTS;
+ property.data = 0;
+ property.size = 0;
+
+ ret = igt_ioctl(fd, DRM_IOCTL_XE_VM_GET_PROPERTY, &property);
+ igt_assert_eq(ret, 0);
+
+
+ if (property.size > 0) {
+ faults_1 = malloc(property.size);
+ igt_assert(faults_1);
+ property.data = to_user_pointer(faults_1);
+ ret = igt_ioctl(fd, DRM_IOCTL_XE_VM_GET_PROPERTY, &property);
+ igt_assert_eq(ret, 0);
+ free(faults_1);
+ }
+
+ fault_count = property.size / sizeof(struct xe_vm_fault);
+ f0 = faults_1[0];
+
+ for (int i = 0; i < fault_count; i++) {
+ f = faults_1[i];
+ print_pf(&f);
+ igt_assert_eq(f.address, f0.address);
+ igt_assert_eq(f.access_type, f0.access_type);
+ igt_assert_eq(f.fault_type, f0.fault_type);
+ }
+ free(faults_1);
+
+ /* Step 2: Trigger a page fault via compute job */
+ xe_for_each_engine(fd, hwe) {
+ if (hwe->engine_class != DRM_XE_ENGINE_CLASS_COMPUTE)
+ continue;
+ found_compute = true;
+
+ exec_queue1 = xe_exec_queue_create(fd, vm1, hwe, 0);
+ sync_val = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+ igt_assert(sync_val != MAP_FAILED);
+ *sync_val = 0;
+ sync.addr = to_user_pointer(sync_val);
+
+ /* Create a faulting job (access unmapped address) */
+ bo = xe_bo_create(fd, vm1, 4096, vram_if_possible(fd, 0), 0);
+ exec.exec_queue_id = exec_queue1;
+ exec.num_batch_buffer = 1;
+ exec.address = addr; /* Unmapped - will fault */
+ exec.syncs = to_user_pointer(&sync);
+
+ /* This exec should trigger page fault */
+ ret = igt_ioctl(fd, DRM_IOCTL_XE_EXEC, &exec);
+
+ /* Wait for fault handling */
+ usleep(100000); /* 100ms for page fault to be recorded */
+
+ gem_close(fd, bo);
+
+ /* Step 3: Query pagefault count after fault */
+ faults_1 = malloc(property.size);
+ igt_assert(faults_1);
+ property.data = to_user_pointer(faults_1);
+ property.size = 0;
+ ret = igt_ioctl(fd, DRM_IOCTL_XE_VM_GET_PROPERTY, &property);
+ igt_assert_eq(ret, 0);
+
+ if (property.size > 0) {
+ faults_1 = malloc(property.size);
+ igt_assert(faults_1);
+ property.data = to_user_pointer(faults_1);
+ ret = igt_ioctl(fd, DRM_IOCTL_XE_VM_GET_PROPERTY, &property);
+ igt_assert_eq(ret, 0);
+
+ final_fault_count = property.size / sizeof(struct xe_vm_fault);
+ check_count = final_fault_count > 50 ? 50 : final_fault_count;
+ f0 = faults_1[0];
+
+ for (int i = 0; i < check_count; i++) {
+ f = faults_1[i];
+ print_pf(&f);
+ igt_assert_eq(f.address, f0.address);
+ igt_assert_eq(f.access_type, f0.access_type);
+ igt_assert_eq(f.fault_type, f0.fault_type);
+ }
+ free(faults_1);
+ }
+
+ munmap(sync_val, 4096);
+ xe_exec_queue_destroy(fd, exec_queue1);
+ }
+ igt_require(found_compute);
+
+ /* Step 4: Create VM2 for isolation test */
+ vm2 = xe_vm_create(fd, DRM_XE_VM_CREATE_FLAG_LR_MODE |
+ DRM_XE_VM_CREATE_FLAG_FAULT_MODE, 0);
+ igt_assert(vm2);
+
+ property.vm_id = vm2;
+ property.property = DRM_XE_VM_GET_PROPERTY_FAULTS;
+ property.data = 0;
+ property.size = 0;
+ ret = igt_ioctl(fd, DRM_IOCTL_XE_VM_GET_PROPERTY, &property);
+ igt_assert_eq(ret, 0);
+
+ if (property.size > 0) {
+ faults_1 = malloc(property.size);
+ igt_assert(faults_1);
+ property.data = to_user_pointer(faults_1);
+ ret = igt_ioctl(fd, DRM_IOCTL_XE_VM_GET_PROPERTY, &property);
+ igt_assert_eq(ret, 0);
+ free(faults_1);
+ }
+
+ /* Cleanup */
+ xe_vm_destroy(fd, vm1);
+ xe_vm_destroy(fd, vm2);
+ drm_close_driver(fd);
+}
+
igt_main
{
int xe, ccs_mode[4];
@@ -565,6 +733,9 @@ igt_main
test_eu_busy(5 * LOOP_DURATION_2s);
}
+ igt_subtest("vm-get-property-pagefault-reporting")
+ test_vm_pagefault_reporting();
+
igt_fixture {
if (!sriov_enabled)
igt_restore_ccs_mode(ccs_mode, ARRAY_SIZE(ccs_mode));
--
2.43.0
reply other threads:[~2025-12-03 9:48 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251203094820.14800-1-nishit.sharma@intel.com \
--to=nishit.sharma@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=jonathan.cavitt@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).