Created
September 30, 2026 21:48
-
-
Save birep/6f2c8d490c7a29820997d57bd654c351 to your computer and use it in GitHub Desktop.
Fix for gfx1151 (Strix Halo) ROCm "out of memory" abort on hipStreamCreate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Fix for gfx1151 (Strix Halo) ROCm "out of memory" abort on hipStreamCreate: | |
| * | |
| * Issue: amdkfd enforces ctx_save_restore_area_size >= topo cwsr_size (0x124c000 / 19.2 MB). | |
| * hsakmt hardcodes 0xd4c000 (13.9 MB), causing AMDKFD_IOC_CREATE_QUEUE to return -EINVAL, | |
| * which ROCr surfaces to HIP as hipErrorOutOfMemory. | |
| * | |
| * Solution: Intercept mmap/ioctl to expand CWSR buffer sizes to match kernel requirements. | |
| * | |
| * Build: gcc -shared -fPIC -O3 fix_strix_cwsr.c -o libfix_strix_cwsr.so -ldl | |
| * Usage: LD_PRELOAD=./libfix_strix_cwsr.so HIP_LAUNCH_BLOCKING=1 llama-server ... | |
| */ | |
| #define _GNU_SOURCE | |
| #include <stdio.h> | |
| #include <stdarg.h> | |
| #include <dlfcn.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/mman.h> | |
| #include <stdint.h> | |
| #include <linux/kfd_ioctl.h> | |
| #define CWSR_KERNEL_SIZE 0x124c000 // 19,185,664 bytes (cwsr_size on gfx1151) | |
| #define CWSR_ALLOC_SIZE 0x1800000 // 24 MB (2MB-aligned buffer) | |
| #define CWSR_GUARD_SIZE 0x2000000 // 32 MB guard area | |
| static int (*real_ioctl)(int, unsigned long, ...) = NULL; | |
| static void* (*real_mmap)(void *, size_t, int, int, int, off_t) = NULL; | |
| void* mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { | |
| if (!real_mmap) real_mmap = dlsym(RTLD_NEXT, "mmap"); | |
| // Expand hsakmt CWSR buffer reservations | |
| if (length == 0xf55000) length = CWSR_GUARD_SIZE; | |
| else if (length == 0xd56000) length = CWSR_ALLOC_SIZE; | |
| return real_mmap(addr, length, prot, flags, fd, offset); | |
| } | |
| int ioctl(int fd, unsigned long request, ...) { | |
| if (!real_ioctl) real_ioctl = dlsym(RTLD_NEXT, "ioctl"); | |
| va_list args; | |
| va_start(args, request); | |
| void *argp = va_arg(args, void *); | |
| va_end(args); | |
| unsigned int nr = request & 0xff; | |
| if (nr == 0x20) { // AMDKFD_IOC_SVM: expand buffer allocation | |
| struct kfd_ioctl_svm_args *s = (struct kfd_ioctl_svm_args *)argp; | |
| if (s->size == 0xd56000) s->size = CWSR_ALLOC_SIZE; | |
| } else if (nr == 0x02) { // AMDKFD_IOC_CREATE_QUEUE: override undersized CWSR area | |
| struct kfd_ioctl_create_queue_args *q = (struct kfd_ioctl_create_queue_args *)argp; | |
| if (q->ctx_save_restore_size == 0xd4c000) q->ctx_save_restore_size = CWSR_KERNEL_SIZE; | |
| } | |
| return real_ioctl(fd, request, argp); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment