| From 379e1ebb34144d05b1332d4028b595a4ddad3d30 Mon Sep 17 00:00:00 2001 |
| From: Alexey Kardashevskiy <aik@ozlabs.ru> |
| Date: Wed, 30 Nov 2016 17:52:00 +1100 |
| Subject: [PATCH] powerpc/iommu: Stop using @current in mm_iommu_xxx |
| |
| commit d7baee6901b34c4895eb78efdbf13a49079d7404 upstream. |
| |
| This changes mm_iommu_xxx helpers to take mm_struct as a parameter |
| instead of getting it from @current which in some situations may |
| not have a valid reference to mm. |
| |
| This changes helpers to receive @mm and moves all references to @current |
| to the caller, including checks for !current and !current->mm; |
| checks in mm_iommu_preregistered() are removed as there is no caller |
| yet. |
| |
| This moves the mm_iommu_adjust_locked_vm() call to the caller as |
| it receives mm_iommu_table_group_mem_t but it needs mm. |
| |
| This should cause no behavioral change. |
| |
| Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> |
| Reviewed-by: David Gibson <david@gibson.dropbear.id.au> |
| Acked-by: Alex Williamson <alex.williamson@redhat.com> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h |
| index 31deb7d813e8..b85cc7bd1c03 100644 |
| --- a/arch/powerpc/include/asm/mmu_context.h |
| +++ b/arch/powerpc/include/asm/mmu_context.h |
| @@ -18,16 +18,18 @@ extern void destroy_context(struct mm_struct *mm); |
| #ifdef CONFIG_SPAPR_TCE_IOMMU |
| struct mm_iommu_table_group_mem_t; |
| |
| -extern bool mm_iommu_preregistered(void); |
| -extern long mm_iommu_get(unsigned long ua, unsigned long entries, |
| +extern bool mm_iommu_preregistered(struct mm_struct *mm); |
| +extern long mm_iommu_get(struct mm_struct *mm, |
| + unsigned long ua, unsigned long entries, |
| struct mm_iommu_table_group_mem_t **pmem); |
| -extern long mm_iommu_put(struct mm_iommu_table_group_mem_t *mem); |
| +extern long mm_iommu_put(struct mm_struct *mm, |
| + struct mm_iommu_table_group_mem_t *mem); |
| extern void mm_iommu_init(struct mm_struct *mm); |
| extern void mm_iommu_cleanup(struct mm_struct *mm); |
| -extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(unsigned long ua, |
| - unsigned long size); |
| -extern struct mm_iommu_table_group_mem_t *mm_iommu_find(unsigned long ua, |
| - unsigned long entries); |
| +extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm, |
| + unsigned long ua, unsigned long size); |
| +extern struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm, |
| + unsigned long ua, unsigned long entries); |
| extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem, |
| unsigned long ua, unsigned long *hpa); |
| extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem); |
| diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c |
| index 699cd80f4e39..a0b6c34e7c04 100644 |
| --- a/arch/powerpc/mm/mmu_context_iommu.c |
| +++ b/arch/powerpc/mm/mmu_context_iommu.c |
| @@ -53,7 +53,7 @@ static long mm_iommu_adjust_locked_vm(struct mm_struct *mm, |
| } |
| |
| pr_debug("[%d] RLIMIT_MEMLOCK HASH64 %c%ld %ld/%ld\n", |
| - current->pid, |
| + current ? current->pid : 0, |
| incr ? '+' : '-', |
| npages << PAGE_SHIFT, |
| mm->locked_vm << PAGE_SHIFT, |
| @@ -63,28 +63,22 @@ static long mm_iommu_adjust_locked_vm(struct mm_struct *mm, |
| return ret; |
| } |
| |
| -bool mm_iommu_preregistered(void) |
| +bool mm_iommu_preregistered(struct mm_struct *mm) |
| { |
| - if (!current || !current->mm) |
| - return false; |
| - |
| - return !list_empty(¤t->mm->context.iommu_group_mem_list); |
| + return !list_empty(&mm->context.iommu_group_mem_list); |
| } |
| EXPORT_SYMBOL_GPL(mm_iommu_preregistered); |
| |
| -long mm_iommu_get(unsigned long ua, unsigned long entries, |
| +long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries, |
| struct mm_iommu_table_group_mem_t **pmem) |
| { |
| struct mm_iommu_table_group_mem_t *mem; |
| long i, j, ret = 0, locked_entries = 0; |
| struct page *page = NULL; |
| |
| - if (!current || !current->mm) |
| - return -ESRCH; /* process exited */ |
| - |
| mutex_lock(&mem_list_mutex); |
| |
| - list_for_each_entry_rcu(mem, ¤t->mm->context.iommu_group_mem_list, |
| + list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list, |
| next) { |
| if ((mem->ua == ua) && (mem->entries == entries)) { |
| ++mem->used; |
| @@ -102,7 +96,7 @@ long mm_iommu_get(unsigned long ua, unsigned long entries, |
| |
| } |
| |
| - ret = mm_iommu_adjust_locked_vm(current->mm, entries, true); |
| + ret = mm_iommu_adjust_locked_vm(mm, entries, true); |
| if (ret) |
| goto unlock_exit; |
| |
| @@ -142,11 +136,11 @@ long mm_iommu_get(unsigned long ua, unsigned long entries, |
| mem->entries = entries; |
| *pmem = mem; |
| |
| - list_add_rcu(&mem->next, ¤t->mm->context.iommu_group_mem_list); |
| + list_add_rcu(&mem->next, &mm->context.iommu_group_mem_list); |
| |
| unlock_exit: |
| if (locked_entries && ret) |
| - mm_iommu_adjust_locked_vm(current->mm, locked_entries, false); |
| + mm_iommu_adjust_locked_vm(mm, locked_entries, false); |
| |
| mutex_unlock(&mem_list_mutex); |
| |
| @@ -191,17 +185,13 @@ static void mm_iommu_free(struct rcu_head *head) |
| static void mm_iommu_release(struct mm_iommu_table_group_mem_t *mem) |
| { |
| list_del_rcu(&mem->next); |
| - mm_iommu_adjust_locked_vm(current->mm, mem->entries, false); |
| call_rcu(&mem->rcu, mm_iommu_free); |
| } |
| |
| -long mm_iommu_put(struct mm_iommu_table_group_mem_t *mem) |
| +long mm_iommu_put(struct mm_struct *mm, struct mm_iommu_table_group_mem_t *mem) |
| { |
| long ret = 0; |
| |
| - if (!current || !current->mm) |
| - return -ESRCH; /* process exited */ |
| - |
| mutex_lock(&mem_list_mutex); |
| |
| if (mem->used == 0) { |
| @@ -224,6 +214,8 @@ long mm_iommu_put(struct mm_iommu_table_group_mem_t *mem) |
| /* @mapped became 0 so now mappings are disabled, release the region */ |
| mm_iommu_release(mem); |
| |
| + mm_iommu_adjust_locked_vm(mm, mem->entries, false); |
| + |
| unlock_exit: |
| mutex_unlock(&mem_list_mutex); |
| |
| @@ -231,14 +223,12 @@ unlock_exit: |
| } |
| EXPORT_SYMBOL_GPL(mm_iommu_put); |
| |
| -struct mm_iommu_table_group_mem_t *mm_iommu_lookup(unsigned long ua, |
| - unsigned long size) |
| +struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm, |
| + unsigned long ua, unsigned long size) |
| { |
| struct mm_iommu_table_group_mem_t *mem, *ret = NULL; |
| |
| - list_for_each_entry_rcu(mem, |
| - ¤t->mm->context.iommu_group_mem_list, |
| - next) { |
| + list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list, next) { |
| if ((mem->ua <= ua) && |
| (ua + size <= mem->ua + |
| (mem->entries << PAGE_SHIFT))) { |
| @@ -251,14 +241,12 @@ struct mm_iommu_table_group_mem_t *mm_iommu_lookup(unsigned long ua, |
| } |
| EXPORT_SYMBOL_GPL(mm_iommu_lookup); |
| |
| -struct mm_iommu_table_group_mem_t *mm_iommu_find(unsigned long ua, |
| - unsigned long entries) |
| +struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm, |
| + unsigned long ua, unsigned long entries) |
| { |
| struct mm_iommu_table_group_mem_t *mem, *ret = NULL; |
| |
| - list_for_each_entry_rcu(mem, |
| - ¤t->mm->context.iommu_group_mem_list, |
| - next) { |
| + list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list, next) { |
| if ((mem->ua == ua) && (mem->entries == entries)) { |
| ret = mem; |
| break; |
| diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c |
| index 2a6e13892397..4efd2b20c35c 100644 |
| --- a/drivers/vfio/vfio_iommu_spapr_tce.c |
| +++ b/drivers/vfio/vfio_iommu_spapr_tce.c |
| @@ -107,14 +107,17 @@ static long tce_iommu_unregister_pages(struct tce_container *container, |
| { |
| struct mm_iommu_table_group_mem_t *mem; |
| |
| + if (!current || !current->mm) |
| + return -ESRCH; /* process exited */ |
| + |
| if ((vaddr & ~PAGE_MASK) || (size & ~PAGE_MASK)) |
| return -EINVAL; |
| |
| - mem = mm_iommu_find(vaddr, size >> PAGE_SHIFT); |
| + mem = mm_iommu_find(current->mm, vaddr, size >> PAGE_SHIFT); |
| if (!mem) |
| return -ENOENT; |
| |
| - return mm_iommu_put(mem); |
| + return mm_iommu_put(current->mm, mem); |
| } |
| |
| static long tce_iommu_register_pages(struct tce_container *container, |
| @@ -124,11 +127,14 @@ static long tce_iommu_register_pages(struct tce_container *container, |
| struct mm_iommu_table_group_mem_t *mem = NULL; |
| unsigned long entries = size >> PAGE_SHIFT; |
| |
| + if (!current || !current->mm) |
| + return -ESRCH; /* process exited */ |
| + |
| if ((vaddr & ~PAGE_MASK) || (size & ~PAGE_MASK) || |
| ((vaddr + size) < vaddr)) |
| return -EINVAL; |
| |
| - ret = mm_iommu_get(vaddr, entries, &mem); |
| + ret = mm_iommu_get(current->mm, vaddr, entries, &mem); |
| if (ret) |
| return ret; |
| |
| @@ -375,7 +381,7 @@ static int tce_iommu_prereg_ua_to_hpa(unsigned long tce, unsigned long size, |
| long ret = 0; |
| struct mm_iommu_table_group_mem_t *mem; |
| |
| - mem = mm_iommu_lookup(tce, size); |
| + mem = mm_iommu_lookup(current->mm, tce, size); |
| if (!mem) |
| return -EINVAL; |
| |
| -- |
| 2.12.0 |
| |