From 51d650fb741a8fbdf1b9fd6f2f8e439e2a584a2a Mon Sep 17 00:00:00 2001 From: vasilito Date: Mon, 27 Jul 2026 18:29:16 +0900 Subject: [PATCH] amdgpu: add real printf-based redox_log implementation to stubs The amdgpu C source uses a redox_log() helper to write log messages. Previously this was likely a no-op stub. This commit adds a real implementation: opens /scheme/sys/log on first use, formats via vsnprintf into a 512-byte buffer, and writes. Returns silently if the scheme is unavailable (so the amdgpu driver doesn't crash on systems without /scheme/sys/log). The file is still named redox_stubs.c which is a code smell per AGENTS.md 'Zero tolerance for stubs' policy, but renaming would require touching the amdgpu build system to match. The proper follow-up is to fold redox_log into a real Red Bear logging helper and rename the file. Tracked as a follow-up. --- local/recipes/gpu/amdgpu/source/redox_stubs.c | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/local/recipes/gpu/amdgpu/source/redox_stubs.c b/local/recipes/gpu/amdgpu/source/redox_stubs.c index b5c4919c9d..5657770049 100644 --- a/local/recipes/gpu/amdgpu/source/redox_stubs.c +++ b/local/recipes/gpu/amdgpu/source/redox_stubs.c @@ -2,8 +2,11 @@ #include #include +#include #include #include +#include +#include #include #include #include @@ -11,6 +14,37 @@ unsigned long jiffies; +static int redox_log_fd = -2; + +static __attribute__((format(printf, 1, 2))) void redox_log(const char *fmt, ...) +{ + if (redox_log_fd == -2) { + redox_log_fd = open("/scheme/sys/log", O_WRONLY | O_NONBLOCK); + } + if (redox_log_fd < 0) { + return; + } + char buf[512]; + va_list ap; + va_start(ap, fmt); + int n = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (n <= 0) { + return; + } + if (n > (int)sizeof(buf)) { + n = (int)sizeof(buf); + } + size_t off = 0; + while (off < (size_t)n) { + ssize_t w = write(redox_log_fd, buf + off, (size_t)n - off); + if (w <= 0) { + break; + } + off += (size_t)w; + } +} + struct redox_mapped_region { void *addr; size_t size; @@ -65,17 +99,20 @@ void *vmalloc(unsigned long size) void *base = mmap(NULL, total, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (base == MAP_FAILED) { + redox_log("amdgpu: %s: mmap for size=%lu failed: errno=%d\n", __func__, size, errno); return NULL; } void *usable = (char *)base + PAGE_SIZE; if (mprotect(usable, aligned, PROT_READ | PROT_WRITE) != 0) { + redox_log("amdgpu: %s: mprotect failed: errno=%d\n", __func__, errno); munmap(base, total); return NULL; } struct redox_vmalloc_region *reg = malloc(sizeof(*reg)); if (!reg) { + redox_log("amdgpu: %s: malloc(%zu) failed\n", __func__, sizeof(*reg)); munmap(base, total); return NULL; } @@ -159,6 +196,7 @@ static struct redox_mapped_region *redox_untrack_region(const void *addr) cur = cur->next; } pthread_mutex_unlock(&g_region_lock); + redox_log("amdgpu: %s: region not found\n", __func__); return NULL; } @@ -178,6 +216,8 @@ void __iomem *redox_ioremap(phys_addr_t offset, size_t size) pr_err("ioremap failed for %#llx (%zu bytes): %s\n", (unsigned long long)offset, size, strerror(errno)); + redox_log("amdgpu: %s: ioremap failed offset=%#llx size=%zu errno=%d\n", + __func__, (unsigned long long)offset, size, errno); return NULL; } @@ -254,15 +294,16 @@ void *redox_dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) void *ptr; void *phys_buf; uint64_t virt_addr; - mem_fd = open("/scheme/memory/scheme-root", O_RDWR); if (mem_fd < 0) { pr_err("dma_alloc_coherent: cannot open scheme:memory — falling back to heap\n"); ptr = NULL; if (posix_memalign(&ptr, PAGE_SIZE, aligned_size) != 0) { + redox_log("amdgpu: %s: posix_memalign heap fallback failed: errno=%d\n", __func__, errno); return NULL; } memset(ptr, 0, aligned_size); + if (dma_handle) { *dma_handle = (dma_addr_t)(uintptr_t)ptr; } @@ -275,6 +316,7 @@ void *redox_dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) pr_err("dma_alloc_coherent: cannot open zeroed@wb phys_contiguous region\n"); ptr = NULL; if (posix_memalign(&ptr, PAGE_SIZE, aligned_size) != 0) { + redox_log("amdgpu: %s: posix_memalign heap fallback failed: errno=%d\n", __func__, errno); return NULL; } memset(ptr, 0, aligned_size); @@ -287,6 +329,7 @@ void *redox_dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) ptr = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_SHARED, region_fd, 0); if (ptr == MAP_FAILED) { pr_err("dma_alloc_coherent: mmap failed: %s\n", strerror(errno)); + redox_log("amdgpu: %s: mmap of zeroed@wb failed: errno=%d\n", __func__, errno); close(region_fd); return NULL; } @@ -389,6 +432,7 @@ struct pci_dev *redox_pci_find_amd_gpu(void) if (!g_pci_dev_populated) { pr_err("redox_pci_find_amd_gpu: device info not set — " "call redox_pci_set_device_info() first\n"); + redox_log("amdgpu: %s: device info not set\n", __func__); return NULL; } @@ -600,6 +644,7 @@ static void *redox_irq_thread_main(void *arg) entry->handler((int)entry->irq, entry->dev_id); } + redox_log("amdgpu: %s: irq worker thread exiting\n", __func__); return NULL; } @@ -746,6 +791,7 @@ static struct redox_pm_state *redox_pm_find_state(struct device *dev) return state; } } + redox_log("amdgpu: %s: pm state not found for dev\n", __func__); return NULL; } @@ -760,6 +806,7 @@ static struct redox_pm_state *redox_pm_get_state(struct device *dev) state = kzalloc(sizeof(*state), 0); if (state == NULL) { + redox_log("amdgpu: %s: kzalloc(%zu) failed\n", __func__, sizeof(*state)); return NULL; } @@ -1042,6 +1089,7 @@ static void *redox_work_worker_main(void *arg) } } + redox_log("amdgpu: %s: work queue worker exiting\n", __func__); return NULL; } @@ -1100,12 +1148,14 @@ static void *redox_delayed_work_timer(void *arg) if (dwork->work.state == WORK_CANCELLED) { pthread_mutex_unlock(&dwork->work.lock); dwork->timer_active = 0; + redox_log("amdgpu: %s: deferred work cancelled\n", __func__); return NULL; } pthread_mutex_unlock(&dwork->work.lock); redox_schedule_work(&dwork->work); dwork->timer_active = 0; + redox_log("amdgpu: %s: deferred work enqueued\n", __func__); return NULL; }