diff options
| -rw-r--r-- | nvdebug.h | 37 | ||||
| -rw-r--r-- | nvdebug_entry.c | 53 | ||||
| -rw-r--r-- | runlist.c | 69 | ||||
| -rw-r--r-- | runlist_procfs.c | 198 |
4 files changed, 260 insertions, 97 deletions
| @@ -172,7 +172,8 @@ enum PREEMPT_TYPE {PREEMPT_TYPE_CHANNEL = 0, PREEMPT_TYPE_TSG = 1}; | |||
| 172 | IS_PENDING : Is a context switch pending? (read-only) | 172 | IS_PENDING : Is a context switch pending? (read-only) |
| 173 | TYPE : PREEMPT_TYPE_CHANNEL or PREEMPT_TYPE_TSG | 173 | TYPE : PREEMPT_TYPE_CHANNEL or PREEMPT_TYPE_TSG |
| 174 | 174 | ||
| 175 | Support: Kepler, Maxwell, Pascal, Volta, Turing | 175 | Support: Fermi*, Kepler, Maxwell, Pascal, Volta, Turing |
| 176 | *Fermi only supports PREEMPT_TYPE_CHANNEL. | ||
| 176 | */ | 177 | */ |
| 177 | #define NV_PFIFO_PREEMPT 0x00002634 | 178 | #define NV_PFIFO_PREEMPT 0x00002634 |
| 178 | typedef union { | 179 | typedef union { |
| @@ -187,10 +188,26 @@ typedef union { | |||
| 187 | uint32_t raw; | 188 | uint32_t raw; |
| 188 | } pfifo_preempt_t; | 189 | } pfifo_preempt_t; |
| 189 | 190 | ||
| 191 | /* Preempt a TSG or Runlist by ID | ||
| 192 | Similar as on older GPUs (see above), but located at an offset in Runlist RAM. | ||
| 193 | This means that there's one instance of this register for each runlist. | ||
| 194 | |||
| 195 | IS_PENDING is now IS_TSG_PREEMPT_PENDING and IS_RUNLIST_PREEMPT_PENDING was | ||
| 196 | added in the following bit (bit 22). As these fields are unused in nvdebug, | ||
| 197 | we use the old structure for simplicity. | ||
| 198 | |||
| 199 | TYPE is now better described as IS_TSG_PREEMPT. TYPE == 0 requests a preempt | ||
| 200 | of the runlist (rather than a channel preemption, as on older GPUs). | ||
| 201 | |||
| 202 | Support: Ampere, Hopper, Ada, [newer untested] | ||
| 203 | */ | ||
| 204 | #define NV_RUNLIST_PREEMPT_GA100 0x098 | ||
| 205 | #define PREEMPT_TYPE_RUNLIST 0 | ||
| 206 | |||
| 190 | /* | 207 | /* |
| 191 | "Initiate a preempt of the engine by writing the bit associated with its | 208 | "Initiate a preempt of the engine by writing the bit associated with its |
| 192 | runlist to NV_PFIFO_RUNLIST_PREEMPT... Do not poll NV_PFIFO_RUNLIST_PREEMPT | 209 | runlist to NV_PFIFO_RUNLIST_PREEMPT... Do not poll NV_PFIFO_RUNLIST_PREEMPT |
| 193 | for the preempt to complete." | 210 | for the preempt to complete." (open-gpu-doc) |
| 194 | 211 | ||
| 195 | Useful for preempting multiple runlists at once. | 212 | Useful for preempting multiple runlists at once. |
| 196 | 213 | ||
| @@ -204,7 +221,10 @@ typedef union { | |||
| 204 | rl_preempt.raw |= BIT(nr); | 221 | rl_preempt.raw |= BIT(nr); |
| 205 | nvdebug_writel(g, NV_PFIFO_RUNLIST_PREEMPT, rl_preempt.raw); | 222 | nvdebug_writel(g, NV_PFIFO_RUNLIST_PREEMPT, rl_preempt.raw); |
| 206 | 223 | ||
| 207 | Support: Volta, Turing | 224 | Support: Maxwell, Pascal, Volta, Turing |
| 225 | |||
| 226 | This register was deleted starting with Ampere, with functionality subsumed by | ||
| 227 | the NV_RUNLIST_PREEMPT register. | ||
| 208 | */ | 228 | */ |
| 209 | #define NV_PFIFO_RUNLIST_PREEMPT 0x00002638 | 229 | #define NV_PFIFO_RUNLIST_PREEMPT 0x00002638 |
| 210 | typedef union { | 230 | typedef union { |
| @@ -285,7 +305,7 @@ typedef union { | |||
| 285 | TARGET : Aperture of runlist (video or system memory) | 305 | TARGET : Aperture of runlist (video or system memory) |
| 286 | 306 | ||
| 287 | Support: Fermi*, Kepler, Maxwell, Pascal, Volta | 307 | Support: Fermi*, Kepler, Maxwell, Pascal, Volta |
| 288 | *Fermi may expose this information 8 bytes earlier, starting at 0x227C? | 308 | *Fermi may expose ENG_RUNLING_* 8 bytes earlier, starting at 0x227C? |
| 289 | */ | 309 | */ |
| 290 | #define NV_PFIFO_RUNLIST_BASE_GF100 0x00002270 // Write-only | 310 | #define NV_PFIFO_RUNLIST_BASE_GF100 0x00002270 // Write-only |
| 291 | #define NV_PFIFO_ENG_RUNLIST_BASE_GF100(i) (0x00002280+(i)*8) // Read-only | 311 | #define NV_PFIFO_ENG_RUNLIST_BASE_GF100(i) (0x00002280+(i)*8) // Read-only |
| @@ -428,7 +448,11 @@ typedef union { | |||
| 428 | See also: manuals/turing/tu104/dev_fifo.ref.txt in NVIDIA's open-gpu-doc | 448 | See also: manuals/turing/tu104/dev_fifo.ref.txt in NVIDIA's open-gpu-doc |
| 429 | */ | 449 | */ |
| 430 | #define NV_PCCSR_CHANNEL_INST(i) (0x00800000+(i)*8) | 450 | #define NV_PCCSR_CHANNEL_INST(i) (0x00800000+(i)*8) |
| 431 | #define MAX_CHID 512 | 451 | // Maximum valid channel index in the PCCSR region |
| 452 | // Channel IDs start at 0, and there are 4096 bytes of 8-byte CCSR entries (per | ||
| 453 | // NV_PCCSR_CHANNEL_INST__SIZE_1 in at least Volta and Turing), yielding a total | ||
| 454 | // of 512 channel IDs, with a maximum ID of 511. | ||
| 455 | #define MAX_CHID 511 | ||
| 432 | typedef union { | 456 | typedef union { |
| 433 | struct { | 457 | struct { |
| 434 | // 0:31 | 458 | // 0:31 |
| @@ -554,6 +578,7 @@ typedef union { | |||
| 554 | #define NV_CHIP_ID_GP106 0x136 // Discrete GeForce GTX 1060 | 578 | #define NV_CHIP_ID_GP106 0x136 // Discrete GeForce GTX 1060 |
| 555 | #define NV_CHIP_ID_GV11B 0x15B // Jetson Xavier embedded GPU | 579 | #define NV_CHIP_ID_GV11B 0x15B // Jetson Xavier embedded GPU |
| 556 | 580 | ||
| 581 | #define NV_CHIP_ID_FERMI 0x0C0 | ||
| 557 | #define NV_CHIP_ID_KEPLER 0x0E0 | 582 | #define NV_CHIP_ID_KEPLER 0x0E0 |
| 558 | #define NV_CHIP_ID_MAXWELL 0x120 | 583 | #define NV_CHIP_ID_MAXWELL 0x120 |
| 559 | #define NV_CHIP_ID_PASCAL 0x130 | 584 | #define NV_CHIP_ID_PASCAL 0x130 |
| @@ -1505,7 +1530,7 @@ int get_runlist_iter( | |||
| 1505 | struct nvdebug_state *g, | 1530 | struct nvdebug_state *g, |
| 1506 | int rl_id, | 1531 | int rl_id, |
| 1507 | struct runlist_iter *rl_iter /* out */); | 1532 | struct runlist_iter *rl_iter /* out */); |
| 1508 | int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id); | 1533 | int preempt_tsg(struct nvdebug_state *g, uint32_t rl_id, uint32_t tsg_id); |
| 1509 | int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id); | 1534 | int preempt_runlist(struct nvdebug_state *g, uint32_t rl_id); |
| 1510 | int resubmit_runlist(struct nvdebug_state *g, uint32_t rl_id); | 1535 | int resubmit_runlist(struct nvdebug_state *g, uint32_t rl_id); |
| 1511 | 1536 | ||
diff --git a/nvdebug_entry.c b/nvdebug_entry.c index 5f99976..d5df7db 100644 --- a/nvdebug_entry.c +++ b/nvdebug_entry.c | |||
| @@ -289,17 +289,45 @@ int __init nvdebug_init(void) { | |||
| 289 | snprintf(runlist_name, 12, "runlist%lu", last_runlist); | 289 | snprintf(runlist_name, 12, "runlist%lu", last_runlist); |
| 290 | if (!(rl_dir = proc_mkdir_data(runlist_name, 0555, dir, (void*)device_id))) | 290 | if (!(rl_dir = proc_mkdir_data(runlist_name, 0555, dir, (void*)device_id))) |
| 291 | goto out_nomem; | 291 | goto out_nomem; |
| 292 | // Create one file for each runlist on Ampere+, or one file for each GPU on older | ||
| 293 | if (g_nvdebug_state[res].chip_id >= NV_CHIP_ID_AMPERE || last_runlist == 0) { | ||
| 294 | struct proc_dir_entry *chram_scope; | ||
| 295 | // preempt_tsg, enable_channel, and disable_channel refer to a GPU-global channel | ||
| 296 | // RAM on pre-Ampere GPUs | ||
| 297 | if (g_nvdebug_state[res].chip_id >= NV_CHIP_ID_AMPERE) | ||
| 298 | chram_scope = rl_dir; | ||
| 299 | else | ||
| 300 | chram_scope = dir; | ||
| 301 | // Create file `/proc/gpu#/runlist#/preempt_tsg`, world writable | ||
| 302 | // On Turing and older, `/proc/gpu#/preempt_tsg` | ||
| 303 | if (!proc_create_data( | ||
| 304 | "preempt_tsg", 0222, chram_scope, compat_ops(&preempt_tsg_file_ops), | ||
| 305 | (void*)last_runlist)) | ||
| 306 | goto out_nomem; | ||
| 307 | // Create file `/proc/gpu#/runlist#/disable_channel`, world writable | ||
| 308 | // On Turing and older, `/proc/gpu#/disable_channel` | ||
| 309 | if (!proc_create_data( | ||
| 310 | "disable_channel", 0222, chram_scope, compat_ops(&disable_channel_file_ops), | ||
| 311 | (void*)last_runlist)) | ||
| 312 | goto out_nomem; | ||
| 313 | // Create file `/proc/gpu#/runlist#/enable_channel`, world writable | ||
| 314 | // On Turing and older, `/proc/gpu#/enable_channel` | ||
| 315 | if (!proc_create_data( | ||
| 316 | "enable_channel", 0222, chram_scope, compat_ops(&enable_channel_file_ops), | ||
| 317 | (void*)last_runlist)) | ||
| 318 | goto out_nomem; | ||
| 319 | } | ||
| 292 | // Create file `/proc/gpu#/runlist#/runlist`, world readable | 320 | // Create file `/proc/gpu#/runlist#/runlist`, world readable |
| 293 | if (!proc_create_data( | 321 | if (!proc_create_data( |
| 294 | "runlist", 0444, rl_dir, compat_ops(&runlist_file_ops), | 322 | "runlist", 0444, rl_dir, compat_ops(&runlist_file_ops), |
| 295 | (void*)last_runlist)) | 323 | (void*)last_runlist)) |
| 296 | goto out_nomem; | 324 | goto out_nomem; |
| 325 | // Create file `/proc/gpu#/runlist#/switch_to_tsg`, world writable | ||
| 326 | if (!proc_create_data( | ||
| 327 | "switch_to_tsg", 0222, rl_dir, compat_ops(&switch_to_tsg_file_ops), | ||
| 328 | (void*)last_runlist)) | ||
| 329 | goto out_nomem; | ||
| 297 | } while (last_runlist-- > 0); | 330 | } while (last_runlist-- > 0); |
| 298 | // Create file `/proc/gpu#/preempt_tsg`, world writable | ||
| 299 | if (!proc_create_data( | ||
| 300 | "preempt_tsg", 0222, dir, compat_ops(&preempt_tsg_file_ops), | ||
| 301 | (void*)device_id)) | ||
| 302 | goto out_nomem; | ||
| 303 | /* On the TU104, the context scheduler (contained in the Host, aka | 331 | /* On the TU104, the context scheduler (contained in the Host, aka |
| 304 | * PFIFO, unit) has been observed to sometimes to fail to schedule TSGs | 332 | * PFIFO, unit) has been observed to sometimes to fail to schedule TSGs |
| 305 | * containing re-enabled channels. Resubmitting the runlist | 333 | * containing re-enabled channels. Resubmitting the runlist |
| @@ -311,21 +339,6 @@ int __init nvdebug_init(void) { | |||
| 311 | "resubmit_runlist", 0222, dir, compat_ops(&resubmit_runlist_file_ops), | 339 | "resubmit_runlist", 0222, dir, compat_ops(&resubmit_runlist_file_ops), |
| 312 | (void*)device_id)) | 340 | (void*)device_id)) |
| 313 | goto out_nomem; | 341 | goto out_nomem; |
| 314 | // Create file `/proc/gpu#/disable_channel`, world writable | ||
| 315 | if (!proc_create_data( | ||
| 316 | "disable_channel", 0222, dir, compat_ops(&disable_channel_file_ops), | ||
| 317 | (void*)device_id)) | ||
| 318 | goto out_nomem; | ||
| 319 | // Create file `/proc/gpu#/enable_channel`, world writable | ||
| 320 | if (!proc_create_data( | ||
| 321 | "enable_channel", 0222, dir, compat_ops(&enable_channel_file_ops), | ||
| 322 | (void*)device_id)) | ||
| 323 | goto out_nomem; | ||
| 324 | // Create file `/proc/gpu#/switch_to_tsg`, world writable | ||
| 325 | if (!proc_create_data( | ||
| 326 | "switch_to_tsg", 0222, dir, compat_ops(&switch_to_tsg_file_ops), | ||
| 327 | (void*)device_id)) | ||
| 328 | goto out_nomem; | ||
| 329 | // Create file `/proc/gpu#/device_info`, world readable | 342 | // Create file `/proc/gpu#/device_info`, world readable |
| 330 | if (!proc_create_data( | 343 | if (!proc_create_data( |
| 331 | "device_info", 0444, dir, compat_ops(&device_info_file_ops), | 344 | "device_info", 0444, dir, compat_ops(&device_info_file_ops), |
| @@ -169,24 +169,35 @@ attempt_pramin_access: | |||
| 169 | 169 | ||
| 170 | /* Trigger a preempt of the specified TSG | 170 | /* Trigger a preempt of the specified TSG |
| 171 | @param tsg_id ID of TSG to preempt. | 171 | @param tsg_id ID of TSG to preempt. |
| 172 | @param rl_id Which channel RAM address space to search? | ||
| 172 | @return 0 or -errno on error | 173 | @return 0 or -errno on error |
| 173 | 174 | ||
| 174 | Note: If no other TSGs exist in the associated runlist, this TSG may | 175 | Note: If no other TSGs exist in the associated runlist, this TSG may |
| 175 | continue executing, unless NV_PFIFO_SCHED_DISABLE is set, or all the | 176 | continue executing, unless NV_PFIFO_SCHED_DISABLE is set, or all the |
| 176 | channels of the TSG to be preempted are disabled. | 177 | channels of the TSG to be preempted are disabled. |
| 177 | */ | 178 | */ |
| 178 | int preempt_tsg(struct nvdebug_state *g, uint32_t tsg_id) { | 179 | int preempt_tsg(struct nvdebug_state *g, uint32_t rl_id, uint32_t tsg_id) { |
| 179 | pfifo_preempt_t pfifo_preempt; | 180 | pfifo_preempt_t preempt; |
| 181 | // Fermi does not support time-slice groups | ||
| 180 | if (g->chip_id < NV_CHIP_ID_KEPLER) | 182 | if (g->chip_id < NV_CHIP_ID_KEPLER) |
| 181 | return -EOPNOTSUPP; | 183 | return -EOPNOTSUPP; |
| 182 | |||
