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