diff options
author | Joshua Bakita <jbakita@cs.unc.edu> | 2021-08-26 18:53:29 -0400 |
---|---|---|
committer | Joshua Bakita <jbakita@cs.unc.edu> | 2021-08-26 18:53:29 -0400 |
commit | 54e783959b5d3622556bbf34a3a7ad8e481d9e25 (patch) | |
tree | 3221f3d93c6a12d2098ddd6ef95a39b2c2b69347 /runlist.c | |
parent | 5f661d8a5db3f7875f6bf36b4843a71fd08ecbea (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.c | 106 |
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 | ||
9 | extern struct bus_type platform_bus_type; | ||
10 | |||
11 | int 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 | } | ||