1 /*******************************************************************************
2 Copyright (c) 2015-2023 NVIDIA Corporation
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to
6 deal in the Software without restriction, including without limitation the
7 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 sell copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be
12 included in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 DEALINGS IN THE SOFTWARE.
21
22 *******************************************************************************/
23
24 #include "uvm_channel.h"
25
26 #include "uvm_api.h"
27 #include "uvm_common.h"
28 #include "uvm_global.h"
29 #include "uvm_hal.h"
30 #include "uvm_procfs.h"
31 #include "uvm_push.h"
32 #include "uvm_gpu_semaphore.h"
33 #include "uvm_lock.h"
34 #include "uvm_kvmalloc.h"
35
36 #include "nv_uvm_types.h"
37 #include "nv_uvm_interface.h"
38 #include "clb06f.h"
39 #include "uvm_conf_computing.h"
40
41 // WLC push is decrypted by SEC2 or CE (in WLC schedule).
42 // In sysmem it's followed by auth tag.
43 #define WLC_PUSHBUFFER_ALIGNMENT max3(UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT, \
44 UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT, \
45 UVM_CONF_COMPUTING_BUF_ALIGNMENT)
46 #define WLC_ALIGNED_MAX_PUSH_SIZE UVM_ALIGN_UP(UVM_MAX_WLC_PUSH_SIZE, WLC_PUSHBUFFER_ALIGNMENT)
47
48 // WLC uses the following structures in unprotected sysmem:
49 // * Encrypted pushbuffer location. This gets populated via cpu_encrypt to
50 // launch work on a WLC channel.
51 // * Auth tag associated with the above encrypted (push)buffer
52 // * Another auth tag used to encrypt another channel's pushbuffer during
53 // indirect work launch. This can be allocated with the launched work
54 // but since WLC can oly launch one pushbuffer at a time it's easier
55 // to include it here.
56 #define WLC_SYSMEM_TOTAL_SIZE UVM_ALIGN_UP(WLC_ALIGNED_MAX_PUSH_SIZE + 2 * UVM_CONF_COMPUTING_AUTH_TAG_SIZE, \
57 WLC_PUSHBUFFER_ALIGNMENT)
58
59 #define WLC_SYSMEM_PUSHBUFFER_OFFSET 0
60 #define WLC_SYSMEM_PUSHBUFFER_AUTH_TAG_OFFSET (WLC_SYSMEM_PUSHBUFFER_OFFSET + WLC_ALIGNED_MAX_PUSH_SIZE)
61 #define WLC_SYSMEM_LAUNCH_AUTH_TAG_OFFSET (WLC_SYSMEM_PUSHBUFFER_AUTH_TAG_OFFSET + UVM_CONF_COMPUTING_AUTH_TAG_SIZE)
62
63 // LCIC pushbuffer is populated by SEC2
64 #define LCIC_PUSHBUFFER_ALIGNMENT UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT
65 #define LCIC_ALIGNED_PUSH_SIZE UVM_ALIGN_UP(UVM_LCIC_PUSH_SIZE, LCIC_PUSHBUFFER_ALIGNMENT)
66
67 static unsigned uvm_channel_num_gpfifo_entries = UVM_CHANNEL_NUM_GPFIFO_ENTRIES_DEFAULT;
68
69 #define UVM_CHANNEL_GPFIFO_LOC_DEFAULT "auto"
70
71 static char *uvm_channel_gpfifo_loc = UVM_CHANNEL_GPFIFO_LOC_DEFAULT;
72
73 #define UVM_CHANNEL_GPPUT_LOC_DEFAULT "auto"
74
75 static char *uvm_channel_gpput_loc = UVM_CHANNEL_GPPUT_LOC_DEFAULT;
76
77 #define UVM_CHANNEL_PUSHBUFFER_LOC_DEFAULT "auto"
78
79 static char *uvm_channel_pushbuffer_loc = UVM_CHANNEL_PUSHBUFFER_LOC_DEFAULT;
80
81 module_param(uvm_channel_num_gpfifo_entries, uint, S_IRUGO);
82 module_param(uvm_channel_gpfifo_loc, charp, S_IRUGO);
83 module_param(uvm_channel_gpput_loc, charp, S_IRUGO);
84 module_param(uvm_channel_pushbuffer_loc, charp, S_IRUGO);
85
86 static NV_STATUS manager_create_procfs_dirs(uvm_channel_manager_t *manager);
87 static NV_STATUS manager_create_procfs(uvm_channel_manager_t *manager);
88 static NV_STATUS channel_create_procfs(uvm_channel_t *channel);
89
90 typedef enum
91 {
92 // Only remove completed GPFIFO entries from the pushbuffer
93 UVM_CHANNEL_UPDATE_MODE_COMPLETED,
94
95 // Remove all remaining GPFIFO entries from the pushbuffer, regardless of
96 // whether they're actually done yet.
97 UVM_CHANNEL_UPDATE_MODE_FORCE_ALL
98 } uvm_channel_update_mode_t;
99
uvm_channel_pool_uses_mutex(uvm_channel_pool_t * pool)100 bool uvm_channel_pool_uses_mutex(uvm_channel_pool_t *pool)
101 {
102 // Work submission to proxy channels in SR-IOV heavy entails calling RM API
103 // that acquires a mutex, so the proxy channel pool must use a mutex.
104 if (uvm_channel_pool_is_proxy(pool))
105 return true;
106
107 // When Confidential Computing is enabled push submission requires call to
108 // CSL routines which acquire the CSL context mutex lock. Moreover, WLC
109 // submission uses UVM_SPIN_LOOP, which can call 'schedule', to wait for
110 // LCIC completion. Indirect submission is synchronous, calling
111 // uvm_push_wait which again uses UVM_SPIN_LOOP.
112 if (g_uvm_global.conf_computing_enabled)
113 return true;
114
115 // Unless the mutex is required, the spinlock is preferred when work
116 // submission is expected to take little time.
117 return false;
118 }
119
channel_pool_lock_init(uvm_channel_pool_t * pool)120 static void channel_pool_lock_init(uvm_channel_pool_t *pool)
121 {
122 uvm_lock_order_t order = UVM_LOCK_ORDER_CHANNEL;
123
124 if (g_uvm_global.conf_computing_enabled && uvm_channel_pool_is_wlc(pool))
125 order = UVM_LOCK_ORDER_WLC_CHANNEL;
126
127 if (uvm_channel_pool_uses_mutex(pool))
128 uvm_mutex_init(&pool->mutex, order);
129 else
130 uvm_spin_lock_init(&pool->spinlock, order);
131 }
132
channel_pool_lock(uvm_channel_pool_t * pool)133 static void channel_pool_lock(uvm_channel_pool_t *pool)
134 {
135 if (uvm_channel_pool_uses_mutex(pool))
136 uvm_mutex_lock(&pool->mutex);
137 else
138 uvm_spin_lock(&pool->spinlock);
139 }
140
channel_pool_unlock(uvm_channel_pool_t * pool)141 static void channel_pool_unlock(uvm_channel_pool_t *pool)
142 {
143 if (uvm_channel_pool_uses_mutex(pool))
144 uvm_mutex_unlock(&pool->mutex);
145 else
146 uvm_spin_unlock(&pool->spinlock);
147 }
148
149 // Update channel progress, completing up to max_to_complete entries
uvm_channel_update_progress_with_max(uvm_channel_t * channel,NvU32 max_to_complete,uvm_channel_update_mode_t mode)150 static NvU32 uvm_channel_update_progress_with_max(uvm_channel_t *channel,
151 NvU32 max_to_complete,
152 uvm_channel_update_mode_t mode)
153 {
154 NvU32 gpu_get;
155 NvU32 cpu_put;
156 NvU32 completed_count = 0;
157 NvU32 pending_gpfifos;
158
159 NvU64 completed_value = uvm_channel_update_completed_value(channel);
160
161 channel_pool_lock(channel->pool);
162
163 // Completed value should never exceed the queued value
164 UVM_ASSERT_MSG_RELEASE(completed_value <= channel->tracking_sem.queued_value,
165 "GPU %s channel %s unexpected completed_value 0x%llx > queued_value 0x%llx\n",
166 uvm_gpu_name(uvm_channel_get_gpu(channel)),
167 channel->name,
168 completed_value,
169 channel->tracking_sem.queued_value);
170
171 cpu_put = channel->cpu_put;
172 gpu_get = channel->gpu_get;
173
174 while (gpu_get != cpu_put && completed_count < max_to_complete) {
175 uvm_gpfifo_entry_t *entry = &channel->gpfifo_entries[gpu_get];
176
177 if (mode == UVM_CHANNEL_UPDATE_MODE_COMPLETED && entry->tracking_semaphore_value > completed_value)
178 break;
179
180 if (entry->type == UVM_GPFIFO_ENTRY_TYPE_NORMAL) {
181 uvm_pushbuffer_mark_completed(channel, entry);
182 list_add_tail(&entry->push_info->available_list_node, &channel->available_push_infos);
183 }
184
185 gpu_get = (gpu_get + 1) % channel->num_gpfifo_entries;
186 ++completed_count;
187 }
188
189 channel->gpu_get = gpu_get;
190
191 channel_pool_unlock(channel->pool);
192
193 if (cpu_put >= gpu_get)
194 pending_gpfifos = cpu_put - gpu_get;
195 else
196 pending_gpfifos = channel->num_gpfifo_entries - gpu_get + cpu_put;
197
198 return pending_gpfifos;
199 }
200
uvm_channel_update_progress(uvm_channel_t * channel)201 NvU32 uvm_channel_update_progress(uvm_channel_t *channel)
202 {
203 // By default, don't complete too many entries at a time to spread the cost
204 // of doing so across callers and avoid potentially holding a spin lock for
205 // too long.
206 return uvm_channel_update_progress_with_max(channel, 8, UVM_CHANNEL_UPDATE_MODE_COMPLETED);
207 }
208
209 // Update progress for all pending GPFIFO entries. This might take a longer time
210 // and should be only used in exceptional circumstances like when a channel
211 // error is encountered. Otherwise, uvm_chanel_update_progress() should be used.
channel_update_progress_all(uvm_channel_t * channel,uvm_channel_update_mode_t mode)212 static NvU32 channel_update_progress_all(uvm_channel_t *channel, uvm_channel_update_mode_t mode)
213 {
214 return uvm_channel_update_progress_with_max(channel, channel->num_gpfifo_entries, mode);
215 }
216
uvm_channel_update_progress_all(uvm_channel_t * channel)217 NvU32 uvm_channel_update_progress_all(uvm_channel_t *channel)
218 {
219 return channel_update_progress_all(channel, UVM_CHANNEL_UPDATE_MODE_COMPLETED);
220 }
221
uvm_channel_manager_update_progress(uvm_channel_manager_t * channel_manager)222 NvU32 uvm_channel_manager_update_progress(uvm_channel_manager_t *channel_manager)
223 {
224 NvU32 pending_gpfifos = 0;
225 uvm_channel_pool_t *pool;
226
227 uvm_for_each_pool(pool, channel_manager) {
228 uvm_channel_t *channel;
229
230 uvm_for_each_channel_in_pool(channel, pool)
231 pending_gpfifos += uvm_channel_update_progress(channel);
232 }
233
234 return pending_gpfifos;
235 }
236
channel_get_available_gpfifo_entries(uvm_channel_t * channel)237 static NvU32 channel_get_available_gpfifo_entries(uvm_channel_t *channel)
238 {
239 NvU32 available = channel->num_gpfifo_entries;
240
241 uvm_channel_pool_assert_locked(channel->pool);
242
243 // Remove sentinel entry
244 available -= 1;
245
246 // Remove entries of ongoing pushes
247 available -= channel->current_gpfifo_count;
248
249 // Remove pending entries
250 if (channel->cpu_put >= channel->gpu_get)
251 available -= (channel->cpu_put - channel->gpu_get);
252 else
253 available -= (channel->cpu_put + channel->num_gpfifo_entries - channel->gpu_get);
254
255 UVM_ASSERT(available < channel->num_gpfifo_entries);
256
257 return available;
258 }
259
uvm_channel_get_available_gpfifo_entries(uvm_channel_t * channel)260 NvU32 uvm_channel_get_available_gpfifo_entries(uvm_channel_t *channel)
261 {
262 NvU32 available;
263
264 channel_pool_lock(channel->pool);
265 available = channel_get_available_gpfifo_entries(channel);
266 channel_pool_unlock(channel->pool);
267
268 return available;
269 }
270
try_claim_channel_locked(uvm_channel_t * channel,NvU32 num_gpfifo_entries)271 static bool try_claim_channel_locked(uvm_channel_t *channel, NvU32 num_gpfifo_entries)
272 {
273 bool claimed = false;
274
275 UVM_ASSERT(num_gpfifo_entries > 0);
276 UVM_ASSERT(num_gpfifo_entries < channel->num_gpfifo_entries);
277
278 uvm_channel_pool_assert_locked(channel->pool);
279
280 if (channel_get_available_gpfifo_entries(channel) >= num_gpfifo_entries) {
281 channel->current_gpfifo_count += num_gpfifo_entries;
282 claimed = true;
283 }
284
285 return claimed;
286 }
287
try_claim_channel(uvm_channel_t * channel,NvU32 num_gpfifo_entries)288 static bool try_claim_channel(uvm_channel_t *channel, NvU32 num_gpfifo_entries)
289 {
290 bool claimed;
291
292 channel_pool_lock(channel->pool);
293 claimed = try_claim_channel_locked(channel, num_gpfifo_entries);
294 channel_pool_unlock(channel->pool);
295
296 return claimed;
297 }
298
unlock_channel_for_push(uvm_channel_t * channel)299 static void unlock_channel_for_push(uvm_channel_t *channel)
300 {
301 NvU32 index;
302
303 if (!g_uvm_global.conf_computing_enabled)
304 return;
305
306 index = uvm_channel_index_in_pool(channel);
307
308 uvm_channel_pool_assert_locked(channel->pool);
309 UVM_ASSERT(test_bit(index, channel->pool->conf_computing.push_locks));
310
311 __clear_bit(index, channel->pool->conf_computing.push_locks);
312 uvm_up_out_of_order(&channel->pool->conf_computing.push_sem);
313 }
314
uvm_channel_is_locked_for_push(uvm_channel_t * channel)315 bool uvm_channel_is_locked_for_push(uvm_channel_t *channel)
316 {
317 if (g_uvm_global.conf_computing_enabled)
318 return test_bit(uvm_channel_index_in_pool(channel), channel->pool->conf_computing.push_locks);
319
320 // For CE and proxy channels, we always return that the channel is locked,
321 // which has no functional impact in the UVM channel code-flow, this is only
322 // used in UVM_ASSERTs.
323 return true;
324 }
325
lock_channel_for_push(uvm_channel_t * channel)326 static void lock_channel_for_push(uvm_channel_t *channel)
327 {
328 NvU32 index = uvm_channel_index_in_pool(channel);
329
330 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
331 uvm_channel_pool_assert_locked(channel->pool);
332 UVM_ASSERT(!test_bit(index, channel->pool->conf_computing.push_locks));
333
334 __set_bit(index, channel->pool->conf_computing.push_locks);
335 }
336
test_claim_and_lock_channel(uvm_channel_t * channel,NvU32 num_gpfifo_entries)337 static bool test_claim_and_lock_channel(uvm_channel_t *channel, NvU32 num_gpfifo_entries)
338 {
339 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
340 uvm_channel_pool_assert_locked(channel->pool);
341
342 // Already locked by someone else
343 if (uvm_channel_is_locked_for_push(channel))
344 return false;
345
346 if (try_claim_channel_locked(channel, num_gpfifo_entries)) {
347 lock_channel_for_push(channel);
348 return true;
349 }
350
351 return false;
352 }
353
354 // Reserve, or release, all channels in the given pool.
355 //
356 // One scenario where reservation of the entire pool is useful is key rotation,
357 // because the reservation blocks addition of new work to the pool while
358 // rotation is in progress.
channel_pool_reserve_release_all_channels(uvm_channel_pool_t * pool,bool reserve)359 static void channel_pool_reserve_release_all_channels(uvm_channel_pool_t *pool, bool reserve)
360 {
361 NvU32 i;
362
363 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
364
365 // Disable lock tracking: a single thread is acquiring multiple locks of
366 // the same order
367 uvm_thread_context_lock_disable_tracking();
368
369 for (i = 0; i < pool->num_channels; i++) {
370 if (reserve)
371 uvm_down(&pool->conf_computing.push_sem);
372 else
373 uvm_up(&pool->conf_computing.push_sem);
374 }
375
376 uvm_thread_context_lock_enable_tracking();
377 }
378
channel_pool_reserve_all_channels(uvm_channel_pool_t * pool)379 static void channel_pool_reserve_all_channels(uvm_channel_pool_t *pool)
380 {
381 channel_pool_reserve_release_all_channels(pool, true);
382 }
383
channel_pool_release_all_channels(uvm_channel_pool_t * pool)384 static void channel_pool_release_all_channels(uvm_channel_pool_t *pool)
385 {
386 channel_pool_reserve_release_all_channels(pool, false);
387 }
388
channel_pool_rotate_key_locked(uvm_channel_pool_t * pool)389 static NV_STATUS channel_pool_rotate_key_locked(uvm_channel_pool_t *pool)
390 {
391 uvm_channel_t *channel;
392
393 // A rotation is not necessarily pending, because UVM can trigger rotations
394 // at will.
395 UVM_ASSERT(uvm_conf_computing_is_key_rotation_enabled_in_pool(pool));
396
397 uvm_assert_mutex_locked(&pool->conf_computing.key_rotation.mutex);
398
399 uvm_for_each_channel_in_pool(channel, pool) {
400 NV_STATUS status = uvm_channel_wait(channel);
401 if (status != NV_OK)
402 return status;
403
404 if (uvm_channel_pool_is_wlc(pool)) {
405 uvm_spin_loop_t spin;
406 uvm_channel_t *lcic_channel = uvm_channel_wlc_get_paired_lcic(channel);
407
408 // LCIC pushes don't exist as such. Rely on the tracking semaphore
409 // to determine completion, instead of uvm_channel_wait
410 UVM_SPIN_WHILE(!uvm_gpu_tracking_semaphore_is_completed(&lcic_channel->tracking_sem), &spin);
411 }
412 }
413
414 return uvm_conf_computing_rotate_pool_key(pool);
415 }
416
channel_pool_rotate_key(uvm_channel_pool_t * pool,bool force_rotation)417 static NV_STATUS channel_pool_rotate_key(uvm_channel_pool_t *pool, bool force_rotation)
418 {
419 NV_STATUS status = NV_OK;
420
421 uvm_mutex_lock(&pool->conf_computing.key_rotation.mutex);
422
423 if (force_rotation || uvm_conf_computing_is_key_rotation_pending_in_pool(pool)) {
424 channel_pool_reserve_all_channels(pool);
425
426 status = channel_pool_rotate_key_locked(pool);
427
428 channel_pool_release_all_channels(pool);
429 }
430
431 uvm_mutex_unlock(&pool->conf_computing.key_rotation.mutex);
432
433 return status;
434 }
435
channel_pool_rotate_key_if_pending(uvm_channel_pool_t * pool)436 static NV_STATUS channel_pool_rotate_key_if_pending(uvm_channel_pool_t *pool)
437 {
438 NV_STATUS status;
439 bool force_rotation = false;
440
441 if (!uvm_conf_computing_is_key_rotation_enabled_in_pool(pool))
442 return NV_OK;
443
444 status = channel_pool_rotate_key(pool, force_rotation);
445
446 // RM couldn't acquire the locks it needed, so UVM will try again later.
447 if (status == NV_ERR_STATE_IN_USE)
448 status = NV_OK;
449
450 return status;
451 }
452
uvm_channel_pool_rotate_key(uvm_channel_pool_t * pool)453 NV_STATUS uvm_channel_pool_rotate_key(uvm_channel_pool_t *pool)
454 {
455 bool force_rotation = true;
456
457 return channel_pool_rotate_key(pool, force_rotation);
458 }
459
460 // Reserve a channel in the specified pool. The channel is locked until the push
461 // ends
channel_reserve_and_lock_in_pool(uvm_channel_pool_t * pool,uvm_channel_t ** channel_out)462 static NV_STATUS channel_reserve_and_lock_in_pool(uvm_channel_pool_t *pool, uvm_channel_t **channel_out)
463 {
464 uvm_channel_t *channel;
465 uvm_spin_loop_t spin;
466 NvU32 index;
467 NV_STATUS status;
468
469 UVM_ASSERT(pool);
470 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
471
472 // LCIC channels are reserved directly during GPU initialization.
473 UVM_ASSERT(!uvm_channel_pool_is_lcic(pool));
474
475 status = channel_pool_rotate_key_if_pending(pool);
476 if (status != NV_OK)
477 return status;
478
479 // This semaphore is uvm_up() in unlock_channel_for_push() as part of the
480 // uvm_channel_end_push() routine.
481 uvm_down(&pool->conf_computing.push_sem);
482
483 // At least one channel is unlocked. We check if any unlocked channel is
484 // available, i.e., if it has free GPFIFO entries.
485
486 channel_pool_lock(pool);
487
488 for_each_clear_bit(index, pool->conf_computing.push_locks, pool->num_channels) {
489 channel = &pool->channels[index];
490 if (try_claim_channel_locked(channel, 1)) {
491 lock_channel_for_push(channel);
492 goto done;
493 }
494 }
495
496 channel_pool_unlock(pool);
497
498 // No channels are available. Update and check errors on all channels until
499 // one becomes available.
500 uvm_spin_loop_init(&spin);
501 while (1) {
502 uvm_for_each_channel_in_pool(channel, pool) {
503 uvm_channel_update_progress(channel);
504
505 channel_pool_lock(pool);
506
507 if (test_claim_and_lock_channel(channel, 1))
508 goto done;
509
510 channel_pool_unlock(pool);
511
512 status = uvm_channel_check_errors(channel);
513 if (status != NV_OK) {
514 uvm_up(&pool->conf_computing.push_sem);
515 return status;
516 }
517
518 UVM_SPIN_LOOP(&spin);
519 }
520 }
521
522 done:
523 channel_pool_unlock(pool);
524 *channel_out = channel;
525 return NV_OK;
526 }
527
528 // Reserve a channel in the specified pool
channel_reserve_in_pool(uvm_channel_pool_t * pool,uvm_channel_t ** channel_out)529 static NV_STATUS channel_reserve_in_pool(uvm_channel_pool_t *pool, uvm_channel_t **channel_out)
530 {
531 uvm_channel_t *channel;
532 uvm_spin_loop_t spin;
533
534 UVM_ASSERT(pool);
535
536 if (g_uvm_global.conf_computing_enabled)
537 return channel_reserve_and_lock_in_pool(pool, channel_out);
538
539 uvm_for_each_channel_in_pool(channel, pool) {
540 // TODO: Bug 1764953: Prefer idle/less busy channels
541 if (try_claim_channel(channel, 1)) {
542 *channel_out = channel;
543 return NV_OK;
544 }
545 }
546
547 uvm_spin_loop_init(&spin);
548 while (1) {
549 uvm_for_each_channel_in_pool(channel, pool) {
550 NV_STATUS status;
551
552 uvm_channel_update_progress(channel);
553
554 if (try_claim_channel(channel, 1)) {
555 *channel_out = channel;
556
557 return NV_OK;
558 }
559
560 status = uvm_channel_check_errors(channel);
561 if (status != NV_OK)
562 return status;
563
564 UVM_SPIN_LOOP(&spin);
565 }
566 }
567
568 UVM_ASSERT_MSG(0, "Cannot get here?!\n");
569
570 return NV_ERR_GENERIC;
571 }
572
uvm_channel_reserve_type(uvm_channel_manager_t * manager,uvm_channel_type_t type,uvm_channel_t ** channel_out)573 NV_STATUS uvm_channel_reserve_type(uvm_channel_manager_t *manager, uvm_channel_type_t type, uvm_channel_t **channel_out)
574 {
575 uvm_channel_pool_t *pool = manager->pool_to_use.default_for_type[type];
576
577 UVM_ASSERT(pool != NULL);
578 UVM_ASSERT(type < UVM_CHANNEL_TYPE_COUNT);
579
580 return channel_reserve_in_pool(pool, channel_out);
581 }
582
uvm_channel_reserve_gpu_to_gpu(uvm_channel_manager_t * manager,uvm_gpu_t * dst_gpu,uvm_channel_t ** channel_out)583 NV_STATUS uvm_channel_reserve_gpu_to_gpu(uvm_channel_manager_t *manager,
584 uvm_gpu_t *dst_gpu,
585 uvm_channel_t **channel_out)
586 {
587 const NvU32 dst_gpu_index = uvm_id_gpu_index(dst_gpu->id);
588 uvm_channel_pool_t *pool = manager->pool_to_use.gpu_to_gpu[dst_gpu_index];
589
590 // If there is no recommended pool for the given GPU pair, use default
591 if (pool == NULL)
592 pool = manager->pool_to_use.default_for_type[UVM_CHANNEL_TYPE_GPU_TO_GPU];
593
594 UVM_ASSERT(pool->pool_type == UVM_CHANNEL_POOL_TYPE_CE);
595
596 return channel_reserve_in_pool(pool, channel_out);
597 }
598
uvm_channel_manager_wait(uvm_channel_manager_t * manager)599 NV_STATUS uvm_channel_manager_wait(uvm_channel_manager_t *manager)
600 {
601 NV_STATUS status = NV_OK;
602 uvm_spin_loop_t spin;
603
604 if (uvm_channel_manager_update_progress(manager) == 0)
605 return uvm_channel_manager_check_errors(manager);
606
607 uvm_spin_loop_init(&spin);
608 while (uvm_channel_manager_update_progress(manager) > 0 && status == NV_OK) {
609 UVM_SPIN_LOOP(&spin);
610 status = uvm_channel_manager_check_errors(manager);
611 }
612
613 return status;
614 }
615
channel_get_available_push_info_index(uvm_channel_t * channel)616 static NvU32 channel_get_available_push_info_index(uvm_channel_t *channel)
617 {
618 uvm_push_info_t *push_info;
619
620 channel_pool_lock(channel->pool);
621
622 push_info = list_first_entry_or_null(&channel->available_push_infos, uvm_push_info_t, available_list_node);
623 UVM_ASSERT(push_info != NULL);
624 UVM_ASSERT(push_info->on_complete == NULL && push_info->on_complete_data == NULL);
625 list_del(&push_info->available_list_node);
626
627 channel_pool_unlock(channel->pool);
628
629 return push_info - channel->push_infos;
630 }
631
channel_pool_num_gpfifo_entries(uvm_channel_pool_t * pool)632 static unsigned channel_pool_num_gpfifo_entries(uvm_channel_pool_t *pool)
633 {
634 UVM_ASSERT(uvm_pool_type_is_valid(pool->pool_type));
635
636 // WLC benefits from larger number of entries since more available entries
637 // result in less frequent calls to uvm_channel_update_progress. 16 is the
638 // maximum size that can re-use static pb preallocated memory when uploading
639 // the WLC schedule.
640 if (uvm_channel_pool_is_wlc(pool))
641 return 16;
642
643 // Every channel needs at least 3 entries; 1 for sentinel and 2 for
644 // submitting GPFIFO control entries. The number also has to be power of 2,
645 // as the HW stores the size as log2 value. LCIC does not accept external
646 // pushes, uvm_channel_update_progress is not a concern.
647 if (uvm_channel_pool_is_lcic(pool))
648 return 4;
649
650 return pool->manager->conf.num_gpfifo_entries;
651 }
652
channel_semaphore_gpu_encrypt_payload(uvm_push_t * push,NvU64 semaphore_va)653 static void channel_semaphore_gpu_encrypt_payload(uvm_push_t *push, NvU64 semaphore_va)
654 {
655 NvU32 iv_index;
656 uvm_gpu_t *gpu = push->gpu;
657 uvm_channel_t *channel = push->channel;
658 uvm_gpu_semaphore_t *semaphore = &channel->tracking_sem.semaphore;
659 uvm_gpu_address_t notifier_gpu_va = uvm_gpu_semaphore_get_notifier_gpu_va(semaphore);
660 uvm_gpu_address_t auth_tag_gpu_va = uvm_gpu_semaphore_get_auth_tag_gpu_va(semaphore);
661 uvm_gpu_address_t encrypted_payload_gpu_va = uvm_gpu_semaphore_get_encrypted_payload_gpu_va(semaphore);
662 uvm_gpu_address_t semaphore_gpu_va = uvm_gpu_address_virtual(semaphore_va);
663 UvmCslIv *iv_cpu_addr = semaphore->conf_computing.ivs;
664 NvU32 payload_size = sizeof(*uvm_gpu_semaphore_get_encrypted_payload_cpu_va(semaphore));
665 uvm_gpu_semaphore_notifier_t *last_pushed_notifier = &semaphore->conf_computing.last_pushed_notifier;
666
667 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
668 UVM_ASSERT(uvm_channel_is_ce(channel));
669
670 iv_index = ((*last_pushed_notifier + 2) / 2) % channel->num_gpfifo_entries;
671
672 uvm_conf_computing_log_gpu_encryption(channel, payload_size, &iv_cpu_addr[iv_index]);
673
674 gpu->parent->ce_hal->memset_4(push, notifier_gpu_va, ++(*last_pushed_notifier), sizeof(*last_pushed_notifier));
675 gpu->parent->ce_hal->encrypt(push, encrypted_payload_gpu_va, semaphore_gpu_va, payload_size, auth_tag_gpu_va);
676 gpu->parent->ce_hal->memset_4(push, notifier_gpu_va, ++(*last_pushed_notifier), sizeof(*last_pushed_notifier));
677 }
678
679 // Auxiliary buffer only used by SEC2 channels for CPU computation of the method
680 // stream signature. Note that it is required that this inline pushbuffer buffer
681 // is reserved at push->begin.
push_reserve_csl_sign_buf(uvm_push_t * push)682 static void push_reserve_csl_sign_buf(uvm_push_t *push)
683 {
684 uvm_gpu_address_t dummy;
685 NvU32 *buf;
686
687 buf = uvm_push_get_single_inline_buffer(push, UVM_CONF_COMPUTING_SIGN_BUF_MAX_SIZE, UVM_METHOD_SIZE, &dummy);
688
689 // Offset UVM_METHOD_SIZE from buf due to the NOP method.
690 UVM_ASSERT((buf - UVM_METHOD_SIZE / sizeof(*buf)) == push->begin);
691 }
692
get_paired_pool(uvm_channel_pool_t * pool)693 static uvm_channel_pool_t *get_paired_pool(uvm_channel_pool_t *pool)
694 {
695 uvm_channel_type_t paired_channel_type;
696 uvm_channel_pool_t *paired_pool;
697
698 UVM_ASSERT(pool);
699 UVM_ASSERT(uvm_channel_pool_is_wlc(pool) || uvm_channel_pool_is_lcic(pool));
700
701 paired_channel_type = uvm_channel_pool_is_wlc(pool) ? UVM_CHANNEL_TYPE_LCIC : UVM_CHANNEL_TYPE_WLC;
702 paired_pool = pool->manager->pool_to_use.default_for_type[paired_channel_type];
703
704 // Prevent accessing a non-existing paired pool. This can happen if, for
705 // example, the function is invoked when the WLC pool exists, but the LCIC
706 // doesn't (it hasn't been created yet, or it has been already destroyed).
707 UVM_ASSERT(paired_pool);
708
709 return paired_pool;
710 }
711
get_paired_channel(uvm_channel_t * channel)712 static uvm_channel_t *get_paired_channel(uvm_channel_t *channel)
713 {
714 uvm_channel_pool_t *paired_pool;
715 unsigned index;
716
717 UVM_ASSERT(channel);
718
719 paired_pool = get_paired_pool(channel->pool);
720 index = uvm_channel_index_in_pool(channel);
721
722 return paired_pool->channels + index;
723 }
724
uvm_channel_lcic_get_paired_wlc(uvm_channel_t * lcic_channel)725 uvm_channel_t *uvm_channel_lcic_get_paired_wlc(uvm_channel_t *lcic_channel)
726 {
727 UVM_ASSERT(lcic_channel);
728 UVM_ASSERT(uvm_channel_is_lcic(lcic_channel));
729
730 return get_paired_channel(lcic_channel);
731 }
732
uvm_channel_wlc_get_paired_lcic(uvm_channel_t * wlc_channel)733 uvm_channel_t *uvm_channel_wlc_get_paired_lcic(uvm_channel_t *wlc_channel)
734 {
735 UVM_ASSERT(wlc_channel);
736 UVM_ASSERT(uvm_channel_is_wlc(wlc_channel));
737
738 return get_paired_channel(wlc_channel);
739 }
740
uvm_channel_get_static_pb_protected_vidmem_gpu_va(uvm_channel_t * channel)741 NvU64 uvm_channel_get_static_pb_protected_vidmem_gpu_va(uvm_channel_t *channel)
742 {
743 unsigned channel_index;
744 NvU64 pool_vidmem_base;
745
746 UVM_ASSERT(channel);
747 UVM_ASSERT(uvm_channel_is_wlc(channel) || uvm_channel_is_lcic(channel));
748
749 channel_index = uvm_channel_index_in_pool(channel);
750 pool_vidmem_base = uvm_rm_mem_get_gpu_uvm_va(channel->pool->conf_computing.pool_vidmem,
751 uvm_channel_get_gpu(channel));
752
753 if (uvm_channel_is_lcic(channel))
754 return pool_vidmem_base + channel_index * LCIC_ALIGNED_PUSH_SIZE;
755
756 return pool_vidmem_base + 2 * channel_index * WLC_ALIGNED_MAX_PUSH_SIZE;
757 }
758
get_channel_unprotected_sysmem_gpu_va(uvm_channel_t * channel)759 static NvU64 get_channel_unprotected_sysmem_gpu_va(uvm_channel_t *channel)
760 {
761 unsigned channel_index;
762 NvU64 pool_sysmem_base;
763
764 UVM_ASSERT(channel);
765 UVM_ASSERT(uvm_channel_is_wlc(channel));
766
767 channel_index = uvm_channel_index_in_pool(channel);
768 pool_sysmem_base = uvm_rm_mem_get_gpu_uvm_va(channel->pool->conf_computing.pool_sysmem,
769 uvm_channel_get_gpu(channel));
770
771 return pool_sysmem_base + (channel_index * WLC_SYSMEM_TOTAL_SIZE);
772 }
773
uvm_channel_get_static_pb_unprotected_sysmem_gpu_va(uvm_channel_t * channel)774 NvU64 uvm_channel_get_static_pb_unprotected_sysmem_gpu_va(uvm_channel_t *channel)
775 {
776 return get_channel_unprotected_sysmem_gpu_va(channel) + WLC_SYSMEM_PUSHBUFFER_OFFSET;
777 }
778
get_channel_unprotected_sysmem_cpu(uvm_channel_t * channel)779 static char* get_channel_unprotected_sysmem_cpu(uvm_channel_t *channel)
780 {
781 unsigned channel_index;
782 char* pool_sysmem_base;
783
784 UVM_ASSERT(channel);
785 UVM_ASSERT(uvm_channel_is_wlc(channel));
786
787 channel_index = uvm_channel_index_in_pool(channel);
788 pool_sysmem_base = uvm_rm_mem_get_cpu_va(channel->pool->conf_computing.pool_sysmem);
789
790 return pool_sysmem_base + (channel_index * WLC_SYSMEM_TOTAL_SIZE);
791 }
792
uvm_channel_get_static_pb_unprotected_sysmem_cpu(uvm_channel_t * channel)793 char* uvm_channel_get_static_pb_unprotected_sysmem_cpu(uvm_channel_t *channel)
794 {
795 return get_channel_unprotected_sysmem_cpu(channel) + WLC_SYSMEM_PUSHBUFFER_OFFSET;
796 }
797
uvm_channel_get_push_crypto_bundle_auth_tags_cpu_va(uvm_channel_t * channel,unsigned tag_index)798 char *uvm_channel_get_push_crypto_bundle_auth_tags_cpu_va(uvm_channel_t *channel, unsigned tag_index)
799 {
800 char *pool_sysmem_base;
801 unsigned index;
802
803 UVM_ASSERT(channel);
804 UVM_ASSERT(!uvm_channel_is_wlc(channel));
805 UVM_ASSERT(!uvm_channel_is_lcic(channel));
806 UVM_ASSERT(uvm_channel_is_ce(channel));
807 UVM_ASSERT(channel->num_gpfifo_entries == channel_pool_num_gpfifo_entries(channel->pool));
808 UVM_ASSERT(tag_index < channel->num_gpfifo_entries);
809
810 index = uvm_channel_index_in_pool(channel) * channel->num_gpfifo_entries + tag_index;
811 pool_sysmem_base = uvm_rm_mem_get_cpu_va(channel->pool->conf_computing.pool_sysmem);
812
813 return pool_sysmem_base + index * UVM_CONF_COMPUTING_AUTH_TAG_SIZE;
814 }
815
get_push_crypto_bundle_auth_tags_gpu_va(uvm_channel_t * channel,unsigned tag_index)816 static NvU64 get_push_crypto_bundle_auth_tags_gpu_va(uvm_channel_t *channel, unsigned tag_index)
817 {
818 unsigned index;
819 NvU64 pool_sysmem_base;
820
821 UVM_ASSERT(channel);
822 UVM_ASSERT(!uvm_channel_is_wlc(channel));
823 UVM_ASSERT(!uvm_channel_is_lcic(channel));
824 UVM_ASSERT(uvm_channel_is_ce(channel));
825 UVM_ASSERT(channel->num_gpfifo_entries == channel_pool_num_gpfifo_entries(channel->pool));
826 UVM_ASSERT(tag_index < channel->num_gpfifo_entries);
827
828 index = uvm_channel_index_in_pool(channel) * channel->num_gpfifo_entries + tag_index;
829 pool_sysmem_base = uvm_rm_mem_get_gpu_uvm_va(channel->pool->conf_computing.pool_sysmem,
830 uvm_channel_get_gpu(channel));
831
832
833 return pool_sysmem_base + index * UVM_CONF_COMPUTING_AUTH_TAG_SIZE;
834 }
835
channel_rotate_and_reserve_launch_channel(uvm_channel_t * channel,uvm_channel_t ** launch_channel)836 static NV_STATUS channel_rotate_and_reserve_launch_channel(uvm_channel_t *channel, uvm_channel_t **launch_channel)
837 {
838 uvm_channel_manager_t *manager = channel->pool->manager;
839 NV_STATUS status;
840
841 status = uvm_conf_computing_maybe_rotate_channel_ivs(channel);
842 if (status != NV_OK)
843 return status;
844
845 // CE channels, other than WLC fix launch schedule setup, need a launch
846 // channel that needs to be reserved
847 if (uvm_channel_is_ce(channel) &&
848 !(uvm_channel_is_wlc(channel) && uvm_channel_manager_is_wlc_ready(manager))) {
849 uvm_channel_t *local_launch_channel = NULL;
850 uvm_channel_type_t indirect_channel_type = uvm_channel_manager_is_wlc_ready(manager) ?
851 UVM_CHANNEL_TYPE_WLC :
852 UVM_CHANNEL_TYPE_SEC2;
853 status = uvm_channel_reserve_type(manager, indirect_channel_type, &local_launch_channel);
854 if (status != NV_OK)
855 return status;
856
857 // Indirect launch relies on pre-allocated resources to avoid failure
858 // paths. This includes pre-allocating IV space. There's no way to
859 // undo the launch channel reservation, so just return an error.
860 status = uvm_conf_computing_maybe_rotate_channel_ivs(local_launch_channel);
861 if (status != NV_OK) {
862 uvm_channel_release(local_launch_channel, 1);
863 return status;
864 }
865
866 if (uvm_channel_is_wlc(local_launch_channel)) {
867 status = uvm_conf_computing_maybe_rotate_channel_ivs(uvm_channel_wlc_get_paired_lcic(local_launch_channel));
868 if (status != NV_OK) {
869 uvm_channel_release(local_launch_channel, 1);
870 return status;
871 }
872 }
873 *launch_channel = local_launch_channel;
874 }
875
876
877 return NV_OK;
878 }
879
uvm_channel_begin_push(uvm_channel_t * channel,uvm_push_t * push)880 NV_STATUS uvm_channel_begin_push(uvm_channel_t *channel, uvm_push_t *push)
881 {
882 NV_STATUS status = NV_OK;
883 uvm_channel_manager_t *manager;
884
885 UVM_ASSERT(channel);
886 UVM_ASSERT(push);
887
888 manager = channel->pool->manager;
889
890 // Only SEC2 and WLC with set up fixed schedule can use direct push
891 // submission. All other cases (including WLC pre-schedule) need to
892 // reserve a launch channel that will be used to submit this push
893 // indirectly.
894 if (g_uvm_global.conf_computing_enabled) {
895 status = channel_rotate_and_reserve_launch_channel(channel, &push->launch_channel);
896 if (status != NV_OK)
897 return status;
898 }
899
900 // When the Confidential Computing feature is enabled, the channel's lock
901 // should have already been acquired in uvm_channel_reserve() or
902 // channel_reserve_and_lock_in_pool().
903 UVM_ASSERT(uvm_channel_is_locked_for_push(channel));
904
905 push->channel = channel;
906 push->channel_tracking_value = 0;
907
908 status = uvm_pushbuffer_begin_push(manager->pushbuffer, push);
909 if (status != NV_OK)
910 return status;
911
912 push->push_info_index = channel_get_available_push_info_index(channel);
913
914 if (uvm_channel_is_sec2(push->channel))
915 push_reserve_csl_sign_buf(push);
916 else if (uvm_channel_is_wlc(push->channel) && uvm_channel_manager_is_wlc_ready(manager))
917 uvm_conf_computing_acquire_encryption_iv(push->channel, &push->launch_iv);
918
919 return NV_OK;
920 }
921
internal_channel_submit_work(uvm_push_t * push,NvU32 push_size,NvU32 new_gpu_put)922 static void internal_channel_submit_work(uvm_push_t *push, NvU32 push_size, NvU32 new_gpu_put)
923 {
924 NvU64 *gpfifo_entry;
925 NvU64 pushbuffer_va;
926 uvm_channel_t *channel = push->channel;
927 uvm_pushbuffer_t *pushbuffer = uvm_channel_get_pushbuffer(channel);
928 uvm_gpu_t *gpu = uvm_channel_get_gpu(channel);
929
930 BUILD_BUG_ON(sizeof(*gpfifo_entry) != NVB06F_GP_ENTRY__SIZE);
931 UVM_ASSERT(!uvm_channel_is_proxy(channel));
932
933 gpfifo_entry = (NvU64*)channel->channel_info.gpFifoEntries + channel->cpu_put;
934 pushbuffer_va = uvm_pushbuffer_get_gpu_va_for_push(pushbuffer, push);
935
936 if (g_uvm_global.conf_computing_enabled) {
937 void *unprotected_pb = uvm_pushbuffer_get_unprotected_cpu_va_for_push(pushbuffer, push);
938 UVM_ASSERT(uvm_channel_is_sec2(channel));
939
940 // Copy push data to unprotected sysmem, it has already been signed.
941 memcpy(unprotected_pb, push->begin, push_size);
942 }
943
944 gpu->parent->host_hal->set_gpfifo_entry(gpfifo_entry, pushbuffer_va, push_size, UVM_GPFIFO_SYNC_PROCEED);
945
946 // Need to make sure all the pushbuffer and the GPFIFO entries writes
947 // complete before updating GPPUT. We also don't want any reads to be moved
948 // after the GPPut write as the GPU might modify the data they read as soon
949 // as the GPPut write happens.
950 mb();
951
952 gpu->parent->host_hal->write_gpu_put(channel, new_gpu_put);
953 }
954
proxy_channel_submit_work(uvm_push_t * push,NvU32 push_size)955 static void proxy_channel_submit_work(uvm_push_t *push, NvU32 push_size)
956 {
957 NV_STATUS status;
958 uvm_channel_t *channel = push->channel;
959
960 UVM_ASSERT(uvm_channel_is_proxy(channel));
961
962 status = nvUvmInterfacePagingChannelPushStream(channel->proxy.handle, (char *) push->begin, push_size);
963
964 if (status != NV_OK) {
965 uvm_push_info_t *push_info = uvm_push_info_from_push(push);
966
967 // If the RM invocation fails, there is no clean recovery available
968 // (for example, the vGPU plugin may have crashed), so swallow the error
969 // but print a descriptive message about the failed push.
970 UVM_ASSERT_MSG(status == NV_OK,
971 "nvUvmInterfacePagingChannelPushStream() failed: %s, GPU %s, push '%s' started at %s:%d in %s()\n",
972 nvstatusToString(status),
973 uvm_gpu_name(uvm_channel_get_gpu(channel)),
974 push_info->description,
975 push_info->filename,
976 push_info->line,
977 push_info->function);
978 }
979 }
980
do_semaphore_release(uvm_push_t * push,NvU64 semaphore_va,NvU32 new_payload)981 static void do_semaphore_release(uvm_push_t *push, NvU64 semaphore_va, NvU32 new_payload)
982 {
983 uvm_gpu_t *gpu = uvm_push_get_gpu(push);
984
985 if (uvm_channel_is_ce(push->channel))
986 gpu->parent->ce_hal->semaphore_release(push, semaphore_va, new_payload);
987 else
988 gpu->parent->sec2_hal->semaphore_release(push, semaphore_va, new_payload);
989 }
990
uvm_channel_tracking_semaphore_release(uvm_push_t * push,NvU64 semaphore_va,NvU32 new_payload)991 static void uvm_channel_tracking_semaphore_release(uvm_push_t *push, NvU64 semaphore_va, NvU32 new_payload)
992 {
993 // We used to skip the membar or use membar GPU for the semaphore release
994 // for a few pushes, but that doesn't provide sufficient ordering guarantees
995 // in some cases (e.g. ga100 with an LCE with PCEs from both HSHUBs) for the
996 // semaphore writes. To be safe, just always uses a membar sys for now.
997 // TODO: Bug 3770539: Optimize membars used by end of push semaphore releases
998 (void)uvm_push_get_and_reset_flag(push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU);
999 (void)uvm_push_get_and_reset_flag(push, UVM_PUSH_FLAG_NEXT_MEMBAR_NONE);
1000
1001 do_semaphore_release(push, semaphore_va, new_payload);
1002
1003 // When the Confidential Computing feature is enabled, additional work
1004 // needs to be scheduled to get an encrypted shadow copy in unprotected
1005 // sysmem. This allows UVM to later decrypt it and observe the new
1006 // semaphore value.
1007 if (g_uvm_global.conf_computing_enabled && uvm_channel_is_ce(push->channel))
1008 channel_semaphore_gpu_encrypt_payload(push, semaphore_va);
1009 }
1010
lcic_static_entry_notifier_cpu_va(uvm_channel_t * lcic)1011 static uvm_gpu_semaphore_notifier_t *lcic_static_entry_notifier_cpu_va(uvm_channel_t *lcic)
1012 {
1013 uvm_gpu_semaphore_notifier_t *notifier_base;
1014
1015 UVM_ASSERT(uvm_channel_is_lcic(lcic));
1016
1017 notifier_base = uvm_rm_mem_get_cpu_va(lcic->pool->conf_computing.pool_sysmem);
1018 return notifier_base + uvm_channel_index_in_pool(lcic) * 2;
1019 }
1020
lcic_static_exit_notifier_cpu_va(uvm_channel_t * lcic)1021 static uvm_gpu_semaphore_notifier_t *lcic_static_exit_notifier_cpu_va(uvm_channel_t *lcic)
1022 {
1023 return lcic_static_entry_notifier_cpu_va(lcic) + 1;
1024 }
1025
lcic_static_entry_notifier_gpu_va(uvm_channel_t * lcic)1026 static uvm_gpu_address_t lcic_static_entry_notifier_gpu_va(uvm_channel_t *lcic)
1027 {
1028 NvU64 notifier_base;
1029 const NvU64 offset = uvm_channel_index_in_pool(lcic) * 2 * sizeof(uvm_gpu_semaphore_notifier_t);
1030
1031 UVM_ASSERT(uvm_channel_is_lcic(lcic));
1032
1033 notifier_base = uvm_rm_mem_get_gpu_uvm_va(lcic->pool->conf_computing.pool_sysmem, uvm_channel_get_gpu(lcic));
1034 return uvm_gpu_address_virtual_unprotected(notifier_base + offset);
1035 }
1036
lcic_static_exit_notifier_gpu_va(uvm_channel_t * lcic)1037 static uvm_gpu_address_t lcic_static_exit_notifier_gpu_va(uvm_channel_t *lcic)
1038 {
1039 uvm_gpu_address_t notifier_address = lcic_static_entry_notifier_gpu_va(lcic);
1040
1041 notifier_address.address += sizeof(uvm_gpu_semaphore_notifier_t);
1042 return notifier_address;
1043 }
1044
internal_channel_submit_work_wlc(uvm_push_t * push)1045 static void internal_channel_submit_work_wlc(uvm_push_t *push)
1046 {
1047 size_t payload_size;
1048 uvm_channel_t *wlc_channel = push->channel;
1049 uvm_channel_t *lcic_channel = uvm_channel_wlc_get_paired_lcic(wlc_channel);
1050 uvm_gpu_semaphore_t *lcic_semaphore = &lcic_channel->tracking_sem.semaphore;
1051 UvmCslIv *iv_cpu_addr = lcic_semaphore->conf_computing.ivs;
1052 uvm_gpu_semaphore_notifier_t *last_pushed_notifier;
1053 NvU32 iv_index;
1054 uvm_spin_loop_t spin;
1055 void* auth_tag_cpu = get_channel_unprotected_sysmem_cpu(wlc_channel) + WLC_SYSMEM_PUSHBUFFER_AUTH_TAG_OFFSET;
1056
1057
1058 // Wait for the WLC/LCIC to be primed. This means that PUT == GET + 2
1059 // and a WLC doorbell ring is enough to start work.
1060 UVM_SPIN_WHILE(!uvm_gpu_tracking_semaphore_is_completed(&lcic_channel->tracking_sem), &spin);
1061
1062 // Executing WLC adds an extra job to LCIC
1063 ++lcic_channel->tracking_sem.queued_value;
1064
1065 UVM_ASSERT_MSG(uvm_push_get_size(push) == UVM_MAX_WLC_PUSH_SIZE,
1066 "WLC push submission size mismatch, expected: %u, got: %u",
1067 UVM_MAX_WLC_PUSH_SIZE,
1068 uvm_push_get_size(push));
1069
1070 // Handles the CPU part of the setup for the LCIC to be able to do GPU
1071 // encryption of its tracking semaphore value. See setup_lcic_schedule().
1072 last_pushed_notifier = &lcic_semaphore->conf_computing.last_pushed_notifier;
1073 *lcic_static_entry_notifier_cpu_va(lcic_channel) = ++(*last_pushed_notifier);
1074 *lcic_static_exit_notifier_cpu_va(lcic_channel) = ++(*last_pushed_notifier);
1075 iv_index = (*last_pushed_notifier / 2) % lcic_channel->num_gpfifo_entries;
1076
1077 payload_size = sizeof(*uvm_gpu_semaphore_get_encrypted_payload_cpu_va(lcic_semaphore));
1078 uvm_conf_computing_log_gpu_encryption(lcic_channel, payload_size, &iv_cpu_addr[iv_index]);
1079
1080 // Move push data
1081 uvm_conf_computing_cpu_encrypt(wlc_channel,
1082 uvm_channel_get_static_pb_unprotected_sysmem_cpu(wlc_channel),
1083 push->begin,
1084 &push->launch_iv,
1085 UVM_MAX_WLC_PUSH_SIZE,
1086 auth_tag_cpu);
1087
1088 // Make sure all encrypted data is observable before ringing the doorbell.
1089 wmb();
1090
1091 // Ring the WLC doorbell to start processing the above push
1092 UVM_GPU_WRITE_ONCE(*wlc_channel->channel_info.workSubmissionOffset, wlc_channel->channel_info.workSubmissionToken);
1093 }
1094
internal_channel_submit_work_indirect_wlc(uvm_push_t * push,NvU32 old_cpu_put,NvU32 new_gpu_put)1095 static void internal_channel_submit_work_indirect_wlc(uvm_push_t *push, NvU32 old_cpu_put, NvU32 new_gpu_put)
1096 {
1097 uvm_pushbuffer_t *pushbuffer = uvm_channel_get_pushbuffer(push->channel);
1098 uvm_gpu_t *gpu = uvm_push_get_gpu(push);
1099
1100 uvm_push_t indirect_push;
1101 NV_STATUS status;
1102 NvU64 gpfifo_entry;
1103
1104 void *push_enc_cpu = uvm_pushbuffer_get_unprotected_cpu_va_for_push(pushbuffer, push);
1105 NvU64 push_enc_gpu = uvm_pushbuffer_get_unprotected_gpu_va_for_push(pushbuffer, push);
1106 void *push_enc_auth_tag_cpu;
1107 uvm_gpu_address_t push_enc_auth_tag_gpu;
1108 NvU64 gpfifo_gpu_va = push->channel->channel_info.gpFifoGpuVa + old_cpu_put * sizeof(gpfifo_entry);
1109
1110 UVM_ASSERT(uvm_channel_is_ce(push->channel));
1111 UVM_ASSERT(uvm_channel_is_wlc(push->launch_channel));
1112
1113 // WLC submissions are done under channel lock, so there should be no
1114 // contention to get the right submission order.
1115 UVM_ASSERT(push->channel->conf_computing.gpu_put == old_cpu_put);
1116
1117 // This can never stall or return error. WLC launch after WLC channels are
1118 // initialized uses private static pb space and it neither needs the general
1119 // PB space, nor it counts towards max concurrent pushes.
1120 status = uvm_push_begin_on_reserved_channel(push->launch_channel,
1121 &indirect_push,
1122 "Worklaunch to '%s' via '%s'",
1123 push->channel->name,
1124 push->launch_channel->name);
1125 UVM_ASSERT(status == NV_OK);
1126
1127
1128 // Move over the pushbuffer data
1129 // WLC channels use a static preallocated space for launch auth tags
1130 push_enc_auth_tag_cpu = get_channel_unprotected_sysmem_cpu(indirect_push.channel) + WLC_SYSMEM_LAUNCH_AUTH_TAG_OFFSET;
1131 push_enc_auth_tag_gpu = uvm_gpu_address_virtual_unprotected(
1132 get_channel_unprotected_sysmem_gpu_va(indirect_push.channel) + WLC_SYSMEM_LAUNCH_AUTH_TAG_OFFSET);
1133
1134 uvm_conf_computing_cpu_encrypt(indirect_push.channel,
1135 push_enc_cpu,
1136 push->begin,
1137 NULL,
1138 uvm_push_get_size(push),
1139 push_enc_auth_tag_cpu);
1140
1141 uvm_push_set_flag(&indirect_push, UVM_PUSH_FLAG_NEXT_MEMBAR_NONE);
1142
1143 gpu->parent->ce_hal->decrypt(&indirect_push,
1144 uvm_gpu_address_virtual(uvm_pushbuffer_get_gpu_va_for_push(pushbuffer, push)),
1145 uvm_gpu_address_virtual(push_enc_gpu),
1146 uvm_push_get_size(push),
1147 push_enc_auth_tag_gpu);
1148
1149 gpu->parent->host_hal->set_gpfifo_entry(&gpfifo_entry,
1150 uvm_pushbuffer_get_gpu_va_for_push(pushbuffer, push),
1151 uvm_push_get_size(push),
1152 UVM_GPFIFO_SYNC_PROCEED);
1153
1154 gpu->parent->ce_hal->memset_8(&indirect_push,
1155 uvm_gpu_address_virtual(gpfifo_gpu_va),
1156 gpfifo_entry,
1157 sizeof(gpfifo_entry));
1158
1159 uvm_push_set_flag(&indirect_push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU);
1160 do_semaphore_release(&indirect_push, push->channel->channel_info.gpPutGpuVa, new_gpu_put);
1161
1162 uvm_push_set_flag(&indirect_push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU);
1163 do_semaphore_release(&indirect_push,
1164 push->channel->channel_info.workSubmissionOffsetGpuVa,
1165 push->channel->channel_info.workSubmissionToken);
1166
1167 // Ignore return value of push_wait. It can only fail with channel error
1168 // which will be detected when waiting for the primary push.
1169 (void)uvm_push_end_and_wait(&indirect_push);
1170
1171 push->channel->conf_computing.gpu_put = new_gpu_put;
1172 }
1173
update_gpput_via_sec2(uvm_push_t * sec2_push,uvm_channel_t * channel,NvU32 new_gpu_put)1174 static void update_gpput_via_sec2(uvm_push_t *sec2_push, uvm_channel_t *channel, NvU32 new_gpu_put)
1175 {
1176 uvm_gpu_t *gpu = uvm_push_get_gpu(sec2_push);
1177 void *gpput_auth_tag_cpu, *gpput_enc_cpu;
1178 uvm_gpu_address_t gpput_auth_tag_gpu, gpput_enc_gpu;
1179 NvU32 gpput_scratchpad[UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT/sizeof(new_gpu_put)];
1180
1181 UVM_ASSERT(uvm_channel_is_sec2(sec2_push->channel));
1182
1183 gpput_enc_cpu = uvm_push_get_single_inline_buffer(sec2_push,
1184 UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT,
1185 UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT,
1186 &gpput_enc_gpu);
1187 gpput_auth_tag_cpu = uvm_push_get_single_inline_buffer(sec2_push,
1188 UVM_CONF_COMPUTING_AUTH_TAG_SIZE,
1189 UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT,
1190 &gpput_auth_tag_gpu);
1191
1192 // Update GPPUT. The update needs 4B write to specific offset,
1193 // however we can only do 16B aligned decrypt writes.
1194 // A poison value is written to all other locations, this is ignored in
1195 // most locations and overwritten by HW for GPGET location
1196 memset(gpput_scratchpad, 0, sizeof(gpput_scratchpad));
1197 UVM_ASSERT(sizeof(*gpput_scratchpad) == sizeof(new_gpu_put));
1198 gpput_scratchpad[(channel->channel_info.gpPutGpuVa % UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT) /
1199 sizeof(*gpput_scratchpad)] = new_gpu_put;
1200
1201 // Set value of GPGET to be the same as GPPUT. It will be overwritten by
1202 // HW next time GET value changes. UVM never reads GPGET.
1203 // However, RM does read it when freeing a channel. When this function
1204 // is called from 'channel_manager_stop_wlc' we set the value of GPGET
1205 // to the same value as GPPUT. Mismatch between these two values makes
1206 // RM wait for any "pending" tasks, leading to significant delays in the
1207 // channel teardown sequence.
1208 UVM_ASSERT(channel->channel_info.gpPutGpuVa / UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT ==
1209 channel->channel_info.gpGetGpuVa / UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT);
1210 gpput_scratchpad[(channel->channel_info.gpGetGpuVa % UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT) /
1211 sizeof(*gpput_scratchpad)] = new_gpu_put;
1212
1213 uvm_conf_computing_cpu_encrypt(sec2_push->channel,
1214 gpput_enc_cpu,
1215 gpput_scratchpad,
1216 NULL,
1217 sizeof(gpput_scratchpad),
1218 gpput_auth_tag_cpu);
1219 gpu->parent->sec2_hal->decrypt(sec2_push,
1220 UVM_ALIGN_DOWN(channel->channel_info.gpPutGpuVa,
1221 UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT),
1222 gpput_enc_gpu.address,
1223 sizeof(gpput_scratchpad),
1224 gpput_auth_tag_gpu.address);
1225 }
1226
set_gpfifo_via_sec2(uvm_push_t * sec2_push,uvm_channel_t * channel,NvU32 put,NvU64 value)1227 static void set_gpfifo_via_sec2(uvm_push_t *sec2_push, uvm_channel_t *channel, NvU32 put, NvU64 value)
1228 {
1229 uvm_gpu_t *gpu = uvm_push_get_gpu(sec2_push);
1230 void *gpfifo_auth_tag_cpu, *gpfifo_enc_cpu;
1231 uvm_gpu_address_t gpfifo_auth_tag_gpu, gpfifo_enc_gpu;
1232 NvU64 gpfifo_gpu = channel->channel_info.gpFifoGpuVa + put * sizeof(value);
1233 NvU64 gpfifo_scratchpad[2];
1234
1235 UVM_ASSERT(uvm_channel_is_sec2(sec2_push->channel));
1236
1237 gpfifo_enc_cpu = uvm_push_get_single_inline_buffer(sec2_push,
1238 sizeof(gpfifo_scratchpad),
1239 UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT,
1240 &gpfifo_enc_gpu);
1241 gpfifo_auth_tag_cpu = uvm_push_get_single_inline_buffer(sec2_push,
1242 UVM_CONF_COMPUTING_AUTH_TAG_SIZE,
1243 UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT,
1244 &gpfifo_auth_tag_gpu);
1245
1246 if (IS_ALIGNED(gpfifo_gpu, UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT)) {
1247 gpfifo_scratchpad[0] = value;
1248
1249 // Set the value of the odd entry to noop.
1250 // It will be overwritten when the next entry is submitted.
1251 gpu->parent->host_hal->set_gpfifo_noop(&gpfifo_scratchpad[1]);
1252 }
1253 else {
1254 uvm_gpfifo_entry_t *previous_gpfifo;
1255
1256 UVM_ASSERT(put > 0);
1257
1258 previous_gpfifo = &channel->gpfifo_entries[put - 1];
1259
1260 if (previous_gpfifo->type == UVM_GPFIFO_ENTRY_TYPE_CONTROL) {
1261 gpfifo_scratchpad[0] = previous_gpfifo->control_value;
1262 }
1263 else {
1264 uvm_pushbuffer_t *pushbuffer = uvm_channel_get_pushbuffer(channel);
1265 NvU64 prev_pb_va = uvm_pushbuffer_get_gpu_va_base(pushbuffer) + previous_gpfifo->pushbuffer_offset;
1266
1267 // Reconstruct the previous GPFIFO entry. UVM_GPFIFO_SYNC_WAIT is
1268 // used only in static WLC schedule.
1269 // Overwriting the previous entry with the same value doesn't hurt,
1270 // whether the previous entry has been processed or not
1271 gpu->parent->host_hal->set_gpfifo_entry(&gpfifo_scratchpad[0],
1272 prev_pb_va,
1273 previous_gpfifo->pushbuffer_size,
1274 UVM_GPFIFO_SYNC_PROCEED);
1275 }
1276
1277 gpfifo_scratchpad[1] = value;
1278 }
1279
1280 uvm_conf_computing_cpu_encrypt(sec2_push->channel,
1281 gpfifo_enc_cpu,
1282 gpfifo_scratchpad,
1283 NULL,
1284 sizeof(gpfifo_scratchpad),
1285 gpfifo_auth_tag_cpu);
1286 gpu->parent->sec2_hal->decrypt(sec2_push,
1287 UVM_ALIGN_DOWN(gpfifo_gpu, UVM_CONF_COMPUTING_SEC2_BUF_ALIGNMENT),
1288 gpfifo_enc_gpu.address,
1289 sizeof(gpfifo_scratchpad),
1290 gpfifo_auth_tag_gpu.address);
1291 }
1292
internal_channel_submit_work_indirect_sec2(uvm_push_t * push,NvU32 old_cpu_put,NvU32 new_gpu_put)1293 static NV_STATUS internal_channel_submit_work_indirect_sec2(uvm_push_t *push, NvU32 old_cpu_put, NvU32 new_gpu_put)
1294 {
1295 uvm_pushbuffer_t *pushbuffer = uvm_channel_get_pushbuffer(push->channel);
1296 uvm_gpu_t *gpu = uvm_push_get_gpu(push);
1297
1298 uvm_push_t indirect_push;
1299 NV_STATUS status;
1300 NvU64 gpfifo_entry;
1301
1302 void *push_enc_cpu = uvm_pushbuffer_get_unprotected_cpu_va_for_push(pushbuffer, push);
1303 NvU64 push_enc_gpu = uvm_pushbuffer_get_unprotected_gpu_va_for_push(pushbuffer, push);
1304 void *push_auth_tag_cpu;
1305 uvm_gpu_address_t push_auth_tag_gpu;
1306 uvm_spin_loop_t spin;
1307
1308 UVM_ASSERT(uvm_channel_is_ce(push->channel));
1309 UVM_ASSERT(uvm_channel_is_sec2(push->launch_channel));
1310
1311 // If the old_cpu_put is not equal to the last gpu put, other pushes are
1312 // pending that need to be submitted. That push/es' submission will update
1313 // the gpu_put pointer to expected value.
1314 UVM_SPIN_WHILE(push->channel->conf_computing.gpu_put != old_cpu_put, &spin);
1315
1316 // This can never stall or return error. SEC2 launch used during init has
1317 // plenty of PB space available before it needs to check for push
1318 // completion/channel status. WLC launch after WLC channels are initialized
1319 // uses private static pb space and needs neither general PB space, nor it
1320 // counts towards max concurrent pushes.
1321 status = uvm_push_begin_on_reserved_channel(push->launch_channel,
1322 &indirect_push,
1323 "Worklaunch to '%s' via '%s'",
1324 push->channel->name,
1325 push->launch_channel->name);
1326 if (status != NV_OK)
1327 return status;
1328
1329
1330 // Move over the pushbuffer data
1331 push_auth_tag_cpu = uvm_push_get_single_inline_buffer(&indirect_push,
1332 UVM_CONF_COMPUTING_AUTH_TAG_SIZE,
1333 UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT,
1334 &push_auth_tag_gpu);
1335
1336 uvm_conf_computing_cpu_encrypt(indirect_push.channel,
1337 push_enc_cpu,
1338 push->begin,
1339 NULL,
1340 uvm_push_get_size(push),
1341 push_auth_tag_cpu);
1342
1343 uvm_push_set_flag(&indirect_push, UVM_PUSH_FLAG_NEXT_MEMBAR_NONE);
1344
1345 gpu->parent->sec2_hal->decrypt(&indirect_push,
1346 uvm_pushbuffer_get_gpu_va_for_push(pushbuffer, push),
1347 push_enc_gpu,
1348 uvm_push_get_size(push),
1349 push_auth_tag_gpu.address);
1350
1351 gpu->parent->host_hal->set_gpfifo_entry(&gpfifo_entry,
1352 uvm_pushbuffer_get_gpu_va_for_push(pushbuffer, push),
1353 uvm_push_get_size(push),
1354 UVM_GPFIFO_SYNC_PROCEED);
1355
1356
1357 set_gpfifo_via_sec2(&indirect_push, push->channel, old_cpu_put, gpfifo_entry);
1358 update_gpput_via_sec2(&indirect_push, push->channel, new_gpu_put);
1359
1360 // Ring the doorbell
1361 uvm_push_set_flag(&indirect_push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU);
1362 do_semaphore_release(&indirect_push,
1363 push->channel->channel_info.workSubmissionOffsetGpuVa,
1364 push->channel->channel_info.workSubmissionToken);
1365
1366 status = uvm_push_end_and_wait(&indirect_push);
1367 if (status != NV_OK)
1368 return status;
1369
1370 push->channel->conf_computing.gpu_put = new_gpu_put;
1371
1372 return status;
1373 }
1374
1375 // When the Confidential Computing feature is enabled, the CPU is unable to
1376 // access and read the pushbuffer. This is because it is located in the CPR of
1377 // vidmem in this configuration. This function allows UVM to retrieve the
1378 // content of the pushbuffer in an encrypted form for later decryption, hence,
1379 // simulating the original access pattern. E.g, reading timestamp semaphores.
1380 // See also: decrypt_push().
encrypt_push(uvm_push_t * push)1381 static void encrypt_push(uvm_push_t *push)
1382 {
1383 NvU64 push_protected_gpu_va;
1384 NvU64 push_unprotected_gpu_va;
1385 NvU64 auth_tag_gpu_va;
1386 uvm_channel_t *channel = push->channel;
1387 uvm_push_crypto_bundle_t *crypto_bundle;
1388 uvm_gpu_t *gpu = uvm_push_get_gpu(push);
1389 NvU32 push_size = uvm_push_get_size(push);
1390 uvm_push_info_t *push_info = uvm_push_info_from_push(push);
1391 uvm_pushbuffer_t *pushbuffer = uvm_channel_get_pushbuffer(channel);
1392
1393 if (!g_uvm_global.conf_computing_enabled)
1394 return;
1395
1396 if (!push_info->on_complete)
1397 return;
1398
1399 if (!uvm_channel_is_ce(channel))
1400 return;
1401
1402 if (push_size == 0)
1403 return;
1404
1405 UVM_ASSERT(!uvm_channel_is_wlc(channel));
1406 UVM_ASSERT(!uvm_channel_is_lcic(channel));
1407 UVM_ASSERT(channel->conf_computing.push_crypto_bundles != NULL);
1408
1409 crypto_bundle = channel->conf_computing.push_crypto_bundles + push->push_info_index;
1410 auth_tag_gpu_va = get_push_crypto_bundle_auth_tags_gpu_va(channel, push->push_info_index);
1411
1412 crypto_bundle->push_size = push_size;
1413 push_protected_gpu_va = uvm_pushbuffer_get_gpu_va_for_push(pushbuffer, push);
1414 push_unprotected_gpu_va = uvm_pushbuffer_get_unprotected_gpu_va_for_push(pushbuffer, push);
1415
1416 uvm_conf_computing_log_gpu_encryption(channel, push_size, &crypto_bundle->iv);
1417 crypto_bundle->key_version = uvm_channel_pool_key_version(channel->pool);
1418
1419 gpu->parent->ce_hal->encrypt(push,
1420 uvm_gpu_address_virtual_unprotected(push_unprotected_gpu_va),
1421 uvm_gpu_address_virtual(push_protected_gpu_va),
1422 push_size,
1423 uvm_gpu_address_virtual_unprotected(auth_tag_gpu_va));
1424 }
1425
uvm_channel_end_push(uvm_push_t * push)1426 void uvm_channel_end_push(uvm_push_t *push)
1427 {
1428 uvm_channel_t *channel = push->channel;
1429 uvm_channel_manager_t *channel_manager = channel->pool->manager;
1430 uvm_pushbuffer_t *pushbuffer = channel_manager->pushbuffer;
1431 uvm_gpfifo_entry_t *entry;
1432 NvU64 semaphore_va;
1433 NvU64 new_tracking_value;
1434 NvU32 new_payload;
1435 NvU32 push_size;
1436 NvU32 cpu_put;
1437 NvU32 new_cpu_put;
1438 bool needs_sec2_work_submit = false;
1439
1440 channel_pool_lock(channel->pool);
1441
1442 encrypt_push(push);
1443
1444 new_tracking_value = ++channel->tracking_sem.queued_value;
1445 new_payload = (NvU32)new_tracking_value;
1446
1447 semaphore_va = uvm_channel_tracking_semaphore_get_gpu_va(channel);
1448 uvm_channel_tracking_semaphore_release(push, semaphore_va, new_payload);
1449
1450 if (uvm_channel_is_wlc(channel) && uvm_channel_manager_is_wlc_ready(channel_manager)) {
1451 uvm_gpu_t *gpu = uvm_channel_get_gpu(channel);
1452 uvm_channel_t *paired_lcic = uvm_channel_wlc_get_paired_lcic(channel);
1453
1454 gpu->parent->ce_hal->semaphore_reduction_inc(push,
1455 paired_lcic->channel_info.gpPutGpuVa,
1456 paired_lcic->num_gpfifo_entries - 1);
1457 uvm_push_set_flag(push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU);
1458 do_semaphore_release(push,
1459 paired_lcic->channel_info.workSubmissionOffsetGpuVa,
1460 paired_lcic->channel_info.workSubmissionToken);
1461
1462 if (uvm_push_get_size(push) < UVM_MAX_WLC_PUSH_SIZE) {
1463 // The UVM_MAX_WLC_PUSH_SIZE is set to fit indirect work launch
1464 // pushes. However, direct pushes to WLC can be smaller than this
1465 // size. This is used e.g. by indirect submission of control
1466 // GPFIFO entries.
1467 gpu->parent->host_hal->noop(push, UVM_MAX_WLC_PUSH_SIZE - uvm_push_get_size(push));
1468 }
1469 }
1470
1471 push_size = uvm_push_get_size(push);
1472 UVM_ASSERT_MSG(push_size <= UVM_MAX_PUSH_SIZE, "push size %u\n", push_size);
1473
1474 cpu_put = channel->cpu_put;
1475 new_cpu_put = (cpu_put + 1) % channel->num_gpfifo_entries;
1476
1477 entry = &channel->gpfifo_entries[cpu_put];
1478 entry->tracking_semaphore_value = new_tracking_value;
1479 entry->pushbuffer_offset = uvm_pushbuffer_get_offset_for_push(pushbuffer, push);
1480 entry->pushbuffer_size = push_size;
1481
1482 // Indirect submission via SEC2/WLC needs pushes to be aligned for
1483 // encryption/decryption. The pushbuffer_size of this push
1484 // influences starting address of the next push.
1485 if (g_uvm_global.conf_computing_enabled)
1486 entry->pushbuffer_size = UVM_ALIGN_UP(push_size, UVM_CONF_COMPUTING_BUF_ALIGNMENT);
1487
1488 entry->push_info = &channel->push_infos[push->push_info_index];
1489 entry->type = UVM_GPFIFO_ENTRY_TYPE_NORMAL;
1490
1491 UVM_ASSERT(channel->current_gpfifo_count > 0);
1492 --channel->current_gpfifo_count;
1493
1494 if (uvm_channel_is_proxy(channel)) {
1495 proxy_channel_submit_work(push, push_size);
1496 }
1497 else if (uvm_channel_is_wlc(channel) && uvm_channel_manager_is_wlc_ready(channel_manager)) {
1498 internal_channel_submit_work_wlc(push);
1499 }
1500 else if (g_uvm_global.conf_computing_enabled && uvm_channel_is_ce(channel)) {
1501 if (uvm_channel_manager_is_wlc_ready(channel_manager)) {
1502 internal_channel_submit_work_indirect_wlc(push, cpu_put, new_cpu_put);
1503 }
1504 else {
1505 // submitting via SEC2 starts a push, postpone until this push is
1506 // ended
1507 needs_sec2_work_submit = true;
1508 }
1509 }
1510 else {
1511 internal_channel_submit_work(push, push_size, new_cpu_put);
1512 }
1513
1514 channel->cpu_put = new_cpu_put;
1515
1516 uvm_pushbuffer_end_push(pushbuffer, push, entry);
1517
1518 // The moment the channel is unlocked uvm_channel_update_progress_with_max()
1519 // may notice the GPU work to be completed and hence all state tracking the
1520 // push must be updated before that. Notably uvm_pushbuffer_end_push() has
1521 // to be called first.
1522 unlock_channel_for_push(channel);
1523 channel_pool_unlock(channel->pool);
1524
1525 // This memory barrier is borrowed from CUDA, as it supposedly fixes perf
1526 // issues on some systems. Comment from CUDA: "fixes throughput-related
1527 // performance problems, e.g. bugs 626179, 593841. This may be related to
1528 // bug 124888, which GL works around by doing a clflush"
1529 wmb();
1530
1531 if (needs_sec2_work_submit) {
1532 NV_STATUS status = internal_channel_submit_work_indirect_sec2(push, cpu_put, new_cpu_put);
1533
1534 // This codepath should only be used during initialization and thus
1535 // NEVER return an error.
1536 UVM_ASSERT(status == NV_OK);
1537 }
1538
1539 push->push_info_index = channel->num_gpfifo_entries;
1540 push->channel_tracking_value = new_tracking_value;
1541 }
1542
submit_ctrl_gpfifo(uvm_channel_t * channel,uvm_gpfifo_entry_t * entry,NvU32 new_cpu_put)1543 static void submit_ctrl_gpfifo(uvm_channel_t *channel, uvm_gpfifo_entry_t *entry, NvU32 new_cpu_put)
1544 {
1545 uvm_gpu_t *gpu = uvm_channel_get_gpu(channel);
1546 NvU32 cpu_put = channel->cpu_put;
1547 NvU64 *gpfifo_entry;
1548
1549 UVM_ASSERT(entry == &channel->gpfifo_entries[cpu_put]);
1550
1551 if (g_uvm_global.conf_computing_enabled && uvm_channel_is_ce(channel))
1552 return;
1553
1554 gpfifo_entry = (NvU64*)channel->channel_info.gpFifoEntries + cpu_put;
1555 *gpfifo_entry = entry->control_value;
1556
1557 // Need to make sure all the GPFIFO entries writes complete before updating
1558 // GPPUT. We also don't want any reads to be moved after the GPPut write as
1559 // the GPU might modify the data they read as soon as the GPPut write
1560 // happens.
1561 mb();
1562
1563 gpu->parent->host_hal->write_gpu_put(channel, new_cpu_put);
1564 }
1565
submit_ctrl_gpfifo_indirect(uvm_channel_t * channel,uvm_gpfifo_entry_t * entry,NvU32 old_cpu_put,NvU32 new_gpu_put)1566 static NV_STATUS submit_ctrl_gpfifo_indirect(uvm_channel_t *channel,
1567 uvm_gpfifo_entry_t *entry,
1568 NvU32 old_cpu_put,
1569 NvU32 new_gpu_put)
1570 {
1571 uvm_push_t indirect_push;
1572 NV_STATUS status = NV_OK;
1573 uvm_spin_loop_t spin;
1574 uvm_channel_type_t indirect_channel_type = uvm_channel_manager_is_wlc_ready(channel->pool->manager) ?
1575 UVM_CHANNEL_TYPE_WLC :
1576 UVM_CHANNEL_TYPE_SEC2;
1577
1578 UVM_ASSERT(uvm_channel_is_ce(channel));
1579
1580 // If the old_cpu_put is not equal to the last gpu put,
1581 // Another push(es) is pending that needs to be submitted.
1582 // That push/es' submission will update the gpu_put pointer
1583 // to expected value.
1584 UVM_SPIN_WHILE(channel->conf_computing.gpu_put != old_cpu_put, &spin);
1585
1586 status = uvm_push_begin(channel->pool->manager,
1587 indirect_channel_type,
1588 &indirect_push,
1589 "GPFIFO submit to '%s' via '%s'",
1590 channel->name,
1591 uvm_channel_type_to_string(indirect_channel_type));
1592 if (status != NV_OK)
1593 return status;
1594
1595 if (uvm_channel_is_sec2(indirect_push.channel)) {
1596 set_gpfifo_via_sec2(&indirect_push, channel, old_cpu_put, entry->control_value);
1597 update_gpput_via_sec2(&indirect_push, channel, new_gpu_put);
1598 } else {
1599 uvm_gpu_t *gpu = uvm_push_get_gpu(&indirect_push);
1600 NvU64 gpfifo_gpu_va = channel->channel_info.gpFifoGpuVa + (old_cpu_put * sizeof(entry->control_value));
1601
1602 gpu->parent->ce_hal->memset_8(&indirect_push,
1603 uvm_gpu_address_virtual(gpfifo_gpu_va),
1604 entry->control_value,
1605 sizeof(entry->control_value));
1606
1607 uvm_push_set_flag(&indirect_push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU);
1608 do_semaphore_release(&indirect_push, channel->channel_info.gpPutGpuVa, new_gpu_put);
1609 }
1610
1611 uvm_push_set_flag(&indirect_push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU);
1612 do_semaphore_release(&indirect_push,
1613 channel->channel_info.workSubmissionOffsetGpuVa,
1614 channel->channel_info.workSubmissionToken);
1615
1616 status = uvm_push_end_and_wait(&indirect_push);
1617 if (status != NV_OK)
1618 return status;
1619
1620 channel->conf_computing.gpu_put = new_gpu_put;
1621
1622 return NV_OK;
1623 }
1624
1625 // The caller must submit a normal GPFIFO entry with a semaphore release
1626 // following the control GPFIFO, refer to uvm_channel_write_ctrl_gpfifo() for an
1627 // example.
write_ctrl_gpfifo(uvm_channel_t * channel,NvU64 ctrl_fifo_entry_value)1628 static void write_ctrl_gpfifo(uvm_channel_t *channel, NvU64 ctrl_fifo_entry_value)
1629 {
1630 uvm_gpfifo_entry_t *entry;
1631 NvU32 cpu_put;
1632 NvU32 new_cpu_put;
1633
1634 channel_pool_lock(channel->pool);
1635
1636 cpu_put = channel->cpu_put;
1637 new_cpu_put = (cpu_put + 1) % channel->num_gpfifo_entries;
1638
1639 entry = &channel->gpfifo_entries[cpu_put];
1640 memset(entry, 0, sizeof(*entry));
1641 entry->type = UVM_GPFIFO_ENTRY_TYPE_CONTROL;
1642 entry->control_value = ctrl_fifo_entry_value;
1643
1644 // Control GPFIFO entries are followed by a semaphore_release push in UVM.
1645 // We add the tracking semaphore value of the next GPFIFO entry,
1646 // potentially the associated semaphore release push. Even if a different
1647 // GPFIFO entry sneaks in, the purposes of signaling that this control
1648 // GPFIFO entry has been processed is accomplished.
1649 entry->tracking_semaphore_value = channel->tracking_sem.queued_value + 1;
1650
1651 UVM_ASSERT(channel->current_gpfifo_count > 1);
1652 --channel->current_gpfifo_count;
1653
1654 submit_ctrl_gpfifo(channel, entry, new_cpu_put);
1655
1656 channel->cpu_put = new_cpu_put;
1657
1658 // The moment the channel is unlocked uvm_channel_update_progress_with_max()
1659 // may notice the GPU work to be completed and hence all state tracking the
1660 // push must be updated before that. Note that we do not call
1661 // unlock_channel_for_push() because a control GPFIFO is followed by a
1662 // semaphore release, where the channel is unlocked.
1663 channel_pool_unlock(channel->pool);
1664
1665 // Trigger indirect submission when needed.
1666 if (g_uvm_global.conf_computing_enabled && uvm_channel_is_ce(channel)) {
1667 NV_STATUS status = submit_ctrl_gpfifo_indirect(channel, entry, cpu_put, new_cpu_put);
1668
1669 // All failures are globally fatal. There's nothing we do to recover.
1670 UVM_ASSERT_RELEASE(status == NV_OK);
1671 }
1672
1673 // This memory barrier is borrowed from CUDA, as it supposedly fixes perf
1674 // issues on some systems. Comment from CUDA: "fixes throughput-related
1675 // performance problems, e.g. bugs 626179, 593841. This may be related to
1676 // bug 124888, which GL works around by doing a clflush"
1677 wmb();
1678 }
1679
uvm_channel_write_ctrl_gpfifo(uvm_channel_t * channel,NvU64 ctrl_fifo_entry_value)1680 NV_STATUS uvm_channel_write_ctrl_gpfifo(uvm_channel_t *channel, NvU64 ctrl_fifo_entry_value)
1681 {
1682 NV_STATUS status;
1683 uvm_push_t push;
1684
1685 UVM_ASSERT(!uvm_channel_is_proxy(channel));
1686
1687 // WLC/LCIC channels can only process custom GPFIFO entries before
1688 // their schedule is set up.
1689 UVM_ASSERT(!uvm_channel_is_lcic(channel) || !uvm_channel_manager_is_wlc_ready(channel->pool->manager));
1690 UVM_ASSERT(!uvm_channel_is_wlc(channel) || !uvm_channel_manager_is_wlc_ready(channel->pool->manager));
1691
1692 // We reserve two GPFIFO entries, i.e., the control GPFIFO entry and the
1693 // subsequent semaphore_release push. There is, however, a potential case
1694 // for GPFIFO control submission starvation. This may happen because a
1695 // GPFIFO control submission requires two available GPFIFO entries. If you
1696 // have a full GPFIFO ring buffer that frees one entry at a time, while
1697 // there is another thread consuming this recently released entry at the
1698 // same rate, a concurrent thread trying to reserve two entries for a GPFIFO
1699 // control submission may starve. We could handle this by imposing minimal
1700 // release entries in uvm_channel.c:uvm_channel_update_progress(). Instead,
1701 // we don't deal with this potential starvation case because:
1702 // - Control GPFIFO are rarely used.
1703 // - By default, we release up to 8 GPFIFO entries at a time, except if the
1704 // release rate is constrained by lengthy pushbuffers -- another rare
1705 // situation.
1706 // - It would add unnecessary complexity to channel_update_progress().
1707 status = uvm_channel_reserve(channel, 2);
1708 if (status != NV_OK)
1709 return status;
1710
1711 if (g_uvm_global.conf_computing_enabled) {
1712 // Rotating IV needs to idle the channel. However, there's no semaphore
1713 // release after submitting a control entry. It is not possible to wait
1714 // for in-flight entries after the GPFIFO submission.
1715 // Instead, check for IV rotation early. Secure channels are locked for
1716 // pushes after reservation so the IV space gained here can't be used
1717 // up by concurrent pushes.
1718 status = uvm_conf_computing_maybe_rotate_channel_ivs_retry_busy(channel);
1719 if (status != NV_OK) {
1720 uvm_channel_release(channel, 2);
1721 return status;
1722 }
1723 }
1724
1725 write_ctrl_gpfifo(channel, ctrl_fifo_entry_value);
1726
1727 status = uvm_push_begin_on_reserved_channel(channel, &push, "write_ctrl_GPFIFO");
1728 if (status != NV_OK) {
1729 uvm_gpu_t *gpu = uvm_channel_get_gpu(channel);
1730
1731 // One entry was consumed by GPFIFO entry
1732 uvm_channel_release(channel, 1);
1733 UVM_ERR_PRINT("Failed to begin push on channel: %s, GPU %s\n", nvstatusToString(status), uvm_gpu_name(gpu));
1734 return status;
1735 }
1736
1737 // This is an empty push, the push's embedded semaphore_release signals that
1738 // the GPFIFO control entry has been processed.
1739 uvm_push_end(&push);
1740
1741 return NV_OK;
1742 }
1743
channel_reserve_and_lock(uvm_channel_t * channel,NvU32 num_gpfifo_entries)1744 static NV_STATUS channel_reserve_and_lock(uvm_channel_t *channel, NvU32 num_gpfifo_entries)
1745 {
1746 NV_STATUS status;
1747 uvm_spin_loop_t spin;
1748 uvm_channel_pool_t *pool = channel->pool;
1749
1750 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
1751
1752 status = channel_pool_rotate_key_if_pending(pool);
1753 if (status != NV_OK)
1754 return status;
1755
1756 // This semaphore is uvm_up() in unlock_channel_for_push() as part of the
1757 // uvm_channel_end_push() routine. Note that different than in
1758 // channel_reserve_and_lock_in_pool, we cannot pick an unlocked channel from
1759 // the pool, even when there is one available and *channel is locked.
1760 // Not a concern given that uvm_channel_reserve() is not the common-case for
1761 // channel reservation, and only used for channel initialization, GPFIFO
1762 // control work submission, and testing.
1763 uvm_down(&pool->conf_computing.push_sem);
1764
1765 channel_pool_lock(pool);
1766
1767 if (test_claim_and_lock_channel(channel, num_gpfifo_entries))
1768 goto out;
1769
1770 channel_pool_unlock(pool);
1771
1772 uvm_spin_loop_init(&spin);
1773 while (1) {
1774 uvm_channel_update_progress(channel);
1775
1776 channel_pool_lock(pool);
1777
1778 if (test_claim_and_lock_channel(channel, num_gpfifo_entries))
1779 goto out;
1780
1781 channel_pool_unlock(pool);
1782
1783 status = uvm_channel_check_errors(channel);
1784 if (status != NV_OK) {
1785 uvm_up(&pool->conf_computing.push_sem);
1786 return status;
1787 }
1788
1789 UVM_SPIN_LOOP(&spin);
1790 }
1791
1792 out:
1793 channel_pool_unlock(pool);
1794 return NV_OK;
1795 }
1796
uvm_channel_reserve(uvm_channel_t * channel,NvU32 num_gpfifo_entries)1797 NV_STATUS uvm_channel_reserve(uvm_channel_t *channel, NvU32 num_gpfifo_entries)
1798 {
1799 NV_STATUS status = NV_OK;
1800 uvm_spin_loop_t spin;
1801
1802 if (g_uvm_global.conf_computing_enabled)
1803 return channel_reserve_and_lock(channel, num_gpfifo_entries);
1804
1805 if (try_claim_channel(channel, num_gpfifo_entries))
1806 return NV_OK;
1807
1808 uvm_channel_update_progress(channel);
1809
1810 uvm_spin_loop_init(&spin);
1811 while (!try_claim_channel(channel, num_gpfifo_entries) && status == NV_OK) {
1812 UVM_SPIN_LOOP(&spin);
1813 status = uvm_channel_check_errors(channel);
1814 uvm_channel_update_progress(channel);
1815 }
1816
1817 return status;
1818 }
1819
uvm_channel_release(uvm_channel_t * channel,NvU32 num_gpfifo_entries)1820 void uvm_channel_release(uvm_channel_t *channel, NvU32 num_gpfifo_entries)
1821 {
1822 channel_pool_lock(channel->pool);
1823
1824 UVM_ASSERT(uvm_channel_is_locked_for_push(channel));
1825 unlock_channel_for_push(channel);
1826
1827 UVM_ASSERT(channel->current_gpfifo_count >= num_gpfifo_entries);
1828 channel->current_gpfifo_count -= num_gpfifo_entries;
1829 channel_pool_unlock(channel->pool);
1830 }
1831
1832 // Get the first pending GPFIFO entry, if any.
1833 // This doesn't stop the entry from being reused.
uvm_channel_get_first_pending_entry(uvm_channel_t * channel)1834 static uvm_gpfifo_entry_t *uvm_channel_get_first_pending_entry(uvm_channel_t *channel)
1835 {
1836 uvm_gpfifo_entry_t *entry = NULL;
1837 NvU32 pending_count = channel_update_progress_all(channel, UVM_CHANNEL_UPDATE_MODE_COMPLETED);
1838
1839 if (pending_count == 0)
1840 return NULL;
1841
1842 channel_pool_lock(channel->pool);
1843
1844 if (channel->gpu_get != channel->cpu_put)
1845 entry = &channel->gpfifo_entries[channel->gpu_get];
1846
1847 channel_pool_unlock(channel->pool);
1848
1849 return entry;
1850 }
1851
uvm_channel_get_status(uvm_channel_t * channel)1852 NV_STATUS uvm_channel_get_status(uvm_channel_t *channel)
1853 {
1854 uvm_gpu_t *gpu;
1855 NvNotification *errorNotifier;
1856
1857 if (uvm_channel_is_proxy(channel))
1858 errorNotifier = channel->proxy.channel_info.shadowErrorNotifier;
1859 else
1860 errorNotifier = channel->channel_info.errorNotifier;
1861
1862 if (errorNotifier->status == 0)
1863 return NV_OK;
1864
1865 // In case we hit a channel error, check the ECC error notifier as well so
1866 // that a more precise ECC error can be returned in case there is indeed an
1867 // ECC error.
1868 //
1869 // Notably this might be racy depending on the ordering of the notifications,
1870 // but we can't always call RM to service interrupts from this context.
1871 gpu = uvm_channel_get_gpu(channel);
1872 if (gpu->ecc.enabled && *gpu->ecc.error_notifier)
1873 return NV_ERR_ECC_ERROR;
1874
1875 return NV_ERR_RC_ERROR;
1876 }
1877
uvm_channel_get_fatal_entry(uvm_channel_t * channel)1878 uvm_gpfifo_entry_t *uvm_channel_get_fatal_entry(uvm_channel_t *channel)
1879 {
1880 UVM_ASSERT(uvm_channel_get_status(channel) != NV_OK);
1881
1882 return uvm_channel_get_first_pending_entry(channel);
1883 }
1884
uvm_channel_check_errors(uvm_channel_t * channel)1885 NV_STATUS uvm_channel_check_errors(uvm_channel_t *channel)
1886 {
1887 uvm_gpfifo_entry_t *fatal_entry;
1888 NV_STATUS status = uvm_channel_get_status(channel);
1889
1890 if (status == NV_OK)
1891 return NV_OK;
1892
1893 UVM_ERR_PRINT("Detected a channel error, channel %s GPU %s\n",
1894 channel->name,
1895 uvm_gpu_name(uvm_channel_get_gpu(channel)));
1896
1897 fatal_entry = uvm_channel_get_fatal_entry(channel);
1898 if (fatal_entry != NULL) {
1899 if (fatal_entry->type == UVM_GPFIFO_ENTRY_TYPE_NORMAL) {
1900 uvm_push_info_t *push_info = fatal_entry->push_info;
1901 UVM_ERR_PRINT("Channel error likely caused by push '%s' started at %s:%d in %s()\n",
1902 push_info->description,
1903 push_info->filename,
1904 push_info->line,
1905 push_info->function);
1906 }
1907 else {
1908 UVM_ASSERT(!uvm_channel_is_proxy(channel));
1909
1910 UVM_ERR_PRINT("Channel error likely caused by GPFIFO control entry, data: 0x%llx, gpu_get: %d\n",
1911 fatal_entry->control_value,
1912 channel->gpu_get);
1913 }
1914 }
1915
1916 uvm_global_set_fatal_error(status);
1917
1918 return status;
1919 }
1920
uvm_channel_manager_check_errors(uvm_channel_manager_t * channel_manager)1921 NV_STATUS uvm_channel_manager_check_errors(uvm_channel_manager_t *channel_manager)
1922 {
1923 uvm_channel_pool_t *pool;
1924 NV_STATUS status = uvm_global_get_status();
1925
1926 if (status != NV_OK)
1927 return status;
1928
1929 uvm_for_each_pool(pool, channel_manager) {
1930 uvm_channel_t *channel;
1931
1932 uvm_for_each_channel_in_pool(channel, pool) {
1933 status = uvm_channel_check_errors(channel);
1934 if (status != NV_OK)
1935 return status;
1936 }
1937 }
1938
1939 return status;
1940 }
1941
uvm_channel_is_value_completed(uvm_channel_t * channel,NvU64 value)1942 bool uvm_channel_is_value_completed(uvm_channel_t *channel, NvU64 value)
1943 {
1944 return uvm_gpu_tracking_semaphore_is_value_completed(&channel->tracking_sem, value);
1945 }
1946
uvm_channel_update_completed_value(uvm_channel_t * channel)1947 NvU64 uvm_channel_update_completed_value(uvm_channel_t *channel)
1948 {
1949 return uvm_gpu_tracking_semaphore_update_completed_value(&channel->tracking_sem);
1950 }
1951
uvm_channel_wait(uvm_channel_t * channel)1952 NV_STATUS uvm_channel_wait(uvm_channel_t *channel)
1953 {
1954 NV_STATUS status = uvm_global_get_status();
1955 uvm_spin_loop_t spin;
1956
1957 if (uvm_channel_update_progress(channel) == 0 && status == NV_OK)
1958 return uvm_channel_check_errors(channel);
1959
1960 uvm_spin_loop_init(&spin);
1961 while (uvm_channel_update_progress(channel) > 0 && status == NV_OK) {
1962 UVM_SPIN_LOOP(&spin);
1963 status = uvm_global_get_status();
1964
1965 if (status == NV_OK)
1966 status = uvm_channel_check_errors(channel);
1967 }
1968
1969 return status;
1970 }
1971
csl_init(uvm_channel_t * channel)1972 static NV_STATUS csl_init(uvm_channel_t *channel)
1973 {
1974 NV_STATUS status;
1975 unsigned context_index = uvm_channel_index_in_pool(channel);
1976 uvm_channel_pool_t *pool = channel->pool;
1977
1978 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
1979
1980 status = uvm_rm_locked_call(nvUvmInterfaceCslInitContext(&channel->csl.ctx, channel->handle));
1981 if (status != NV_OK) {
1982 uvm_gpu_t *gpu = uvm_channel_get_gpu(channel);
1983
1984 UVM_DBG_PRINT("nvUvmInterfaceCslInitContext() failed: %s, GPU %s\n",
1985 nvstatusToString(status),
1986 uvm_gpu_name(gpu));
1987 return status;
1988 }
1989
1990 uvm_mutex_init(&channel->csl.ctx_lock, UVM_LOCK_ORDER_CSL_CTX);
1991 channel->csl.is_ctx_initialized = true;
1992
1993 if (uvm_channel_is_lcic(channel)) {
1994 pool = get_paired_pool(pool);
1995 context_index += pool->num_channels;
1996 }
1997
1998 UVM_ASSERT(pool->conf_computing.key_rotation.csl_contexts != NULL);
1999
2000 pool->conf_computing.key_rotation.csl_contexts[context_index] = &channel->csl.ctx;
2001
2002 return NV_OK;
2003 }
2004
csl_destroy(uvm_channel_t * channel)2005 static void csl_destroy(uvm_channel_t *channel)
2006 {
2007 uvm_channel_pool_t *pool = channel->pool;
2008 unsigned context_index = uvm_channel_index_in_pool(channel);
2009
2010 if (!channel->csl.is_ctx_initialized)
2011 return;
2012
2013 uvm_assert_mutex_unlocked(&channel->csl.ctx_lock);
2014 UVM_ASSERT(!uvm_channel_is_locked_for_push(channel));
2015
2016 if (uvm_channel_is_lcic(channel)) {
2017 pool = get_paired_pool(pool);
2018 context_index += pool->num_channels;
2019 }
2020
2021 UVM_ASSERT(pool->conf_computing.key_rotation.csl_contexts != NULL);
2022
2023 pool->conf_computing.key_rotation.csl_contexts[context_index] = NULL;
2024
2025 uvm_rm_locked_call_void(nvUvmInterfaceDeinitCslContext(&channel->csl.ctx));
2026 channel->csl.is_ctx_initialized = false;
2027 }
2028
free_conf_computing_buffers(uvm_channel_t * channel)2029 static void free_conf_computing_buffers(uvm_channel_t *channel)
2030 {
2031 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
2032 UVM_ASSERT(uvm_channel_is_ce(channel));
2033
2034 uvm_kvfree(channel->conf_computing.static_pb_protected_sysmem);
2035 channel->conf_computing.static_pb_protected_sysmem = NULL;
2036
2037 uvm_kvfree(channel->conf_computing.push_crypto_bundles);
2038 channel->conf_computing.push_crypto_bundles = NULL;
2039
2040 uvm_kvfree(channel->tracking_sem.semaphore.conf_computing.ivs);
2041 channel->tracking_sem.semaphore.conf_computing.ivs = NULL;
2042 }
2043
alloc_conf_computing_buffers(uvm_channel_t * channel)2044 static NV_STATUS alloc_conf_computing_buffers(uvm_channel_t *channel)
2045 {
2046 uvm_gpu_semaphore_t *semaphore = &channel->tracking_sem.semaphore;
2047
2048 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
2049 UVM_ASSERT(uvm_channel_is_ce(channel));
2050
2051 semaphore->conf_computing.ivs =
2052 uvm_kvmalloc(sizeof(*semaphore->conf_computing.ivs) * channel->num_gpfifo_entries);
2053
2054 if (!semaphore->conf_computing.ivs)
2055 return NV_ERR_NO_MEMORY;
2056
2057 if (uvm_channel_is_wlc(channel)) {
2058 channel->conf_computing.static_pb_protected_sysmem =
2059 uvm_kvmalloc(UVM_ALIGN_UP(UVM_MAX_WLC_PUSH_SIZE, UVM_PAGE_SIZE_4K));
2060
2061 if (!channel->conf_computing.static_pb_protected_sysmem)
2062 return NV_ERR_NO_MEMORY;
2063 }
2064 else if (!uvm_channel_is_lcic(channel)) {
2065 channel->conf_computing.push_crypto_bundles =
2066 uvm_kvmalloc(sizeof(*channel->conf_computing.push_crypto_bundles) * channel->num_gpfifo_entries);
2067
2068 if (!channel->conf_computing.push_crypto_bundles)
2069 return NV_ERR_NO_MEMORY;
2070 }
2071
2072 return NV_OK;
2073 }
2074
channel_destroy(uvm_channel_pool_t * pool,uvm_channel_t * channel)2075 static void channel_destroy(uvm_channel_pool_t *pool, uvm_channel_t *channel)
2076 {
2077 UVM_ASSERT(pool->num_channels > 0);
2078
2079 if (channel->tracking_sem.queued_value > 0) {
2080 // The channel should have been idled before being destroyed, unless an
2081 // error was triggered. We need to check both error cases (global and
2082 // channel) to handle the UVM_TEST_CHANNEL_SANITY unit test.
2083 if (uvm_global_get_status() == NV_OK && uvm_channel_get_status(channel) == NV_OK)
2084 UVM_ASSERT(uvm_gpu_tracking_semaphore_is_completed(&channel->tracking_sem));
2085
2086 // Remove all remaining GPFIFOs from their pushbuffer chunk, since the
2087 // pushbuffer has a longer lifetime.
2088 channel_update_progress_all(channel, UVM_CHANNEL_UPDATE_MODE_FORCE_ALL);
2089 }
2090
2091 proc_remove(channel->procfs.pushes);
2092 proc_remove(channel->procfs.info);
2093 proc_remove(channel->procfs.dir);
2094
2095 uvm_kvfree(channel->push_acquire_infos);
2096 uvm_kvfree(channel->push_infos);
2097
2098 uvm_kvfree(channel->gpfifo_entries);
2099
2100 if (g_uvm_global.conf_computing_enabled) {
2101 csl_destroy(channel);
2102
2103 if (uvm_channel_is_ce(channel))
2104 free_conf_computing_buffers(channel);
2105 }
2106
2107 if (uvm_channel_is_proxy(channel))
2108 uvm_rm_locked_call_void(nvUvmInterfacePagingChannelDestroy(channel->proxy.handle));
2109 else
2110 uvm_rm_locked_call_void(nvUvmInterfaceChannelDestroy(channel->handle));
2111
2112 uvm_gpu_tracking_semaphore_free(&channel->tracking_sem);
2113
2114 UVM_ASSERT(list_empty(&channel->tools.channel_list_node));
2115 UVM_ASSERT(channel->tools.pending_event_count == 0);
2116
2117 pool->num_channels--;
2118 }
2119
2120 // Returns the TSG for a given channel.
channel_get_tsg(uvm_channel_t * channel)2121 static uvmGpuTsgHandle channel_get_tsg(uvm_channel_t *channel)
2122 {
2123 unsigned tsg_index = 0;
2124 uvm_channel_pool_t *pool = channel->pool;
2125
2126 if (uvm_channel_pool_is_wlc(pool) || uvm_channel_pool_is_lcic(pool)) {
2127 if (uvm_channel_pool_is_lcic(pool)) {
2128 channel = uvm_channel_lcic_get_paired_wlc(channel);
2129 pool = channel->pool;
2130 }
2131
2132 tsg_index = uvm_channel_index_in_pool(channel);
2133 }
2134 UVM_ASSERT(tsg_index < pool->num_tsgs);
2135
2136 return pool->tsg_handles[tsg_index];
2137 }
2138
internal_channel_create(uvm_channel_t * channel)2139 static NV_STATUS internal_channel_create(uvm_channel_t *channel)
2140 {
2141 NV_STATUS status;
2142 UvmGpuChannelAllocParams channel_alloc_params;
2143 UvmGpuChannelInfo *channel_info = &channel->channel_info;
2144 uvm_channel_manager_t *manager = channel->pool->manager;
2145
2146 memset(&channel_alloc_params, 0, sizeof(channel_alloc_params));
2147 channel_alloc_params.numGpFifoEntries = channel_pool_num_gpfifo_entries(channel->pool);
2148 channel_alloc_params.gpFifoLoc = manager->conf.gpfifo_loc;
2149 channel_alloc_params.gpPutLoc = manager->conf.gpput_loc;
2150
2151 if (uvm_channel_is_sec2(channel)) {
2152 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
2153
2154 // SEC2 channels' GPPUT and GPFIFO must be allocated in sysmem.
2155 channel_alloc_params.gpFifoLoc = UVM_BUFFER_LOCATION_SYS;
2156 channel_alloc_params.gpPutLoc = UVM_BUFFER_LOCATION_SYS;
2157 }
2158
2159 status = uvm_rm_locked_call(nvUvmInterfaceChannelAllocate(channel_get_tsg(channel),
2160 &channel_alloc_params,
2161 &channel->handle,
2162 channel_info));
2163 if (status != NV_OK) {
2164 UVM_ERR_PRINT("nvUvmInterfaceChannelAllocate() failed: %s, GPU %s, type %s\n",
2165 nvstatusToString(status),
2166 uvm_gpu_name(manager->gpu),
2167 uvm_channel_pool_type_to_string(channel->pool->pool_type));
2168 return status;
2169 }
2170
2171 snprintf(channel->name,
2172 sizeof(channel->name),
2173 "ID %u:%u (0x%x:0x%x) %s %u",
2174 channel_info->hwRunlistId,
2175 channel_info->hwChannelId,
2176 channel_info->hwRunlistId,
2177 channel_info->hwChannelId,
2178 uvm_channel_is_sec2(channel) ? "SEC2" :
2179 uvm_channel_is_wlc(channel) ? "WLC" :
2180 uvm_channel_is_lcic(channel) ? "LCIC" : "CE",
2181 channel->pool->engine_index);
2182
2183 return NV_OK;
2184 }
2185
proxy_channel_create(uvm_channel_t * channel,unsigned ce_index)2186 static NV_STATUS proxy_channel_create(uvm_channel_t *channel, unsigned ce_index)
2187 {
2188 NV_STATUS status;
2189 unsigned proxy_index;
2190 UvmGpuPagingChannelAllocParams channel_alloc_params;
2191 uvm_channel_manager_t *manager = channel->pool->manager;
2192 uvm_gpu_t *gpu = manager->gpu;
2193
2194 UVM_ASSERT(uvm_channel_is_proxy(channel));
2195
2196 memset(&channel_alloc_params, 0, sizeof(channel_alloc_params));
2197 channel_alloc_params.engineIndex = ce_index;
2198
2199 status = uvm_rm_locked_call(nvUvmInterfacePagingChannelAllocate(uvm_gpu_device_handle(gpu),
2200 &channel_alloc_params,
2201 &channel->proxy.handle,
2202 &channel->proxy.channel_info));
2203 if (status != NV_OK) {
2204 UVM_ERR_PRINT("nvUvmInterfacePagingChannelAllocate() failed: %s, GPU %s\n",
2205 nvstatusToString(status),
2206 uvm_gpu_name(gpu));
2207 return status;
2208 }
2209
2210 proxy_index = uvm_channel_index_in_pool(channel);
2211 snprintf(channel->name, sizeof(channel->name), "Proxy %u CE %u", proxy_index, ce_index);
2212
2213 return NV_OK;
2214 }
2215
channel_create(uvm_channel_pool_t * pool,uvm_channel_t * channel)2216 static NV_STATUS channel_create(uvm_channel_pool_t *pool, uvm_channel_t *channel)
2217 {
2218 NV_STATUS status;
2219 uvm_channel_manager_t *manager = pool->manager;
2220 uvm_gpu_t *gpu = manager->gpu;
2221 uvm_gpu_semaphore_pool_t *semaphore_pool = gpu->semaphore_pool;
2222 unsigned int i;
2223
2224 UVM_ASSERT(channel != NULL);
2225
2226 channel->pool = pool;
2227 pool->num_channels++;
2228 INIT_LIST_HEAD(&channel->available_push_infos);
2229 channel->tools.pending_event_count = 0;
2230 INIT_LIST_HEAD(&channel->tools.channel_list_node);
2231
2232 if (g_uvm_global.conf_computing_enabled && uvm_channel_is_ce(channel))
2233 semaphore_pool = gpu->secure_semaphore_pool;
2234
2235 status = uvm_gpu_tracking_semaphore_alloc(semaphore_pool, &channel->tracking_sem);
2236 if (status != NV_OK) {
2237 UVM_ERR_PRINT("uvm_gpu_tracking_semaphore_alloc() failed: %s, GPU %s\n",
2238 nvstatusToString(status),
2239 uvm_gpu_name(gpu));
2240 goto error;
2241 }
2242
2243 if (uvm_channel_is_proxy(channel))
2244 status = proxy_channel_create(channel, pool->engine_index);
2245 else
2246 status = internal_channel_create(channel);
2247
2248 if (status != NV_OK)
2249 goto error;
2250
2251 channel->num_gpfifo_entries = channel_pool_num_gpfifo_entries(pool);
2252 channel->gpfifo_entries = uvm_kvmalloc_zero(sizeof(*channel->gpfifo_entries) * channel->num_gpfifo_entries);
2253 if (channel->gpfifo_entries == NULL) {
2254 status = NV_ERR_NO_MEMORY;
2255 goto error;
2256 }
2257
2258 if (g_uvm_global.conf_computing_enabled) {
2259 status = csl_init(channel);
2260 if (status != NV_OK)
2261 goto error;
2262
2263 if (uvm_channel_is_ce(channel)) {
2264 // Must happen after the channel's num_gpfifo_entries is known, as
2265 // UVM needs one IV slot per GPFIFO entry.
2266 status = alloc_conf_computing_buffers(channel);
2267 if (status != NV_OK)
2268 goto error;
2269 }
2270 }
2271
2272 channel->push_infos = uvm_kvmalloc_zero(sizeof(*channel->push_infos) * channel->num_gpfifo_entries);
2273 if (channel->push_infos == NULL) {
2274 status = NV_ERR_NO_MEMORY;
2275 goto error;
2276 }
2277
2278 if (uvm_push_info_is_tracking_acquires()) {
2279 channel->push_acquire_infos = uvm_kvmalloc_zero(sizeof(*channel->push_acquire_infos) * channel->num_gpfifo_entries);
2280 if (channel->push_acquire_infos == NULL) {
2281 status = NV_ERR_NO_MEMORY;
2282 goto error;
2283 }
2284 }
2285
2286 for (i = 0; i < channel->num_gpfifo_entries; i++)
2287 list_add_tail(&channel->push_infos[i].available_list_node, &channel->available_push_infos);
2288
2289 status = channel_create_procfs(channel);
2290 if (status != NV_OK)
2291 goto error;
2292
2293 return NV_OK;
2294
2295 error:
2296 channel_destroy(pool, channel);
2297
2298 return status;
2299 }
2300
uvm_channel_tracking_semaphore_get_gpu_va_in_channel(uvm_channel_t * semaphore_channel,uvm_channel_t * access_channel)2301 NvU64 uvm_channel_tracking_semaphore_get_gpu_va_in_channel(uvm_channel_t *semaphore_channel,
2302 uvm_channel_t *access_channel)
2303 {
2304 uvm_gpu_semaphore_t *semaphore = &semaphore_channel->tracking_sem.semaphore;
2305 uvm_gpu_t *gpu = uvm_channel_get_gpu(access_channel);
2306
2307 return uvm_gpu_semaphore_get_gpu_va(semaphore, gpu, uvm_channel_is_proxy(access_channel));
2308 }
2309
channel_init(uvm_channel_t * channel)2310 static NV_STATUS channel_init(uvm_channel_t *channel)
2311 {
2312 uvm_push_t push;
2313 uvm_gpu_t *gpu = uvm_channel_get_gpu(channel);
2314 NV_STATUS status;
2315 NvU32 num_entries = 1;
2316
2317 if (uvm_parent_gpu_needs_pushbuffer_segments(gpu->parent))
2318 num_entries++;
2319
2320 status = uvm_channel_reserve(channel, num_entries);
2321 if (status != NV_OK)
2322 return status;
2323
2324 if (uvm_parent_gpu_needs_pushbuffer_segments(gpu->parent)) {
2325 NvU64 gpfifo_entry;
2326 uvm_pushbuffer_t *pushbuffer = uvm_channel_get_pushbuffer(channel);
2327 NvU64 pb_base = uvm_pushbuffer_get_gpu_va_base(pushbuffer);
2328
2329 if (uvm_channel_is_sec2(channel))
2330 pb_base = uvm_pushbuffer_get_sec2_gpu_va_base(pushbuffer);
2331 else if (uvm_channel_is_wlc(channel) || uvm_channel_is_lcic(channel))
2332 pb_base = uvm_channel_get_static_pb_protected_vidmem_gpu_va(channel);
2333
2334 gpu->parent->host_hal->set_gpfifo_pushbuffer_segment_base(&gpfifo_entry, pb_base);
2335 write_ctrl_gpfifo(channel, gpfifo_entry);
2336 }
2337
2338 status = uvm_push_begin_on_reserved_channel(channel, &push, "Init channel");
2339 if (status != NV_OK) {
2340
2341 // One entry was consumed by control GPFIFO entry above, release the
2342 // second one.
2343 uvm_channel_release(channel, 1);
2344 UVM_ERR_PRINT("Failed to begin push on channel: %s, GPU %s\n", nvstatusToString(status), uvm_gpu_name(gpu));
2345 return status;
2346 }
2347
2348 if (uvm_channel_is_ce(channel))
2349 gpu->parent->ce_hal->init(&push);
2350 else
2351 gpu->parent->sec2_hal->init(&push);
2352
2353 gpu->parent->host_hal->init(&push);
2354
2355 status = uvm_push_end_and_wait(&push);
2356 if (status != NV_OK) {
2357 UVM_ERR_PRINT("Channel '%s' init failed: %s, GPU %s\n",
2358 channel->name,
2359 nvstatusToString(status),
2360 uvm_gpu_name(gpu));
2361 }
2362
2363 return status;
2364 }
2365
channel_manager_uses_proxy_pool(uvm_channel_manager_t * manager)2366 static bool channel_manager_uses_proxy_pool(uvm_channel_manager_t *manager)
2367 {
2368 return uvm_parent_gpu_is_virt_mode_sriov_heavy(manager->gpu->parent);
2369 }
2370
2371 // Number of channels to create in a pool of the given type.
channel_manager_num_channels(uvm_channel_manager_t * manager,uvm_channel_pool_type_t pool_type)2372 static unsigned channel_manager_num_channels(uvm_channel_manager_t *manager, uvm_channel_pool_type_t pool_type)
2373 {
2374 unsigned num_channels;
2375
2376 // In the common case, create two channels per pool.
2377 //
2378 // TODO: Bug 1764958: Tweak this number after benchmarking real workloads.
2379 const unsigned channel_pool_type_ce_num_channels = 2;
2380
2381 UVM_ASSERT(uvm_pool_type_is_valid(pool_type));
2382
2383 if (pool_type == UVM_CHANNEL_POOL_TYPE_CE_PROXY) {
2384
2385 // TODO: Bug 3387454: The vGPU plugin implementation supports a single
2386 // proxy channel per GPU
2387 num_channels = 1;
2388 }
2389 else if (pool_type == UVM_CHANNEL_POOL_TYPE_SEC2) {
2390
2391 // Not all GPU architectures support more than 1 channel per TSG. Since
2392 // SEC2 is not in UVM critical path for performance, conservatively
2393 // create a pool/TSG with a single channel.
2394 num_channels = 1;
2395 }
2396 else if ((pool_type == UVM_CHANNEL_POOL_TYPE_WLC) || (pool_type == UVM_CHANNEL_POOL_TYPE_LCIC)) {
2397 unsigned max_concurrent_ce_pushes;
2398 unsigned num_used_ces = bitmap_weight(manager->ce_mask, UVM_COPY_ENGINE_COUNT_MAX);
2399
2400 // CE selection should happen before this function is invoked.
2401 UVM_ASSERT(num_used_ces > 0);
2402
2403 // Create as many WLC and LCIC channels as concurrent, ongoing, pushes
2404 // of interest are allowed. In the general case, this number of pushes
2405 // is capped by UVM_PUSH_MAX_CONCURRENT_PUSHES. But in Confidential
2406 // Computing there is at most one ongoing push per channel, so the
2407 // number of WLC/LCIC channels is also limited by the number of CE
2408 // channels.
2409 //
2410 // The calculation only considers channels mapped to the
2411 // UVM_CHANNEL_POOL_TYPE_CE type, because WLC and LCIC channels are
2412 // created to enable work launch exclusively in those other channels.
2413 max_concurrent_ce_pushes = num_used_ces * channel_pool_type_ce_num_channels;
2414 num_channels = min(max_concurrent_ce_pushes, (unsigned) UVM_PUSH_MAX_CONCURRENT_PUSHES);
2415 }
2416 else {
2417 UVM_ASSERT(pool_type == UVM_CHANNEL_POOL_TYPE_CE);
2418
2419 num_channels = channel_pool_type_ce_num_channels;
2420 }
2421
2422 UVM_ASSERT(num_channels <= UVM_CHANNEL_MAX_NUM_CHANNELS_PER_POOL);
2423
2424 return num_channels;
2425 }
2426
2427 // Number of TSGs to create in a pool of a given type.
channel_manager_num_tsgs(uvm_channel_manager_t * manager,uvm_channel_pool_type_t pool_type)2428 static unsigned channel_manager_num_tsgs(uvm_channel_manager_t *manager, uvm_channel_pool_type_t pool_type)
2429 {
2430 // For WLC and LCIC channels, we create one TSG per WLC/LCIC channel pair.
2431 // The TSG is stored in the WLC pool.
2432 if (pool_type == UVM_CHANNEL_POOL_TYPE_WLC)
2433 return channel_manager_num_channels(manager, pool_type);
2434 else if (pool_type == UVM_CHANNEL_POOL_TYPE_LCIC)
2435 return 0;
2436
2437 return 1;
2438 }
2439
pool_type_to_engine_type(uvm_channel_pool_type_t pool_type)2440 static UVM_GPU_CHANNEL_ENGINE_TYPE pool_type_to_engine_type(uvm_channel_pool_type_t pool_type)
2441 {
2442 if (pool_type == UVM_CHANNEL_POOL_TYPE_SEC2)
2443 return UVM_GPU_CHANNEL_ENGINE_TYPE_SEC2;
2444 return UVM_GPU_CHANNEL_ENGINE_TYPE_CE;
2445 }
2446
tsg_destroy(uvm_channel_pool_t * pool,uvmGpuTsgHandle tsg_handle)2447 static void tsg_destroy(uvm_channel_pool_t *pool, uvmGpuTsgHandle tsg_handle)
2448 {
2449 UVM_ASSERT(pool->num_tsgs > 0);
2450
2451 uvm_rm_locked_call_void(nvUvmInterfaceTsgDestroy(tsg_handle));
2452 pool->num_tsgs--;
2453 }
2454
tsg_create(uvm_channel_pool_t * pool,uvmGpuTsgHandle * tsg_handle)2455 static NV_STATUS tsg_create(uvm_channel_pool_t *pool, uvmGpuTsgHandle *tsg_handle)
2456 {
2457 NV_STATUS status;
2458 UvmGpuTsgAllocParams tsg_alloc_params;
2459 uvm_gpu_t *gpu = pool->manager->gpu;
2460
2461 pool->num_tsgs++;
2462
2463 tsg_alloc_params.engineType = pool_type_to_engine_type(pool->pool_type);
2464 tsg_alloc_params.engineIndex = pool->engine_index;
2465
2466 status = uvm_rm_locked_call(nvUvmInterfaceTsgAllocate(gpu->rm_address_space, &tsg_alloc_params, tsg_handle));
2467 if (status != NV_OK) {
2468 UVM_ERR_PRINT("nvUvmInterfaceTsgAllocate() failed: %s, GPU %s, type %s\n",
2469 nvstatusToString(status),
2470 uvm_gpu_name(gpu),
2471 uvm_channel_pool_type_to_string(pool->pool_type));
2472 goto error;
2473 }
2474
2475 return NV_OK;
2476
2477 error:
2478 tsg_destroy(pool, *tsg_handle);
2479
2480 return status;
2481 }
2482
channel_pool_destroy(uvm_channel_pool_t * pool)2483 static void channel_pool_destroy(uvm_channel_pool_t *pool)
2484 {
2485 UVM_ASSERT(pool->manager->num_channel_pools > 0);
2486
2487 while (pool->num_channels > 0)
2488 channel_destroy(pool, pool->channels + pool->num_channels - 1);
2489
2490 uvm_kvfree(pool->channels);
2491 pool->channels = NULL;
2492
2493 while (pool->num_tsgs > 0)
2494 tsg_destroy(pool, *(pool->tsg_handles + pool->num_tsgs - 1));
2495
2496 uvm_kvfree(pool->tsg_handles);
2497 pool->tsg_handles = NULL;
2498
2499 uvm_kvfree(pool->conf_computing.key_rotation.csl_contexts);
2500 pool->conf_computing.key_rotation.csl_contexts = NULL;
2501
2502 uvm_rm_mem_free(pool->conf_computing.pool_sysmem);
2503 uvm_rm_mem_free(pool->conf_computing.pool_vidmem);
2504
2505 pool->manager->num_channel_pools--;
2506 }
2507
channel_pool_initialize_locks(uvm_channel_pool_t * pool,unsigned num_channels)2508 static void channel_pool_initialize_locks(uvm_channel_pool_t *pool, unsigned num_channels)
2509 {
2510 uvm_lock_order_t order;
2511
2512 channel_pool_lock_init(pool);
2513
2514 if (!g_uvm_global.conf_computing_enabled)
2515 return;
2516
2517 // Use different order lock for SEC2 and WLC channels.
2518 // This allows reserving a SEC2 or WLC channel for indirect work
2519 // submission while holding a reservation for a channel.
2520 if (uvm_channel_pool_is_sec2(pool))
2521 order = UVM_LOCK_ORDER_CSL_SEC2_PUSH;
2522 else if (uvm_channel_pool_is_wlc(pool))
2523 order = UVM_LOCK_ORDER_CSL_WLC_PUSH;
2524 else
2525 order = UVM_LOCK_ORDER_CSL_PUSH;
2526
2527 uvm_sema_init(&pool->conf_computing.push_sem, num_channels, order);
2528
2529 if (uvm_channel_pool_is_wlc(pool))
2530 order = UVM_LOCK_ORDER_KEY_ROTATION_WLC;
2531 else
2532 order = UVM_LOCK_ORDER_KEY_ROTATION;
2533
2534 uvm_mutex_init(&pool->conf_computing.key_rotation.mutex, order);
2535 }
2536
channel_pool_alloc_key_rotation_data(uvm_channel_pool_t * pool,unsigned num_channels)2537 static NV_STATUS channel_pool_alloc_key_rotation_data(uvm_channel_pool_t *pool, unsigned num_channels)
2538 {
2539 size_t csl_contexts_size;
2540
2541 // uvm_conf_computing_is_key_rotation_enabled_in_pool cannot be used to
2542 // skip key rotation data initialization, because during GPU initialization
2543 // the function always returns false.
2544 if (!g_uvm_global.conf_computing_enabled)
2545 return NV_OK;
2546
2547 // CSL contexts associated with LCIC channels are saved in the WLC context
2548 // array, not in the LCIC context array, so all the underlying engine
2549 // contexts are stored contiguously.
2550 if (uvm_channel_pool_is_lcic(pool))
2551 return NV_OK;
2552
2553 if (uvm_channel_pool_is_wlc(pool)) {
2554 UVM_ASSERT(channel_manager_num_channels(pool->manager, UVM_CHANNEL_POOL_TYPE_WLC) == num_channels);
2555 UVM_ASSERT(channel_manager_num_channels(pool->manager, UVM_CHANNEL_POOL_TYPE_LCIC) == num_channels);
2556
2557 num_channels *= 2;
2558 }
2559
2560 csl_contexts_size = sizeof(*pool->conf_computing.key_rotation.csl_contexts) * num_channels;
2561 pool->conf_computing.key_rotation.csl_contexts = uvm_kvmalloc_zero(csl_contexts_size);
2562
2563 if (pool->conf_computing.key_rotation.csl_contexts == NULL)
2564 return NV_ERR_NO_MEMORY;
2565
2566 pool->conf_computing.key_rotation.num_csl_contexts = num_channels;
2567
2568 return NV_OK;
2569 }
2570
channel_pool_alloc_conf_computing_buffers(uvm_channel_pool_t * pool,unsigned num_channels)2571 static NV_STATUS channel_pool_alloc_conf_computing_buffers(uvm_channel_pool_t *pool, unsigned num_channels)
2572 {
2573 uvm_gpu_t *gpu = pool->manager->gpu;
2574 NV_STATUS status = NV_OK;
2575
2576 if (!g_uvm_global.conf_computing_enabled)
2577 return NV_OK;
2578
2579 if (uvm_channel_pool_is_wlc(pool)) {
2580
2581 // Allocate unprotected sysmem buffers for WLC channels.
2582 // The use/substructures are described by WLC_SYSMEM_TOTAL_SIZE
2583 status = uvm_rm_mem_alloc_and_map_cpu(gpu,
2584 UVM_RM_MEM_TYPE_SYS,
2585 WLC_SYSMEM_TOTAL_SIZE * num_channels,
2586 WLC_PUSHBUFFER_ALIGNMENT,
2587 &pool->conf_computing.pool_sysmem);
2588 if (status != NV_OK)
2589 return status;
2590
2591 // WLC stores two pushbuffers used by its static schedule in vidmem.
2592 // See setup_wlc_schedule for the expected use of each of the static
2593 // pushbuffers.
2594 status = uvm_rm_mem_alloc(gpu,
2595 UVM_RM_MEM_TYPE_GPU,
2596 WLC_ALIGNED_MAX_PUSH_SIZE * 2 * num_channels,
2597 WLC_PUSHBUFFER_ALIGNMENT,
2598 &pool->conf_computing.pool_vidmem);
2599 if (status != NV_OK)
2600 return status;
2601 }
2602 else if (uvm_channel_pool_is_lcic(pool)) {
2603
2604 // LCIC uses only static schedule so in order to use dynamic values
2605 // for entry/exit notifiers for its tracking semaphore they need
2606 // to be populated in a pre-defined sysmem location, before invoking
2607 // the LCIC schedule.
2608 status = uvm_rm_mem_alloc_and_map_cpu(gpu,
2609 UVM_RM_MEM_TYPE_SYS,
2610 sizeof(uvm_gpu_semaphore_notifier_t) * 2 * num_channels,
2611 0,
2612 &pool->conf_computing.pool_sysmem);
2613 if (status != NV_OK)
2614 return status;
2615
2616 // LCIC static schedule pushbuffer is in vidmem
2617 status = uvm_rm_mem_alloc(gpu,
2618 UVM_RM_MEM_TYPE_GPU,
2619 LCIC_ALIGNED_PUSH_SIZE * num_channels,
2620 LCIC_PUSHBUFFER_ALIGNMENT,
2621 &pool->conf_computing.pool_vidmem);
2622 if (status != NV_OK)
2623 return status;
2624 }
2625 else if (uvm_channel_pool_is_ce(pool)) {
2626
2627 // General CE channels need to provide bi-directional communication
2628 // using the pushbuffer. Encrypting an updated push from vidmem
2629 // to sysmem still needs a place for auth tag in sysmem.
2630 status = uvm_rm_mem_alloc_and_map_cpu(gpu,
2631 UVM_RM_MEM_TYPE_SYS,
2632 UVM_CONF_COMPUTING_AUTH_TAG_SIZE * num_channels *
2633 channel_pool_num_gpfifo_entries(pool),
2634 UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT,
2635 &pool->conf_computing.pool_sysmem);
2636 if (status != NV_OK)
2637 return status;
2638 }
2639
2640 status = channel_pool_alloc_key_rotation_data(pool, num_channels);
2641 if (status != NV_OK)
2642 return status;
2643
2644 return NV_OK;
2645 }
2646
channel_pool_add(uvm_channel_manager_t * channel_manager,uvm_channel_pool_type_t pool_type,unsigned engine_index,uvm_channel_pool_t ** pool_out)2647 static NV_STATUS channel_pool_add(uvm_channel_manager_t *channel_manager,
2648 uvm_channel_pool_type_t pool_type,
2649 unsigned engine_index,
2650 uvm_channel_pool_t **pool_out)
2651 {
2652 NV_STATUS status;
2653 unsigned i;
2654 unsigned num_channels;
2655 unsigned num_tsgs;
2656 uvm_channel_pool_t *pool;
2657
2658 UVM_ASSERT(uvm_pool_type_is_valid(pool_type));
2659
2660 pool = channel_manager->channel_pools + channel_manager->num_channel_pools;
2661 channel_manager->num_channel_pools++;
2662
2663 pool->manager = channel_manager;
2664 pool->engine_index = engine_index;
2665 pool->pool_type = pool_type;
2666
2667 num_tsgs = channel_manager_num_tsgs(channel_manager, pool_type);
2668 if (num_tsgs != 0) {
2669 pool->tsg_handles = uvm_kvmalloc_zero(sizeof(*pool->tsg_handles) * num_tsgs);
2670 if (!pool->tsg_handles) {
2671 status = NV_ERR_NO_MEMORY;
2672 goto error;
2673 }
2674
2675 for (i = 0; i < num_tsgs; i++) {
2676 uvmGpuTsgHandle *tsg_handle = pool->tsg_handles + i;
2677
2678 status = tsg_create(pool, tsg_handle);
2679 if (status != NV_OK)
2680 goto error;
2681 }
2682 }
2683
2684 num_channels = channel_manager_num_channels(channel_manager, pool_type);
2685
2686 channel_pool_initialize_locks(pool, num_channels);
2687
2688 status = channel_pool_alloc_conf_computing_buffers(pool, num_channels);
2689 if (status != NV_OK)
2690 goto error;
2691
2692 pool->channels = uvm_kvmalloc_zero(sizeof(*pool->channels) * num_channels);
2693 if (!pool->channels) {
2694 status = NV_ERR_NO_MEMORY;
2695 goto error;
2696 }
2697
2698 for (i = 0; i < num_channels; i++) {
2699 uvm_channel_t *channel = pool->channels + i;
2700
2701 status = channel_create(pool, channel);
2702 if (status != NV_OK)
2703 goto error;
2704
2705 status = channel_init(channel);
2706 if (status != NV_OK)
2707 goto error;
2708 }
2709
2710 *pool_out = pool;
2711 return NV_OK;
2712
2713 error:
2714 channel_pool_destroy(pool);
2715 return status;
2716 }
2717
ce_is_usable(const UvmGpuCopyEngineCaps * cap)2718 static bool ce_is_usable(const UvmGpuCopyEngineCaps *cap)
2719 {
2720 return cap->supported && !cap->grce;
2721 }
2722
2723 // Check that all asynchronous CEs are usable, and that there is at least one
2724 // such CE.
ces_validate(uvm_channel_manager_t * manager,const UvmGpuCopyEngineCaps * ces_caps)2725 static NV_STATUS ces_validate(uvm_channel_manager_t *manager, const UvmGpuCopyEngineCaps *ces_caps)
2726 {
2727 unsigned ce;
2728 bool found_usable_ce = false;
2729
2730 for (ce = 0; ce < UVM_COPY_ENGINE_COUNT_MAX; ++ce) {
2731 const UvmGpuCopyEngineCaps *ce_caps = ces_caps + ce;
2732
2733 if (!ce_is_usable(ce_caps))
2734 continue;
2735
2736 found_usable_ce = true;
2737
2738 // All channels may need to release their semaphore to sysmem.
2739 // All CEs are expected to have the sysmem flag set.
2740 if (!ce_caps->sysmem)
2741 return NV_ERR_NOT_SUPPORTED;
2742
2743 // While P2P capabilities are only required for transfers between GPUs,
2744 // in practice all CEs are expected to have the corresponding flag set.
2745 if (!ce_caps->p2p)
2746 return NV_ERR_NOT_SUPPORTED;
2747 }
2748
2749 if (!found_usable_ce)
2750 return NV_ERR_NOT_SUPPORTED;
2751
2752 return NV_OK;
2753 }
2754
ce_usage_count(NvU32 ce,const unsigned * preferred_ce)2755 static unsigned ce_usage_count(NvU32 ce, const unsigned *preferred_ce)
2756 {
2757 unsigned i;
2758 unsigned count = 0;
2759
2760 UVM_ASSERT(ce < UVM_COPY_ENGINE_COUNT_MAX);
2761
2762 for (i = 0; i < UVM_CHANNEL_TYPE_CE_COUNT; i++) {
2763 if (ce == preferred_ce[i])
2764 count++;
2765 }
2766
2767 return count;
2768 }
2769
2770 // Returns negative if the first CE should be considered better than the second
compare_ce_for_channel_type(const UvmGpuCopyEngineCaps * ce_caps,uvm_channel_type_t type,NvU32 ce_index0,NvU32 ce_index1,NvU32 * preferred_ce)2771 static int compare_ce_for_channel_type(const UvmGpuCopyEngineCaps *ce_caps,
2772 uvm_channel_type_t type,
2773 NvU32 ce_index0,
2774 NvU32 ce_index1,
2775 NvU32 *preferred_ce)
2776 {
2777 unsigned ce0_usage, ce1_usage;
2778 const UvmGpuCopyEngineCaps *cap0 = ce_caps + ce_index0;
2779 const UvmGpuCopyEngineCaps *cap1 = ce_caps + ce_index1;
2780
2781 UVM_ASSERT(ce_index0 < UVM_COPY_ENGINE_COUNT_MAX);
2782 UVM_ASSERT(ce_index1 < UVM_COPY_ENGINE_COUNT_MAX);
2783 UVM_ASSERT(ce_index0 != ce_index1);
2784
2785 switch (type) {
2786 // For CPU to GPU fast sysmem read is the most important
2787 case UVM_CHANNEL_TYPE_CPU_TO_GPU:
2788 if (cap0->sysmemRead != cap1->sysmemRead)
2789 return cap1->sysmemRead - cap0->sysmemRead;
2790
2791 // Prefer not to take up the CEs for nvlink P2P
2792 if (cap0->nvlinkP2p != cap1->nvlinkP2p)
2793 return cap0->nvlinkP2p - cap1->nvlinkP2p;
2794
2795 break;
2796
2797 // For GPU to CPU fast sysmem write is the most important
2798 case UVM_CHANNEL_TYPE_GPU_TO_CPU:
2799 if (cap0->sysmemWrite != cap1->sysmemWrite)
2800 return cap1->sysmemWrite - cap0->sysmemWrite;
2801
2802 // Prefer not to take up the CEs for nvlink P2P
2803 if (cap0->nvlinkP2p != cap1->nvlinkP2p)
2804 return cap0->nvlinkP2p - cap1->nvlinkP2p;
2805
2806 break;
2807
2808 // For GPU to GPU prefer the LCE with the most PCEs
2809 case UVM_CHANNEL_TYPE_GPU_TO_GPU:
2810 {
2811 int pce_diff = (int)hweight32(cap1->cePceMask) - (int)hweight32(cap0->cePceMask);
2812
2813 if (pce_diff != 0)
2814 return pce_diff;
2815 }
2816
2817 break;
2818
2819 // For GPU_INTERNAL we want the max possible bandwidth for CEs. For now
2820 // assume that the number of PCEs is a good measure.
2821 // TODO: Bug 1735254: Add a direct CE query for local FB bandwidth
2822 case UVM_CHANNEL_TYPE_GPU_INTERNAL:
2823 {
2824 int pce_diff = (int)hweight32(cap1->cePceMask) - (int)hweight32(cap0->cePceMask);
2825
2826 if (pce_diff != 0)
2827 return pce_diff;
2828 }
2829
2830 // Leave P2P CEs to the GPU_TO_GPU channel type, when possible
2831 if (cap0->nvlinkP2p != cap1->nvlinkP2p)
2832 return cap0->nvlinkP2p - cap1->nvlinkP2p;
2833
2834 break;
2835
2836 // For MEMOPS we mostly care about latency which should be better with
2837 // less used CEs (although we only know about our own usage and not
2838 // system-wide) so just break out to get the default ordering which
2839 // prioritizes usage count.
2840 case UVM_CHANNEL_TYPE_MEMOPS:
2841 // For WLC we only care about using a dedicated CE, which requires
2842 // knowing the global CE mappings. For now just rely on the default
2843 // ordering, which results on selecting an unused CE (if available).
2844 case UVM_CHANNEL_TYPE_WLC:
2845 break;
2846
2847 default:
2848 UVM_ASSERT_MSG(false, "Unexpected channel type 0x%x\n", type);
2849 return 0;
2850 }
2851
2852 // By default, prefer less used CEs (within the UVM driver at least)
2853 ce0_usage = ce_usage_count(ce_index0, preferred_ce);
2854 ce1_usage = ce_usage_count(ce_index1, preferred_ce);
2855
2856 if (ce0_usage != ce1_usage)
2857 return ce0_usage - ce1_usage;
2858
2859 // And CEs that don't share PCEs
2860 if (cap0->shared != cap1->shared)
2861 return cap0->shared - cap1->shared;
2862
2863 // Last resort, just order by index
2864 return ce_index0 - ce_index1;
2865 }
2866
2867 // Select the preferred CE for the given channel types.
pick_ces_for_channel_types(uvm_channel_manager_t * manager,const UvmGpuCopyEngineCaps * ce_caps,uvm_channel_type_t * channel_types,unsigned num_channel_types,unsigned * preferred_ce)2868 static void pick_ces_for_channel_types(uvm_channel_manager_t *manager,
2869 const UvmGpuCopyEngineCaps *ce_caps,
2870 uvm_channel_type_t *channel_types,
2871 unsigned num_channel_types,
2872 unsigned *preferred_ce)
2873 {
2874 unsigned i;
2875
2876 // In Confidential Computing, do not mark all usable CEs, only the preferred
2877 // ones, because non-preferred CE channels are guaranteed to not be used.
2878 bool mark_all_usable_ces = !g_uvm_global.conf_computing_enabled;
2879
2880 for (i = 0; i < num_channel_types; ++i) {
2881 unsigned ce;
2882 unsigned best_ce = UVM_COPY_ENGINE_COUNT_MAX;
2883 uvm_channel_type_t type = channel_types[i];
2884
2885 for (ce = 0; ce < UVM_COPY_ENGINE_COUNT_MAX; ++ce) {
2886 if (!ce_is_usable(ce_caps + ce))
2887 continue;
2888
2889 if (mark_all_usable_ces)
2890 __set_bit(ce, manager->ce_mask);
2891
2892 if (best_ce == UVM_COPY_ENGINE_COUNT_MAX) {
2893 best_ce = ce;
2894 continue;
2895 }
2896
2897 if (compare_ce_for_channel_type(ce_caps, type, ce, best_ce, preferred_ce) < 0)
2898 best_ce = ce;
2899 }
2900
2901 UVM_ASSERT(best_ce != UVM_COPY_ENGINE_COUNT_MAX);
2902
2903 preferred_ce[type] = best_ce;
2904
2905 // Preferred CEs are always marked as usable.
2906 if (type < UVM_CHANNEL_TYPE_CE_COUNT)
2907 __set_bit(best_ce, manager->ce_mask);
2908 }
2909 }
2910
pick_ces(uvm_channel_manager_t * manager,const UvmGpuCopyEngineCaps * ce_caps,unsigned * preferred_ce)2911 static void pick_ces(uvm_channel_manager_t *manager, const UvmGpuCopyEngineCaps *ce_caps, unsigned *preferred_ce)
2912 {
2913 // The order of picking CEs for each type matters as it's affected by
2914 // the usage count of each CE and it increases every time a CE
2915 // is selected. MEMOPS has the least priority as it only cares about
2916 // low usage of the CE to improve latency
2917 uvm_channel_type_t types[] = {UVM_CHANNEL_TYPE_CPU_TO_GPU,
2918 UVM_CHANNEL_TYPE_GPU_TO_CPU,
2919 UVM_CHANNEL_TYPE_GPU_INTERNAL,
2920 UVM_CHANNEL_TYPE_GPU_TO_GPU,
2921 UVM_CHANNEL_TYPE_MEMOPS};
2922
2923 UVM_ASSERT(!g_uvm_global.conf_computing_enabled);
2924
2925 pick_ces_for_channel_types(manager, ce_caps, types, ARRAY_SIZE(types), preferred_ce);
2926 }
2927
pick_ces_conf_computing(uvm_channel_manager_t * manager,const UvmGpuCopyEngineCaps * ce_caps,unsigned * preferred_ce)2928 static void pick_ces_conf_computing(uvm_channel_manager_t *manager,
2929 const UvmGpuCopyEngineCaps *ce_caps,
2930 unsigned *preferred_ce)
2931 {
2932 unsigned best_wlc_ce;
2933
2934 // The WLC type must go last so an unused CE is chosen, if available
2935 uvm_channel_type_t types[] = {UVM_CHANNEL_TYPE_CPU_TO_GPU,
2936 UVM_CHANNEL_TYPE_GPU_TO_CPU,
2937 UVM_CHANNEL_TYPE_GPU_INTERNAL,
2938 UVM_CHANNEL_TYPE_MEMOPS,
2939 UVM_CHANNEL_TYPE_WLC};
2940
2941 UVM_ASSERT(g_uvm_global.conf_computing_enabled);
2942
2943 pick_ces_for_channel_types(manager, ce_caps, types, ARRAY_SIZE(types), preferred_ce);
2944
2945 // Direct transfers between GPUs are disallowed in Confidential Computing,
2946 // but the preferred CE is still set to an arbitrary value for consistency.
2947 preferred_ce[UVM_CHANNEL_TYPE_GPU_TO_GPU] = preferred_ce[UVM_CHANNEL_TYPE_GPU_TO_CPU];
2948
2949 best_wlc_ce = preferred_ce[UVM_CHANNEL_TYPE_WLC];
2950
2951 // TODO: Bug 4576908: in HCC, the WLC type should not share a CE with any
2952 // channel type other than LCIC. The assertion should be a check instead.
2953 UVM_ASSERT(ce_usage_count(best_wlc_ce, preferred_ce) == 0);
2954 }
2955
channel_manager_pick_ces(uvm_channel_manager_t * manager,unsigned * preferred_ce)2956 static NV_STATUS channel_manager_pick_ces(uvm_channel_manager_t *manager, unsigned *preferred_ce)
2957 {
2958 NV_STATUS status;
2959 UvmGpuCopyEnginesCaps *ces_caps;
2960 uvm_channel_type_t type;
2961
2962 for (type = 0; type < UVM_CHANNEL_TYPE_COUNT; type++)
2963 preferred_ce[type] = UVM_COPY_ENGINE_COUNT_MAX;
2964
2965 ces_caps = uvm_kvmalloc_zero(sizeof(*ces_caps));
2966 if (!ces_caps)
2967 return NV_ERR_NO_MEMORY;
2968
2969 status = uvm_rm_locked_call(nvUvmInterfaceQueryCopyEnginesCaps(uvm_gpu_device_handle(manager->gpu), ces_caps));
2970 if (status != NV_OK)
2971 goto out;
2972
2973 status = ces_validate(manager, ces_caps->copyEngineCaps);
2974 if (status != NV_OK)
2975 goto out;
2976
2977 if (g_uvm_global.conf_computing_enabled)
2978 pick_ces_conf_computing(manager, ces_caps->copyEngineCaps, preferred_ce);
2979 else
2980 pick_ces(manager, ces_caps->copyEngineCaps, preferred_ce);
2981 out:
2982 uvm_kvfree(ces_caps);
2983
2984 return status;
2985 }
2986
2987 // Return the pool corresponding to the given CE index
2988 //
2989 // This function cannot be used to access the proxy pool in SR-IOV heavy.
channel_manager_ce_pool(uvm_channel_manager_t * manager,NvU32 ce)2990 static uvm_channel_pool_t *channel_manager_ce_pool(uvm_channel_manager_t *manager, NvU32 ce)
2991 {
2992 uvm_channel_pool_t *pool;
2993
2994 UVM_ASSERT(test_bit(ce, manager->ce_mask));
2995
2996 // The index of the pool associated with 'ce' is the number of usable CEs
2997 // in [0, ce)
2998 pool = manager->channel_pools + bitmap_weight(manager->ce_mask, ce);
2999
3000 UVM_ASSERT(pool->pool_type == UVM_CHANNEL_POOL_TYPE_CE);
3001 UVM_ASSERT(pool->engine_index == ce);
3002
3003 return pool;
3004 }
3005
uvm_channel_manager_set_p2p_ce(uvm_channel_manager_t * manager,uvm_gpu_t * peer,NvU32 optimal_ce)3006 void uvm_channel_manager_set_p2p_ce(uvm_channel_manager_t *manager, uvm_gpu_t *peer, NvU32 optimal_ce)
3007 {
3008 const NvU32 peer_gpu_index = uvm_id_gpu_index(peer->id);
3009
3010 UVM_ASSERT(manager->gpu != peer);
3011 UVM_ASSERT(optimal_ce < UVM_COPY_ENGINE_COUNT_MAX);
3012
3013 manager->pool_to_use.gpu_to_gpu[peer_gpu_index] = channel_manager_ce_pool(manager, optimal_ce);
3014 }
3015
is_string_valid_location(const char * loc)3016 static bool is_string_valid_location(const char *loc)
3017 {
3018 return strcmp(uvm_channel_gpfifo_loc, "sys") == 0 ||
3019 strcmp(uvm_channel_gpfifo_loc, "vid") == 0 ||
3020 strcmp(uvm_channel_gpfifo_loc, "auto") == 0;
3021 }
3022
string_to_buffer_location(const char * loc)3023 static UVM_BUFFER_LOCATION string_to_buffer_location(const char *loc)
3024 {
3025 UVM_ASSERT(is_string_valid_location(loc));
3026
3027 if (strcmp(loc, "sys") == 0)
3028 return UVM_BUFFER_LOCATION_SYS;
3029 else if (strcmp(loc, "vid") == 0)
3030 return UVM_BUFFER_LOCATION_VID;
3031 else
3032 return UVM_BUFFER_LOCATION_DEFAULT;
3033 }
3034
buffer_location_to_string(UVM_BUFFER_LOCATION loc)3035 static const char *buffer_location_to_string(UVM_BUFFER_LOCATION loc)
3036 {
3037 if (loc == UVM_BUFFER_LOCATION_SYS)
3038 return "sys";
3039 else if (loc == UVM_BUFFER_LOCATION_VID)
3040 return "vid";
3041 else if (loc == UVM_BUFFER_LOCATION_DEFAULT)
3042 return "auto";
3043
3044 UVM_ASSERT_MSG(false, "Invalid buffer location value %d\n", loc);
3045 return NULL;
3046 }
3047
init_channel_manager_conf(uvm_channel_manager_t * manager)3048 static void init_channel_manager_conf(uvm_channel_manager_t *manager)
3049 {
3050 const char *gpfifo_loc_value;
3051 const char *gpput_loc_value;
3052 const char *pushbuffer_loc_value;
3053
3054 uvm_gpu_t *gpu = manager->gpu;
3055
3056 // 1- Number of GPFIFO entries
3057 manager->conf.num_gpfifo_entries = uvm_channel_num_gpfifo_entries;
3058
3059 if (uvm_channel_num_gpfifo_entries < UVM_CHANNEL_NUM_GPFIFO_ENTRIES_MIN)
3060 manager->conf.num_gpfifo_entries = UVM_CHANNEL_NUM_GPFIFO_ENTRIES_MIN;
3061 else if (uvm_channel_num_gpfifo_entries > UVM_CHANNEL_NUM_GPFIFO_ENTRIES_MAX)
3062 manager->conf.num_gpfifo_entries = UVM_CHANNEL_NUM_GPFIFO_ENTRIES_MAX;
3063
3064 if (!is_power_of_2(manager->conf.num_gpfifo_entries))
3065 manager->conf.num_gpfifo_entries = UVM_CHANNEL_NUM_GPFIFO_ENTRIES_DEFAULT;
3066
3067 if (manager->conf.num_gpfifo_entries != uvm_channel_num_gpfifo_entries) {
3068 pr_info("Invalid value for uvm_channel_num_gpfifo_entries = %u, using %u instead\n",
3069 uvm_channel_num_gpfifo_entries,
3070 manager->conf.num_gpfifo_entries);
3071 }
3072
3073 // 2- Allocation locations
3074
3075 if (uvm_conf_computing_mode_is_hcc(gpu)) {
3076 UVM_ASSERT(gpu->mem_info.size > 0);
3077
3078 // When the Confidential Computing feature is enabled, the GPU is
3079 // guaranteed to have a frame buffer and the hardware enforces the
3080 // following apertures for all channel types but SEC2. We create SEC2
3081 // channels by overriding their GPPUT and GPFIFO locations and ignoring
3082 // the location from the channel manager. SEC2 channels are used to
3083 // bootstrap secure work submission. To setup secure work launch, data
3084 // transfers from unprotected main memory to protected vidmem are
3085 // performed by the SEC2 engine and the driver must push work to SEC2
3086 // channels using unprotected locations.
3087 manager->conf.gpfifo_loc = UVM_BUFFER_LOCATION_VID;
3088 manager->conf.gpput_loc = UVM_BUFFER_LOCATION_VID;
3089
3090 // Pushbuffer is located in unprotected sysmem. This is the location
3091 // that gets mapped to both CPU and GPU. It is populated either by
3092 // signed pushes (SEC2 channels), or encrypted pushes (CE channels).
3093 manager->conf.pushbuffer_loc = UVM_BUFFER_LOCATION_SYS;
3094 return;
3095 }
3096
3097 // Override if the GPU doesn't have memory
3098 if (gpu->mem_info.size == 0) {
3099 manager->conf.pushbuffer_loc = UVM_BUFFER_LOCATION_SYS;
3100 manager->conf.gpfifo_loc = UVM_BUFFER_LOCATION_SYS;
3101 manager->conf.gpput_loc = UVM_BUFFER_LOCATION_SYS;
3102 return;
3103 }
3104
3105 manager->conf.pushbuffer_loc = UVM_BUFFER_LOCATION_SYS;
3106
3107 pushbuffer_loc_value = uvm_channel_pushbuffer_loc;
3108 if (!is_string_valid_location(pushbuffer_loc_value)) {
3109 pushbuffer_loc_value = UVM_CHANNEL_PUSHBUFFER_LOC_DEFAULT;
3110 pr_info("Invalid value for uvm_channel_pushbuffer_loc = %s, using %s instead\n",
3111 uvm_channel_pushbuffer_loc,
3112 pushbuffer_loc_value);
3113 }
3114
3115 // Override the default value if requested by the user
3116 if (strcmp(pushbuffer_loc_value, "vid") == 0) {
3117 // aarch64 requires memset_io/memcpy_io instead of memset/memcpy for
3118 // mapped GPU memory. The existing push paths only use memset/memcpy,
3119 // so force the location to sys for now.
3120 // TODO: Bug 2904133: Remove the following "if" after the bug is fixed.
3121 if (NVCPU_IS_AARCH64) {
3122 pr_info("uvm_channel_pushbuffer_loc = %s is not supported on AARCH64, using sys instead\n",
3123 pushbuffer_loc_value);
3124 manager->conf.pushbuffer_loc = UVM_BUFFER_LOCATION_SYS;
3125 }
3126 else {
3127 manager->conf.pushbuffer_loc = UVM_BUFFER_LOCATION_VID;
3128 }
3129 }
3130
3131 // 3- GPFIFO/GPPut location
3132 // Only support the knobs for GPFIFO/GPPut on Volta+
3133 if (!gpu->parent->gpfifo_in_vidmem_supported) {
3134 if (manager->conf.gpput_loc == UVM_BUFFER_LOCATION_SYS) {
3135 pr_info("CAUTION: allocating GPPut in sysmem is NOT supported and may crash the system, using %s instead\n",
3136 buffer_location_to_string(UVM_BUFFER_LOCATION_DEFAULT));
3137 }
3138
3139 manager->conf.gpfifo_loc = UVM_BUFFER_LOCATION_DEFAULT;
3140 manager->conf.gpput_loc = UVM_BUFFER_LOCATION_DEFAULT;
3141
3142 return;
3143 }
3144
3145 gpfifo_loc_value = uvm_channel_gpfifo_loc;
3146 if (!is_string_valid_location(gpfifo_loc_value)) {
3147 gpfifo_loc_value = UVM_CHANNEL_GPFIFO_LOC_DEFAULT;
3148 pr_info("Invalid value for uvm_channel_gpfifo_loc = %s, using %s instead\n",
3149 uvm_channel_gpfifo_loc,
3150 gpfifo_loc_value);
3151 }
3152
3153 gpput_loc_value = uvm_channel_gpput_loc;
3154 if (!is_string_valid_location(gpput_loc_value)) {
3155 gpput_loc_value = UVM_CHANNEL_GPPUT_LOC_DEFAULT;
3156 pr_info("Invalid value for uvm_channel_gpput_loc = %s, using %s instead\n",
3157 uvm_channel_gpput_loc,
3158 gpput_loc_value);
3159 }
3160
3161 // On coherent platforms where the GPU does not cache sysmem but the CPU
3162 // caches vidmem (and sysmem), we place GPFIFO and GPPUT on sysmem to avoid
3163 // cache thrash. The memory access latency is reduced, despite the required
3164 // access through the bus, because no cache coherence message is exchanged.
3165 if (uvm_parent_gpu_is_coherent(gpu->parent)) {
3166 manager->conf.gpfifo_loc = UVM_BUFFER_LOCATION_SYS;
3167
3168 // On GPUs with limited ESCHED addressing range, e.g., Volta on P9, RM
3169 // cannot guarantee that USERD/GPPUT physical address is accessible by
3170 // ESCHED. We set GPPUT location to vidmem where physical addresses are
3171 // all accessible by ESCHED. We use the max_host_va as a proxy for the
3172 // PA limitation, since all architectures with 40b VA limits also have
3173 // 40b PA limits.
3174 manager->conf.gpput_loc = gpu->parent->max_host_va == (1ull << 40) ? UVM_BUFFER_LOCATION_VID :
3175 UVM_BUFFER_LOCATION_SYS;
3176 }
3177 else {
3178 // By default we place GPFIFO and GPPUT on vidmem as it potentially has
3179 // lower latency.
3180 manager->conf.gpfifo_loc = UVM_BUFFER_LOCATION_VID;
3181 manager->conf.gpput_loc = UVM_BUFFER_LOCATION_VID;
3182 }
3183
3184 // Override defaults
3185 if (string_to_buffer_location(gpfifo_loc_value) != UVM_BUFFER_LOCATION_DEFAULT)
3186 manager->conf.gpfifo_loc = string_to_buffer_location(gpfifo_loc_value);
3187
3188 if (string_to_buffer_location(gpput_loc_value) != UVM_BUFFER_LOCATION_DEFAULT)
3189 manager->conf.gpput_loc = string_to_buffer_location(gpput_loc_value);
3190 }
3191
3192 // Returns the maximum number of pools that are needed in the current
3193 // configuration. The implementation may choose to create a smaller number of
3194 // pools.
channel_manager_get_max_pools(uvm_channel_manager_t * manager)3195 static unsigned channel_manager_get_max_pools(uvm_channel_manager_t *manager)
3196 {
3197 unsigned num_channel_pools;
3198
3199 // Create one CE channel pool per usable CE
3200 num_channel_pools = bitmap_weight(manager->ce_mask, UVM_COPY_ENGINE_COUNT_MAX);
3201
3202 // CE proxy channel pool.
3203 if (uvm_parent_gpu_needs_proxy_channel_pool(manager->gpu->parent))
3204 num_channel_pools++;
3205
3206 // SEC2 pool, WLC pool, LCIC pool
3207 if (g_uvm_global.conf_computing_enabled)
3208 num_channel_pools += 3;
3209
3210 return num_channel_pools;
3211 }
3212
channel_manager_create_ce_pools(uvm_channel_manager_t * manager,unsigned * preferred_ce)3213 static NV_STATUS channel_manager_create_ce_pools(uvm_channel_manager_t *manager, unsigned *preferred_ce)
3214 {
3215 unsigned ce;
3216
3217 // A pool is created for each usable CE, even if it has not been selected as
3218 // the preferred CE for any type, because as more information is discovered
3219 // (for example, a pair of peer GPUs is added) we may start using the
3220 // previously idle pools. Configurations where non-preferred CEs are
3221 // guaranteed to remain unused are allowed to avoid marking those engines as
3222 // usable.
3223 for_each_set_bit(ce, manager->ce_mask, UVM_COPY_ENGINE_COUNT_MAX) {
3224 NV_STATUS status;
3225 unsigned type;
3226 uvm_channel_pool_t *pool = NULL;
3227
3228 status = channel_pool_add(manager, UVM_CHANNEL_POOL_TYPE_CE, ce, &pool);
3229 if (status != NV_OK)
3230 return status;
3231
3232 for (type = 0; type < UVM_CHANNEL_TYPE_CE_COUNT; type++) {
3233 // Set pool type if it hasn't been set before.
3234 if (preferred_ce[type] == ce && manager->pool_to_use.default_for_type[type] == NULL)
3235 manager->pool_to_use.default_for_type[type] = pool;
3236 }
3237 }
3238
3239 return NV_OK;
3240 }
3241
setup_wlc_schedule(uvm_channel_t * wlc)3242 static NV_STATUS setup_wlc_schedule(uvm_channel_t *wlc)
3243 {
3244 uvm_gpu_t *gpu = uvm_channel_get_gpu(wlc);
3245 NvU64 protected_vidmem_gpu_va = uvm_channel_get_static_pb_protected_vidmem_gpu_va(wlc);
3246 NvU64 unprotected_sysmem_gpu_va = get_channel_unprotected_sysmem_gpu_va(wlc);
3247
3248 NvU64 *wlc_gpfifo_entries;
3249 uvm_push_t wlc_decrypt_push, sec2_push;
3250 NvU32 decrypt_push_size;
3251 int i;
3252 NV_STATUS status = NV_OK;
3253
3254 // "gpfifo" is the representation of GPFIFO copied to gpFifoGpuVa.
3255 // Resuse static pushbuffer sysmem location for uploading GPFIFO schedule
3256 const size_t gpfifo_size = wlc->num_gpfifo_entries * sizeof(*wlc_gpfifo_entries);
3257 NvU64 gpfifo_unprotected_gpu_va = unprotected_sysmem_gpu_va;
3258 void *gpfifo_unprotected_cpu = get_channel_unprotected_sysmem_cpu(wlc);
3259
3260 // "run_push" represents mutable push location used by WLC. This is the
3261 // first part of the WLC schedule, commands are decrypted as part of the
3262 // launch sequence to protected_vidmem_gpu_va + 0.
3263 // These locations are used in the static part ("decrypt_push") of the WLC schedule.
3264 uvm_gpu_address_t run_push_protected_gpu = uvm_gpu_address_virtual(protected_vidmem_gpu_va);
3265 uvm_gpu_address_t run_push_unprotected_gpu =
3266 uvm_gpu_address_virtual_unprotected(unprotected_sysmem_gpu_va + WLC_SYSMEM_PUSHBUFFER_OFFSET);
3267 uvm_gpu_address_t run_push_unprotected_auth_tag_gpu =
3268 uvm_gpu_address_virtual_unprotected(unprotected_sysmem_gpu_va + WLC_SYSMEM_PUSHBUFFER_AUTH_TAG_OFFSET);
3269
3270 // "decrypt_push" represents WLC decrypt push, constructed using fake_push.
3271 // Copied to protected_vidmem_gpu_va + UVM_MAX_WLC_PUSH_SIZE, as the second of the two
3272 // pushes that make the WLC fixed schedule.
3273 NvU64 decrypt_push_protected_gpu_va = protected_vidmem_gpu_va + WLC_ALIGNED_MAX_PUSH_SIZE;
3274
3275 // Similar to gpfifo, uploading the "decrypt_push" reuses static sysmem
3276 // locations later used for "run_push" when the WLC/LCIC schedule is active
3277 NvU64 decrypt_push_unprotected_gpu_va = gpfifo_unprotected_gpu_va + gpfifo_size;
3278 void *decrypt_push_unprotected_cpu = (char*)gpfifo_unprotected_cpu + gpfifo_size;
3279
3280 // Tags for upload via SEC2
3281 void *decrypt_push_auth_tag, *gpfifo_auth_tag;
3282 uvm_gpu_address_t decrypt_push_auth_tag_gpu, gpfifo_auth_tag_gpu;
3283
3284 BUILD_BUG_ON(sizeof(*wlc_gpfifo_entries) != sizeof(*wlc->channel_info.gpFifoEntries));
3285
3286 UVM_ASSERT(uvm_channel_is_wlc(wlc));
3287
3288 // WLC schedule consists of two parts, the number of entries needs to be even.
3289 // This also guarantees that the size is 16B aligned
3290 UVM_ASSERT(IS_ALIGNED(wlc->num_gpfifo_entries, 2));
3291
3292 wlc_gpfifo_entries = uvm_kvmalloc(gpfifo_size);
3293 if (!wlc_gpfifo_entries)
3294 return NV_ERR_NO_MEMORY;
3295
3296 // WLC can only process one job at a time.
3297 // Prune any initialization entries and block all but one (+1 for sentinel)
3298 uvm_channel_update_progress(wlc);
3299 if (!try_claim_channel(wlc, wlc->num_gpfifo_entries - 2)) {
3300 status = NV_ERR_INVALID_STATE;
3301 goto free_gpfifo_entries;
3302 }
3303
3304 // WLC schedule has two steps:
3305 // 1.) Decrypt from gpu_unprotected_base to wlc_pb_base
3306 // Increment LCIC PUT
3307 // 2.) Execute push at wlc_pb_base
3308 // The first one is a push, the second one is just a GPFIFO entry
3309 status = uvm_push_begin_fake(gpu, &wlc_decrypt_push);
3310 if (status != NV_OK)
3311 goto free_gpfifo_entries;
3312
3313 // Begin WLC DECRYPT push
3314 uvm_push_set_flag(&wlc_decrypt_push, UVM_PUSH_FLAG_NEXT_MEMBAR_GPU);
3315 gpu->parent->ce_hal->decrypt(&wlc_decrypt_push,
3316 run_push_protected_gpu,
3317 run_push_unprotected_gpu,
3318 UVM_MAX_WLC_PUSH_SIZE,
3319 run_push_unprotected_auth_tag_gpu);
3320 uvm_hal_wfi_membar(&wlc_decrypt_push, UVM_MEMBAR_NONE);
3321 decrypt_push_size = uvm_push_get_size(&wlc_decrypt_push);
3322
3323 // The code below reuses static unprotected sysmem buffer as a temporary
3324 // storage for uploading the schedule. Check that everything fits.
3325 UVM_ASSERT(gpfifo_size + decrypt_push_size <= UVM_MAX_WLC_PUSH_SIZE);
3326
3327 // GPFIFO schedule should alternate between the decrypt routine
3328 // we don't know if initialization used even or odd number of
3329 // GPFIFO entries so the exact pattern depends on the value of "PUT"
3330 for (i = 0; i < wlc->num_gpfifo_entries; ++i) {
3331 if (i % 2 == wlc->cpu_put % 2) {
3332 gpu->parent->host_hal->set_gpfifo_entry(wlc_gpfifo_entries + i,
3333 decrypt_push_protected_gpu_va,
3334 decrypt_push_size,
3335 UVM_GPFIFO_SYNC_PROCEED);
3336 }
3337 else {
3338 gpu->parent->host_hal->set_gpfifo_entry(wlc_gpfifo_entries + i,
3339 run_push_protected_gpu.address,
3340 UVM_MAX_WLC_PUSH_SIZE,
3341 UVM_GPFIFO_SYNC_WAIT);
3342 }
3343 }
3344
3345 // The schedule is prepared. Upload to vidmem
3346 status = uvm_push_begin(wlc->pool->manager,
3347 UVM_CHANNEL_TYPE_SEC2,
3348 &sec2_push,
3349 "Upload WLC schedule for: %s", wlc->name);
3350 if (status != NV_OK)
3351 goto end_wlc_dec_push;
3352
3353 decrypt_push_auth_tag = uvm_push_get_single_inline_buffer(&sec2_push,
3354 UVM_CONF_COMPUTING_AUTH_TAG_SIZE,
3355 UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT,
3356 &decrypt_push_auth_tag_gpu);
3357
3358 gpfifo_auth_tag = uvm_push_get_single_inline_buffer(&sec2_push,
3359 UVM_CONF_COMPUTING_AUTH_TAG_SIZE,
3360 UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT,
3361 &gpfifo_auth_tag_gpu);
3362
3363 // Upload WLC pushbuffer
3364 uvm_conf_computing_cpu_encrypt(sec2_push.channel,
3365 decrypt_push_unprotected_cpu,
3366 wlc_decrypt_push.begin,
3367 NULL,
3368 decrypt_push_size,
3369 decrypt_push_auth_tag);
3370 gpu->parent->sec2_hal->decrypt(&sec2_push,
3371 decrypt_push_protected_gpu_va,
3372 decrypt_push_unprotected_gpu_va,
3373 decrypt_push_size,
3374 decrypt_push_auth_tag_gpu.address);
3375
3376 // Upload WLC GPFIFO
3377 uvm_conf_computing_cpu_encrypt(sec2_push.channel,
3378 gpfifo_unprotected_cpu,
3379 wlc_gpfifo_entries,
3380 NULL,
3381 gpfifo_size,
3382 gpfifo_auth_tag);
3383 gpu->parent->sec2_hal->decrypt(&sec2_push,
3384 wlc->channel_info.gpFifoGpuVa,
3385 gpfifo_unprotected_gpu_va,
3386 gpfifo_size,
3387 gpfifo_auth_tag_gpu.address);
3388
3389 // Prime the WLC by setting "PUT" two steps ahead. Reuse the current
3390 // cpu_put value that was used during channel initialization.
3391 // Don't update wlc->cpu_put, it will be used to track submitted pushes
3392 // as any other channel.
3393 update_gpput_via_sec2(&sec2_push, wlc, (wlc->cpu_put + 2) % wlc->num_gpfifo_entries);
3394
3395 status = uvm_push_end_and_wait(&sec2_push);
3396
3397 end_wlc_dec_push:
3398 uvm_push_end_fake(&wlc_decrypt_push);
3399 free_gpfifo_entries:
3400 uvm_kvfree(wlc_gpfifo_entries);
3401 return status;
3402 }
3403
setup_lcic_schedule(uvm_channel_t * paired_wlc,uvm_channel_t * lcic)3404 static NV_STATUS setup_lcic_schedule(uvm_channel_t *paired_wlc, uvm_channel_t *lcic)
3405 {
3406 uvm_gpu_t *gpu = uvm_channel_get_gpu(lcic);
3407 NvU64 lcic_pb_base = uvm_channel_get_static_pb_protected_vidmem_gpu_va(lcic);
3408
3409 // Reuse WLC sysmem allocation
3410 NvU64 gpu_unprotected = get_channel_unprotected_sysmem_gpu_va(paired_wlc);
3411 char *cpu_unprotected = get_channel_unprotected_sysmem_cpu(paired_wlc);
3412
3413 uvm_gpu_semaphore_t *lcic_semaphore = &lcic->tracking_sem.semaphore;
3414
3415 uvm_gpu_address_t notifier_src_entry_addr = lcic_static_entry_notifier_gpu_va(lcic);
3416 uvm_gpu_address_t notifier_src_exit_addr = lcic_static_exit_notifier_gpu_va(lcic);
3417 uvm_gpu_address_t notifier_dst_addr = uvm_gpu_semaphore_get_notifier_gpu_va(lcic_semaphore);
3418 uvm_gpu_address_t encrypted_payload_gpu_va = uvm_gpu_semaphore_get_encrypted_payload_gpu_va(lcic_semaphore);
3419 uvm_gpu_address_t auth_tag_gpu_va = uvm_gpu_semaphore_get_auth_tag_gpu_va(lcic_semaphore);
3420 uvm_gpu_address_t semaphore_gpu_va = uvm_gpu_address_virtual(uvm_channel_tracking_semaphore_get_gpu_va(lcic));
3421 NvU32 payload_size = sizeof(*uvm_gpu_semaphore_get_encrypted_payload_cpu_va(lcic_semaphore));
3422 NvU32 notifier_size = sizeof(uvm_gpu_semaphore_notifier_t);
3423
3424 NvU64 *lcic_gpfifo_entries;
3425 uvm_push_t lcic_push, sec2_push;
3426 NvU32 lcic_push_size;
3427 int i;
3428 NV_STATUS status;
3429
3430 const size_t gpfifo_size = lcic->num_gpfifo_entries * sizeof(*lcic_gpfifo_entries);
3431 char *gpfifo_unprotected_cpu = cpu_unprotected;
3432 NvU64 gpfifo_unprotected_gpu = gpu_unprotected;
3433 char *lcic_push_unprotected_cpu = gpfifo_unprotected_cpu + gpfifo_size;
3434 NvU64 lcic_push_unprotected_gpu = gpfifo_unprotected_gpu + gpfifo_size;
3435 NvU64 lcic_push_protected_gpu = lcic_pb_base;
3436
3437 char *lcic_push_enc_tag, *gpfifo_enc_tag;
3438 uvm_gpu_address_t lcic_push_enc_tag_gpu, gpfifo_enc_tag_gpu;
3439
3440 BUILD_BUG_ON(sizeof(*lcic_gpfifo_entries) != sizeof(*lcic->channel_info.gpFifoEntries));
3441
3442 UVM_ASSERT(uvm_channel_is_wlc(paired_wlc));
3443 UVM_ASSERT(uvm_channel_is_lcic(lcic));
3444
3445 lcic_gpfifo_entries = uvm_kvmalloc(gpfifo_size);
3446 if (!lcic_gpfifo_entries)
3447 return NV_ERR_NO_MEMORY;
3448
3449 // LCIC can not process outside jobs.
3450 // Prune any initialization entries and
3451 // block all gpfifo entries (-1 for sentinel)
3452 uvm_channel_update_progress(lcic);
3453 if (!try_claim_channel(lcic, lcic->num_gpfifo_entries - 1)) {
3454 status = NV_ERR_INVALID_STATE;
3455 goto free_gpfifo_entries;
3456 }
3457
3458 status = uvm_push_begin_fake(gpu, &lcic_push);
3459 if (status != NV_OK)
3460 goto free_gpfifo_entries;
3461
3462 // LCIC schedule is simple:
3463 // 1.) wait for engine idle
3464 // 2.) advance the WLC PUT by 2
3465 // 3.) release driver semaphore
3466 uvm_hal_wfi_membar(&lcic_push, UVM_MEMBAR_NONE);
3467 gpu->parent->ce_hal->semaphore_reduction_inc(&lcic_push,
3468 paired_wlc->channel_info.gpPutGpuVa,
3469 paired_wlc->num_gpfifo_entries - 1);
3470 gpu->parent->ce_hal->semaphore_reduction_inc(&lcic_push,
3471 paired_wlc->channel_info.gpPutGpuVa,
3472 paired_wlc->num_gpfifo_entries - 1);
3473 gpu->parent->ce_hal->semaphore_reduction_inc(&lcic_push,
3474 semaphore_gpu_va.address,
3475 0xffffffff);
3476
3477 gpu->parent->ce_hal->memcopy(&lcic_push, notifier_dst_addr, notifier_src_entry_addr, notifier_size);
3478
3479 // This CE encryption does not need to be logged, it will be logged on every
3480 // push_end instead
3481 gpu->parent->ce_hal->encrypt(&lcic_push, encrypted_payload_gpu_va, semaphore_gpu_va, payload_size, auth_tag_gpu_va);
3482
3483 gpu->parent->ce_hal->memcopy(&lcic_push, notifier_dst_addr, notifier_src_exit_addr, notifier_size);
3484
3485 // End LCIC push
3486 lcic_push_size = uvm_push_get_size(&lcic_push);
3487
3488 // We're reusing pre-allocated structures from WLC, make sure we fit.
3489 UVM_ASSERT(lcic_push_size == UVM_LCIC_PUSH_SIZE);
3490 UVM_ASSERT(lcic_push_size + gpfifo_size <= UVM_MAX_WLC_PUSH_SIZE);
3491
3492 // Set all entries to execute the above push
3493 for (i = 0; i < lcic->num_gpfifo_entries; ++i)
3494 gpu->parent->host_hal->set_gpfifo_entry(lcic_gpfifo_entries + i,
3495 lcic_push_protected_gpu,
3496 lcic_push_size,
3497 UVM_GPFIFO_SYNC_PROCEED);
3498
3499 // Upload the prepared schedule using SEC2
3500 status = uvm_push_begin(lcic->pool->manager,
3501 UVM_CHANNEL_TYPE_SEC2,
3502 &sec2_push,
3503 "Upload LCIC schedule for: %s", lcic->name);
3504 if (status != NV_OK)
3505 goto end_lcic_push;
3506
3507 lcic_push_enc_tag = uvm_push_get_single_inline_buffer(&sec2_push,
3508 UVM_CONF_COMPUTING_AUTH_TAG_SIZE,
3509 UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT,
3510 &lcic_push_enc_tag_gpu);
3511
3512 gpfifo_enc_tag = uvm_push_get_single_inline_buffer(&sec2_push,
3513 UVM_CONF_COMPUTING_AUTH_TAG_SIZE,
3514 UVM_CONF_COMPUTING_AUTH_TAG_ALIGNMENT,
3515 &gpfifo_enc_tag_gpu);
3516
3517 // Upload LCIC pushbuffer
3518 uvm_conf_computing_cpu_encrypt(sec2_push.channel,
3519 lcic_push_unprotected_cpu,
3520 lcic_push.begin,
3521 NULL,
3522 lcic_push_size,
3523 lcic_push_enc_tag);
3524 gpu->parent->sec2_hal->decrypt(&sec2_push,
3525 lcic_push_protected_gpu,
3526 lcic_push_unprotected_gpu,
3527 lcic_push_size,
3528 lcic_push_enc_tag_gpu.address);
3529
3530 // Upload LCIC GPFIFO
3531 uvm_conf_computing_cpu_encrypt(sec2_push.channel,
3532 gpfifo_unprotected_cpu,
3533 lcic_gpfifo_entries,
3534 NULL,
3535 gpfifo_size,
3536 gpfifo_enc_tag);
3537 gpu->parent->sec2_hal->decrypt(&sec2_push,
3538 lcic->channel_info.gpFifoGpuVa,
3539 gpfifo_unprotected_gpu,
3540 gpfifo_size,
3541 gpfifo_enc_tag_gpu.address);
3542 status = uvm_push_end_and_wait(&sec2_push);
3543
3544 end_lcic_push:
3545 uvm_push_end_fake(&lcic_push);
3546 free_gpfifo_entries:
3547 uvm_kvfree(lcic_gpfifo_entries);
3548 return status;
3549 }
3550
channel_manager_setup_wlc_lcic(uvm_channel_pool_t * wlc_pool,uvm_channel_pool_t * lcic_pool)3551 static NV_STATUS channel_manager_setup_wlc_lcic(uvm_channel_pool_t *wlc_pool, uvm_channel_pool_t *lcic_pool)
3552 {
3553 NvU32 i;
3554
3555 UVM_ASSERT(wlc_pool->manager == lcic_pool->manager);
3556 UVM_ASSERT(!uvm_channel_manager_is_wlc_ready(wlc_pool->manager));
3557 UVM_ASSERT(wlc_pool->manager->pool_to_use.default_for_type[UVM_CHANNEL_TYPE_WLC] != NULL);
3558 UVM_ASSERT(lcic_pool->manager->pool_to_use.default_for_type[UVM_CHANNEL_TYPE_LCIC] == NULL);
3559 UVM_ASSERT(wlc_pool->num_channels == lcic_pool->num_channels);
3560
3561 for (i = 0; i < wlc_pool->num_channels; ++i) {
3562 uvm_channel_t *wlc = wlc_pool->channels + i;
3563 uvm_channel_t *lcic = lcic_pool->channels + i;
3564 NV_STATUS status;
3565
3566 status = setup_wlc_schedule(wlc);
3567 if (status != NV_OK)
3568 return status;
3569
3570 status = setup_lcic_schedule(wlc, lcic);
3571 if (status != NV_OK)
3572 return status;
3573 }
3574
3575 return NV_OK;
3576 }
3577
channel_manager_create_conf_computing_pools(uvm_channel_manager_t * manager,unsigned * preferred_ce)3578 static NV_STATUS channel_manager_create_conf_computing_pools(uvm_channel_manager_t *manager, unsigned *preferred_ce)
3579 {
3580 NV_STATUS status;
3581 unsigned wlc_lcic_ce_index;
3582 uvm_channel_pool_t *sec2_pool = NULL;
3583 uvm_channel_pool_t *wlc_pool = NULL;
3584 uvm_channel_pool_t *lcic_pool = NULL;
3585
3586 if (!g_uvm_global.conf_computing_enabled)
3587 return NV_OK;
3588
3589 status = uvm_rm_mem_alloc(manager->gpu,
3590 UVM_RM_MEM_TYPE_SYS,
3591 sizeof(UvmCslIv),
3592 UVM_CONF_COMPUTING_BUF_ALIGNMENT,
3593 &manager->gpu->conf_computing.iv_rm_mem);
3594 if (status != NV_OK)
3595 return status;
3596
3597 // Create SEC2 pool. This needs to be done first, initialization of
3598 // other channels needs SEC2.
3599 status = channel_pool_add(manager, UVM_CHANNEL_POOL_TYPE_SEC2, 0, &sec2_pool);
3600 if (status != NV_OK)
3601 return status;
3602
3603 manager->pool_to_use.default_for_type[UVM_CHANNEL_TYPE_SEC2] = sec2_pool;
3604
3605 // WLC and LCIC must use the same engine for the fixed schedule to work.
3606 wlc_lcic_ce_index = preferred_ce[UVM_CHANNEL_TYPE_WLC];
3607
3608 // Create WLC/LCIC pools. This should be done early, CE channels use
3609 // them for secure launch. The WLC pool must be created before the LCIC.
3610 status = channel_pool_add(manager, UVM_CHANNEL_POOL_TYPE_WLC, wlc_lcic_ce_index, &wlc_pool);
3611 if (status != NV_OK)
3612 return status;
3613
3614 manager->pool_to_use.default_for_type[UVM_CHANNEL_TYPE_WLC] = wlc_pool;
3615
3616 status = channel_pool_add(manager, UVM_CHANNEL_POOL_TYPE_LCIC, wlc_lcic_ce_index, &lcic_pool);
3617 if (status != NV_OK)
3618 return status;
3619
3620 status = channel_manager_setup_wlc_lcic(wlc_pool, lcic_pool);
3621 if (status != NV_OK)
3622 return status;
3623
3624 // The LCIC pool must be assigned after the call to
3625 // channel_manager_setup_wlc_lcic(). It determines WLC and LCIC channels
3626 // are ready to be used for secure work submission.
3627 manager->pool_to_use.default_for_type[UVM_CHANNEL_TYPE_LCIC] = lcic_pool;
3628
3629 // WLC and LCIC pools are ready
3630 manager->conf_computing.wlc_ready = true;
3631
3632 return NV_OK;
3633 }
3634
channel_manager_create_pools(uvm_channel_manager_t * manager)3635 static NV_STATUS channel_manager_create_pools(uvm_channel_manager_t *manager)
3636 {
3637 NV_STATUS status;
3638 unsigned max_channel_pools;
3639 unsigned preferred_ce[UVM_CHANNEL_TYPE_COUNT];
3640
3641 status = channel_manager_pick_ces(manager, preferred_ce);
3642 if (status != NV_OK)
3643 return status;
3644
3645 max_channel_pools = channel_manager_get_max_pools(manager);
3646
3647 manager->channel_pools = uvm_kvmalloc_zero(sizeof(*manager->channel_pools) * max_channel_pools);
3648 if (!manager->channel_pools)
3649 return NV_ERR_NO_MEMORY;
3650
3651 status = channel_manager_create_conf_computing_pools(manager, preferred_ce);
3652 if (status != NV_OK)
3653 return status;
3654
3655 status = channel_manager_create_ce_pools(manager, preferred_ce);
3656 if (status != NV_OK)
3657 return status;
3658
3659 // In SR-IOV heavy, add an additional, single-channel, pool that is
3660 // dedicated to the MEMOPS type.
3661 if (uvm_parent_gpu_needs_proxy_channel_pool(manager->gpu->parent)) {
3662 uvm_channel_pool_t *proxy_pool = NULL;
3663 uvm_channel_type_t channel_type = uvm_channel_proxy_channel_type();
3664
3665 status = channel_pool_add(manager, UVM_CHANNEL_POOL_TYPE_CE_PROXY, preferred_ce[channel_type], &proxy_pool);
3666 if (status != NV_OK)
3667 return status;
3668
3669 manager->pool_to_use.default_for_type[channel_type] = proxy_pool;
3670 }
3671
3672 return NV_OK;
3673 }
3674
uvm_channel_manager_create(uvm_gpu_t * gpu,uvm_channel_manager_t ** channel_manager_out)3675 NV_STATUS uvm_channel_manager_create(uvm_gpu_t *gpu, uvm_channel_manager_t **channel_manager_out)
3676 {
3677 NV_STATUS status = NV_OK;
3678 uvm_channel_manager_t *channel_manager;
3679
3680 channel_manager = uvm_kvmalloc_zero(sizeof(*channel_manager));
3681 if (!channel_manager)
3682 return NV_ERR_NO_MEMORY;
3683
3684 *channel_manager_out = channel_manager;
3685
3686 channel_manager->gpu = gpu;
3687 init_channel_manager_conf(channel_manager);
3688 status = uvm_pushbuffer_create(channel_manager, &channel_manager->pushbuffer);
3689 if (status != NV_OK)
3690 goto error;
3691
3692 status = manager_create_procfs_dirs(channel_manager);
3693 if (status != NV_OK)
3694 goto error;
3695
3696 status = channel_manager_create_pools(channel_manager);
3697 if (status != NV_OK)
3698 goto error;
3699
3700 status = manager_create_procfs(channel_manager);
3701 if (status != NV_OK)
3702 goto error;
3703
3704 // Key rotation is enabled only after all the channels have been created:
3705 // RM does not support channel allocation on an engine if key rotation is
3706 // pending on that engine. This can become a problem during testing if
3707 // key rotation thresholds are very low.
3708 uvm_conf_computing_enable_key_rotation(gpu);
3709
3710 return NV_OK;
3711
3712 error:
3713 *channel_manager_out = NULL;
3714 uvm_channel_manager_destroy(channel_manager);
3715
3716 return status;
3717 }
3718
channel_manager_destroy_pools(uvm_channel_manager_t * manager)3719 static void channel_manager_destroy_pools(uvm_channel_manager_t *manager)
3720 {
3721 uvm_rm_mem_free(manager->gpu->conf_computing.iv_rm_mem);
3722 manager->gpu->conf_computing.iv_rm_mem = NULL;
3723 while (manager->num_channel_pools > 0)
3724 channel_pool_destroy(manager->channel_pools + manager->num_channel_pools - 1);
3725
3726 uvm_kvfree(manager->channel_pools);
3727 }
3728
3729 // Because the WLC at rest state has PUT = GET + 2, there's always pending work
3730 // This is what enables the driver to submit work just by ringing a doorbell.
3731 // However, this also means that the pending work has to be removed before
3732 // the channel is passed to RM for deallocation.
channel_manager_stop_wlc(uvm_channel_manager_t * manager)3733 static void channel_manager_stop_wlc(uvm_channel_manager_t *manager)
3734 {
3735 uvm_channel_pool_t *wlc_pool = manager->pool_to_use.default_for_type[UVM_CHANNEL_TYPE_WLC];
3736 uvm_channel_pool_t *lcic_pool = manager->pool_to_use.default_for_type[UVM_CHANNEL_TYPE_LCIC];
3737 uvm_channel_t *channel;
3738 uvm_push_t push;
3739 NV_STATUS status;
3740
3741 uvm_for_each_channel_in_pool(channel, lcic_pool) {
3742 uvm_spin_loop_t spin;
3743
3744 // Wait for the WLC/LCIC to be primed. This means that PUT == GET + 2
3745 // and a WLC doorbell ring is enough to start work.
3746 UVM_SPIN_WHILE(!uvm_gpu_tracking_semaphore_is_completed(&channel->tracking_sem), &spin);
3747 }
3748
3749 status = uvm_push_begin(manager, UVM_CHANNEL_TYPE_SEC2, &push, "Stop WLC channels");
3750 if (status != NV_OK) {
3751 UVM_ERR_PRINT_NV_STATUS("Failed to begin stop push for WLC", status);
3752 return;
3753 }
3754
3755 uvm_for_each_channel_in_pool(channel, wlc_pool) {
3756 // Every gpfifo entry advances the gpu put of WLC by two so the current
3757 // value is: (cpu_put * 2) % num_gpfifo_entries and it's ahead of the
3758 // get pointer by 2.
3759 update_gpput_via_sec2(&push, channel, (channel->cpu_put * 2 - 2) % channel->num_gpfifo_entries);
3760 }
3761
3762 status = uvm_push_end_and_wait(&push);
3763 if (status != NV_OK)
3764 UVM_ERR_PRINT_NV_STATUS("Failed to end stop push for WLC", status);
3765
3766 manager->conf_computing.wlc_ready = false;
3767 }
3768
uvm_channel_manager_destroy(uvm_channel_manager_t * channel_manager)3769 void uvm_channel_manager_destroy(uvm_channel_manager_t *channel_manager)
3770 {
3771 if (channel_manager == NULL)
3772 return;
3773
3774 proc_remove(channel_manager->procfs.pending_pushes);
3775
3776 if (uvm_channel_manager_is_wlc_ready(channel_manager))
3777 channel_manager_stop_wlc(channel_manager);
3778
3779 channel_manager_destroy_pools(channel_manager);
3780
3781 proc_remove(channel_manager->procfs.channels_dir);
3782
3783 uvm_pushbuffer_destroy(channel_manager->pushbuffer);
3784
3785 uvm_kvfree(channel_manager);
3786 }
3787
uvm_channel_pool_key_version(uvm_channel_pool_t * pool)3788 NvU32 uvm_channel_pool_key_version(uvm_channel_pool_t *pool)
3789 {
3790 if (uvm_channel_pool_is_lcic(pool))
3791 pool = get_paired_pool(pool);
3792
3793 return pool->conf_computing.key_rotation.version;
3794 }
3795
uvm_channel_is_privileged(uvm_channel_t * channel)3796 bool uvm_channel_is_privileged(uvm_channel_t *channel)
3797 {
3798 if (uvm_parent_gpu_is_virt_mode_sriov_heavy(uvm_channel_get_gpu(channel)->parent))
3799 return uvm_channel_is_proxy(channel);
3800
3801 return true;
3802 }
3803
3804 // Return the first channel pool of the given type(s) starting at begin_pool
3805 // (included).
3806 //
3807 // The pool type mask must be a non empty mask of uvm_channel_pool_type_t
3808 // values.
channel_pool_first_from(uvm_channel_manager_t * manager,uvm_channel_pool_t * begin_pool,NvU32 pool_type_mask)3809 static uvm_channel_pool_t *channel_pool_first_from(uvm_channel_manager_t *manager,
3810 uvm_channel_pool_t *begin_pool,
3811 NvU32 pool_type_mask)
3812 {
3813 uvm_channel_pool_t *curr_pool, *end_pool;
3814
3815 UVM_ASSERT(manager->channel_pools != NULL);
3816 UVM_ASSERT(begin_pool != NULL);
3817 UVM_ASSERT(begin_pool >= manager->channel_pools);
3818 UVM_ASSERT(pool_type_mask > 0);
3819 UVM_ASSERT(pool_type_mask <= UVM_CHANNEL_POOL_TYPE_MASK);
3820
3821 end_pool = manager->channel_pools + manager->num_channel_pools;
3822 UVM_ASSERT(begin_pool <= end_pool);
3823
3824 for (curr_pool = begin_pool; curr_pool != end_pool; curr_pool++) {
3825 if (curr_pool->pool_type & pool_type_mask)
3826 return curr_pool;
3827 }
3828
3829 return NULL;
3830 }
3831
uvm_channel_pool_first(uvm_channel_manager_t * manager,NvU32 pool_type_mask)3832 uvm_channel_pool_t *uvm_channel_pool_first(uvm_channel_manager_t *manager, NvU32 pool_type_mask)
3833 {
3834 return channel_pool_first_from(manager, manager->channel_pools, pool_type_mask);
3835 }
3836
uvm_channel_pool_next(uvm_channel_manager_t * manager,uvm_channel_pool_t * pool,NvU32 pool_type_mask)3837 uvm_channel_pool_t *uvm_channel_pool_next(uvm_channel_manager_t *manager,
3838 uvm_channel_pool_t *pool,
3839 NvU32 pool_type_mask)
3840 {
3841 return channel_pool_first_from(manager, pool + 1, pool_type_mask);
3842 }
3843
uvm_channel_any_of_type(uvm_channel_manager_t * manager,NvU32 pool_type_mask)3844 uvm_channel_t *uvm_channel_any_of_type(uvm_channel_manager_t *manager, NvU32 pool_type_mask)
3845 {
3846 uvm_channel_pool_t *pool = uvm_channel_pool_first(manager, pool_type_mask);
3847
3848 if (pool == NULL)
3849 return NULL;
3850
3851 UVM_ASSERT(pool->channels);
3852
3853 return pool->channels;
3854 }
3855
uvm_channel_type_to_string(uvm_channel_type_t channel_type)3856 const char *uvm_channel_type_to_string(uvm_channel_type_t channel_type)
3857 {
3858 BUILD_BUG_ON(UVM_CHANNEL_TYPE_COUNT != 8);
3859
3860 switch (channel_type) {
3861 UVM_ENUM_STRING_CASE(UVM_CHANNEL_TYPE_CPU_TO_GPU);
3862 UVM_ENUM_STRING_CASE(UVM_CHANNEL_TYPE_GPU_TO_CPU);
3863 UVM_ENUM_STRING_CASE(UVM_CHANNEL_TYPE_GPU_INTERNAL);
3864 UVM_ENUM_STRING_CASE(UVM_CHANNEL_TYPE_MEMOPS);
3865 UVM_ENUM_STRING_CASE(UVM_CHANNEL_TYPE_GPU_TO_GPU);
3866 UVM_ENUM_STRING_CASE(UVM_CHANNEL_TYPE_SEC2);
3867 UVM_ENUM_STRING_CASE(UVM_CHANNEL_TYPE_WLC);
3868 UVM_ENUM_STRING_CASE(UVM_CHANNEL_TYPE_LCIC);
3869 UVM_ENUM_STRING_DEFAULT();
3870 }
3871 }
3872
uvm_channel_pool_type_to_string(uvm_channel_pool_type_t channel_pool_type)3873 const char *uvm_channel_pool_type_to_string(uvm_channel_pool_type_t channel_pool_type)
3874 {
3875 BUILD_BUG_ON(UVM_CHANNEL_POOL_TYPE_COUNT != 5);
3876
3877 switch (channel_pool_type) {
3878 UVM_ENUM_STRING_CASE(UVM_CHANNEL_POOL_TYPE_CE);
3879 UVM_ENUM_STRING_CASE(UVM_CHANNEL_POOL_TYPE_CE_PROXY);
3880 UVM_ENUM_STRING_CASE(UVM_CHANNEL_POOL_TYPE_SEC2);
3881 UVM_ENUM_STRING_CASE(UVM_CHANNEL_POOL_TYPE_WLC);
3882 UVM_ENUM_STRING_CASE(UVM_CHANNEL_POOL_TYPE_LCIC);
3883 UVM_ENUM_STRING_DEFAULT();
3884 }
3885 }
3886
get_gpfifo_location_string(uvm_channel_t * channel)3887 static const char *get_gpfifo_location_string(uvm_channel_t *channel)
3888 {
3889 // SEC2 channels override the channel manager location for GPFIFO.
3890 if (uvm_channel_is_sec2(channel))
3891 return buffer_location_to_string(UVM_BUFFER_LOCATION_SYS);
3892 return buffer_location_to_string(channel->pool->manager->conf.gpfifo_loc);
3893 }
3894
get_gpput_location_string(uvm_channel_t * channel)3895 static const char *get_gpput_location_string(uvm_channel_t *channel)
3896 {
3897 // SEC2 channels override the channel manager location for GPPUT.
3898 if (uvm_channel_is_sec2(channel))
3899 return buffer_location_to_string(UVM_BUFFER_LOCATION_SYS);
3900 return buffer_location_to_string(channel->pool->manager->conf.gpput_loc);
3901 }
3902
uvm_channel_print_info(uvm_channel_t * channel,struct seq_file * s)3903 static void uvm_channel_print_info(uvm_channel_t *channel, struct seq_file *s)
3904 {
3905 UVM_SEQ_OR_DBG_PRINT(s, "Channel %s\n", channel->name);
3906
3907 channel_pool_lock(channel->pool);
3908
3909 UVM_SEQ_OR_DBG_PRINT(s, "completed %llu\n", uvm_channel_update_completed_value(channel));
3910 UVM_SEQ_OR_DBG_PRINT(s, "queued %llu\n", channel->tracking_sem.queued_value);
3911 UVM_SEQ_OR_DBG_PRINT(s, "GPFIFO count %u\n", channel->num_gpfifo_entries);
3912 UVM_SEQ_OR_DBG_PRINT(s, "GPFIFO location %s\n", get_gpfifo_location_string(channel));
3913 UVM_SEQ_OR_DBG_PRINT(s, "GPPUT location %s\n", get_gpput_location_string(channel));
3914 UVM_SEQ_OR_DBG_PRINT(s, "get %u\n", channel->gpu_get);
3915 UVM_SEQ_OR_DBG_PRINT(s, "put %u\n", channel->cpu_put);
3916 UVM_SEQ_OR_DBG_PRINT(s, "Semaphore GPU VA 0x%llx\n", uvm_channel_tracking_semaphore_get_gpu_va(channel));
3917 UVM_SEQ_OR_DBG_PRINT(s, "Semaphore CPU VA 0x%llx\n", (NvU64)uvm_gpu_semaphore_get_cpu_va(&channel->tracking_sem.semaphore));
3918
3919 channel_pool_unlock(channel->pool);
3920 }
3921
channel_print_push_acquires(uvm_push_acquire_info_t * push_acquire_info,struct seq_file * seq)3922 static void channel_print_push_acquires(uvm_push_acquire_info_t *push_acquire_info, struct seq_file *seq)
3923 {
3924 NvU32 i;
3925 NvU32 valid_entries;
3926
3927 UVM_ASSERT(uvm_push_info_is_tracking_acquires());
3928 UVM_ASSERT(push_acquire_info);
3929
3930 if (push_acquire_info->num_values == 0)
3931 return;
3932
3933 valid_entries = min(push_acquire_info->num_values, (NvU32)UVM_PUSH_ACQUIRE_INFO_MAX_ENTRIES);
3934
3935 for (i = 0; i < valid_entries; ++i) {
3936 bool is_proxy = push_acquire_info->values[i].is_proxy;
3937
3938 UVM_SEQ_OR_DBG_PRINT(seq,
3939 "%s (gpu %u, channel %d:%u, value %llu)",
3940 i == 0? " acquiring values" : "",
3941 uvm_id_value(push_acquire_info->values[i].gpu_id),
3942 is_proxy? -1 : push_acquire_info->values[i].runlist_id,
3943 is_proxy? push_acquire_info->values[i].proxy.pool_index :
3944 push_acquire_info->values[i].channel_id,
3945 push_acquire_info->values[i].value);
3946 }
3947
3948 if (push_acquire_info->num_values > valid_entries)
3949 UVM_SEQ_OR_DBG_PRINT(seq, " (missing %u entries)", push_acquire_info->num_values - valid_entries);
3950
3951 UVM_SEQ_OR_DBG_PRINT(seq, "\n");
3952 }
3953
3954 // Print all pending pushes and up to finished_pushes_count completed if their
3955 // GPFIFO entries haven't been reused yet.
channel_print_pushes(uvm_channel_t * channel,NvU32 finished_pushes_count,struct seq_file * seq)3956 static void channel_print_pushes(uvm_channel_t *channel, NvU32 finished_pushes_count, struct seq_file *seq)
3957 {
3958 NvU32 gpu_get;
3959 NvU32 cpu_put;
3960
3961 NvU64 completed_value = uvm_channel_update_completed_value(channel);
3962
3963 channel_pool_lock(channel->pool);
3964
3965 cpu_put = channel->cpu_put;
3966
3967 for (gpu_get = channel->gpu_get; gpu_get != cpu_put; gpu_get = (gpu_get + 1) % channel->num_gpfifo_entries) {
3968 uvm_gpfifo_entry_t *entry = &channel->gpfifo_entries[gpu_get];
3969 uvm_push_info_t *push_info = entry->push_info;
3970 uvm_push_acquire_info_t *push_acquire_info = NULL;
3971
3972 if (entry->tracking_semaphore_value + finished_pushes_count <= completed_value)
3973 continue;
3974
3975 if (entry->type == UVM_GPFIFO_ENTRY_TYPE_CONTROL) {
3976 UVM_ASSERT(!uvm_channel_is_proxy(channel));
3977
3978 UVM_SEQ_OR_DBG_PRINT(seq,
3979 " control GPFIFO entry - data: 0x%llx, gpu_get: %d\n",
3980 entry->control_value,
3981 gpu_get);
3982 }
3983 else {
3984
3985 // Obtain the value acquire tracking information from the push_info
3986 // index
3987 if (uvm_push_info_is_tracking_acquires()) {
3988 NvU32 push_info_index = push_info - channel->push_infos;
3989 UVM_ASSERT(push_info_index < channel->num_gpfifo_entries);
3990
3991 push_acquire_info = &channel->push_acquire_infos[push_info_index];
3992 }
3993
3994 UVM_SEQ_OR_DBG_PRINT(seq,
3995 " %s push '%s' started at %s:%d in %s() releasing value %llu%s",
3996 entry->tracking_semaphore_value <= completed_value ? "finished" : "pending",
3997 push_info->description,
3998 push_info->filename,
3999 push_info->line,
4000 push_info->function,
4001 entry->tracking_semaphore_value,
4002 !push_acquire_info || push_acquire_info->num_values == 0 ? "\n" : "");
4003
4004 if (push_acquire_info)
4005 channel_print_push_acquires(push_acquire_info, seq);
4006 }
4007 }
4008 channel_pool_unlock(channel->pool);
4009 }
4010
uvm_channel_print_pending_pushes(uvm_channel_t * channel)4011 void uvm_channel_print_pending_pushes(uvm_channel_t *channel)
4012 {
4013 channel_print_pushes(channel, 0, NULL);
4014 }
4015
channel_manager_print_pending_pushes(uvm_channel_manager_t * manager,struct seq_file * seq)4016 static void channel_manager_print_pending_pushes(uvm_channel_manager_t *manager, struct seq_file *seq)
4017 {
4018 uvm_channel_pool_t *pool;
4019
4020 uvm_for_each_pool(pool, manager) {
4021 uvm_channel_t *channel;
4022
4023 uvm_for_each_channel_in_pool(channel, pool) {
4024 UVM_SEQ_OR_DBG_PRINT(seq, "Channel %s, pending pushes:\n", channel->name);
4025
4026 channel_print_pushes(channel, 0, seq);
4027 }
4028 }
4029 }
4030
manager_create_procfs_dirs(uvm_channel_manager_t * manager)4031 static NV_STATUS manager_create_procfs_dirs(uvm_channel_manager_t *manager)
4032 {
4033 uvm_gpu_t *gpu = manager->gpu;
4034
4035 // The channel manager procfs files are debug only
4036 if (!uvm_procfs_is_debug_enabled())
4037 return NV_OK;
4038
4039 manager->procfs.channels_dir = NV_CREATE_PROC_DIR("channels", gpu->procfs.dir);
4040 if (manager->procfs.channels_dir == NULL)
4041 return NV_ERR_OPERATING_SYSTEM;
4042
4043 return NV_OK;
4044 }
4045
nv_procfs_read_manager_pending_pushes(struct seq_file * s,void * v)4046 static int nv_procfs_read_manager_pending_pushes(struct seq_file *s, void *v)
4047 {
4048 uvm_channel_manager_t *manager = (uvm_channel_manager_t *)s->private;
4049
4050 if (!uvm_down_read_trylock(&g_uvm_global.pm.lock))
4051 return -EAGAIN;
4052
4053 channel_manager_print_pending_pushes(manager, s);
4054
4055 uvm_up_read(&g_uvm_global.pm.lock);
4056
4057 return 0;
4058 }
4059
nv_procfs_read_manager_pending_pushes_entry(struct seq_file * s,void * v)4060 static int nv_procfs_read_manager_pending_pushes_entry(struct seq_file *s, void *v)
4061 {
4062 UVM_ENTRY_RET(nv_procfs_read_manager_pending_pushes(s, v));
4063 }
4064
4065 UVM_DEFINE_SINGLE_PROCFS_FILE(manager_pending_pushes_entry);
4066
manager_create_procfs(uvm_channel_manager_t * manager)4067 static NV_STATUS manager_create_procfs(uvm_channel_manager_t *manager)
4068 {
4069 uvm_gpu_t *gpu = manager->gpu;
4070
4071 // The channel manager procfs files are debug only
4072 if (!uvm_procfs_is_debug_enabled())
4073 return NV_OK;
4074
4075 manager->procfs.pending_pushes = NV_CREATE_PROC_FILE("pending_pushes",
4076 gpu->procfs.dir,
4077 manager_pending_pushes_entry,
4078 manager);
4079 if (manager->procfs.pending_pushes == NULL)
4080 return NV_ERR_OPERATING_SYSTEM;
4081
4082 return NV_OK;
4083 }
4084
nv_procfs_read_channel_info(struct seq_file * s,void * v)4085 static int nv_procfs_read_channel_info(struct seq_file *s, void *v)
4086 {
4087 uvm_channel_t *channel = (uvm_channel_t *)s->private;
4088
4089 if (!uvm_down_read_trylock(&g_uvm_global.pm.lock))
4090 return -EAGAIN;
4091
4092 uvm_channel_print_info(channel, s);
4093
4094 uvm_up_read(&g_uvm_global.pm.lock);
4095
4096 return 0;
4097 }
4098
nv_procfs_read_channel_info_entry(struct seq_file * s,void * v)4099 static int nv_procfs_read_channel_info_entry(struct seq_file *s, void *v)
4100 {
4101 UVM_ENTRY_RET(nv_procfs_read_channel_info(s, v));
4102 }
4103
4104 UVM_DEFINE_SINGLE_PROCFS_FILE(channel_info_entry);
4105
nv_procfs_read_channel_pushes(struct seq_file * s,void * v)4106 static int nv_procfs_read_channel_pushes(struct seq_file *s, void *v)
4107 {
4108 uvm_channel_t *channel = (uvm_channel_t *)s->private;
4109
4110 if (!uvm_down_read_trylock(&g_uvm_global.pm.lock))
4111 return -EAGAIN;
4112
4113 // Include up to 5 finished pushes for some context
4114 channel_print_pushes(channel, 5, s);
4115
4116 uvm_up_read(&g_uvm_global.pm.lock);
4117
4118 return 0;
4119 }
4120
nv_procfs_read_channel_pushes_entry(struct seq_file * s,void * v)4121 static int nv_procfs_read_channel_pushes_entry(struct seq_file *s, void *v)
4122 {
4123 UVM_ENTRY_RET(nv_procfs_read_channel_pushes(s, v));
4124 }
4125
4126 UVM_DEFINE_SINGLE_PROCFS_FILE(channel_pushes_entry);
4127
channel_create_procfs(uvm_channel_t * channel)4128 static NV_STATUS channel_create_procfs(uvm_channel_t *channel)
4129 {
4130 char dirname[16];
4131 uvm_channel_manager_t *manager = channel->pool->manager;
4132
4133 // The channel procfs files are debug only
4134 if (!uvm_procfs_is_debug_enabled())
4135 return NV_OK;
4136
4137 // For internal channels, the directory name contains the HW IDs. Those are
4138 // not available for proxy channels, so use -1:<channel index> instead.
4139 if (uvm_channel_is_proxy(channel))
4140 snprintf(dirname, sizeof(dirname), "-1:%u", uvm_channel_index_in_pool(channel));
4141 else
4142 snprintf(dirname, sizeof(dirname), "%u:%u", channel->channel_info.hwRunlistId, channel->channel_info.hwChannelId);
4143
4144 channel->procfs.dir = NV_CREATE_PROC_DIR(dirname, manager->procfs.channels_dir);
4145 if (channel->procfs.dir == NULL)
4146 return NV_ERR_OPERATING_SYSTEM;
4147
4148 channel->procfs.info = NV_CREATE_PROC_FILE("info", channel->procfs.dir, channel_info_entry, channel);
4149 if (channel->procfs.info == NULL)
4150 return NV_ERR_OPERATING_SYSTEM;
4151
4152 channel->procfs.pushes = NV_CREATE_PROC_FILE("pushes", channel->procfs.dir, channel_pushes_entry, channel);
4153 if (channel->procfs.pushes == NULL)
4154 return NV_ERR_OPERATING_SYSTEM;
4155
4156 return NV_OK;
4157 }
4158