From: Varun Gupta <varun.gupta@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: nishit.sharma@intel.com, priyanka.dandamudi@intel.com
Subject: [PATCH i-g-t v5] tests/intel/xe_prefetch_fault: Add SVM and hit-under-miss validation
Date: Mon, 23 Mar 2026 14:55:21 +0530 [thread overview]
Message-ID: <20260323092521.2984407-1-varun.gupta@intel.com> (raw)
Add a second batch to validate hit-under-miss behavior: placing the BB
at PREFETCH_ADDR ensures the page is already mapped when the shader
prefetch runs, so the prefetch fault counter should not increment.
Add SVM mode (prefetch-fault-svm subtest) that creates the VM with
CPU_ADDR_MIRROR and uses mmap() at PREFETCH_ADDR to make the page
GPU-accessible before the hit-under-miss batch.
Other changes:
- Extract PREFETCH_ADDR and USER_FENCE_VALUE into defines
- Update stat name to 'invalid_prefetch_pagefault_count'
- Add missing cleanup (intel_buf_destroy, xe_exec_queue_destroy,
xe_vm_destroy)
v2:
- Move xe_vm_create() before if(svm) as it is common to both paths (Nishit)
- Separate SVM and non-SVM specific code into if/else blocks (Nishit)
- Add BB_OFFSET and BB_OFFSET_SVM defines (Nishit)
- Add comments wherever needed (Nishit)
v3:
- Drop const from bb_offset and bb_offset2 (Nishit)
- Rename prefetch_pos to prefetch_post (Nishit)
v4:
- Fix build error: misplaced closing bracket.
v5:
- Use xe_supports_faults() in fixture to probe SVM support and store
in svm_supported bool; skip prefetch-fault-svm early with igt_skip() (Priyanka)
Reviewed-by: Nishit Sharma <nishit.sharma@intel.com>
Reviewed-by: Priyanka Dandamudi <priyanka.dandamudi@intel.com>
Signed-off-by: Varun Gupta <varun.gupta@intel.com>
---
tests/intel/xe_prefetch_fault.c | 133 ++++++++++++++++++++++++++------
1 file changed, 108 insertions(+), 25 deletions(-)
diff --git a/tests/intel/xe_prefetch_fault.c b/tests/intel/xe_prefetch_fault.c
index 4a143374a..fcbf305b5 100644
--- a/tests/intel/xe_prefetch_fault.c
+++ b/tests/intel/xe_prefetch_fault.c
@@ -25,6 +25,10 @@
#define WALKER_Y_DIM 1
#define PAGE_SIZE 4096
#define COLOR_C4 0xC4C4C4C4
+#define USER_FENCE_VALUE 0xdeadbeefdeadbeefull
+#define PREFETCH_ADDR 0x1f000000
+#define BB_OFFSET 0x1b000000
+#define BB_OFFSET_SVM 0x2b000000
struct dim_t {
uint32_t x;
@@ -118,7 +122,7 @@ static struct gpgpu_shader *get_prefetch_shader(int fd)
static struct gpgpu_shader *shader;
shader = gpgpu_shader_create(fd);
- gpgpu_shader__prefetch_fault(shader, xe_canonical_va(fd, 0x1f000000));
+ gpgpu_shader__prefetch_fault(shader, xe_canonical_va(fd, PREFETCH_ADDR));
gpgpu_shader__eot(shader);
return shader;
@@ -126,73 +130,139 @@ static struct gpgpu_shader *get_prefetch_shader(int fd)
/**
* SUBTEST: prefetch-fault
- * Description: Validate L1/L2 cache prefetch fault.
+ * Description: Validate prefetch fault and hit-under-miss behavior
+ * Run type: FULL
+ *
+ * SUBTEST: prefetch-fault-svm
+ * Description: Validate prefetch fault and hit-under-miss behavior in SVM mode
* Run type: FULL
*/
-
-static void test_prefetch(int fd, struct drm_xe_engine_class_instance *hwe)
+static void test_prefetch_fault(int fd, struct drm_xe_engine_class_instance *hwe, bool svm)
{
- /* faulty address 0x1f000000 should be beyond bb_offset+bb_size. */
- const uint64_t bb_offset = 0x1b000000;
+ uint64_t bb_offset = BB_OFFSET;
+ /*
+ * For the hit-under-miss run, place the batch at PREFETCH_ADDR in
+ * non-SVM mode so the BO bind maps that page before the shader runs.
+ * In SVM mode PREFETCH_ADDR is reserved for the mmap, so use a
+ * separate offset that doesn't collide with it.
+ */
+ uint64_t bb_offset2 = svm ? BB_OFFSET_SVM : PREFETCH_ADDR;
const size_t bb_size = 4096;
- struct dim_t w_dim;
+ static const char *stat = "invalid_prefetch_pagefault_count";
+ struct dim_t w_dim = { .x = WALKER_X_DIM, .y = WALKER_Y_DIM };
struct gpgpu_shader *shader;
struct intel_bb *ibb;
struct intel_buf *buf;
- uint32_t *ptr;
uint32_t exec_queue_id, vm;
- int prefetch_pre, prefetch_pos;
- static const char *stat = "prefetch_pagefault_count";
-
- w_dim.x = WALKER_X_DIM;
- w_dim.y = WALKER_Y_DIM;
+ void *cpu_data = NULL;
+ int prefetch_pre, prefetch_post;
+ uint32_t *ptr;
buf = create_buf(fd, w_dim.x, w_dim.y, COLOR_C4);
- prefetch_pre = xe_gt_stats_get_count(fd, hwe->gt_id, stat);
-
vm = xe_vm_create(fd, DRM_XE_VM_CREATE_FLAG_LR_MODE |
DRM_XE_VM_CREATE_FLAG_FAULT_MODE, 0);
+ if (svm) {
+ /*
+ * Enable SVM: mirror the full VA space so GPU page faults are
+ * resolved via HMM against the CPU page tables.
+ */
+ struct xe_device *xe = xe_device_get(fd);
+ uint64_t vm_sync = 0;
+ struct drm_xe_sync sync[1] = {
+ { .type = DRM_XE_SYNC_TYPE_USER_FENCE, .flags = DRM_XE_SYNC_FLAG_SIGNAL,
+ .timeline_value = USER_FENCE_VALUE },
+ };
+
+ sync[0].addr = to_user_pointer(&vm_sync);
+ __xe_vm_bind_assert(fd, vm, 0, 0, 0, 0, 0x1ull << xe->va_bits,
+ DRM_XE_VM_BIND_OP_MAP,
+ DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR,
+ sync, 1, 0, 0);
+ xe_wait_ufence(fd, &vm_sync, USER_FENCE_VALUE, 0, NSEC_PER_SEC);
+ }
+
exec_queue_id = xe_exec_queue_create(fd, vm, hwe, 0);
- ibb = xe_bb_create_on_offset(fd, exec_queue_id, vm,
- bb_offset, bb_size);
+ prefetch_pre = xe_gt_stats_get_count(fd, hwe->gt_id, stat);
+
+ /* First run: PREFETCH_ADDR is unmapped, so each shader lane raises a prefetch fault. */
+ ibb = xe_bb_create_on_offset(fd, exec_queue_id, vm, bb_offset, bb_size);
intel_bb_set_lr_mode(ibb, true);
shader = get_prefetch_shader(fd);
-
gpgpu_shader_exec(ibb, buf, w_dim.x, w_dim.y, shader, NULL, 0, 0);
-
gpgpu_shader_destroy(shader);
+ intel_bb_sync(ibb);
+ intel_bb_destroy(ibb);
+ prefetch_post = xe_gt_stats_get_count(fd, hwe->gt_id, stat);
+ igt_assert_eq(prefetch_post, prefetch_pre + w_dim.x * w_dim.y);
+
+ /*
+ * Hit-under-miss: ensure the page at PREFETCH_ADDR is already mapped
+ * before the prefetch shader runs again. The fault is resolved
+ * successfully so the prefetch counter must not change.
+ *
+ * SVM: mmap at PREFETCH_ADDR creates a CPU page table entry.
+ * The kernel resolves the GPU pagefault via HMM.
+ * Non-SVM: placing the batch buffer at PREFETCH_ADDR causes the
+ * BO fault path to map the page.
+ */
+ if (svm) {
+ cpu_data = mmap((void *)PREFETCH_ADDR, PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ -1, 0);
+ igt_assert(cpu_data == (void *)PREFETCH_ADDR);
+ /* Touch the page to populate the CPU PTE so HMM can resolve the GPU fault. */
+ memset(cpu_data, 0xAB, PAGE_SIZE);
+ prefetch_pre = xe_gt_stats_get_count(fd, hwe->gt_id, stat);
+ } else {
+ prefetch_pre = prefetch_post;
+ }
+ ibb = xe_bb_create_on_offset(fd, exec_queue_id, vm, bb_offset2, bb_size);
+ intel_bb_set_lr_mode(ibb, true);
+
+ shader = get_prefetch_shader(fd);
+ gpgpu_shader_exec(ibb, buf, w_dim.x, w_dim.y, shader, NULL, 0, 0);
+ gpgpu_shader_destroy(shader);
intel_bb_sync(ibb);
- ptr = xe_bo_mmap_ext(fd, buf->handle, buf->size, PROT_READ);
+ prefetch_post = xe_gt_stats_get_count(fd, hwe->gt_id, stat);
+ igt_assert_eq(prefetch_post, prefetch_pre);
+ /* Verify buffer contents */
+ ptr = xe_bo_mmap_ext(fd, buf->handle, buf->size, PROT_READ);
for (int j = 0; j < w_dim.y; j++)
for (int i = 0; i < w_dim.x; i++) {
igt_assert_f(ptr[j * w_dim.x + i] == COLOR_C4,
"Expected 0x%02x, found 0x%02x at (%d,%d)\n",
COLOR_C4, ptr[j * w_dim.x + i], i, j);
}
- /* Validate prefetch count. */
- prefetch_pos = xe_gt_stats_get_count(fd, hwe->gt_id, stat);
- igt_assert_eq(prefetch_pos, prefetch_pre + w_dim.x * w_dim.y);
-
munmap(ptr, buf->size);
+ /* Cleanup */
+ if (svm && cpu_data)
+ munmap(cpu_data, PAGE_SIZE);
+
intel_bb_destroy(ibb);
+ intel_buf_destroy(buf);
+ xe_exec_queue_destroy(fd, exec_queue_id);
+ xe_vm_destroy(fd, vm);
}
int igt_main()
{
struct drm_xe_engine_class_instance *hwe;
+ bool svm_supported;
int fd;
igt_fixture() {
fd = drm_open_driver(DRIVER_XE);
igt_require(intel_graphics_ver(intel_get_drm_devid(fd)) >= IP_VER(35, 0));
+ svm_supported = !xe_supports_faults(fd);
}
igt_subtest_with_dynamic("prefetch-fault") {
@@ -201,7 +271,20 @@ int igt_main()
hwe->engine_class == DRM_XE_ENGINE_CLASS_COMPUTE) {
igt_dynamic_f("%s%d", xe_engine_class_string(hwe->engine_class),
hwe->engine_instance)
- test_prefetch(fd, hwe);
+ test_prefetch_fault(fd, hwe, false);
+ }
+ }
+ }
+
+ igt_subtest_with_dynamic("prefetch-fault-svm") {
+ if (!svm_supported)
+ igt_skip("SVM not supported on this device, skipping.\n");
+ xe_for_each_engine(fd, hwe) {
+ if (hwe->engine_class == DRM_XE_ENGINE_CLASS_RENDER ||
+ hwe->engine_class == DRM_XE_ENGINE_CLASS_COMPUTE) {
+ igt_dynamic_f("%s%d", xe_engine_class_string(hwe->engine_class),
+ hwe->engine_instance)
+ test_prefetch_fault(fd, hwe, true);
}
}
}
--
2.43.0
next reply other threads:[~2026-03-23 9:25 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-23 9:25 Varun Gupta [this message]
2026-03-23 15:18 ` ✓ Xe.CI.BAT: success for tests/intel/xe_prefetch_fault: Add SVM and hit-under-miss validation (rev5) Patchwork
2026-03-23 16:13 ` ✓ i915.CI.BAT: " Patchwork
2026-03-23 21:16 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-03-23 23:41 ` ✓ i915.CI.Full: success " Patchwork
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=20260323092521.2984407-1-varun.gupta@intel.com \
--to=varun.gupta@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=nishit.sharma@intel.com \
--cc=priyanka.dandamudi@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