1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2024 Advanced Micro Devices, Inc. 4 * 5 * Lockdep annotation for AMDGPU lock ordering 6 * 7 * This module teaches lockdep the correct lock ordering to catch 8 * potential deadlocks at development time rather than runtime. 9 * 10 * Based on dma-resv lockdep approach from: 11 * drivers/dma-buf/dma-resv.c:dma_resv_lockdep() 12 */ 13 14 #include "amdgpu.h" 15 #include "amdgpu_reset.h" 16 17 #ifdef CONFIG_LOCKDEP 18 19 struct amdgpu_lockdep_dummy_locks { 20 struct mutex reset_lock; 21 struct mutex userq_sch_mutex; 22 struct mutex userq_mutex; 23 struct mutex notifier_lock; 24 struct mutex vram_lock; 25 struct mutex srbm_mutex; 26 struct mutex grbm_idx_mutex; 27 spinlock_t mmio_idx_lock; 28 }; 29 30 /* Lock class keys for associating with real driver locks */ 31 static struct lock_class_key amdgpu_userq_sch_mutex_key; 32 static struct lock_class_key amdgpu_userq_mutex_key; 33 static struct lock_class_key amdgpu_notifier_lock_key; 34 static struct lock_class_key amdgpu_vram_lock_key; 35 static struct lock_class_key amdgpu_reset_sem_key; 36 static struct lock_class_key amdgpu_reset_lock_key; 37 static struct lock_class_key amdgpu_srbm_lock_key; 38 static struct lock_class_key amdgpu_grbm_lock_key; 39 static struct lock_class_key amdgpu_mmio_lock_key; 40 41 /** 42 * amdgpu_lockdep_set_class - Associate lock class keys with real locks 43 * @adev: AMDGPU device 44 * 45 * Call during device init to associate lock classes with actual locks 46 * so lockdep can track them properly. 47 */ 48 void amdgpu_lockdep_set_class(struct amdgpu_device *adev) 49 { 50 lockdep_set_class(&adev->gfx.userq_sch_mutex, 51 &amdgpu_userq_sch_mutex_key); 52 lockdep_set_class(&adev->notifier_lock, &amdgpu_notifier_lock_key); 53 lockdep_set_class(&adev->srbm_mutex, &amdgpu_srbm_lock_key); 54 lockdep_set_class(&adev->grbm_idx_mutex, &amdgpu_grbm_lock_key); 55 lockdep_set_class(&adev->mmio_idx_lock, &amdgpu_mmio_lock_key); 56 57 if (adev->reset_domain) 58 lockdep_set_class(&adev->reset_domain->sem, 59 &amdgpu_reset_sem_key); 60 } 61 62 /** 63 * amdgpu_lockdep_init - Teach lockdep the correct lock ordering 64 * 65 * Instantiates dummy objects and takes locks in the correct order to 66 * train lockdep. This helps catch lock ordering violations during 67 * development. 68 * 69 * Lock ordering hierarchy (outermost to innermost): 70 * 71 * 1. userq_sch_mutex - Global userq scheduler (enforce_isolation) 72 * 2. userq_mutex - Per-context userq (held across queue create/destroy) 73 * 3. notifier_lock - MMU notifier lock 74 * 4. vram_lock - VRAM allocator lock 75 * 5. reset_domain->sem - GPU reset synchronization 76 * 6. reset_lock - Reset control lock 77 * 7. srbm_mutex - SRBM register access 78 * 8. grbm_idx_mutex - GRBM index access 79 * 9. mmio_idx_lock - MMIO index access (spinlock) 80 * 81 * Evidence: 82 * - userq_sch_mutex -> userq_mutex: amdgpu_gfx_kfd_sch_ctrl() calls 83 * amdgpu_userq_stop_sched_for_enforce_isolation() which takes userq_mutex 84 * - userq_mutex -> notifier_lock: userq paths may trigger MMU notifier 85 * invalidation which acquires notifier_lock 86 * - notifier_lock -> reset_domain->sem: HMM invalidation callback holds 87 * notifier_lock and can wait for GPU reset completion, so notifier_lock 88 * must be outer to reset_domain->sem 89 * - vram_lock -> reset_domain->sem: VRAM management paths may need to 90 * wait for ongoing reset to complete 91 * 92 * Note: mmap_lock ordering relative to GPU locks is already taught 93 * by dma-resv (drivers/dma-buf/dma-resv.c). 94 */ 95 int amdgpu_lockdep_init(void) 96 { 97 struct amdgpu_reset_domain *reset_domain = NULL; 98 struct amdgpu_lockdep_dummy_locks *locks; 99 unsigned long flags; 100 101 locks = kzalloc(sizeof(*locks), GFP_KERNEL); 102 if (!locks) 103 return -ENOMEM; 104 105 /* 106 * Initialize dummy reset domain 107 */ 108 reset_domain = amdgpu_reset_create_reset_domain(SINGLE_DEVICE, 109 "lockdep_test"); 110 if (!reset_domain) { 111 kfree(locks); 112 return -ENOMEM; 113 } 114 /* Initialize dummy locks */ 115 mutex_init(&locks->userq_sch_mutex); 116 mutex_init(&locks->userq_mutex); 117 mutex_init(&locks->notifier_lock); 118 mutex_init(&locks->vram_lock); 119 mutex_init(&locks->reset_lock); 120 mutex_init(&locks->srbm_mutex); 121 mutex_init(&locks->grbm_idx_mutex); 122 spin_lock_init(&locks->mmio_idx_lock); 123 124 /* 125 * Associate dummy locks with the same class keys used for real 126 * driver locks. This ensures lockdep connects the ordering learned 127 * here with the actual locks used at runtime. 128 */ 129 lockdep_set_class(&locks->userq_sch_mutex, &amdgpu_userq_sch_mutex_key); 130 lockdep_set_class(&locks->userq_mutex, &amdgpu_userq_mutex_key); 131 lockdep_set_class(&locks->notifier_lock, &amdgpu_notifier_lock_key); 132 lockdep_set_class(&locks->vram_lock, &amdgpu_vram_lock_key); 133 lockdep_set_class(&reset_domain->sem, &amdgpu_reset_sem_key); 134 lockdep_set_class(&locks->reset_lock, &amdgpu_reset_lock_key); 135 lockdep_set_class(&locks->srbm_mutex, &amdgpu_srbm_lock_key); 136 lockdep_set_class(&locks->grbm_idx_mutex, &amdgpu_grbm_lock_key); 137 lockdep_set_class(&locks->mmio_idx_lock, &amdgpu_mmio_lock_key); 138 139 /* 140 * Register fs_reclaim lock class FIRST, before taking any locks. 141 * 142 * This acquire/release pair does NOT create a static lockdep edge 143 * (no locks are held between acquire and release). It only registers 144 * the fs_reclaim lock class with lockdep. 145 * 146 * The actual fs_reclaim -> notifier_lock dependency is established at 147 * RUNTIME when memory reclaim invokes MMU notifiers: 148 * fs_reclaim (held by reclaim) -> notifier_lock (acquired in callback) 149 */ 150 fs_reclaim_acquire(GFP_KERNEL); 151 fs_reclaim_release(GFP_KERNEL); 152 153 /* 154 * Take locks in the correct order to train lockdep. 155 * This establishes the dependency chain. 156 */ 157 158 /* Level 1: Global userq scheduler mutex (outermost) */ 159 mutex_lock(&locks->userq_sch_mutex); 160 161 /* Level 2: Per-context userq mutex */ 162 mutex_lock(&locks->userq_mutex); 163 /* Level 3: MMU notifier lock */ 164 mutex_lock(&locks->notifier_lock); 165 /* Level 4: VRAM allocator lock */ 166 mutex_lock(&locks->vram_lock); 167 /* Level 5: Reset domain semaphore */ 168 down_read(&reset_domain->sem); 169 170 /* Level 6: Reset control lock */ 171 mutex_lock(&locks->reset_lock); 172 173 /* Level 7: SRBM register access */ 174 mutex_lock(&locks->srbm_mutex); 175 /* Level 8: GRBM index access */ 176 mutex_lock(&locks->grbm_idx_mutex); 177 178 /* Level 9: MMIO index access (innermost lock, spinlock) */ 179 spin_lock_irqsave(&locks->mmio_idx_lock, flags); 180 /* 181 * All locks acquired in order. 182 * Lockdep has now learned the valid dependency chain. 183 */ 184 185 /* Release in reverse order */ 186 spin_unlock_irqrestore(&locks->mmio_idx_lock, flags); 187 mutex_unlock(&locks->grbm_idx_mutex); 188 mutex_unlock(&locks->srbm_mutex); 189 190 mutex_unlock(&locks->reset_lock); 191 up_read(&reset_domain->sem); 192 193 mutex_unlock(&locks->vram_lock); 194 mutex_unlock(&locks->notifier_lock); 195 mutex_unlock(&locks->userq_mutex); 196 mutex_unlock(&locks->userq_sch_mutex); 197 198 /* Cleanup */ 199 amdgpu_reset_put_reset_domain(reset_domain); 200 201 kfree(locks); 202 pr_info("AMDGPU: Lockdep annotations initialized (9 lock levels)\n"); 203 204 return 0; 205 } 206 207 #endif /* CONFIG_LOCKDEP */ 208