diff options
author | Joshua Bakita <jbakita@cs.unc.edu> | 2024-04-11 13:42:54 -0400 |
---|---|---|
committer | Joshua Bakita <jbakita@cs.unc.edu> | 2024-04-11 13:42:54 -0400 |
commit | 7cfa24cebeaf144b446d07e15fb25e78bb14841e (patch) | |
tree | 639db3695c54a1e50b3f10e1abb2bfaf5b8dd906 /nvdebug_linux.c | |
parent | a8fd5a8dee066d0008e7667b0c9e6a60cd5f3a2e (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.c | 61 |
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) | ||
9 | u32 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() | ||
25 | u64 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() | ||
43 | void 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 | ||
54 | void 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 | } | ||