Skip to content

Commit ffb48e7

Browse files
committed
Merge tag 'powerpc-4.18-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: "Two regression fixes, one for xmon disassembly formatting and the other to fix the E500 build. Two commits to fix a potential security issue in the VFIO code under obscure circumstances. And finally a fix to the Power9 idle code to restore SPRG3, which is user visible and used for sched_getcpu(). Thanks to: Alexey Kardashevskiy, David Gibson. Gautham R. Shenoy, James Clarke" * tag 'powerpc-4.18-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/powernv: Fix save/restore of SPRG3 on entry/exit from stop (idle) powerpc/Makefile: Assemble with -me500 when building for E500 KVM: PPC: Check if IOMMU page is contained in the pinned physical page vfio/spapr: Use IOMMU pageshift rather than pagesize powerpc/xmon: Fix disassembly since printf changes
2 parents 55b636b + b03897c commit ffb48e7

File tree

8 files changed

+52
-14
lines changed

8 files changed

+52
-14
lines changed

arch/powerpc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ endif
243243
cpu-as-$(CONFIG_4xx) += -Wa,-m405
244244
cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec)
245245
cpu-as-$(CONFIG_E200) += -Wa,-me200
246+
cpu-as-$(CONFIG_E500) += -Wa,-me500
246247
cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4
247248
cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc)
248249

arch/powerpc/include/asm/mmu_context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(
3535
extern struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
3636
unsigned long ua, unsigned long entries);
3737
extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
38-
unsigned long ua, unsigned long *hpa);
38+
unsigned long ua, unsigned int pageshift, unsigned long *hpa);
3939
extern long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
40-
unsigned long ua, unsigned long *hpa);
40+
unsigned long ua, unsigned int pageshift, unsigned long *hpa);
4141
extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
4242
extern void mm_iommu_mapped_dec(struct mm_iommu_table_group_mem_t *mem);
4343
#endif

arch/powerpc/kernel/idle_book3s.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ power9_restore_additional_sprs:
144144
mtspr SPRN_MMCR1, r4
145145

146146
ld r3, STOP_MMCR2(r13)
147+
ld r4, PACA_SPRG_VDSO(r13)
147148
mtspr SPRN_MMCR2, r3
149+
mtspr SPRN_SPRG3, r4
148150
blr
149151

150152
/*

arch/powerpc/kvm/book3s_64_vio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ long kvmppc_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
449449
/* This only handles v2 IOMMU type, v1 is handled via ioctl() */
450450
return H_TOO_HARD;
451451

452-
if (WARN_ON_ONCE(mm_iommu_ua_to_hpa(mem, ua, &hpa)))
452+
if (WARN_ON_ONCE(mm_iommu_ua_to_hpa(mem, ua, tbl->it_page_shift, &hpa)))
453453
return H_HARDWARE;
454454

455455
if (mm_iommu_mapped_inc(mem))

arch/powerpc/kvm/book3s_64_vio_hv.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ static long kvmppc_rm_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
279279
if (!mem)
280280
return H_TOO_HARD;
281281

282-
if (WARN_ON_ONCE_RM(mm_iommu_ua_to_hpa_rm(mem, ua, &hpa)))
282+
if (WARN_ON_ONCE_RM(mm_iommu_ua_to_hpa_rm(mem, ua, tbl->it_page_shift,
283+
&hpa)))
283284
return H_HARDWARE;
284285

285286
pua = (void *) vmalloc_to_phys(pua);
@@ -469,7 +470,8 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
469470

470471
mem = mm_iommu_lookup_rm(vcpu->kvm->mm, ua, IOMMU_PAGE_SIZE_4K);
471472
if (mem)
472-
prereg = mm_iommu_ua_to_hpa_rm(mem, ua, &tces) == 0;
473+
prereg = mm_iommu_ua_to_hpa_rm(mem, ua,
474+
IOMMU_PAGE_SHIFT_4K, &tces) == 0;
473475
}
474476

475477
if (!prereg) {

arch/powerpc/mm/mmu_context_iommu.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/hugetlb.h>
2020
#include <linux/swap.h>
2121
#include <asm/mmu_context.h>
22+
#include <asm/pte-walk.h>
2223

2324
static DEFINE_MUTEX(mem_list_mutex);
2425

@@ -27,6 +28,7 @@ struct mm_iommu_table_group_mem_t {
2728
struct rcu_head rcu;
2829
unsigned long used;
2930
atomic64_t mapped;
31+
unsigned int pageshift;
3032
u64 ua; /* userspace address */
3133
u64 entries; /* number of entries in hpas[] */
3234
u64 *hpas; /* vmalloc'ed */
@@ -125,6 +127,8 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
125127
{
126128
struct mm_iommu_table_group_mem_t *mem;
127129
long i, j, ret = 0, locked_entries = 0;
130+
unsigned int pageshift;
131+
unsigned long flags;
128132
struct page *page = NULL;
129133

130134
mutex_lock(&mem_list_mutex);
@@ -159,6 +163,12 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
159163
goto unlock_exit;
160164
}
161165

166+
/*
167+
* For a starting point for a maximum page size calculation
168+
* we use @ua and @entries natural alignment to allow IOMMU pages
169+
* smaller than huge pages but still bigger than PAGE_SIZE.
170+
*/
171+
mem->pageshift = __ffs(ua | (entries << PAGE_SHIFT));
162172
mem->hpas = vzalloc(array_size(entries, sizeof(mem->hpas[0])));
163173
if (!mem->hpas) {
164174
kfree(mem);
@@ -199,6 +209,23 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
199209
}
200210
}
201211
populate:
212+
pageshift = PAGE_SHIFT;
213+
if (PageCompound(page)) {
214+
pte_t *pte;
215+
struct page *head = compound_head(page);
216+
unsigned int compshift = compound_order(head);
217+
218+
local_irq_save(flags); /* disables as well */
219+
pte = find_linux_pte(mm->pgd, ua, NULL, &pageshift);
220+
local_irq_restore(flags);
221+
222+
/* Double check it is still the same pinned page */
223+
if (pte && pte_page(*pte) == head &&
224+
pageshift == compshift)
225+
pageshift = max_t(unsigned int, pageshift,
226+
PAGE_SHIFT);
227+
}
228+
mem->pageshift = min(mem->pageshift, pageshift);
202229
mem->hpas[i] = page_to_pfn(page) << PAGE_SHIFT;
203230
}
204231

