Skip to content

Commit 0d82044

Browse files
committed
Merge tag 'powerpc-5.1-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: "A one-liner to make our Radix MMU support depend on HUGETLB_PAGE. We use some of the hugetlb inlines (eg. pud_huge()) when operating on the linear mapping and if they're compiled into empty wrappers we can corrupt memory. Then two fixes to our VFIO IOMMU code. The first is not a regression but fixes the locking to avoid a user-triggerable deadlock. The second does fix a regression since rc1, and depends on the first fix. It makes it possible to run guests with large amounts of memory again (~256GB). Thanks to Alexey Kardashevskiy" * tag 'powerpc-5.1-6' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/mm_iommu: Allow pinning large regions powerpc/mm_iommu: Fix potential deadlock powerpc/mm/radix: Make Radix require HUGETLB_PAGE
2 parents 975a0f4 + 7a3a4d7 commit 0d82044

File tree

3 files changed

+60
-40
lines changed

3 files changed

+60
-40
lines changed

arch/powerpc/configs/skiroot_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ CONFIG_UDF_FS=m
266266
CONFIG_MSDOS_FS=m
267267
CONFIG_VFAT_FS=m
268268
CONFIG_PROC_KCORE=y
269+
CONFIG_HUGETLBFS=y
269270
# CONFIG_MISC_FILESYSTEMS is not set
270271
# CONFIG_NETWORK_FILESYSTEMS is not set
271272
CONFIG_NLS=y

arch/powerpc/mm/mmu_context_iommu.c

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -95,28 +95,15 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
9595
unsigned long entries, unsigned long dev_hpa,
9696
struct mm_iommu_table_group_mem_t **pmem)
9797
{
98-
struct mm_iommu_table_group_mem_t *mem;
99-
long i, ret, locked_entries = 0;
98+
struct mm_iommu_table_group_mem_t *mem, *mem2;
99+
long i, ret, locked_entries = 0, pinned = 0;
100100
unsigned int pageshift;
101-
102-
mutex_lock(&mem_list_mutex);
103-
104-
list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list,
105-
next) {
106-
/* Overlap? */
107-
if ((mem->ua < (ua + (entries << PAGE_SHIFT))) &&
108-
(ua < (mem->ua +
109-
(mem->entries << PAGE_SHIFT)))) {
110-
ret = -EINVAL;
111-
goto unlock_exit;
112-
}
113-
114-
}
101+
unsigned long entry, chunk;
115102

116103
if (dev_hpa == MM_IOMMU_TABLE_INVALID_HPA) {
117104
ret = mm_iommu_adjust_locked_vm(mm, entries, true);
118105
if (ret)
119-
goto unlock_exit;
106+
return ret;
120107

121108
locked_entries = entries;
122109
}
@@ -148,17 +135,27 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
148135
}
149136

150137
down_read(&mm->mmap_sem);
151-
ret = get_user_pages_longterm(ua, entries, FOLL_WRITE, mem->hpages, NULL);
138+
chunk = (1UL << (PAGE_SHIFT + MAX_ORDER - 1)) /
139+
sizeof(struct vm_area_struct *);
140+
chunk = min(chunk, entries);
141+
for (entry = 0; entry < entries; entry += chunk) {
142+
unsigned long n = min(entries - entry, chunk);
143+
144+
ret = get_user_pages_longterm(ua + (entry << PAGE_SHIFT), n,
145+
FOLL_WRITE, mem->hpages + entry, NULL);
146+
if (ret == n) {
147+
pinned += n;
148+
continue;
149+
}
150+
if (ret > 0)
151+
pinned += ret;
152+
break;
153+
}
152154
up_read(&mm->mmap_sem);
153-
if (ret != entries) {
154-
/* free the reference taken */
155-
for (i = 0; i < ret; i++)
156-
put_page(mem->hpages[i]);
157-
158-
vfree(mem->hpas);
159-
kfree(mem);
160-
ret = -EFAULT;
161-
goto unlock_exit;
155+
if (pinned != entries) {
156+
if (!ret)
157+
ret = -EFAULT;
158+
goto free_exit;
162159
}
163160

164161
pageshift = PAGE_SHIFT;
@@ -183,21 +180,43 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
183180
}
184181

185182
good_exit:
186-
ret = 0;
187183
atomic64_set(&mem->mapped, 1);
188184
mem->used = 1;
189185
mem->ua = ua;
190186
mem->entries = entries;
191-
*pmem = mem;
192187

193-
list_add_rcu(&mem->next, &mm->context.iommu_group_mem_list);
188+
mutex_lock(&mem_list_mutex);
194189

195-
unlock_exit:
196-
if (locked_entries && ret)
197-
mm_iommu_adjust_locked_vm(mm, locked_entries, false);
190+
list_for_each_entry_rcu(mem2, &mm->context.iommu_group_mem_list, next) {
191+
/* Overlap? */
192+
if ((mem2->ua < (ua + (entries << PAGE_SHIFT))) &&
193+
(ua < (mem2->ua +
194+
(mem2->entries << PAGE_SHIFT)))) {
195+
ret = -EINVAL;
196+
mutex_unlock(&mem_list_mutex);
197+
goto free_exit;
198+
}
199+
}
200+
201+
list_add_rcu(&mem->next, &mm->context.iommu_group_mem_list);
198202

199203
mutex_unlock(&mem_list_mutex);
200204

205+
*pmem = mem;
206+
207+
return 0;
208+
209+
free_exit:
210+
/* free the reference taken */
211+
for (i = 0; i < pinned; i++)
212+
put_page(mem->hpages[i]);
213+
214+
vfree(mem->hpas);
215+
kfree(mem);
216+
217+
unlock_exit:
218+
mm_iommu_adjust_locked_vm(mm, locked_entries, false);
219+
201220
return ret;
202221
}
203222

@@ -266,7 +285,7 @@ static void mm_iommu_release(struct mm_iommu_table_group_mem_t *mem)
266285
long mm_iommu_put(struct mm_struct *mm, struct mm_iommu_table_group_mem_t *mem)
267286
{
268287
long ret = 0;
269-
unsigned long entries, dev_hpa;
288+
unsigned long unlock_entries = 0;
270289

271290
mutex_lock(&mem_list_mutex);
272291

@@ -287,17 +306,17 @@ long mm_iommu_put(struct mm_struct *mm, struct mm_iommu_table_group_mem_t *mem)
287306
goto unlock_exit;
288307
}
289308

309+
if (mem->dev_hpa == MM_IOMMU_TABLE_INVALID_HPA)
310+
unlock_entries = mem->entries;
311+
290312
/* @mapped became 0 so now mappings are disabled, release the region */
291-
entries = mem->entries;
292-
dev_hpa = mem->dev_hpa;
293313
mm_iommu_release(mem);
294314

295-
if (dev_hpa == MM_IOMMU_TABLE_INVALID_HPA)
296-
mm_iommu_adjust_locked_vm(mm, entries, false);
297-
298315
unlock_exit:
299316
mutex_unlock(&mem_list_mutex);
300317

318+
mm_iommu_adjust_locked_vm(mm, unlock_entries, false);
319+
301320
return ret;
302321
}
303322
EXPORT_SYMBOL_GPL(mm_iommu_put);

arch/powerpc/platforms/Kconfig.cputype

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ config ARCH_ENABLE_SPLIT_PMD_PTLOCK
324324

325325
config PPC_RADIX_MMU
326326
bool "Radix MMU Support"
327-
depends on PPC_BOOK3S_64
327+
depends on PPC_BOOK3S_64 && HUGETLB_PAGE
328328
select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
329329
default y
330330
help

0 commit comments

Comments
 (0)