Skip to content

Instantly share code, notes, and snippets.

@birep
Created September 30, 2026 21:48
Show Gist options
  • Select an option

  • Save birep/6f2c8d490c7a29820997d57bd654c351 to your computer and use it in GitHub Desktop.

Select an option

Save birep/6f2c8d490c7a29820997d57bd654c351 to your computer and use it in GitHub Desktop.
Fix for gfx1151 (Strix Halo) ROCm "out of memory" abort on hipStreamCreate
/*
* 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