Skip to content

Commit 7978a34

Browse files
committed
Merge tag 'drm-misc-fixes-2026-07-09' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes
drm-misc-fixes for v7.2-rc3: - Fix uaf in amdxdna mmap failure path. - A lot of deadlocks, access races and return value fixes in amdxdna. - Fix analogix_dp bitshifts during link training. - Use direct label in drm_exec. - Fix absent indirect bo handling in v3d. - Sync on first active crtc in fb_dirty, rather than first crtc. - Rework try_harder in the buddy allocator. - Make imagination function static to solve compiler warning. - Fix imagination error checking. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patch.msgid.link/71e5b48b-307f-47f5-8fd5-b60ea43e4196@linux.intel.com
2 parents 58570ef + cf385cf commit 7978a34

16 files changed

Lines changed: 307 additions & 96 deletions

File tree

drivers/accel/amdxdna/aie2_ctx.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
875875
if (!hwctx->cus)
876876
return -ENOMEM;
877877

878-
ret = amdxdna_pm_resume_get_locked(xdna);
878+
ret = amdxdna_pm_resume_get(xdna);
879879
if (ret)
880880
goto free_cus;
881881

@@ -900,13 +900,16 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
900900
static void aie2_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq)
901901
{
902902
struct dma_fence *out_fence = aie2_cmd_get_out_fence(hwctx, seq);
903+
struct amdxdna_dev *xdna = hwctx->client->xdna;
903904

904905
if (!out_fence) {
905-
XDNA_ERR(hwctx->client->xdna, "Failed to get fence");
906+
XDNA_ERR(xdna, "Failed to get fence");
906907
return;
907908
}
908909

910+
mutex_unlock(&xdna->dev_lock);
909911
dma_fence_wait_timeout(out_fence, false, MAX_SCHEDULE_TIMEOUT);
912+
mutex_lock(&xdna->dev_lock);
910913
dma_fence_put(out_fence);
911914
}
912915

@@ -1039,7 +1042,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
10391042
found = false;
10401043
down_write(&xdna->notifier_lock);
10411044
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
1042-
if (mapp->invalid) {
1045+
if (mapp->invalid && kref_get_unless_zero(&mapp->refcnt)) {
10431046
found = true;
10441047
break;
10451048
}
@@ -1050,11 +1053,9 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
10501053
up_write(&xdna->notifier_lock);
10511054
return 0;
10521055
}
1053-
kref_get(&mapp->refcnt);
1056+
10541057
up_write(&xdna->notifier_lock);
10551058

1056-
XDNA_DBG(xdna, "populate memory range %lx %lx",
1057-
mapp->vma->vm_start, mapp->vma->vm_end);
10581059
mm = mapp->notifier.mm;
10591060
if (!mmget_not_zero(mm)) {
10601061
amdxdna_umap_put(mapp);
@@ -1221,10 +1222,6 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx,
12211222
u64 addr;
12221223
int ret;
12231224

1224-
ret = amdxdna_pm_resume_get_locked(xdna);
1225-
if (ret)
1226-
return ret;
1227-
12281225
addr = amdxdna_obj_dma_addr(heap);
12291226
ret = aie2_add_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
12301227
addr, heap->mem.size);
@@ -1233,7 +1230,5 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx,
12331230
hwctx->name, heap->mem.size, ret);
12341231
}
12351232

1236-
amdxdna_pm_suspend_put(xdna);
1237-
12381233
return ret;
12391234
}

drivers/accel/amdxdna/aie2_message.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ static struct aie2_exec_msg_ops npu_exec_message_ops = {
840840
static int aie2_init_exec_req(void *req, struct amdxdna_gem_obj *cmd_abo,
841841
size_t *size, u32 *msg_op)
842842
{
843-
struct amdxdna_dev *xdna = cmd_abo->client->xdna;
843+
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
844844
int ret;
845845
u32 op;
846846

@@ -874,7 +874,7 @@ static int
874874
aie2_cmdlist_fill_slot(void *slot, struct amdxdna_gem_obj *cmd_abo,
875875
size_t *size, u32 *cmd_op)
876876
{
877-
struct amdxdna_dev *xdna = cmd_abo->client->xdna;
877+
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
878878
int ret;
879879
u32 op;
880880

drivers/accel/amdxdna/amdxdna_ctx.c

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d
310310
if (!drm_dev_enter(dev, &idx))
311311
return -ENODEV;
312312

313+
mutex_lock(&xdna->client_lock);
313314
mutex_lock(&xdna->dev_lock);
314315
hwctx = xa_erase(&client->hwctx_xa, args->handle);
315316
if (!hwctx) {
@@ -328,6 +329,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d
328329
XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle);
329330
out:
330331
mutex_unlock(&xdna->dev_lock);
332+
mutex_unlock(&xdna->client_lock);
331333
drm_dev_exit(idx);
332334
return ret;
333335
}
@@ -382,16 +384,27 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
382384
return -EINVAL;
383385
}
384386

385-
guard(mutex)(&xdna->dev_lock);
387+
ret = amdxdna_pm_resume_get(xdna);
388+
if (ret) {
389+
XDNA_ERR(xdna, "Resume failed, ret %d", ret);
390+
goto free_buf;
391+
}
392+
393+
mutex_lock(&xdna->client_lock);
394+
mutex_lock(&xdna->dev_lock);
386395
hwctx = xa_load(&client->hwctx_xa, args->handle);
387396
if (!hwctx) {
388397
XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
389398
ret = -EINVAL;
390-
goto free_buf;
399+
goto unlock;
391400
}
392401

393402
ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
394403

404+
unlock:
405+
mutex_unlock(&xdna->dev_lock);
406+
mutex_unlock(&xdna->client_lock);
407+
amdxdna_pm_suspend_put(xdna);
395408
free_buf:
396409
kfree(buf);
397410
return ret;
@@ -412,16 +425,27 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
412425
if (!gobj)
413426
return -EINVAL;
414427

428+
ret = amdxdna_pm_resume_get(xdna);
429+
if (ret) {
430+
XDNA_ERR(xdna, "Resume failed, ret %d", ret);
431+
goto put_obj;
432+
}
433+
415434
abo = to_xdna_obj(gobj);
416-
guard(mutex)(&xdna->dev_lock);
435+
mutex_lock(&xdna->client_lock);
436+
mutex_lock(&xdna->dev_lock);
417437
hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
418438
if (!hwctx) {
419439
ret = -EINVAL;
420-
goto put_obj;
440+
goto unlock;
421441
}
422442

423443
ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
424444

445+
unlock:
446+
mutex_unlock(&xdna->dev_lock);
447+
mutex_unlock(&xdna->client_lock);
448+
amdxdna_pm_suspend_put(xdna);
425449
put_obj:
426450
drm_gem_object_put(gobj);
427451
return ret;
@@ -448,9 +472,7 @@ static int amdxdna_hwctx_expand_heap(struct amdxdna_hwctx *hwctx)
448472
break;
449473
}
450474

451-
mutex_unlock(&client->mm_lock);
452475
ret = xdna->dev_info->ops->hwctx_heap_expand(hwctx, heap);
453-
mutex_lock(&client->mm_lock);
454476
if (ret) {
455477
amdxdna_gem_unpin(heap);
456478
drm_gem_object_put(to_gobj(heap));
@@ -469,18 +491,26 @@ int amdxdna_update_heap(struct amdxdna_client *client, struct amdxdna_hwctx *hwc
469491
unsigned long hwctx_id;
470492
int ret;
471493

472-
guard(mutex)(&client->mm_lock);
494+
ret = amdxdna_pm_resume_get_locked(client->xdna);
495+
if (ret)
496+
return ret;
473497

474-
if (hwctx)
475-
return amdxdna_hwctx_expand_heap(hwctx);
498+
mutex_lock(&client->mm_lock);
476499

477-
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
500+
if (hwctx) {
478501
ret = amdxdna_hwctx_expand_heap(hwctx);
479-
if (ret)
480-
return ret;
502+
} else {
503+
amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
504+
ret = amdxdna_hwctx_expand_heap(hwctx);
505+
if (ret)
506+
break;
507+
}
481508
}
509+
mutex_unlock(&client->mm_lock);
482510

483-
return 0;
511+
amdxdna_pm_suspend_put(client->xdna);
512+
513+
return ret;
484514
}
485515

486516
static void

drivers/accel/amdxdna/amdxdna_gem.c

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo)
198198
*/
199199
void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
200200
{
201+
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
201202
struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
202203
int ret;
203204

@@ -210,7 +211,7 @@ void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
210211
if (!abo->mem.kva) {
211212
ret = drm_gem_vmap(to_gobj(abo), &map);
212213
if (ret)
213-
XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);
214+
XDNA_ERR(xdna, "Vmap bo failed, ret %d", ret);
214215
else
215216
abo->mem.kva = map.vaddr;
216217
}
@@ -254,7 +255,7 @@ static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni,
254255

255256
xdna = to_xdna_dev(to_gobj(abo)->dev);
256257
XDNA_DBG(xdna, "Invalidating range 0x%lx, 0x%lx, type %d",
257-
mapp->vma->vm_start, mapp->vma->vm_end, abo->type);
258+
mapp->range.start, mapp->range.end, abo->type);
258259

259260
if (!mmu_notifier_range_blockable(range))
260261
return false;
@@ -284,15 +285,23 @@ static const struct mmu_interval_notifier_ops amdxdna_hmm_ops = {
284285
.invalidate = amdxdna_hmm_invalidate,
285286
};
286287

288+
static inline bool compare_range(struct amdxdna_umap *mapp,
289+
struct mm_struct *mm,
290+
unsigned long start, unsigned long end)
291+
{
292+
return (!mapp->unmapped && mapp->notifier.mm == mm &&
293+
mapp->range.start == start && mapp->range.end == end);
294+
}
295+
287296
static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
288297
struct vm_area_struct *vma)
289298
{
290299
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
291300
struct amdxdna_umap *mapp;
292301

293-
down_read(&xdna->notifier_lock);
302+
down_write(&xdna->notifier_lock);
294303
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
295-
if (!vma || mapp->vma == vma) {
304+
if (!vma || compare_range(mapp, vma->vm_mm, vma->vm_start, vma->vm_end)) {
296305
if (!mapp->unmapped) {
297306
queue_work(xdna->notifier_wq, &mapp->hmm_unreg_work);
298307
mapp->unmapped = true;
@@ -301,19 +310,16 @@ static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
301310
break;
302311
}
303312
}
304-
up_read(&xdna->notifier_lock);
313+
up_write(&xdna->notifier_lock);
305314
}
306315

307316
static void amdxdna_umap_release(struct kref *ref)
308317
{
309318
struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);
310319
struct amdxdna_gem_obj *abo = mapp->abo;
311-
struct vm_area_struct *vma = mapp->vma;
312320
struct amdxdna_dev *xdna;
313321

314322
mmu_interval_notifier_remove(&mapp->notifier);
315-
if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
316-
mapping_clear_unevictable(vma->vm_file->f_mapping);
317323

318324
xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
319325
down_write(&xdna->notifier_lock);
@@ -346,15 +352,30 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
346352
unsigned long len = vma->vm_end - vma->vm_start;
347353
unsigned long addr = vma->vm_start;
348354
struct amdxdna_umap *mapp;
349-
u32 nr_pages;
355+
unsigned long nr_pages;
350356
int ret;
351357

352-
if (!amdxdna_pasid_on(abo->client)) {
358+
/*
359+
* When PASID is off, amdxdna_gem_obj_open() called amdxdna_dma_map_bo()
360+
* and mem.dma_addr is valid; use the DMA address directly and skip HMM.
361+
* Avoid dereferencing abo->client which may be NULL (cleared in close())
362+
* while internal kernel references are still held.
363+
*/
364+
if (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) {
353365
/* Need to set uva for heap uva validation */
354366
abo->mem.uva = addr;
355367
return 0;
356368
}
357369

370+
down_read(&xdna->notifier_lock);
371+
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
372+
if (compare_range(mapp, current->mm, addr, addr + len)) {
373+
up_read(&xdna->notifier_lock);
374+
return 0;
375+
}
376+
}
377+
up_read(&xdna->notifier_lock);
378+
358379
mapp = kzalloc_obj(*mapp);
359380
if (!mapp)
360381
return -ENOMEM;
@@ -380,13 +401,10 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo,
380401
mapp->range.start = vma->vm_start;
381402
mapp->range.end = vma->vm_end;
382403
mapp->range.default_flags = HMM_PFN_REQ_FAULT;
383-
mapp->vma = vma;
384404
mapp->abo = abo;
385405
kref_init(&mapp->refcnt);
386406

387407
INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);
388-
if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
389-
mapping_set_unevictable(vma->vm_file->f_mapping);
390408

391409
down_write(&xdna->notifier_lock);
392410
if (list_empty(&abo->mem.umap_list))
@@ -527,6 +545,7 @@ static int amdxdna_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struc
527545

528546
close_vma:
529547
vma->vm_ops->close(vma);
548+
return ret;
530549
put_obj:
531550
drm_gem_object_put(gobj);
532551
return ret;
@@ -652,8 +671,11 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi
652671
/* No need to set up dma addr mapping in PASID mode. */
653672
if (!amdxdna_pasid_on(abo->client)) {
654673
ret = amdxdna_dma_map_bo(xdna, abo);
655-
if (ret)
674+
if (ret) {
675+
abo->open_ref--;
676+
abo->client = NULL;
656677
return ret;
678+
}
657679
}
658680

659681
amdxdna_gem_add_bo_usage(abo);

drivers/accel/amdxdna/amdxdna_gem.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "amdxdna_pci_drv.h"
1313

1414
struct amdxdna_umap {
15-
struct vm_area_struct *vma;
1615
struct mmu_interval_notifier notifier;
1716
struct hmm_range range;
1817
struct work_struct hmm_unreg_work;
@@ -89,12 +88,19 @@ u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo);
8988

9089
static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
9190
{
92-
return amdxdna_gem_dev_addr(abo) - abo->client->xdna->dev_info->dev_mem_base;
91+
return amdxdna_gem_dev_addr(abo) - to_xdna_dev(to_gobj(abo)->dev)->dev_info->dev_mem_base;
9392
}
9493

9594
static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
9695
{
97-
return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) : abo->mem.dma_addr;
96+
/*
97+
* amdxdna_gem_obj_open() calls amdxdna_dma_map_bo() only when PASID is
98+
* off, leaving mem.dma_addr at AMDXDNA_INVALID_ADDR when PASID is on.
99+
* Avoid dereferencing abo->client, which is cleared to NULL by
100+
* amdxdna_gem_obj_close() while internal kernel references remain.
101+
*/
102+
return (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) ?
103+
abo->mem.dma_addr : amdxdna_gem_uva(abo);
98104
}
99105

100106
void amdxdna_umap_put(struct amdxdna_umap *mapp);

0 commit comments

Comments
 (0)