drm/amdkfd: Don't dereference kfd_process.mm
The kfd_process doesn't own a reference to the mm_struct, so it can disappear without warning even while the kfd_process still exists. Therefore, avoid dereferencing the kfd_process.mm pointer and make it opaque. Use get_task_mm to get a temporary reference to the mm when it's needed. v2: removed unnecessary WARN_ON Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com> Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
This commit is contained in:
parent
66b783b446
commit
9b56bb1154
@ -24,8 +24,8 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/sched/signal.h>
|
#include <linux/sched/signal.h>
|
||||||
|
#include <linux/sched/mm.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <linux/mman.h>
|
#include <linux/mman.h>
|
||||||
#include <linux/memory.h>
|
#include <linux/memory.h>
|
||||||
#include "kfd_priv.h"
|
#include "kfd_priv.h"
|
||||||
@ -904,14 +904,24 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
|
|||||||
* running so the lookup function returns a locked process.
|
* running so the lookup function returns a locked process.
|
||||||
*/
|
*/
|
||||||
struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
|
struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
|
||||||
|
struct mm_struct *mm;
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
return; /* Presumably process exited. */
|
return; /* Presumably process exited. */
|
||||||
|
|
||||||
|
/* Take a safe reference to the mm_struct, which may otherwise
|
||||||
|
* disappear even while the kfd_process is still referenced.
|
||||||
|
*/
|
||||||
|
mm = get_task_mm(p->lead_thread);
|
||||||
|
if (!mm) {
|
||||||
|
mutex_unlock(&p->mutex);
|
||||||
|
return; /* Process is exiting */
|
||||||
|
}
|
||||||
|
|
||||||
memset(&memory_exception_data, 0, sizeof(memory_exception_data));
|
memset(&memory_exception_data, 0, sizeof(memory_exception_data));
|
||||||
|
|
||||||
down_read(&p->mm->mmap_sem);
|
down_read(&mm->mmap_sem);
|
||||||
vma = find_vma(p->mm, address);
|
vma = find_vma(mm, address);
|
||||||
|
|
||||||
memory_exception_data.gpu_id = dev->id;
|
memory_exception_data.gpu_id = dev->id;
|
||||||
memory_exception_data.va = address;
|
memory_exception_data.va = address;
|
||||||
@ -937,7 +947,8 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
up_read(&p->mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
|
mmput(mm);
|
||||||
|
|
||||||
mutex_lock(&p->event_mutex);
|
mutex_lock(&p->event_mutex);
|
||||||
|
|
||||||
|
@ -494,7 +494,12 @@ struct kfd_process {
|
|||||||
*/
|
*/
|
||||||
struct hlist_node kfd_processes;
|
struct hlist_node kfd_processes;
|
||||||
|
|
||||||
struct mm_struct *mm;
|
/*
|
||||||
|
* Opaque pointer to mm_struct. We don't hold a reference to
|
||||||
|
* it so it should never be dereferenced from here. This is
|
||||||
|
* only used for looking up processes by their mm.
|
||||||
|
*/
|
||||||
|
void *mm;
|
||||||
|
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
|
|
||||||
|
@ -200,7 +200,6 @@ static void kfd_process_destroy_delayed(struct rcu_head *rcu)
|
|||||||
struct kfd_process *p;
|
struct kfd_process *p;
|
||||||
|
|
||||||
p = container_of(rcu, struct kfd_process, rcu);
|
p = container_of(rcu, struct kfd_process, rcu);
|
||||||
WARN_ON(atomic_read(&p->mm->mm_count) <= 0);
|
|
||||||
|
|
||||||
mmdrop(p->mm);
|
mmdrop(p->mm);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user