aboutsummaryrefslogtreecommitdiffstats
path: root/device_info_procfs.c
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2025-05-05 03:53:01 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2025-05-05 03:53:13 -0400
commit293430fcb5d4013b573556c58457ee706e482b7f (patch)
tree9328fa680f55b4e1a08d24714275b8437be3be5d /device_info_procfs.c
parent494df296bf4abe9b2b484bde1a4fad28c989afec (diff)
Snapshot for ECRTS'25 artifact evaluation
Diffstat (limited to 'device_info_procfs.c')
-rw-r--r--device_info_procfs.c79
1 files changed, 76 insertions, 3 deletions
diff --git a/device_info_procfs.c b/device_info_procfs.c
index 4e4ab03..105e731 100644
--- a/device_info_procfs.c
+++ b/device_info_procfs.c
@@ -18,7 +18,7 @@ static ssize_t nvdebug_reg32_read(struct file *f, char __user *buf, size_t size,
18 return 0; 18 return 0;
19 19
20 if ((read = nvdebug_readl(g, (uintptr_t)pde_data(file_inode(f)))) == -1) 20 if ((read = nvdebug_readl(g, (uintptr_t)pde_data(file_inode(f)))) == -1)
21 return -EOPNOTSUPP; 21 return -EIO;
22 // 32 bit register will always take less than 16 characters to print 22 // 32 bit register will always take less than 16 characters to print
23 chars_written = scnprintf(out, 16, "%#0x\n", read); 23 chars_written = scnprintf(out, 16, "%#0x\n", read);
24 if (copy_to_user(buf, out, chars_written)) 24 if (copy_to_user(buf, out, chars_written))
@@ -32,12 +32,85 @@ struct file_operations nvdebug_read_reg32_file_ops = {
32 .llseek = default_llseek, 32 .llseek = default_llseek,
33}; 33};
34 34
35typedef union {
36 struct {
37 uint8_t partitioning_select:2;
38 uint8_t table_select:2;
39 uint32_t pad_1:12;
40 uint8_t veid_offset:6;
41 uint32_t pad_2:2;
42 uint8_t table_offset:6;
43 uint32_t pad_3:2;
44 };
45 uint32_t raw;
46} partition_ctl_t;
47
48static ssize_t nvdebug_read_part(struct file *f, char __user *buf, size_t size, loff_t *off) {
49 char out[12*64+2];
50 int i, chars_written = 0;
51 partition_ctl_t part_ctl;
52 struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(f)];
53 if (size < 16 || *off != 0)
54 return 0;
55 // 32 bit register will always take less than 16 characters to print
56 part_ctl.raw = nvdebug_readl(g, 0x00405b2c);
57 //part_ctl.partitioning_select = 0; // XXX XXX XXX Temp; 06/18/2024
58 //part_ctl.table_select = 3; // 3 == ???
59 //part_ctl.table_select = 2; // 2 == TBL_SEL_PARTITIONING_LMEM_BLK
60 part_ctl.table_select = 1; // 1 == TBL_SEL_PARTITIONING_ENABLE
61 //part_ctl.table_select = 0; // 0 == TBL_SEL_NONE
62 part_ctl.veid_offset = (uintptr_t)pde_data(file_inode(f)); // Range of [0, 0x3f], aka [0, 63]
63 for (i = 0; i < 64; i++) {
64 // Increment to next table offset in PARTITION_CTL
65 part_ctl.table_offset = i;
66 nvdebug_writel(g, 0x00405b2c, part_ctl.raw);
67 // Verify write applied to PARTITION_CTL
68 part_ctl.raw = nvdebug_readl(g, 0x00405b2c);
69 if (part_ctl.table_offset != i)
70 return -ENOTRECOVERABLE;
71 // Read PARTITION_DATA and print
72 // ---
73 // I get back 0x000000ff on Volta and 0x00000003 on Turing from
74 // PARTITION_DATA for all possible VEID_OFFSET, TBL_OFFSET, and TBL_SEL
75 // combinations.
76 // ---
77 // There's a 48-byte (12-word) gap after the address for PARTITION_DATA.
78 // Exploring this on Turing for TBL_SEL_PARTITIONING_ENABLE, VEID 1, 62, and
79 // 63, with CUDA_MPS_ACTIVE_THREAD_PERCENTAGE=5 for constant_cycles_kernel
80 // running under MPS:
81 // +0x0: 0x3
82 // +0x4: 0
83 // +0x8: 0x100
84 // +0xC: 0
85 // +0x10: 0xffffffff
86 // +0x14: 0
87 // +0x18: 0
88 // +0x1C: 0xffffffff
89 // +0x20: 0
90 // +0x24: 0xffffffff
91 // +0x28: 0xffffffff
92 // +0x2C: 0xffffffff
93 chars_written += scnprintf(out + chars_written, 12, "%#010x ", nvdebug_readl(g, 0x00405b30));
94 }
95 chars_written += scnprintf(out + chars_written, 2, "\n");
96 if (copy_to_user(buf, out, chars_written))
97 printk(KERN_WARNING "Unable to copy all data for %s\n", file_dentry(f)->d_name.name);
98 *off += chars_written;
99 return chars_written;
100}
101
102struct file_operations nvdebug_read_part_file_ops = {
103 .read = nvdebug_read_part,
104 .llseek = default_llseek,
105};
106
35static ssize_t nvdebug_reg_range_read(struct file *f, char __user *buf, size_t size, loff_t *off) { 107static ssize_t nvdebug_reg_range_read(struct file *f, char __user *buf, size_t size, loff_t *off) {
36 char out[12]; 108 char out[12];
37 int chars_written; 109 int chars_written;
38 uint32_t read, mask; 110 uint32_t read, mask;
39 struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(f)]; 111 struct nvdebug_state *g = &g_nvdebug_state[file2parentgpuidx(f)];
40 // See comment in nvdebug_entry.c to understand `union reg_range` 112 // `start_bit` is included, `stop_bit` is not, so to print lower eight bits
113 // from a register, use `start_bit = 0` and `stop_bit = 8`.
41 union reg_range range; 114 union reg_range range;
42 range.raw = (uintptr_t)pde_data(file_inode(f)); 115 range.raw = (uintptr_t)pde_data(file_inode(f));
43 116
@@ -47,7 +120,7 @@ static ssize_t nvdebug_reg_range_read(struct file *f, char __user *buf, size_t s
47 120
48 // Print bits `start_bit` to `stop_bit` from 32 bits at address `offset` 121 // Print bits `start_bit` to `stop_bit` from 32 bits at address `offset`
49 if ((read = nvdebug_readl(g, range.offset)) == -1) 122 if ((read = nvdebug_readl(g, range.offset)) == -1)
50 return -EOPNOTSUPP; 123 return -EIO;
51 // Setup `mask` used to throw out unused upper bits 124 // Setup `mask` used to throw out unused upper bits
52 mask = -1u >> (32 - range.stop_bit + range.start_bit); 125 mask = -1u >> (32 - range.stop_bit + range.start_bit);
53 // Throw out unused lower bits via a shift, apply the mask, and print 126 // Throw out unused lower bits via a shift, apply the mask, and print