From a1598f27a124cb0b5263276f7098ae3a68460b61 Mon Sep 17 00:00:00 2001 From: Joshua Bakita Date: Tue, 18 Jul 2023 10:49:19 -0400 Subject: Fail reads which return the flag value for a non-existent register Also check for read success in get_runlist_iter(). --- nvdebug.h | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'nvdebug.h') diff --git a/nvdebug.h b/nvdebug.h index 8009b84..8db07ee 100644 --- a/nvdebug.h +++ b/nvdebug.h @@ -960,30 +960,42 @@ static inline int file2parentgpuidx(const struct file *f) { // Similar to nvgpu_readl() // (except we don't try to resolve situations where regs is NULL) static inline 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] Attempted nvgpu_readl on non-existent registers!\n"); + printk(KERN_ERR "[nvdebug] nvdebug_readl: Unable to read; registers unavailable. Is GPU on?\n"); return -1; } - return readl(s->regs + r); + 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() static inline 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] Attempted nvgpu_readl on non-existent registers!\n"); + 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() static inline 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] Attempted nvgpu_writel on non-existent registers!\n"); + printk(KERN_ERR "[nvdebug] nvdebug_writel: Unable to write; registers unavailable. Is GPU on?\n"); return; } writel_relaxed(v, s->regs + r); @@ -994,9 +1006,9 @@ static inline void nvdebug_writel(struct nvdebug_state *s, u32 r, u32 v) { // XXX: This probably doesn't work XXX: Untested static inline 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] Attempted nvgpu_writel on non-existent registers!\n"); - return; - } - writeq_relaxed(v, s->regs + r); - wmb(); + printk(KERN_ERR "[nvdebug] nvdebug_writeq: Unable to write; registers unavailable. Is GPU on?\n"); + return; + } + writeq_relaxed(v, s->regs + r); + wmb(); } -- cgit v1.2.2