diff options
| author | Joshua Bakita <jbakita@cs.unc.edu> | 2025-10-01 11:54:47 -0400 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2025-10-01 11:54:47 -0400 |
| commit | b4a937788cead345f8f00419bd250d1d92b0290f (patch) | |
| tree | 231d2d817c89550f744ba1e993700566c1612557 | |
| parent | 217aaa952fb812bfdce62402cfab959910ea7265 (diff) | |
Fix build warnings and errors on Linux 6.14ecrts25-ae
- Remove repetitive declarations of two `bus_type` structs.
- Fix mmu.c to use an always-64-bit member for `parent_addr`.
- Remove call to `page_mapcount_reset()` that isn't needed.
- Correct `nvdebug_pd_page` documentation.
- Disable missing prototype and missing declaration warnings.
- Fix an improper type, and a missing type conversion.
Tested build on Linux 6.14.0 (x86_64), 5.4.0 (x86_64), and
4.9.337 (aarch64).
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | mmu.c | 27 | ||||
| -rw-r--r-- | nvdebug.h | 2 | ||||
| -rw-r--r-- | nvdebug_entry.c | 2 | ||||
| -rw-r--r-- | stubs.h | 1 |
5 files changed, 16 insertions, 19 deletions
| @@ -1,7 +1,8 @@ | |||
| 1 | obj-m += nvdebug.o | 1 | obj-m += nvdebug.o |
| 2 | nvdebug-objs = runlist_procfs.o device_info_procfs.o runlist.o mmu.o \ | 2 | nvdebug-objs = runlist_procfs.o device_info_procfs.o runlist.o mmu.o \ |
| 3 | nvdebug_entry.o bus.o nvdebug_linux.o copy_topology_procfs.o | 3 | nvdebug_entry.o bus.o nvdebug_linux.o copy_topology_procfs.o |
| 4 | KBUILD_CFLAGS += -DGIT_HASH=\"$(shell git --git-dir=$(PWD)/.git rev-parse --short HEAD)\" | 4 | KBUILD_CFLAGS += -DGIT_HASH=\"$(shell git --git-dir=$(PWD)/.git rev-parse --short HEAD)\" \ |
| 5 | -Wno-missing-prototypes -Wno-missing-declarations | ||
| 5 | # -mfentry above if not building due to mcount missing | 6 | # -mfentry above if not building due to mcount missing |
| 6 | 7 | ||
| 7 | all: | 8 | all: |
| @@ -229,19 +229,20 @@ int translate_page_directory(struct nvdebug_state *g, | |||
| 229 | // explictly permitted (see linux/mm_types.h). This struct is thus used by | 229 | // explictly permitted (see linux/mm_types.h). This struct is thus used by |
| 230 | // casting a pointer of struct page to a pointer of struct nvdebug_pd_page, | 230 | // casting a pointer of struct page to a pointer of struct nvdebug_pd_page, |
| 231 | // then accessing the associated fields. This pointer may also be freely cast | 231 | // then accessing the associated fields. This pointer may also be freely cast |
| 232 | // back to a sturct page pointer. | 232 | // back to a struct page pointer. |
| 233 | // We have 24 (32-bit) or 44 (64-bit) bytes available in the page struct | 233 | // We have 20 (32-bit) or 40 (64-bit) bytes available in the page struct |
| 234 | // (according to the documentation on struct page). Our comments indicate what | 234 | // (according to the documentation on struct page). We use 20 (32-bit) or 28 |
| 235 | // available parts of struct page we repurpose for our own needs. | 235 | // (64-bit) bytes. Our comments indicate what available parts of struct page we |
| 236 | // repurpose for our own needs. | ||
| 236 | struct nvdebug_pd_page { | 237 | struct nvdebug_pd_page { |
| 237 | unsigned long __flags; // From struct page; do not touch! | 238 | unsigned long __flags; // From struct page; do not touch! |
| 238 | // Overlaps struct page.lru | 239 | // Overlaps struct page.lru |
| 239 | struct list_head list; // 4/8 bytes | 240 | struct list_head list; // 4/8 bytes |
| 240 | // Overlaps struct page.mapping (and page.share on 32-bit) | 241 | // Overlaps struct page.lru (and page.mapping on 32-bit) |
| 241 | uintptr_t parent_addr; // 8 bytes | 242 | uint64_t parent_addr; // 8 bytes |
| 242 | // Overlaps struct page.share (page.private on 32-bit) | 243 | // Overlaps struct page.mapping (page.share on 32-bit) |
| 243 | enum PD_TARGET parent_aperture; // 4 bytes | 244 | enum PD_TARGET parent_aperture; // 4 bytes |
| 244 | // Overlaps page.private (page.page_type on 32-bit) | 245 | // Overlaps page.mapping and page.share (page.private on 32-bit) |
| 245 | dma_addr_t dma_addr; // 4/8 bytes | 246 | dma_addr_t dma_addr; // 4/8 bytes |
| 246 | }; | 247 | }; |
| 247 | 248 | ||
| @@ -262,12 +263,12 @@ int gc_page_directory(struct nvdebug_state *g, bool force) { | |||
| 262 | // (This is depth-first because map_page_directory() always allocates and | 263 | // (This is depth-first because map_page_directory() always allocates and |
| 263 | // pushes page directory allocations before page table allocations.) | 264 | // pushes page directory allocations before page table allocations.) |
| 264 | list_for_each_entry_safe_reverse(page, _page, &g->pd_allocs, list) { | 265 | list_for_each_entry_safe_reverse(page, _page, &g->pd_allocs, list) { |
| 265 | printk_debug(KERN_DEBUG "[nvdebug] %s: Checking if page directory/table at %llx (SYS_MEM_?) with parent at %lx (%s) is unused...\n", __func__, page->dma_addr, page->parent_addr, pd_target_to_text(page->parent_aperture)); | 266 | printk_debug(KERN_DEBUG "[nvdebug] %s: Checking if page directory/table at %llx (SYS_MEM_?) with parent at %llx (%s) is unused...\n", __func__, page->dma_addr, page->parent_addr, pd_target_to_text(page->parent_aperture)); |
| 266 | // Try to determine if we're still in-use. We consider ourselves | 267 | // Try to determine if we're still in-use. We consider ourselves |
| 267 | // potentially in-use if our parent still points to us. | 268 | // potentially in-use if our parent still points to us. |
| 268 | parent_kva = pd_deref(g, page->parent_addr, page->parent_aperture); | 269 | parent_kva = pd_deref(g, page->parent_addr, page->parent_aperture); |
| 269 | if (IS_ERR(parent_kva)) { | 270 | if (IS_ERR(parent_kva)) { |
| 270 | printk(KERN_ERR "[nvdebug] %s: Error resolving %#lx in GPU %s to a kernel-accessible address. Error %ld.\n", __func__, page->parent_addr, pd_target_to_text(page->parent_aperture), PTR_ERR(parent_kva)); | 271 | printk(KERN_ERR "[nvdebug] %s: Error resolving %#llx in GPU %s to a kernel-accessible address. Error %ld.\n", __func__, page->parent_addr, pd_target_to_text(page->parent_aperture), PTR_ERR(parent_kva)); |
| 271 | return -ENOTRECOVERABLE; | 272 | return -ENOTRECOVERABLE; |
| 272 | } | 273 | } |
| 273 | // A NULL kva indicates parent no longer exists | 274 | // A NULL kva indicates parent no longer exists |
| @@ -277,14 +278,12 @@ int gc_page_directory(struct nvdebug_state *g, bool force) { | |||
| 277 | continue; | 278 | continue; |
| 278 | // Free this page table/directory and delete our parent's pointer to us | 279 | // Free this page table/directory and delete our parent's pointer to us |
| 279 | if (parent_entry.addr_w == (page->dma_addr >> 12)) { | 280 | if (parent_entry.addr_w == (page->dma_addr >> 12)) { |
| 280 | printk(KERN_WARNING "[nvdebug] %s: Deleting page table/directory at %llx (SYS_MEM_?) with parent at %lx (%s) that may still be in-use!\n", __func__, page->dma_addr, page->parent_addr, pd_target_to_text(page->parent_aperture)); | 281 | printk(KERN_WARNING "[nvdebug] %s: Deleting page table/directory at %llx (SYS_MEM_?) with parent at %llx (%s) that may still be in-use!\n", __func__, page->dma_addr, page->parent_addr, pd_target_to_text(page->parent_aperture)); |
| 281 | writeq(0, parent_kva); | 282 | writeq(0, parent_kva); |
| 282 | } | 283 | } |
| 283 | // Unmap, zero, free, and remove from tracking (these all return void) | 284 | // Unmap, zero, free, and remove from tracking (these all return void) |
| 284 | dma_unmap_page(g->dev, page->dma_addr, PAGE_SIZE, DMA_TO_DEVICE); | 285 | dma_unmap_page(g->dev, page->dma_addr, PAGE_SIZE, DMA_TO_DEVICE); |
| 285 | memset(page_to_virt((struct page*)page), 0, PAGE_SIZE); | 286 | memset(page_to_virt((struct page*)page), 0, PAGE_SIZE); |
| 286 | // Necessary to reset mapcount as we (ab)use its state for other things | ||
| 287 | page_mapcount_reset((struct page*)page); | ||
| 288 | // Same reset needed for mapping | 287 | // Same reset needed for mapping |
| 289 | ((struct page*)page)->mapping = NULL; | 288 | ((struct page*)page)->mapping = NULL; |
| 290 | // Remove this page from our list of allocated pages | 289 | // Remove this page from our list of allocated pages |
| @@ -607,7 +606,7 @@ int translate_v1_page_directory(struct nvdebug_state *g, | |||
| 607 | // Convert VID_MEM/SYS_MEM address to Kernel-accessible Virtual Address (KVA) | 606 | // Convert VID_MEM/SYS_MEM address to Kernel-accessible Virtual Address (KVA) |
| 608 | pte_kva = pd_deref(g, pte_phys, V12PD_TARGET(pde.alt_target)); | 607 | pte_kva = pd_deref(g, pte_phys, V12PD_TARGET(pde.alt_target)); |
| 609 | if (IS_ERR_OR_NULL(pde_kva)) { | 608 | if (IS_ERR_OR_NULL(pde_kva)) { |
| 610 | printk(KERN_ERR "[nvdebug] %s: Unable to resolve %#lx in GPU %s to a kernel-accessible address. Error %ld.\n", __func__, pte_phys, pd_target_to_text(pde.alt_target), PTR_ERR(pte_kva)); | 609 | printk(KERN_ERR "[nvdebug] %s: Unable to resolve %#lx in GPU %s to a kernel-accessible address. Error %ld.\n", __func__, pte_phys, pd_target_to_text(V12PD_TARGET(pde.alt_target)), PTR_ERR(pte_kva)); |
| 611 | return PTR_ERR(pte_kva); | 610 | return PTR_ERR(pte_kva); |
| 612 | } | 611 | } |
| 613 | // Read page table entry | 612 | // Read page table entry |
| @@ -1620,7 +1620,7 @@ static inline const char *compute_preempt_type_to_text(enum COMPUTE_PREEMPT_TYPE | |||
| 1620 | return "INVALID"; | 1620 | return "INVALID"; |
| 1621 | } | 1621 | } |
| 1622 | } | 1622 | } |
| 1623 | static inline const char *graphics_preempt_type_to_text(enum COMPUTE_PREEMPT_TYPE t) { | 1623 | static inline const char *graphics_preempt_type_to_text(enum GRAPHICS_PREEMPT_TYPE t) { |
| 1624 | switch (t) { | 1624 | switch (t) { |
| 1625 | case PREEMPT_WFI: | 1625 | case PREEMPT_WFI: |
| 1626 | return "WFI"; | 1626 | return "WFI"; |
diff --git a/nvdebug_entry.c b/nvdebug_entry.c index c0cfa63..8293fdc 100644 --- a/nvdebug_entry.c +++ b/nvdebug_entry.c | |||
| @@ -48,8 +48,6 @@ extern struct file_operations copy_topology_file_ops; | |||
| 48 | 48 | ||
| 49 | struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES]; | 49 | struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES]; |
| 50 | unsigned int g_nvdebug_devices = 0; | 50 | unsigned int g_nvdebug_devices = 0; |
| 51 | // Bus types are global symbols in the kernel | ||
| 52 | extern struct bus_type platform_bus_type; | ||
| 53 | 51 | ||
| 54 | // Starting in Kernel 5.6, proc_ops is required instead of file_operations. | 52 | // Starting in Kernel 5.6, proc_ops is required instead of file_operations. |
| 55 | // As file_operations is larger than proc_ops, we can overwrite the memory | 53 | // As file_operations is larger than proc_ops, we can overwrite the memory |
| @@ -29,7 +29,6 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) | |||
| 29 | // Functions from drivers/pci/search.h | 29 | // Functions from drivers/pci/search.h |
| 30 | #include <linux/device.h> | 30 | #include <linux/device.h> |
| 31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
| 32 | extern struct bus_type pci_bus_type; | ||
| 33 | 32 | ||
| 34 | #if LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0) | 33 | #if LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0) |
| 35 | static int match_pci_dev_by_id(struct device *dev, void *data) | 34 | static int match_pci_dev_by_id(struct device *dev, void *data) |
