Skip to content

Instantly share code, notes, and snippets.

@chadbrewbaker
Created July 30, 2025 15:58
Show Gist options
  • Save chadbrewbaker/1872da5d8cc67ea020131892699ed41c to your computer and use it in GitHub Desktop.
Save chadbrewbaker/1872da5d8cc67ea020131892699ed41c to your computer and use it in GitHub Desktop.
Grok4 spike on egpu address mapping
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <stdint.h>
#include <mach/mach_port.h>
typedef struct {
uint32_t spaceType;
uint32_t bitWidth;
uint64_t options;
union {
uint64_t addr64;
} address;
uint64_t value;
} IOPCIDiagnosticsParameters;
enum {
kIOPCIConfigSpace = 0,
kIOPCI32BitMemorySpace = 1,
kIOPCI64BitMemorySpace = 2,
kIOPCIIOSpace = 3
};
enum {
kIOPCIDiagnosticsMethodRead = 0,
kIOPCIDiagnosticsMethodWrite = 1
};
kern_return_t write_config(io_connect_t conn, uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint32_t width, uint64_t value) {
IOPCIDiagnosticsParameters param = {0};
param.spaceType = kIOPCIConfigSpace;
param.bitWidth = width;
param.options = 0;
param.address.addr64 = ((uint64_t)bus << 24) | ((uint64_t)dev << 16) | ((uint64_t)fn << 8) | offset;
param.value = value;
size_t paramSize = sizeof(param);
return IOConnectCallStructMethod(conn, kIOPCIDiagnosticsMethodWrite, &param, sizeof(param), &param, &paramSize);
}
kern_return_t read_config(io_connect_t conn, uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint32_t width, uint64_t *value) {
IOPCIDiagnosticsParameters param = {0};
param.spaceType = kIOPCIConfigSpace;
param.bitWidth = width;
param.options = 0;
param.address.addr64 = ((uint64_t)bus << 24) | ((uint64_t)dev << 16) | ((uint64_t)fn << 8) | offset;
param.value = 0;
size_t paramSize = sizeof(param);
kern_return_t kr = IOConnectCallStructMethod(conn, kIOPCIDiagnosticsMethodRead, &param, sizeof(param), &param, &paramSize);
if (kr == kIOReturnSuccess) {
*value = param.value;
}
return kr;
}
int main() {
kern_return_t kr;
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOHIDevice"));
if (!service) {
printf("Failed to find IOHIDevice\n");
return 1;
}
kr = IORegistryEntrySetCFProperty(service, CFSTR("IOUserClientClass"), CFSTR("IOPCIDiagnosticsClient"));
if (kr != kIOReturnSuccess) {
printf("Failed to set IOUserClientClass: 0x%x\n", kr);
IOObjectRelease(service);
return 1;
}
io_connect_t conn;
kr = IOServiceOpen(service, mach_task_self(), 0, &conn);
IOObjectRelease(service);
if (kr != kIOReturnSuccess) {
printf("Failed to open service: 0x%x\n", kr);
return 1;
}
// Assume Thunderbolt bridge PCI address: bus 0, device 7, function 0 (replace with actual from ioreg -l)
uint8_t bus = 0;
uint8_t dev = 7;
uint8_t fn = 0;
// Example: Enable memory decoding on the bridge
uint64_t command;
kr = read_config(conn, bus, dev, fn, 0x04, 32, &command);
if (kr == kIOReturnSuccess) {
command |= 0x6; // Enable memory and bus master
kr = write_config(conn, bus, dev, fn, 0x04, 32, command);
if (kr != kIOReturnSuccess) {
printf("Failed to write command register: 0x%x\n", kr);
} else {
printf("Enabled memory on bridge\n");
}
} else {
printf("Failed to read command register: 0x%x\n", kr);
}
// Set large prefetch memory window (example values; adjust based on needs and available address space)
// Prefetch base upper 32 bits: 0x00000001 (for base 0x100000000)
kr = write_config(conn, bus, dev, fn, 0x28, 32, 0x00000001);
// Prefetch limit upper 32 bits: 0x00000003 (for limit 0x3ffffffff)
kr = write_config(conn, bus, dev, fn, 0x2C, 32, 0x00000003);
// Prefetch base/ limit lower: base 0x0000, limit 0xFFF0, with 64bit indicator
kr = write_config(conn, bus, dev, fn, 0x24, 32, 0xFFF00001); // base low 0x0001 (64bit), limit low 0xFFF0
if (kr == kIOReturnSuccess) {
printf("Set large prefetch memory window on Thunderbolt bridge\n");
} else {
printf("Failed to set memory window: 0x%x\n", kr);
}
IOServiceClose(conn);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment