Skip to content

Commit 14b81ab

Browse files
amd-jherichuangalexdeucher
authored andcommitted
drm/amdgpu: prevent immediate PASID reuse case
PASID resue could cause interrupt issue when process immediately runs into hw state left by previous process exited with the same PASID, it's possible that page faults are still pending in the IH ring buffer when the process exits and frees up its PASID. To prevent the case, it uses idr cyclic allocator same as kernel pid's. Signed-off-by: Eric Huang <jinhuieric.huang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 8f1de51) Cc: stable@vger.kernel.org
1 parent 2d300eb commit 14b81ab

3 files changed

Lines changed: 34 additions & 13 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@
3535
* PASIDs are global address space identifiers that can be shared
3636
* between the GPU, an IOMMU and the driver. VMs on different devices
3737
* may use the same PASID if they share the same address
38-
* space. Therefore PASIDs are allocated using a global IDA. VMs are
39-
* looked up from the PASID per amdgpu_device.
38+
* space. Therefore PASIDs are allocated using IDR cyclic allocator
39+
* (similar to kernel PID allocation) which naturally delays reuse.
40+
* VMs are looked up from the PASID per amdgpu_device.
4041
*/
41-
static DEFINE_IDA(amdgpu_pasid_ida);
42+
43+
static DEFINE_IDR(amdgpu_pasid_idr);
44+
static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock);
4245

4346
/* Helper to free pasid from a fence callback */
4447
struct amdgpu_pasid_cb {
@@ -50,23 +53,24 @@ struct amdgpu_pasid_cb {
5053
* amdgpu_pasid_alloc - Allocate a PASID
5154
* @bits: Maximum width of the PASID in bits, must be at least 1
5255
*
53-
* Allocates a PASID of the given width while keeping smaller PASIDs
54-
* available if possible.
56+
* Uses kernel's IDR cyclic allocator (same as PID allocation).
57+
* Allocates sequentially with automatic wrap-around.
5558
*
5659
* Returns a positive integer on success. Returns %-EINVAL if bits==0.
5760
* Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on
5861
* memory allocation failure.
5962
*/
6063
int amdgpu_pasid_alloc(unsigned int bits)
6164
{
62-
int pasid = -EINVAL;
65+
int pasid;
6366

64-
for (bits = min(bits, 31U); bits > 0; bits--) {
65-
pasid = ida_alloc_range(&amdgpu_pasid_ida, 1U << (bits - 1),
66-
(1U << bits) - 1, GFP_KERNEL);
67-
if (pasid != -ENOSPC)
68-
break;
69-
}
67+
if (bits == 0)
68+
return -EINVAL;
69+
70+
spin_lock(&amdgpu_pasid_idr_lock);
71+
pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
72+
1U << bits, GFP_KERNEL);
73+
spin_unlock(&amdgpu_pasid_idr_lock);
7074

7175
if (pasid >= 0)
7276
trace_amdgpu_pasid_allocated(pasid);
@@ -81,7 +85,10 @@ int amdgpu_pasid_alloc(unsigned int bits)
8185
void amdgpu_pasid_free(u32 pasid)
8286
{
8387
trace_amdgpu_pasid_freed(pasid);
84-
ida_free(&amdgpu_pasid_ida, pasid);
88+
89+
spin_lock(&amdgpu_pasid_idr_lock);
90+
idr_remove(&amdgpu_pasid_idr, pasid);
91+
spin_unlock(&amdgpu_pasid_idr_lock);
8592
}
8693

8794
static void amdgpu_pasid_free_cb(struct dma_fence *fence,
@@ -616,3 +623,15 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
616623
}
617624
}
618625
}
626+
627+
/**
628+
* amdgpu_pasid_mgr_cleanup - cleanup PASID manager
629+
*
630+
* Cleanup the IDR allocator.
631+
*/
632+
void amdgpu_pasid_mgr_cleanup(void)
633+
{
634+
spin_lock(&amdgpu_pasid_idr_lock);
635+
idr_destroy(&amdgpu_pasid_idr);
636+
spin_unlock(&amdgpu_pasid_idr_lock);
637+
}

drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ int amdgpu_pasid_alloc(unsigned int bits);
7474
void amdgpu_pasid_free(u32 pasid);
7575
void amdgpu_pasid_free_delayed(struct dma_resv *resv,
7676
u32 pasid);
77+
void amdgpu_pasid_mgr_cleanup(void);
7778

7879
bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
7980
struct amdgpu_vmid *id);

drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2898,6 +2898,7 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
28982898
xa_destroy(&adev->vm_manager.pasids);
28992899

29002900
amdgpu_vmid_mgr_fini(adev);
2901+
amdgpu_pasid_mgr_cleanup();
29012902
}
29022903

29032904
/**

0 commit comments

Comments
 (0)