aboutsummaryrefslogtreecommitdiffstats
path: root/runlist.c
diff options
context:
space:
mode:
authorJoshua Bakita <jbakita@cs.unc.edu>2021-08-26 18:53:29 -0400
committerJoshua Bakita <jbakita@cs.unc.edu>2021-08-26 18:53:29 -0400
commit54e783959b5d3622556bbf34a3a7ad8e481d9e25 (patch)
tree3221f3d93c6a12d2098ddd6ef95a39b2c2b69347 /runlist.c
parent5f661d8a5db3f7875f6bf36b4843a71fd08ecbea (diff)
Use procfs instead of dmesg to print runlist
`cat /proc/runlist` to print the current runlist. Also break nvdebug.c into nvdebug_entry.c, runlist.c, and runlist_procfs.c.
Diffstat (limited to 'runlist.c')
-rw-r--r--runlist.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/runlist.c b/runlist.c
new file mode 100644
index 0000000..8691b51
--- /dev/null
+++ b/runlist.c
@@ -0,0 +1,106 @@
1#include <linux/device.h> // For struct device, bus_find_device*()
2//#include <linux/iommu.h> // For struct iommu_domain
3#include <linux/kernel.h> // Kernel types
4#include <asm/io.h>
5
6#include "nvdebug.h"
7
8// Bus types are global symbols in the kernel
9extern struct bus_type platform_bus_type;
10
11int get_runlist_iter(struct runlist_iter *rl_iter) {
12 struct device *dev = NULL;
13 struct device *temp_dev;
14 struct gk20a *g;
15 struct entry_tsg head;
16 runlist_base_t rl_base;
17 runlist_info_t rl_info;
18 u64 runlist_iova;
19 // Get the last device that matches our name
20 while ((temp_dev = bus_find_device_by_name(&platform_bus_type, dev, "17000000.gv11b"))) {
21 dev = temp_dev;
22 printk(KERN_INFO "[nvdebug] Found a matching device %s\n", dev_name(dev));
23 }
24 if (!dev)
25 return -EIO;
26 g = get_gk20a(dev);
27 // This address seems to not be:
28 // - A GPU address (type is sysmem_coherent)
29 // - A physical address (dereferencing after ioremap crashes)
30 // - A kernel virtual address (dereferencing segfaults)
31 // So maybe it's some sort of custom thing? This is an address that the GPU
32 // can use, so it would make most sense for it to be a physical address.
33 //
34 // BUT, it can't possibly be a physical address, as it would refer to an
35 // address greater than the maximum one on our system (by a lot!).
36 // Maybe I'm reading the runlist base wrong?
37 // Aha, the driver calls it runlist_iova. Sounds like runlist I/O virtual
38 // address! So, what's this I/O address space? All I know is that it's what
39 // nvgpu_mem_get_addr() returns. That function returns the result of either:
40 // - gpu_phys_addr which is __nvgpu_sgl_phys on our platform which (?)
41 // converts an IPA to a PA?
42 // - nvgpu_mem_iommu_translate
43 //
44 // The original memory is allocated with nvgpu_dma_alloc_flags_sys(), which
45 // returns SYSMEM.
46 //
47 // To convert a physical address to a IOMMU address, we add a bit
48 //
49 // BUT, it turns out that it IS JUST A PHYSICAL ADDRESS! It wasn't working
50 // before because the GPU had simply gone to sleep and invalidated its
51 // register state, so nvgpu_readl() was simply returning garbage.
52
53 printk(KERN_INFO "[nvdebug] Pulling runlist base address from %x\n", NV_PFIFO_RUNLIST_BASE);
54 printk(KERN_INFO "[nvdebug] Using struct gk20a* of %px\n", g);
55 printk(KERN_INFO "[nvdebug] g->name: %s, g->power_on: %d, g->sw_ready: %d, g->is_virtual %d\n",
56 g->name, g->power_on, g->sw_ready, g->is_virtual);
57 struct nvgpu_os_linux *l = container_of(g, struct nvgpu_os_linux, g);
58 printk(KERN_INFO "[nvdebug] l->regs %px, l->regs_saved %px\n", l->regs, l->regs_saved);
59 if (!l->regs)
60 return -EIO;
61 rl_base.raw = nvdebug_readl(g, NV_PFIFO_RUNLIST_BASE);
62 rl_info.raw = nvdebug_readl(g, NV_PFIFO_RUNLIST);
63 runlist_iova = ((u64)rl_base.ptr) << 12;
64 printk(KERN_INFO "[nvdebug] Runlist ptr: %x, type: %d, raw: %x, IOVA: %px\n",
65 rl_base.ptr, rl_base.type, rl_base.raw, (void*)runlist_iova);
66 // Segfaults
67 //u32 attempted_read = ioread32(runlist_iova);
68 //printk(KERN_INFO "[nvdebug] first word of runlist: %0x\n", attempted_read);
69
70 // Errors out
71 //u32* virt_rt_addr = ioremap(phys_rl_addr, sizeof(struct entry_tsg));
72 //printk(KERN_INFO "[nvdebug] Runlist virt_addr: %px\n", virt_rt_addr);
73
74 /* Overcomplicated?
75 struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
76 if (!domain) {
77 printk(KERN_INFO "[nvdebug] No IOMMU domain!\n");
78 return -EIO;
79 }
80 u64 phys_addr = platform_bus_type.iommu_ops->iova_to_phys(domain, runlist_iova);
81 printk(KERN_INFO "[nvdebug] Runlist PA: %px\n", phys_addr);
82 */
83
84 printk(KERN_INFO "[nvdebug] Runlist phys_to_virt: %px\n", (void*)phys_to_virt(runlist_iova));
85 printk(KERN_INFO "[nvdebug] Runlist *phys_to_virt: %x\n", *(u32*)phys_to_virt(runlist_iova));
86 head = *(struct entry_tsg*)phys_to_virt(runlist_iova);
87
88 rl_iter->curr_tsg = (struct entry_tsg*)phys_to_virt(runlist_iova);
89 rl_iter->rl_info = rl_info;
90 return 0;
91 //printk(KERN_INFO "[nvdebug] entry_type: %d\n", head.entry_type);
92 //printk(KERN_INFO "[nvdebug] timeslice_scale: %d\n", head.timeslice_scale);
93 //printk(KERN_INFO "[nvdebug] timeslice_timeout: %d\n", head.timeslice_timeout);
94 //printk(KERN_INFO "[nvdebug] tsg_length: %d\n", head.tsg_length);
95 //printk(KERN_INFO "[nvdebug] tsgid: %d\n", head.tsgid);
96
97 //printk(KERN_INFO "[nvdebug] Mem base phys: %p\n", (void*)virt_to_phys((void*)0xffffffc000000000ULL));
98 //printk(KERN_INFO "[nvdebug] Mem end phys: %p\n", (void*)virt_to_phys((void*)0xffffffc400000000ULL));
99 //printk(KERN_INFO "[nvdebug] Runlist *virt_addr: %x\n", readl(virt_rt_addr)); // This crashes
100 //read_bytes(&head, virt_rt_addr, sizeof(struct entry_tsg));
101 /*printk(KERN_INFO "[nvdebug] entry_type: %d\n", head.entry_type);
102 printk(KERN_INFO "[nvdebug] timeslice_scale: %d\n", head.timeslice_scale);
103 printk(KERN_INFO "[nvdebug] timeslice_timeout: %d\n", head.timeslice_timeout);
104 printk(KERN_INFO "[nvdebug] tsg_length: %d\n", head.tsg_length);
105 printk(KERN_INFO "[nvdebug] tsgid: %d\n", head.tsgid); */
106}