@@ -349,22 +376,25 @@ struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
349376
EXPORT_SYMBOL_GPL(mm_iommu_find);
350377

351378
long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
352-
unsigned long ua, unsigned long *hpa)
379+
unsigned long ua, unsigned int pageshift, unsigned long *hpa)
353380
{
354381
const long entry = (ua - mem->ua) >> PAGE_SHIFT;
355382
u64 *va = &mem->hpas[entry];
356383

357384
if (entry >= mem->entries)
358385
return -EFAULT;
359386

387+
if (pageshift > mem->pageshift)
388+
return -EFAULT;
389+
360390
*hpa = *va | (ua & ~PAGE_MASK);
361391

362392
return 0;
363393
}
364394
EXPORT_SYMBOL_GPL(mm_iommu_ua_to_hpa);
365395

366396
long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
367-
unsigned long ua, unsigned long *hpa)
397+
unsigned long ua, unsigned int pageshift, unsigned long *hpa)
368398
{
369399
const long entry = (ua - mem->ua) >> PAGE_SHIFT;
370400
void *va = &mem->hpas[entry];
@@ -373,6 +403,9 @@ long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
373403
if (entry >= mem->entries)
374404
return -EFAULT;
375405

406+
if (pageshift > mem->pageshift)
407+
return -EFAULT;
408+
376409
pa = (void *) vmalloc_to_phys(va);
377410
if (!pa)
378411
return -EFAULT;

arch/powerpc/xmon/xmon.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,7 +2734,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
27342734
{
27352735
int nr, dotted;
27362736
unsigned long first_adr;
2737-
unsigned long inst, last_inst = 0;
2737+
unsigned int inst, last_inst = 0;
27382738
unsigned char val[4];
27392739

27402740
dotted = 0;
@@ -2758,7 +2758,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
27582758
dotted = 0;
27592759
last_inst = inst;
27602760
if (praddr)
2761-
printf(REG" %.8lx", adr, inst);
2761+
printf(REG" %.8x", adr, inst);
27622762
printf("\t");
27632763
dump_func(inst, adr);
27642764
printf("\n");

drivers/vfio/vfio_iommu_spapr_tce.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -457,17 +457,17 @@ static void tce_iommu_unuse_page(struct tce_container *container,
457457
}
458458

459459
static int tce_iommu_prereg_ua_to_hpa(struct tce_container *container,
460-
unsigned long tce, unsigned long size,
460+
unsigned long tce, unsigned long shift,
461461
unsigned long *phpa, struct mm_iommu_table_group_mem_t **pmem)
462462
{
463463
long ret = 0;
464464
struct mm_iommu_table_group_mem_t *mem;
465465

466-
mem = mm_iommu_lookup(container->mm, tce, size);
466+
mem = mm_iommu_lookup(container->mm, tce, 1ULL << shift);
467467
if (!mem)
468468
return -EINVAL;
469469

470-
ret = mm_iommu_ua_to_hpa(mem, tce, phpa);
470+
ret = mm_iommu_ua_to_hpa(mem, tce, shift, phpa);
471471
if (ret)
472472
return -EINVAL;
473473

@@ -487,7 +487,7 @@ static void tce_iommu_unuse_page_v2(struct tce_container *container,
487487
if (!pua)
488488
return;
489489

490-
ret = tce_iommu_prereg_ua_to_hpa(container, *pua, IOMMU_PAGE_SIZE(tbl),
490+
ret = tce_iommu_prereg_ua_to_hpa(container, *pua, tbl->it_page_shift,
491491
&hpa, &mem);
492492
if (ret)
493493
pr_debug("%s: tce %lx at #%lx was not cached, ret=%d\n",
@@ -611,7 +611,7 @@ static long tce_iommu_build_v2(struct tce_container *container,
611611
entry + i);
612612

613613
ret = tce_iommu_prereg_ua_to_hpa(container,
614-
tce, IOMMU_PAGE_SIZE(tbl), &hpa, &mem);
614+
tce, tbl->it_page_shift, &hpa, &mem);
615615
if (ret)
616616
break;
617617

0 commit comments

Comments
 (0)