From 33c915f08f5dc63674b158ecc18897494256a6d0 Mon Sep 17 00:00:00 2001 From: Benjamin Hadad IV Date: Wed, 19 Jul 2023 13:02:52 -0400 Subject: Debugged device_info functionality - Fixed device_info crash bugs - Made further edits to display functionality - Refactored code to enhance readability --- Makefile | 1 + device_info_procfs.c | 53 ++++++++++++++++++---------------------------------- nvdebug.h | 4 +++- nvdebug_entry.c | 4 ++-- 4 files changed, 24 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index 2dc90c7..8e32bd0 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ KBUILD_CFLAGS += -DGIT_HASH=\"$(shell git --git-dir=$(PWD)/.git rev-parse --shor # TODO: Avoid needing to distribute NVIDIA's headers (at least they're MIT...) ccflags-y += -I$(PWD)/include +ccflags-y += -std=gnu99 #ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/drivers/gpu/nvgpu/include #ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/drivers/gpu/nvgpu #ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/include diff --git a/device_info_procfs.c b/device_info_procfs.c index b1e58b1..3cf4bc9 100644 --- a/device_info_procfs.c +++ b/device_info_procfs.c @@ -37,7 +37,7 @@ static void* device_info_file_seq_start_previous(struct seq_file *s, loff_t *pos if (*pos == 0) idx = 0; // Number of possible info entries is fixed, and list is sparse - if (idx >= NV_PTOP_DEVICE_INFO__SIZE_1) + if (idx >= NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS) return NULL; return &idx; } @@ -49,7 +49,7 @@ static void* device_info_file_seq_start_ampere(struct seq_file *s, loff_t *pos) idx = 0; struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; // Number of possible info entries is fixed, and list is sparse - if (idx >= (nvdebug_readl(g, 0x0224fc) >> 20)) + if (idx >= NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g)) return NULL; return &idx; } @@ -60,7 +60,7 @@ static void* device_info_file_seq_next_previous(struct seq_file *s, void *idx, loff_t *pos) { (*pos)++; // Required by seq interface // Number of possible info entries is fixed, and list is sparse - if ((*(int*)idx)++ >= NV_PTOP_DEVICE_INFO__SIZE_1) + if ((*(int*)idx)++ >= NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS) return NULL; return idx; } @@ -72,38 +72,11 @@ static void* device_info_file_seq_next_ampere(struct seq_file *s, void *idx, (*pos)++; // Required by seq interface // Number of possible info entries is fixed, and list is sparse struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; - if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) + if ((*(int*)idx)++ >= NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g)) return NULL; return idx; } -/* -// Steps to next record on Ampere GPUs. Returns new value of `idx`. -static void* device_info_file_seq_next_ampere(struct seq_file *s, void *idx, - loff_t *pos) { - (*pos)++; // Required by seq interface - // Number of possible info entries is fixed, and list is sparse - while(1) { - struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; - if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) - return NULL; - ptop_device_info_t curr_info; - curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx)); - if(!curr_info.raw && !*info_type) continue; - (*info_type)++; - break; - } - while(1) { - struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; - if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) - return NULL; - ptop_device_info_t curr_info; - curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx)); - if(curr_info.raw & 0x80000000) continue; - break; - } - return idx; -} -*/ + // Print info at index *idx. Returns non-zero on error. static int device_info_file_seq_show_previous(struct seq_file *s, void *idx) { ptop_device_info_t curr_info; @@ -162,11 +135,21 @@ static int device_info_file_seq_show_ampere(struct seq_file *s, void *idx) { // Check for read errors if (curr_info.raw == -1) return -EIO; + // The info_type field is not available in the Ampere device_info data, so it must be inferred int info_type = -1; if(curr_info.raw) { - if(*(int*)idx < 1 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 1)) info_type = 0; - if(*(int*)idx < 2 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 2)) info_type = 1; - if(*(int*)idx < 3 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 3)) info_type = 2; + for(int i = 0; i < NV_PTOP_DEVICE_INFO_TYPE_COUNT; i++) { + if(*(int*)idx == i) { + info_type = i; + break; + } + ptop_device_info_t prev_info; + prev_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx - i - 1)); + if(!prev_info.raw || !prev_info.has_next_entry_ampere) { + info_type = i; + break; + } + } } // Parse and print the data switch(info_type) { diff --git a/nvdebug.h b/nvdebug.h index 3ccdcfe..bd893aa 100644 --- a/nvdebug.h +++ b/nvdebug.h @@ -556,7 +556,9 @@ static const char* const ENGINE_TYPES_NAMES[ENGINE_TYPES_LEN] = { #define NV_PTOP_DEVICE_INFO_AMPERE(i) (0x00022800+(i)*4) #define NV_PTOP_DEVICE_INFO_PREVIOUS(i) (0x00022700+(i)*4) -#define NV_PTOP_DEVICE_INFO__SIZE_1 64 +#define NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g) (nvdebug_readl(g, 0x0224fc) >> 20) +#define NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS 64 +#define NV_PTOP_DEVICE_INFO_TYPE_COUNT 3 typedef union { struct { uint32_t fault_id_ampere:7; diff --git a/nvdebug_entry.c b/nvdebug_entry.c index d82c648..3dfe1e8 100644 --- a/nvdebug_entry.c +++ b/nvdebug_entry.c @@ -150,7 +150,7 @@ int create_runlist_files_previous(int device_id, struct proc_dir_entry *dir) { // Figure out how many runlists there are by checking the device info // registers. Runlists are always numbered sequentially, so we just have // to find the highest-valued one and add 1 to get the number of runlists. - for (i = 0; i < NV_PTOP_DEVICE_INFO__SIZE_1; i++) { + for (i = 0; i < NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS; i++) { info.raw = nvdebug_readl(&g_nvdebug_state[device_id], NV_PTOP_DEVICE_INFO_PREVIOUS(i)); if (info.info_type != INFO_TYPE_ENUM || !info.runlist_is_valid) continue; @@ -180,7 +180,7 @@ int create_runlist_files_ampere(int device_id, struct proc_dir_entry *dir) { // Figure out how many runlists there are by checking the device info // registers. Runlists are always numbered sequentially, so we just have // to find the highest-valued one and add 1 to get the number of runlists. - for (i = 0; i < (nvdebug_readl(&g_nvdebug_state[device_id], 0x0224fc) >> 20); i++) { + for (i = 0; i < NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(&g_nvdebug_state[device_id]); i++) { info.raw = nvdebug_readl(&g_nvdebug_state[device_id], NV_PTOP_DEVICE_INFO_AMPERE(i)); if (info.runlist_enum_ampere > max_rl_id) max_rl_id = info.runlist_enum; -- cgit v1.2.2