/* Copyright 2024 Joshua Bakita * Implementation of Kernel-specific function implementations */ #include "nvdebug_linux.h" #include // For read[l,q] and write[l,q] // Similar to nvgpu_readl() // (except we don't try to resolve situations where regs is NULL) u32 nvdebug_readl(struct nvdebug_state *s, u32 r) { u32 ret; if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { printk(KERN_ERR "[nvdebug] nvdebug_readl: Unable to read; registers unavailable. Is GPU on?\n"); return -1; } ret = readl(s->regs + r); // It seems like the GPU returns this as a flag value for bad addresses if (ret == 0xbadf5040) { printk(KERN_ERR "[nvdebug] nvdebug_readl: Unable to read from register offset %#x; bad data\n", r); return -1; } return ret; } // quadword version of nvdebug_readl() u64 nvdebug_readq(struct nvdebug_state *s, u32 r) { u64 ret; if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { printk(KERN_ERR "[nvdebug] nvdebug_readq: Unable to read; registers unavailable. Is GPU on?\n"); return -1; } // readq seems to always return the uppermost 32 bits as 0, so workaround with readl ret = readl(s->regs + r); ret |= ((u64)readl(s->regs + r + 4)) << 32; // It seems like the GPU returns this as a flag value for bad addresses if ((ret & 0xffffffffull) == 0xbadf5040ull) { printk(KERN_ERR "[nvdebug] nvdebug_readq: Unable to read from register offset %#x; bad data\n", r); return -1; } return ret; } // Similar to nvgpu_writel() void nvdebug_writel(struct nvdebug_state *s, u32 r, u32 v) { if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { printk(KERN_ERR "[nvdebug] nvdebug_writel: Unable to write; registers unavailable. Is GPU on?\n"); return; } writel_relaxed(v, s->regs + r); wmb(); } // quadword version of nvdebug_writel() // XXX: This probably doesn't work XXX: Untested void nvdebug_writeq(struct nvdebug_state *s, u32 r, u64 v) { if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) { printk(KERN_ERR "[nvdebug] nvdebug_writeq: Unable to write; registers unavailable. Is GPU on?\n"); return; } writeq_relaxed(v, s->regs + r); wmb(); }