aboutsummaryrefslogtreecommitdiffstats
path: root/nvdebug_linux.c
diff options
context:
space:
mode:
authorJoshua Bakita <jbakita@cs.unc.edu>2024-04-11 13:42:54 -0400
committerJoshua Bakita <jbakita@cs.unc.edu>2024-04-11 13:42:54 -0400
commit7cfa24cebeaf144b446d07e15fb25e78bb14841e (patch)
tree639db3695c54a1e50b3f10e1abb2bfaf5b8dd906 /nvdebug_linux.c
parenta8fd5a8dee066d0008e7667b0c9e6a60cd5f3a2e (diff)
Linux 5.17+ support and allow including nvdebug.h independently
- Move Linux-specific functions to nvdebug_linux.h and .c - Workaround PDE_DATA() being pde_data() on Linux 5.17+
Diffstat (limited to 'nvdebug_linux.c')
-rw-r--r--nvdebug_linux.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/nvdebug_linux.c b/nvdebug_linux.c
new file mode 100644
index 0000000..1d76bc9
--- /dev/null
+++ b/nvdebug_linux.c
@@ -0,0 +1,61 @@
1/* Copyright 2024 Joshua Bakita
2 * Implementation of Kernel-specific function implementations
3 */
4#include "nvdebug_linux.h"
5#include <asm/io.h> // For read[l,q] and write[l,q]
6
7// Similar to nvgpu_readl()
8// (except we don't try to resolve situations where regs is NULL)
9u32 nvdebug_readl(struct nvdebug_state *s, u32 r) {
10 u32 ret;
11 if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) {
12 printk(KERN_ERR "[nvdebug] nvdebug_readl: Unable to read; registers unavailable. Is GPU on?\n");
13 return -1;
14 }
15 ret = readl(s->regs + r);
16 // It seems like the GPU returns this as a flag value for bad addresses
17 if (ret == 0xbadf5040) {
18 printk(KERN_ERR "[nvdebug] nvdebug_readl: Unable to read from register offset %#x; bad data\n", r);
19 return -1;
20 }
21 return ret;
22}
23
24// quadword version of nvdebug_readl()
25u64 nvdebug_readq(struct nvdebug_state *s, u32 r) {
26 u64 ret;
27 if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) {
28 printk(KERN_ERR "[nvdebug] nvdebug_readq: Unable to read; registers unavailable. Is GPU on?\n");
29 return -1;
30 }
31 // readq seems to always return the uppermost 32 bits as 0, so workaround with readl
32 ret = readl(s->regs + r);
33 ret |= ((u64)readl(s->regs + r + 4)) << 32;
34 // It seems like the GPU returns this as a flag value for bad addresses
35 if ((ret & 0xffffffffull) == 0xbadf5040ull) {
36 printk(KERN_ERR "[nvdebug] nvdebug_readq: Unable to read from register offset %#x; bad data\n", r);
37 return -1;
38 }
39 return ret;
40}
41
42// Similar to nvgpu_writel()
43void nvdebug_writel(struct nvdebug_state *s, u32 r, u32 v) {
44 if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) {
45 printk(KERN_ERR "[nvdebug] nvdebug_writel: Unable to write; registers unavailable. Is GPU on?\n");
46 return;
47 }
48 writel_relaxed(v, s->regs + r);
49 wmb();
50}
51
52// quadword version of nvdebug_writel()
53// XXX: This probably doesn't work XXX: Untested
54void nvdebug_writeq(struct nvdebug_state *s, u32 r, u64 v) {
55 if (unlikely(!s->regs || (s->g && !gk20a_regs(s->g)))) {
56 printk(KERN_ERR "[nvdebug] nvdebug_writeq: Unable to write; registers unavailable. Is GPU on?\n");
57 return;
58 }
59 writeq_relaxed(v, s->regs + r);
60 wmb();
61}