diff options
| author | Joshua Bakita <bakitajoshua@gmail.com> | 2024-04-11 12:23:18 -0400 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2024-04-11 13:03:20 -0400 |
| commit | a8fd5a8dee066d0008e7667b0c9e6a60cd5f3a2e (patch) | |
| tree | f05095d4b6458a709034a182649e6d16b6a8558a /runlist.c | |
| parent | 5ea953292441e31e37ae074e48d8b3b5ce1d9440 (diff) | |
Support page directories outside PRAMIN or in SYS_MEM
- Re-read PRAMIN configuration after update to verify change applies
- Return a page_dir_config_t rather than just an address and page.
table version from `get_bar2_pdb()`.
- Less verbose logging for MMU-related functions by default.
- Perform all conversion from SYS_MEM/VID_MEM addresses to kernel
addresses inside the translation functions, via the new function
'pd_deref()`.
- Support use of an I/O MMU, page tables/directories outside the
current PRAMIN window, and page tables/directories arbitrarially
located in SYS_MEM or VID_MEM on different levels of the same tree.
- Heavily improve documentation and add references for Version 1 and
Version 0 page tables.
- Improve logging in `runlist.c` to include runlist and chip IDs.
- Update all users of search_page_directory* to use the new API.
- Remove now-unused supporting functions from `mmu.c`.
Tested on GTX 970, GTX 1060 3GB, Jetson TX2, Titan V, Jetson Xavier,
and RTX 2080 Ti.
Diffstat (limited to 'runlist.c')
| -rw-r--r-- | runlist.c | 33 |
1 files changed, 19 insertions, 14 deletions
| @@ -9,7 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | // Uncomment to, upon BAR2 access failure, return a PRAMIN-based runlist pointer | 10 | // Uncomment to, upon BAR2 access failure, return a PRAMIN-based runlist pointer |
| 11 | // **If enabled, PRAMIN may not be otherwise used while walking the runlist!** | 11 | // **If enabled, PRAMIN may not be otherwise used while walking the runlist!** |
| 12 | #define FALLBACK_TO_PRAMIN | 12 | // Runlists can only be printed on the Jetson TX2 if this is enabled. |
| 13 | //#define FALLBACK_TO_PRAMIN | ||
| 13 | 14 | ||
| 14 | /* Get runlist head and info (incl. length) | 15 | /* Get runlist head and info (incl. length) |
| 15 | @param rl_id Which runlist to obtain? | 16 | @param rl_id Which runlist to obtain? |
| @@ -20,6 +21,7 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl | |||
| 20 | uint64_t runlist_iova; | 21 | uint64_t runlist_iova; |
| 21 | enum INST_TARGET runlist_target; | 22 | enum INST_TARGET runlist_target; |
| 22 | uint16_t runlist_len; | 23 | uint16_t runlist_len; |
| 24 | int err; | ||
| 23 | #ifdef FALLBACK_TO_PRAMIN | 25 | #ifdef FALLBACK_TO_PRAMIN |
| 24 | int off; | 26 | int off; |
| 25 | #endif // FALLBACK_TO_PRAMIN | 27 | #endif // FALLBACK_TO_PRAMIN |
| @@ -33,9 +35,9 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl | |||
| 33 | return -EIO; | 35 | return -EIO; |
| 34 | runlist_iova = ((uint64_t)rl.ptr) << 12; | 36 | runlist_iova = ((uint64_t)rl.ptr) << 12; |
| 35 | runlist_target = rl.target; | 37 | runlist_target = rl.target; |
| 36 | printk(KERN_INFO "[nvdebug] Runlist %d: %d entries @ %llx in %s (config raw: %#018llx)\n", | ||
| 37 | rl_id, rl.len, runlist_iova, target_to_text(rl.target), rl.raw); | ||
| 38 | runlist_len = rl.len; | 38 | runlist_len = rl.len; |
| 39 | printk(KERN_INFO "[nvdebug] Runlist %d for %x: %d entries @ %llx in %s (config raw: %#018llx)\n", | ||
| 40 | rl_id, g->chip_id, rl.len, runlist_iova, target_to_text(rl.target), rl.raw); | ||
| 39 | } else if (g->chip_id < NV_CHIP_ID_AMPERE) { | 41 | } else if (g->chip_id < NV_CHIP_ID_AMPERE) { |
| 40 | runlist_base_tu102_t base; | 42 | runlist_base_tu102_t base; |
| 41 | runlist_submit_tu102_t submit; | 43 | runlist_submit_tu102_t submit; |
| @@ -46,6 +48,8 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl | |||
| 46 | runlist_iova = ((uint64_t)base.ptr) << 12; | 48 | runlist_iova = ((uint64_t)base.ptr) << 12; |
| 47 | runlist_target = base.target; | 49 | runlist_target = base.target; |
| 48 | runlist_len = submit.len; | 50 | runlist_len = submit.len; |
| 51 | printk(KERN_INFO "[nvdebug] Runlist %d for %x: %d entries @ %llx in %s (config raw: %#018llx %#018llx)\n", | ||
| 52 | rl_id, g->chip_id, submit.len, runlist_iova, target_to_text(runlist_target), base.raw, submit.raw); | ||
| 49 | } | 53 | } |
| 50 | // Return early on an empty runlist | 54 | // Return early on an empty runlist |
| 51 | if (!runlist_len) | 55 | if (!runlist_len) |
| @@ -53,24 +57,25 @@ int get_runlist_iter(struct nvdebug_state *g, int rl_id, struct runlist_iter *rl | |||
| 53 | 57 | ||
| 54 | // If the runlist is in VID_MEM, search the BAR2/3 page tables for a mapping | 58 | // If the runlist is in VID_MEM, search the BAR2/3 page tables for a mapping |
| 55 | if (runlist_target == TARGET_VID_MEM) { | 59 | if (runlist_target == TARGET_VID_MEM) { |
| 56 | void __iomem *bar2_page_dir; | ||
| 57 | bool pdb_is_ver2; | ||
| 58 | uint64_t runlist_bar_vaddr; | 60 | uint64_t runlist_bar_vaddr; |
| 61 | page_dir_config_t pd_config; | ||
| 59 | 62 | ||
| 60 | if (get_bar2_pdb(g, &bar2_page_dir, &pdb_is_ver2) < 0) | 63 | if ((err = get_bar2_pdb(g, &pd_config)) < 0) |
| 61 | return -EIO; | 64 | goto attempt_pramin_access; |
| 62 | 65 | ||
| 63 | if (pdb_is_ver2) | 66 | if (pd_config.is_ver2) |
| 64 | runlist_bar_vaddr = search_page_directory(g, bar2_page_dir, phy2PRAMIN, runlist_iova); | 67 | runlist_bar_vaddr = search_page_directory(g, pd_config, runlist_iova); |
| 65 | else | 68 | else |
| 66 | runlist_bar_vaddr = search_v1_page_directory(g, bar2_page_dir, phy2PRAMIN, runlist_iova); | 69 | runlist_bar_vaddr = search_v1_page_directory(g, pd_config, runlist_iova); |
| 67 | if (!runlist_bar_vaddr) { | 70 | if (!runlist_bar_vaddr) { |
| 68 | printk(KERN_WARNING "[nvdebug] Unable to find runlist mapping in BAR2/3 page tables.\n"); | 71 | printk(KERN_WARNING "[nvdebug] Unable to find runlist %d mapping in BAR2/3 page tables for %x.\n", rl_id, g->chip_id); |
| 72 | err = -EOPNOTSUPP; | ||
| 69 | goto attempt_pramin_access; | 73 | goto attempt_pramin_access; |
| 70 | } | 74 | } |
| 71 | printk(KERN_INFO "[nvdebug] Runlist @ %llx in BAR2 virtual address space.\n", runlist_bar_vaddr); | 75 | |
| 76 | printk(KERN_INFO "[nvdebug] Runlist %d for %x @ %llx in BAR2 virtual address space.\n", rl_id, g->chip_id, runlist_bar_vaddr); | ||
| 72 | if (!g->bar2) { | 77 | if (!g->bar2) { |
| 73 | printk(KERN_WARNING "[nvdebug] BAR2/3 not mapped.\n"); | 78 | printk(KERN_WARNING "[nvdebug] BAR2/3 not mapped for %x.\n", g->chip_id); |
| 74 | return -ENODEV; | 79 | return -ENODEV; |
| 75 | } | 80 | } |
| 76 | rl_iter->curr_entry = g->bar2 + runlist_bar_vaddr; | 81 | rl_iter->curr_entry = g->bar2 + runlist_bar_vaddr; |
| @@ -91,7 +96,7 @@ attempt_pramin_access: | |||
| 91 | rl_iter->len = runlist_len; | 96 | rl_iter->len = runlist_len; |
| 92 | return 0; | 97 | return 0; |
| 93 | #else | 98 | #else |
| 94 | return -EOPNOTSUPP; | 99 | return err; |
| 95 | #endif // FALLBACK_TO_PRAMIN | 100 | #endif // FALLBACK_TO_PRAMIN |
| 96 | } | 101 | } |
| 97 | 102 | ||
