Skip to content

Commit 8a7c3ce

Browse files
PhilipYangAalexdeucher
authored andcommitted
drm/amdkfd: Track unified memory when switching xnack mode
Unified memory usage with xnack off is tracked to avoid oversubscribe system memory, with xnack on, we don't track unified memory usage to allow memory oversubscribe. When switching xnack mode from off to on, subsequent free ranges allocated with xnack off will not unreserve memory. When switching xnack mode from on to off, subsequent free ranges allocated with xnack on will unreserve memory. Both cases cause memory accounting unbalanced. When switching xnack mode from on to off, need reserve already allocated svm range memory. When switching xnack mode from off to on, need unreserve already allocated svm range memory. v6: Take prange lock to access range child list v5: Handle prange child ranges v4: Handle reservation memory failure v3: Handle switching xnack mode race with svm_range_deferred_list_work v2: Handle both switching xnack from on to off and from off to on cases Signed-off-by: Philip Yang <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 730548b commit 8a7c3ce

File tree

3 files changed

+80
-7
lines changed

3 files changed

+80
-7
lines changed

drivers/gpu/drm/amd/amdkfd/kfd_chardev.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,8 @@ static int kfd_ioctl_smi_events(struct file *filep,
15841584
return kfd_smi_event_open(pdd->dev, &args->anon_fd);
15851585
}
15861586

1587+
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
1588+
15871589
static int kfd_ioctl_set_xnack_mode(struct file *filep,
15881590
struct kfd_process *p, void *data)
15891591
{
@@ -1594,22 +1596,29 @@ static int kfd_ioctl_set_xnack_mode(struct file *filep,
15941596
if (args->xnack_enabled >= 0) {
15951597
if (!list_empty(&p->pqm.queues)) {
15961598
pr_debug("Process has user queues running\n");
1597-
mutex_unlock(&p->mutex);
1598-
return -EBUSY;
1599+
r = -EBUSY;
1600+
goto out_unlock;
15991601
}
1600-
if (args->xnack_enabled && !kfd_process_xnack_mode(p, true))
1602+
1603+
if (p->xnack_enabled == args->xnack_enabled)
1604+
goto out_unlock;
1605+
1606+
if (args->xnack_enabled && !kfd_process_xnack_mode(p, true)) {
16011607
r = -EPERM;
1602-
else
1603-
p->xnack_enabled = args->xnack_enabled;
1608+
goto out_unlock;
1609+
}
1610+
1611+
r = svm_range_switch_xnack_reserve_mem(p, args->xnack_enabled);
16041612
} else {
16051613
args->xnack_enabled = p->xnack_enabled;
16061614
}
1615+
1616+
out_unlock:
16071617
mutex_unlock(&p->mutex);
16081618

16091619
return r;
16101620
}
16111621

1612-
#if IS_ENABLED(CONFIG_HSA_AMD_SVM)
16131622
static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data)
16141623
{
16151624
struct kfd_ioctl_svm_args *args = data;
@@ -1629,6 +1638,11 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data)
16291638
return r;
16301639
}
16311640
#else
1641+
static int kfd_ioctl_set_xnack_mode(struct file *filep,
1642+
struct kfd_process *p, void *data)
1643+
{
1644+
return -EPERM;
1645+
}
16321646
static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data)
16331647
{
16341648
return -EPERM;

drivers/gpu/drm/amd/amdkfd/kfd_svm.c

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ static void svm_range_free(struct svm_range *prange, bool update_mem_usage)
278278
svm_range_free_dma_mappings(prange);
279279

280280
if (update_mem_usage && !p->xnack_enabled) {
281-
pr_debug("unreserve mem limit: %lld\n", size);
281+
pr_debug("unreserve prange 0x%p size: 0x%llx\n", prange, size);
282282
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
283283
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
284284
}
@@ -2956,6 +2956,64 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
29562956
return r;
29572957
}
29582958

2959+
int
2960+
svm_range_switch_xnack_reserve_mem(struct kfd_process *p, bool xnack_enabled)
2961+
{
2962+
struct svm_range *prange, *pchild;
2963+
uint64_t reserved_size = 0;
2964+
uint64_t size;
2965+
int r = 0;
2966+
2967+
pr_debug("switching xnack from %d to %d\n", p->xnack_enabled, xnack_enabled);
2968+
2969+
mutex_lock(&p->svms.lock);
2970+
2971+
list_for_each_entry(prange, &p->svms.list, list) {
2972+
svm_range_lock(prange);
2973+
list_for_each_entry(pchild, &prange->child_list, child_list) {
2974+
size = (pchild->last - pchild->start + 1) << PAGE_SHIFT;
2975+
if (xnack_enabled) {
2976+
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
2977+
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
2978+
} else {
2979+
r = amdgpu_amdkfd_reserve_mem_limit(NULL, size,
2980+
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
2981+
if (r)
2982+
goto out_unlock;
2983+
reserved_size += size;
2984+
}
2985+
}
2986+
2987+
size = (prange->last - prange->start + 1) << PAGE_SHIFT;
2988+
if (xnack_enabled) {
2989+
amdgpu_amdkfd_unreserve_mem_limit(NULL, size,
2990+
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
2991+
} else {
2992+
r = amdgpu_amdkfd_reserve_mem_limit(NULL, size,
2993+
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
2994+
if (r)
2995+
goto out_unlock;
2996+
reserved_size += size;
2997+
}
2998+
out_unlock:
2999+
svm_range_unlock(prange);
3000+
if (r)
3001+
break;
3002+
}
3003+
3004+
if (r)
3005+
amdgpu_amdkfd_unreserve_mem_limit(NULL, reserved_size,
3006+
KFD_IOC_ALLOC_MEM_FLAGS_USERPTR);
3007+
else
3008+
/* Change xnack mode must be inside svms lock, to avoid race with
3009+
* svm_range_deferred_list_work unreserve memory in parallel.
3010+
*/
3011+
p->xnack_enabled = xnack_enabled;
3012+
3013+
mutex_unlock(&p->svms.lock);
3014+
return r;
3015+
}
3016+
29593017
void svm_range_list_fini(struct kfd_process *p)
29603018
{
29613019
struct svm_range *prange;

drivers/gpu/drm/amd/amdkfd/kfd_svm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_s
203203
void svm_range_bo_unref_async(struct svm_range_bo *svm_bo);
204204

205205
void svm_range_set_max_pages(struct amdgpu_device *adev);
206+
int svm_range_switch_xnack_reserve_mem(struct kfd_process *p, bool xnack_enabled);
206207

207208
#else
208209

0 commit comments

Comments
 (0)