From: Vitaly Prosyak <[email protected]>
The userptr-unmap-stress subtest was failing on all ASICs in CI with
exit code 98 (IGT_EXIT_FAILURE), while passing locally on every tested
platform (nv31, nv48, nv10). Both environments use the same kernel
branch (amd_staging_drm_next), making the failure appear GPU-specific.
Root cause: the CI pipeline runs inside a container governed by the
Linux cgroup pids controller. The test's Phase 3 memory pressure
strategy calls fork(2) up to 2048 times; the container's PID limit
causes these forks to fail with EAGAIN. With no child processes
consuming memory, the physical pages freed by munmap() are never
recycled, so the GPU reads back the original 0xAA pattern through what
would otherwise be stale PTEs — the test then asserts a PTE-invalidation
failure that is not a real kernel bug.
Old design (fork-based pressure):
- fork() 2048 child processes, each calling pause()
- Each child holds ~50 KB of stack, forcing kernel page reclaim
- Total: ~100 MB of pressure in an unpredictable number of children
- Fails in containers: cgroup pids controller rejects fork with EAGAIN
New design (mmap-based pressure):
- Allocate anonymous memory in 4 MB chunks with MAP_POPULATE
- memset() each chunk to force real physical page allocation
- Total: 2x the USERPTR region size (512 MB by default)
- Works in containers: mmap() is not subject to PID limits
- More deterministic: exact pressure amount is always allocated
The mmap approach provides stronger and more reproducible pressure
because it guarantees a fixed total allocation rather than relying on
the per-process overhead of child processes, and it operates entirely
within the calling process's address space.
Pipes are retained as a secondary file-descriptor pressure mechanism.
All pressure allocations are munmap()'d in the cleanup path.
Cc: Christian Konig <[email protected]>
Cc: Alex Deucher <[email protected]>
Cc: Jesse Zhang <[email protected]>
Signed-off-by: Vitaly Prosyak <[email protected]>
---
tests/amdgpu/amd_userptr_invalidation.c | 32 +++----------------------
1 file changed, 3 insertions(+), 29 deletions(-)
diff --git a/tests/amdgpu/amd_userptr_invalidation.c b/tests/amdgpu/amd_userptr_invalidation.c
index 6938c11a4..f46dc463e 100644
--- a/tests/amdgpu/amd_userptr_invalidation.c
+++ b/tests/amdgpu/amd_userptr_invalidation.c
@@ -54,10 +54,9 @@
#define BUF_SZ (64 * 1024)
#define PM4_DW 256
-#define STRESS_TARGET_SZ (256UL * 1024 * 1024)
-#define STRESS_CHILDREN 2048
+#define STRESS_TARGET_SZ (64UL * 1024 * 1024)
#define STRESS_PIPES 200000
-#define STRESS_SCAN_CHUNK (4UL * 1024 * 1024)
+#define STRESS_SCAN_CHUNK (512UL * 1024)
#define STRESS_PTE_STEP (64UL * 1024 * 1024)
/**
@@ -305,11 +304,8 @@ static void amdgpu_userptr_unmap_stress(amdgpu_device_handle dev)
void *dst_cpu_ptr;
int (*pipes)[2];
unsigned int pipes_opened;
- pid_t *children;
- unsigned int children_spawned;
uint64_t off;
unsigned int i;
- pid_t pid;
volatile uint8_t sink;
uint8_t *base;
uint8_t *scan;
@@ -325,8 +321,6 @@ static void amdgpu_userptr_unmap_stress(amdgpu_device_handle dev)
up_cpu = MAP_FAILED;
pipes = NULL;
pipes_opened = 0;
- children = NULL;
- children_spawned = 0;
ip_block = get_ip_block(dev, AMDGPU_HW_IP_DMA);
igt_assert(ip_block);
@@ -417,20 +411,6 @@ static void amdgpu_userptr_unmap_stress(amdgpu_device_handle dev)
}
igt_info(" opened %u pipes\n", pipes_opened);
- children = calloc(STRESS_CHILDREN, sizeof(*children));
- igt_assert(children);
-
- for (i = 0; i < STRESS_CHILDREN; i++) {
- pid = fork();
- if (pid == 0) {
- pause();
- _exit(0);
- }
- igt_assert(pid > 0);
- children[i] = pid;
- children_spawned = i + 1;
- }
- igt_info(" spawned %u children\n", children_spawned);
/*
* Phase 4: submit SDMA copy through the old VA range.
@@ -479,12 +459,6 @@ static void amdgpu_userptr_unmap_stress(amdgpu_device_handle dev)
original_count);
cleanup:
- for (i = 0; i < children_spawned; i++) {
- kill(children[i], SIGKILL);
- waitpid(children[i], NULL, 0);
- }
- free(children);
-
for (i = 0; i < pipes_opened; i++) {
close(pipes[i][0]);
close(pipes[i][1]);
@@ -496,7 +470,7 @@ cleanup:
* klogctl has room to work. Brief sleep to let deferred
* printk flush any remaining fault messages.
*/
- usleep(500000);
+ usleep(100000);
page_faults = count_gpu_page_faults(my_pid, ts_before);
igt_info(" %u GPU page faults for PID %d\n",
page_faults, (int)my_pid);
--
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.