diff options
Diffstat (limited to 'runlist_procfs.c')
| -rw-r--r-- | runlist_procfs.c | 188 |
1 files changed, 111 insertions, 77 deletions
diff --git a/runlist_procfs.c b/runlist_procfs.c index 411f844..a6b0d94 100644 --- a/runlist_procfs.c +++ b/runlist_procfs.c | |||
| @@ -6,7 +6,14 @@ | |||
| 6 | #define RUNLIST_PROCFS_NAME "runlist" | 6 | #define RUNLIST_PROCFS_NAME "runlist" |
| 7 | #define DETAILED_CHANNEL_INFO | 7 | #define DETAILED_CHANNEL_INFO |
| 8 | 8 | ||
| 9 | static int runlist_detail_seq_show_chan(struct seq_file *s, struct gk20a *g, uint32_t chid) { | 9 | /* Print channel details using PCCSR (Programmable Channel Control System RAM?) |
| 10 | * @param s Pointer to state from seq_file subsystem to pass to seq_printf | ||
| 11 | * @param g Pointer to our internal GPU state | ||
| 12 | * @param chid ID of channel to print details on, range [0, 512) | ||
| 13 | * @param prefix Text string to prefix each line with, or empty string | ||
| 14 | */ | ||
| 15 | #ifdef DETAILED_CHANNEL_INFO | ||
| 16 | static int runlist_detail_seq_show_chan(struct seq_file *s, struct nvdebug_state *g, uint32_t chid, char *prefix) { | ||
| 10 | channel_ctrl_t chan; | 17 | channel_ctrl_t chan; |
| 11 | char *loc_txt; | 18 | char *loc_txt; |
| 12 | u64 instance_ptr; | 19 | u64 instance_ptr; |
| @@ -16,23 +23,37 @@ static int runlist_detail_seq_show_chan(struct seq_file *s, struct gk20a *g, uin | |||
| 16 | return -EIO; | 23 | return -EIO; |
| 17 | instance_ptr = chan.inst_ptr; | 24 | instance_ptr = chan.inst_ptr; |
| 18 | instance_ptr <<= 12; | 25 | instance_ptr <<= 12; |
| 19 | seq_printf(s, " +- Channel Info %-4d -+\n", chid); | 26 | seq_printf(s, "%s+- Channel Info %-4d -+\n", prefix, chid); |
| 20 | seq_printf(s, " | Enabled: %d|\n", chan.enable); | 27 | seq_printf(s, "%s| Enabled: %d|\n", prefix, chan.enable); |
| 21 | seq_printf(s, " | Next: %d|\n", chan.next); | 28 | seq_printf(s, "%s| Next: %d|\n", prefix, chan.next); |
| 22 | seq_printf(s, " | Force CTX Reload: %d|\n", chan.force_ctx_reload); | 29 | seq_printf(s, "%s| Force CTX Reload: %d|\n", prefix, chan.force_ctx_reload); |
| 23 | seq_printf(s, " | Enable set: %d|\n", chan.enable_set); | 30 | seq_printf(s, "%s| Enable set: %d|\n", prefix, chan.enable_set); |
| 24 | seq_printf(s, " | Enable clear: %d|\n", chan.enable_clear); | 31 | seq_printf(s, "%s| Enable clear: %d|\n", prefix, chan.enable_clear); |
| 25 | seq_printf(s, " | PBDMA Faulted: %d|\n", chan.pbdma_faulted); | 32 | seq_printf(s, "%s| PBDMA Faulted: %d|\n", prefix, chan.pbdma_faulted); |
| 26 | seq_printf(s, " | ENG Faulted: %d|\n", chan.eng_faulted); | 33 | seq_printf(s, "%s| ENG Faulted: %d|\n", prefix, chan.eng_faulted); |
| 27 | seq_printf(s, " | Status: %2d|\n", chan.status); | 34 | seq_printf(s, "%s| Status: %2d|\n", prefix, chan.status); |
| 28 | seq_printf(s, " | Busy: %d|\n", chan.busy); | 35 | seq_printf(s, "%s| Busy: %d|\n", prefix, chan.busy); |
| 29 | seq_printf(s, " | Instance PTR: |\n"); | 36 | seq_printf(s, "%s| Instance PTR: |\n", prefix); |
| 30 | seq_printf(s, " | %#018llx |\n", instance_ptr); | 37 | seq_printf(s, "%s| %#018llx |\n", prefix, instance_ptr); |
| 31 | seq_printf(s, " | %-20s|\n", loc_txt); | 38 | seq_printf(s, "%s| %-20s|\n", prefix, loc_txt); |
| 32 | seq_printf(s, " | Instance bound: %d|\n", chan.inst_bind); | 39 | seq_printf(s, "%s| Instance bound: %d|\n", prefix, chan.inst_bind); |
| 33 | seq_printf(s, " +---------------------+\n"); | 40 | // START TEMP |
| 41 | // "runlist_id -1 is synonym for the ENGINE_GR_GK20A runlist id" | ||
| 42 | // GR, GRCE, and ASYNC_CE | ||
| 43 | // Note that this appears to be broken?? | ||
| 44 | // Peek into the channel instance RAM | ||
| 45 | if (chan.inst_target == TARGET_SYS_MEM_COHERENT) { | ||
| 46 | seq_printf(s, "%s| Target Engine: %2d|\n", prefix, *(uint32_t*)phys_to_virt(instance_ptr + 4/*bytes for 32bits*/*43/*NV_RAMFC_TARGET*/) & 0x1f); | ||
| 47 | seq_printf(s, "%s| PDB LO: %#08x|\n", prefix, *(uint32_t*)phys_to_virt(instance_ptr + 4/*bytes for 32bits*/*128/*NV_RAMIN_PAGE_DIR_BASE_LO*/) & 0xfffff000); | ||
| 48 | seq_printf(s, "%s| Num subcontexts: %2ld|\n", prefix, hweight64(*(uint64_t*)phys_to_virt(instance_ptr + 4/*bytes for 32bits*/*166/*NV_RAMIN_SC_PDB_VALID*/))); | ||
| 49 | // This appears to be unset on Xavier | ||
| 50 | //seq_printf(s, "%s| PAS ID: %8ld|\n", prefix, *(uint32_t*)phys_to_virt(instance_ptr + 4/*bytes for 32bits*/*135/*NV_RAMIN_PASID*/) & 0xfffff); | ||
| 51 | } | ||
| 52 | // END TEMP | ||
| 53 | seq_printf(s, "%s+---------------------+\n", prefix); | ||
| 34 | return 0; | 54 | return 0; |
| 35 | } | 55 | } |
| 56 | #endif | ||
| 36 | 57 | ||
| 37 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) | 58 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) |
| 38 | // Bug workaround. See comment in runlist_file_seq_start() | 59 | // Bug workaround. See comment in runlist_file_seq_start() |
| @@ -41,10 +62,14 @@ static loff_t pos_fixup; | |||
| 41 | 62 | ||
| 42 | static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) { | 63 | static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) { |
| 43 | static struct runlist_iter rl_iter; | 64 | static struct runlist_iter rl_iter; |
| 65 | struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(s->file)]; | ||
| 44 | // *pos == 0 for first call after read of file | 66 | // *pos == 0 for first call after read of file |
| 45 | if (*pos == 0) { | 67 | if (*pos == 0) { |
| 46 | int err = get_runlist_iter(&rl_iter); | 68 | int err = get_runlist_iter(g, seq2gpuidx(s), &rl_iter); |
| 47 | if (err) | 69 | if (err) |
| 70 | return ERR_PTR(err); | ||
| 71 | // Don't try to print an empty runlist | ||
| 72 | if (rl_iter.rl_info.len <= 0) | ||
| 48 | return NULL; | 73 | return NULL; |
| 49 | return &rl_iter; | 74 | return &rl_iter; |
| 50 | } | 75 | } |
| @@ -68,12 +93,13 @@ static void* runlist_file_seq_next(struct seq_file *s, void *raw_rl_iter, | |||
| 68 | loff_t *pos) { | 93 | loff_t *pos) { |
| 69 | struct runlist_iter* rl_iter = raw_rl_iter; | 94 | struct runlist_iter* rl_iter = raw_rl_iter; |
| 70 | void *ret = NULL; | 95 | void *ret = NULL; |
| 71 | // Advance by one TSG + channels under last TSG | 96 | struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(s->file)]; |
| 72 | *pos += 1 + rl_iter->curr_tsg->tsg_length; | 97 | // Advance by one TSG or channel |
| 98 | (*pos)++; | ||
| 99 | rl_iter->curr_entry += NV_RL_ENTRY_SIZE(g); | ||
| 73 | // Verify we haven't reached the end of the runlist | 100 | // Verify we haven't reached the end of the runlist |
| 74 | // rl_info.len is the num of tsg entries + total num of channel entries | 101 | // rl_info.len is the num of tsg entries + total num of channel entries |
| 75 | if (*pos < rl_iter->rl_info.len) { | 102 | if (*pos < rl_iter->rl_info.len) { |
| 76 | rl_iter->curr_tsg = next_tsg(rl_iter->curr_tsg); | ||
| 77 | ret = rl_iter; | 103 | ret = rl_iter; |
| 78 | } | 104 | } |
| 79 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) | 105 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0) |
| @@ -88,57 +114,57 @@ static void runlist_file_seq_stop(struct seq_file *s, void *raw_rl_iter) { | |||
| 88 | } | 114 | } |
| 89 | 115 | ||
| 90 | static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) { | 116 | static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) { |
| 91 | struct entry_tsg* tsg = ((struct runlist_iter*)raw_rl_iter)->curr_tsg; | 117 | struct runlist_iter *rl_iter = raw_rl_iter; |
| 92 | struct runlist_chan* chan; | 118 | void *entry = rl_iter->curr_entry; |
| 93 | struct gk20a *g = get_live_gk20a(); | 119 | struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(s->file)]; |
| 94 | if (!g) | 120 | if (entry_type(g, entry) == ENTRY_TYPE_TSG) { |
| 95 | return -EIO; | 121 | if (rl_iter->channels_left_in_tsg) { |
| 96 | if (tsg->entry_type != ENTRY_TYPE_TSG) { | 122 | printk(KERN_WARNING "[nvdebug] Found a TSG @ %px when %d channels were still expected under the previous TSG in the runlist!\n", entry, rl_iter->channels_left_in_tsg); |
| 97 | printk(KERN_WARNING "[nvdebug] Attempted to print non-TSG in tsg print logic!\n"); | 123 | return -EIO; |
| 98 | return -EIO; | 124 | } |
| 99 | } | 125 | rl_iter->channels_left_in_tsg = tsg_length(g, entry); |
| 100 | seq_printf(s, "+---- TSG Entry %-2d----+\n", tsg->tsgid); | 126 | seq_printf(s, "+---- TSG Entry %-3d---+\n", tsgid(g, entry)); |
| 101 | seq_printf(s, "| Scale: %-13d|\n", tsg->timeslice_scale); | 127 | seq_printf(s, "| Scale: %-13d|\n", timeslice_scale(g, entry)); |
| 102 | seq_printf(s, "| Timeout: %-11d|\n", tsg->timeslice_timeout); | 128 | seq_printf(s, "| Timeout: %-11d|\n", timeslice_timeout(g, entry)); |
| 103 | seq_printf(s, "+---------------------+\n"); | 129 | seq_printf(s, "| Length: %-12d|\n", tsg_length(g, entry)); |
| 104 | for_chan_in_tsg(chan, tsg) { | 130 | seq_printf(s, "+---------------------+\n"); |
| 131 | } else { | ||
| 132 | char *indt = ""; | ||
| 105 | #ifndef DETAILED_CHANNEL_INFO | 133 | #ifndef DETAILED_CHANNEL_INFO |
| 106 | char* loc_txt; | 134 | u64 instance_ptr = 0; |
| 107 | u64 instance_ptr; | ||
| 108 | #endif | 135 | #endif |
| 109 | if (chan->entry_type != ENTRY_TYPE_CHAN) { | 136 | if (rl_iter->channels_left_in_tsg) { |
| 110 | printk(KERN_WARNING "[nvdebug] Attempted to print non-channel in channel print logic!\n"); | 137 | indt = " "; |
| 111 | return -EIO; | 138 | rl_iter->channels_left_in_tsg--; |
| 112 | } | 139 | } |
| 113 | #ifdef DETAILED_CHANNEL_INFO | 140 | #ifdef DETAILED_CHANNEL_INFO |
| 114 | runlist_detail_seq_show_chan(s, g, chan->chid); | 141 | runlist_detail_seq_show_chan(s, g, chid(g, entry), indt); |
| 115 | #else | 142 | #else |
| 116 | loc_txt = target_to_text(chan->inst_target); | ||
| 117 | if (!loc_txt) { | ||
| 118 | printk(KERN_WARNING "[nvdebug] Invalid apature in channel print logic!\n"); | ||
| 119 | return -EIO; | ||
| 120 | } | ||
| 121 | // Reconstruct pointer to channel instance block | 143 | // Reconstruct pointer to channel instance block |
| 122 | instance_ptr = chan->inst_ptr_hi; | 144 | if (g->chip_id >= NV_CHIP_ID_VOLTA) { |
| 123 | instance_ptr <<= 32; | 145 | instance_ptr = ((struct gv100_runlist_chan*)entry)->inst_ptr_hi; |
| 124 | instance_ptr |= chan->inst_ptr_lo << 12; | 146 | instance_ptr <<= 32; |
| 125 | 147 | } | |
| 126 | seq_printf(s, " +- Channel Entry %-4d-+\n", chan->chid); | 148 | instance_ptr |= inst_ptr_lo(g, entry) << 12; |
| 127 | seq_printf(s, " | Runqueue Selector: %d|\n", chan->runqueue_selector); | 149 | |
| 128 | seq_printf(s, " | Instance PTR: |\n"); | 150 | seq_printf(s, "%s+- Channel Entry %-4d-+\n", indt, chid(g, entry)); |
| 129 | seq_printf(s, " | %#018llx |\n", instance_ptr); | 151 | if (g->chip_id >= NV_CHIP_ID_VOLTA) |
| 130 | seq_printf(s, " | %-20s|\n", loc_txt); | 152 | seq_printf(s, "%s| Runqueue Selector: %d|\n", indt, |
| 131 | seq_printf(s, " +---------------------+\n"); | 153 | ((struct gv100_runlist_chan*)entry)->runqueue_selector); |
| 154 | seq_printf(s, "%s| Instance PTR: |\n", indt); | ||
| 155 | seq_printf(s, "%s| %#018llx |\n", indt, instance_ptr); | ||
| 156 | seq_printf(s, "%s| %-20s|\n", indt, target_to_text(inst_target(g, entry))); | ||
| 157 | seq_printf(s, "%s+---------------------+\n", indt); | ||
| 132 | #endif | 158 | #endif |
| 133 | } | 159 | } |
| 134 | return 0; | 160 | return 0; |
| 135 | } | 161 | } |
| 136 | 162 | ||
| 137 | static const struct seq_operations runlist_file_seq_ops = { | 163 | static const struct seq_operations runlist_file_seq_ops = { |
| 138 | .start = runlist_file_seq_start, | 164 | .start = runlist_file_seq_start, |
| 139 | .next = runlist_file_seq_next, | 165 | .next = runlist_file_seq_next, |
| 140 | .stop = runlist_file_seq_stop, | 166 | .stop = runlist_file_seq_stop, |
| 141 | .show = runlist_file_seq_show, | 167 | .show = runlist_file_seq_show, |
| 142 | }; | 168 | }; |
| 143 | 169 | ||
| 144 | static int runlist_file_open(struct inode *inode, struct file *f) { | 170 | static int runlist_file_open(struct inode *inode, struct file *f) { |
| @@ -157,6 +183,7 @@ ssize_t preempt_tsg_file_write(struct file *f, const char __user *buffer, | |||
| 157 | uint32_t target_tsgid; | 183 | uint32_t target_tsgid; |
| 158 | // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec | 184 | // Passing 0 as the base to kstrtou32 indicates autodetect hex/octal/dec |
| 159 | int err = kstrtou32_from_user(buffer, count, 0, &target_tsgid); | 185 | int err = kstrtou32_from_user(buffer, count, 0, &target_tsgid); |
| 186 | struct nvdebug_state *g = &g_nvdebug_state[file2gpuidx(f)]; | ||
| 160 | if (err) | 187 | if (err) |
| 161 | return err; | 188 | return err; |
| 162 | 189 | ||
| @@ -165,7 +192,7 @@ ssize_t preempt_tsg_file_write(struct file *f, const char __user *buffer, | |||
| 165 | |||
