diff options
| author | Benjamin Hadad IV <bh4@unc.edu> | 2023-07-13 12:13:17 -0400 |
|---|---|---|
| committer | Benjamin Hadad IV <bh4@unc.edu> | 2023-07-13 12:13:17 -0400 |
| commit | bfb4dcf0e78954c0163f3a06a5a088c4d1b437a8 (patch) | |
| tree | 5288dc03523647f01d9952557b282b1019daa774 | |
| parent | 068e7f4e7208d6c9250ad72208e0b36fd9fdf2f6 (diff) | |
This commit is to update the repo for display during a meeting.
- Added an Ampere version of the device info data.
- Added Ampere versions of auxillary functions.
- Modified display functions to accommodate Ampere data.
- Made other various small modifications.
| -rw-r--r-- | device_info_procfs.c | 140 | ||||
| -rw-r--r-- | nvdebug.h | 37 | ||||
| -rw-r--r-- | nvdebug_entry.c | 41 |
3 files changed, 179 insertions, 39 deletions
diff --git a/device_info_procfs.c b/device_info_procfs.c index 1fc0586..b1e58b1 100644 --- a/device_info_procfs.c +++ b/device_info_procfs.c | |||
| @@ -31,7 +31,7 @@ struct file_operations nvdebug_read_reg32_file_ops = { | |||
| 31 | 31 | ||
| 32 | // Called to start or resume a sequence. Prior to 4.19, *pos is unreliable. | 32 | // Called to start or resume a sequence. Prior to 4.19, *pos is unreliable. |
| 33 | // Initializes iterator `idx` state and returns it. Ends sequence on NULL. | 33 | // Initializes iterator `idx` state and returns it. Ends sequence on NULL. |
| 34 | static void* device_info_file_seq_start(struct seq_file *s, loff_t *pos) { | 34 | static void* device_info_file_seq_start_previous(struct seq_file *s, loff_t *pos) { |
| 35 | static int idx; | 35 | static int idx; |
| 36 | // If start of sequence, reset `idx` | 36 | // If start of sequence, reset `idx` |
| 37 | if (*pos == 0) | 37 | if (*pos == 0) |
| @@ -42,9 +42,21 @@ static void* device_info_file_seq_start(struct seq_file *s, loff_t *pos) { | |||
| 42 | return &idx; | 42 | return &idx; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static void* device_info_file_seq_start_ampere(struct seq_file *s, loff_t *pos) { | ||
| 46 | static int idx; | ||
| 47 | // If start of sequence, reset `idx` | ||
| 48 | if (*pos == 0) | ||
| 49 | idx = 0; | ||
| 50 | struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; | ||
| 51 | // Number of possible info entries is fixed, and list is sparse | ||
| 52 | if (idx >= (nvdebug_readl(g, 0x0224fc) >> 20)) | ||
| 53 | return NULL; | ||
| 54 | return &idx; | ||
| 55 | } | ||
| 56 | |||
| 45 | // Steps to next record. Returns new value of `idx`. | 57 | // Steps to next record. Returns new value of `idx`. |
| 46 | // Calls show() on non-NULL return | 58 | // Calls show() on non-NULL return |
| 47 | static void* device_info_file_seq_next(struct seq_file *s, void *idx, | 59 | static void* device_info_file_seq_next_previous(struct seq_file *s, void *idx, |
| 48 | loff_t *pos) { | 60 | loff_t *pos) { |
| 49 | (*pos)++; // Required by seq interface | 61 | (*pos)++; // Required by seq interface |
| 50 | // Number of possible info entries is fixed, and list is sparse | 62 | // Number of possible info entries is fixed, and list is sparse |
| @@ -53,12 +65,50 @@ static void* device_info_file_seq_next(struct seq_file *s, void *idx, | |||
| 53 | return idx; | 65 | return idx; |
| 54 | } | 66 | } |
| 55 | 67 | ||
| 68 | // Steps to next record. Returns new value of `idx`. | ||
| 69 | // Calls show() on non-NULL return | ||
| 70 | static void* device_info_file_seq_next_ampere(struct seq_file *s, void *idx, | ||
| 71 | loff_t *pos) { | ||
| 72 | (*pos)++; // Required by seq interface | ||
| 73 | // Number of possible info entries is fixed, and list is sparse | ||
| 74 | struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; | ||
| 75 | if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) | ||
| 76 | return NULL; | ||
| 77 | return idx; | ||
| 78 | } | ||
| 79 | /* | ||
| 80 | // Steps to next record on Ampere GPUs. Returns new value of `idx`. | ||
| 81 | static void* device_info_file_seq_next_ampere(struct seq_file *s, void *idx, | ||
| 82 | loff_t *pos) { | ||
| 83 | (*pos)++; // Required by seq interface | ||
| 84 | // Number of possible info entries is fixed, and list is sparse | ||
| 85 | while(1) { | ||
| 86 | struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; | ||
| 87 | if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) | ||
| 88 | return NULL; | ||
| 89 | ptop_device_info_t curr_info; | ||
| 90 | curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx)); | ||
| 91 | if(!curr_info.raw && !*info_type) continue; | ||
| 92 | (*info_type)++; | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | while(1) { | ||
| 96 | struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; | ||
| 97 | if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) | ||
| 98 | return NULL; | ||
| 99 | ptop_device_info_t curr_info; | ||
| 100 | curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx)); | ||
| 101 | if(curr_info.raw & 0x80000000) continue; | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | return idx; | ||
| 105 | } | ||
| 106 | */ | ||
| 56 | // Print info at index *idx. Returns non-zero on error. | 107 | // Print info at index *idx. Returns non-zero on error. |
| 57 | static int device_info_file_seq_show(struct seq_file *s, void *idx) { | 108 | static int device_info_file_seq_show_previous(struct seq_file *s, void *idx) { |
| 58 | ptop_device_info_t curr_info; | 109 | ptop_device_info_t curr_info; |
| 59 | struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; | 110 | struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; |
| 60 | 111 | curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_PREVIOUS(*(int*)idx)); | |
| 61 | curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO(*(int*)idx)); | ||
| 62 | // Check for read errors | 112 | // Check for read errors |
| 63 | if (curr_info.raw == -1) | 113 | if (curr_info.raw == -1) |
| 64 | return -EIO; | 114 | return -EIO; |
| @@ -104,24 +154,88 @@ static int device_info_file_seq_show(struct seq_file *s, void *idx) { | |||
| 104 | return 0; | 154 | return 0; |
| 105 | } | 155 | } |
| 106 | 156 | ||
| 157 | // Print info at index *idx for Ampere GPUs. Returns non-zero on error. | ||
| 158 | static int device_info_file_seq_show_ampere(struct seq_file *s, void *idx) { | ||
| 159 | ptop_device_info_t curr_info; | ||
| 160 | struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; | ||
| 161 | curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx)); | ||
| 162 | // Check for read errors | ||
| 163 | if (curr_info.raw == -1) | ||
| 164 | return -EIO; | ||
| 165 | int info_type = -1; | ||
| 166 | if(curr_info.raw) { | ||
| 167 | if(*(int*)idx < 1 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 1)) info_type = 0; | ||
| 168 | if(*(int*)idx < 2 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 2)) info_type = 1; | ||
| 169 | if(*(int*)idx < 3 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 3)) info_type = 2; | ||
| 170 | } | ||
| 171 | // Parse and print the data | ||
| 172 | switch(info_type) { | ||
| 173 | case 0: | ||
| 174 | seq_printf(s, "| instance %d\n", curr_info.inst_id_ampere); | ||
| 175 | seq_printf(s, "| Fault ID: %3d\n", curr_info.fault_id_ampere); | ||
| 176 | seq_printf(s, "| Engine Type: %2d (", curr_info.engine_type_ampere); | ||
| 177 | if (curr_info.engine_type_ampere < ENGINE_TYPES_LEN) | ||
| 178 | seq_printf(s, "%s)\n", ENGINE_TYPES_NAMES[curr_info.engine_type_ampere]); | ||
| 179 | else | ||
| 180 | seq_printf(s, "Unknown Engine, introduced post-Ampere)\n"); | ||
| 181 | break; | ||
| 182 | case 1: | ||
| 183 | seq_printf(s, "| BAR0 Base %#.8x\n", curr_info.pri_base_ampere << 12); | ||
| 184 | seq_printf(s, "| Reset ID: %2d\n", curr_info.reset_enum_ampere); | ||
| 185 | break; | ||
| 186 | case 2: | ||
| 187 | seq_printf(s, "| Host's Engine ID: %2d\n", curr_info.engine_enum_ampere); | ||
| 188 | seq_printf(s, "| Runlist ID: %2d\n", curr_info.runlist_enum_ampere); | ||
| 189 | break; | ||
| 190 | default: | ||
| 191 | // Device info records are sparse, so skip unset or unknown ones | ||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | // Draw a line between each device entry | ||
| 196 | if (!curr_info.has_next_entry_ampere) { | ||
| 197 | seq_printf(s, "+---------------------+\n"); | ||
| 198 | } | ||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | |||
| 107 | static void device_info_file_seq_stop(struct seq_file *s, void *idx) { | 203 | static void device_info_file_seq_stop(struct seq_file *s, void *idx) { |
| 108 | // No cleanup needed | 204 | // No cleanup needed |
| 109 | } | 205 | } |
| 110 | 206 | ||
| 111 | static const struct seq_operations device_info_file_seq_ops = { | 207 | static const struct seq_operations device_info_file_seq_ops_previous = { |
| 112 | .start = device_info_file_seq_start, | 208 | .start = device_info_file_seq_start_previous, |
| 113 | .next = device_info_file_seq_next, | 209 | .next = device_info_file_seq_next_previous, |
| 114 | .stop = device_info_file_seq_stop, | 210 | .stop = device_info_file_seq_stop, |
| 115 | .show = device_info_file_seq_show, | 211 | .show = device_info_file_seq_show_previous, |
| 212 | }; | ||
| 213 | |||
| 214 | static const struct seq_operations device_info_file_seq_ops_ampere = { | ||
| 215 | .start = device_info_file_seq_start_ampere, | ||
| 216 | .next = device_info_file_seq_next_ampere, | ||
| 217 | .stop = device_info_file_seq_stop, | ||
| 218 | .show = device_info_file_seq_show_ampere, | ||
| 116 | }; | 219 | }; |
| 117 | 220 | ||
| 118 | static int device_info_file_open(struct inode *inode, struct file *f) { | 221 | static int device_info_file_open_previous(struct inode *inode, struct file *f) { |
| 119 | return seq_open(f, &device_info_file_seq_ops); | 222 | return seq_open(f, &device_info_file_seq_ops_previous); |
| 120 | } | 223 | } |
| 121 | 224 | ||
| 122 | struct file_operations device_info_file_ops = { | 225 | static int device_info_file_open_ampere(struct inode *inode, struct file *f) { |
| 123 | .open = device_info_file_open, | 226 | return seq_open(f, &device_info_file_seq_ops_ampere); |
| 227 | } | ||
| 228 | |||
| 229 | struct file_operations device_info_file_ops_previous = { | ||
| 230 | .open = device_info_file_open_previous, | ||
| 124 | .read = seq_read, | 231 | .read = seq_read, |
| 125 | .llseek = seq_lseek, | 232 | .llseek = seq_lseek, |
| 126 | .release = seq_release, | 233 | .release = seq_release, |
| 127 | }; | 234 | }; |
| 235 | |||
| 236 | struct file_operations device_info_file_ops_ampere = { | ||
| 237 | .open = device_info_file_open_ampere, | ||
| 238 | .read = seq_read, | ||
| 239 | .llseek = seq_lseek, | ||
| 240 | .release = seq_release, | ||
| 241 | }; | ||
| @@ -554,34 +554,30 @@ static const char* const ENGINE_TYPES_NAMES[ENGINE_TYPES_LEN] = { | |||
| 554 | See dev_top.ref.txt of NVIDIA's open-gpu-doc for more info. | 554 | See dev_top.ref.txt of NVIDIA's open-gpu-doc for more info. |
| 555 | */ | 555 | */ |
| 556 | 556 | ||
| 557 | #ifdef NV_BUILD_FOR_AMPERE | 557 | #define NV_PTOP_DEVICE_INFO_AMPERE(i) (0x00022800+(i)*4) |
| 558 | #define NV_PTOP_DEVICE_INFO(i) (0x00022800+(i)*4) | 558 | #define NV_PTOP_DEVICE_INFO_PREVIOUS(i) (0x00022700+(i)*4) |
| 559 | #define NV_PTOP_DEVICE_INFO__SIZE_1 64 | 559 | #define NV_PTOP_DEVICE_INFO__SIZE_1 64 |
| 560 | typedef union { | 560 | typedef union { |
| 561 | struct { | 561 | struct { |
| 562 | uint32_t fault_id:7; | 562 | uint32_t fault_id_ampere:7; |
| 563 | uint32_t padding0:9; | 563 | |
