powerpc fixes for 4.18 #4
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. -----BEGIN PGP SIGNATURE----- iQIwBAABCAAaBQJbUrFqExxtcGVAZWxsZXJtYW4uaWQuYXUACgkQUevqPMjhpYCW mQ//eYpaYIkEthXH0uHUN2wpWZlhbg0wUtjclsT5RUonDwMC2PM9BUuLk61RtIlD jbi39GrUISHf13U1Ydhb3e1I5B+TpDe6hgb/dGUMAXPe6rt+jFREogZR+vgIU0ep Q8ta1GIgbI6La0zXn5o3apUtqR7bAQ3cWD2T8vN4tQmAQZPw1fV13cZZ2kFs5JFO aYX8pD76wkAUz8Im+bweziRSRYdAIi8Oxt1Cdyg9Oti5y4fp4LuQKa/qbfkswkkk 2ycG3TWr4Ln8RM/GaUPW1UPh1Zd8b6et7vUnhxO1g/JdEXlnm9A+DifJFrUk/+y8 DsyofdXUj+u+LXX/H8uqqse7ysfvkC53R15Jo8irISsIgYZcv4yKsZKGJR27wHGV h9KBDA0ZK+czU2jK4gZAdMTs1IICgXGUVIL+nI8U1sRBep3CI3HguqBVoC/MGes3 WR2+8i2diL1m2jAHR5Nd3+ArBpI876ZalhDmM1Mv3GRUAvjo9nsehk32/nfBDYUM nPQd1vi3F6w1MSlj7aqA3quTeGANwlnOcdC4QB++tz7oO1sY6ZYZtii3jsGSluXL vP/Mxvz2AG3v9KPCDQJqzx0n3vMAmGphetddxYl1X1dSwbwLNx0GggKNe0xw6sjp 6lbin0w/Ot79VoSEncuRdm1hrtIktwubsH5CGB7Gxke5Kgk= =Sfmf -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
ffb48e7924
|
@ -243,6 +243,7 @@ endif
|
|||
cpu-as-$(CONFIG_4xx) += -Wa,-m405
|
||||
cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec)
|
||||
cpu-as-$(CONFIG_E200) += -Wa,-me200
|
||||
cpu-as-$(CONFIG_E500) += -Wa,-me500
|
||||
cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4
|
||||
cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc)
|
||||
|
||||
|
|
|
@ -35,9 +35,9 @@ extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(
|
|||
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);
|
||||
unsigned long ua, unsigned int pageshift, unsigned long *hpa);
|
||||
extern long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
|
||||
unsigned long ua, unsigned long *hpa);
|
||||
unsigned long ua, unsigned int pageshift, unsigned long *hpa);
|
||||
extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
|
||||
extern void mm_iommu_mapped_dec(struct mm_iommu_table_group_mem_t *mem);
|
||||
#endif
|
||||
|
|
|
@ -144,7 +144,9 @@ power9_restore_additional_sprs:
|
|||
mtspr SPRN_MMCR1, r4
|
||||
|
||||
ld r3, STOP_MMCR2(r13)
|
||||
ld r4, PACA_SPRG_VDSO(r13)
|
||||
mtspr SPRN_MMCR2, r3
|
||||
mtspr SPRN_SPRG3, r4
|
||||
blr
|
||||
|
||||
/*
|
||||
|
|
|
@ -449,7 +449,7 @@ long kvmppc_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
|
|||
/* This only handles v2 IOMMU type, v1 is handled via ioctl() */
|
||||
return H_TOO_HARD;
|
||||
|
||||
if (WARN_ON_ONCE(mm_iommu_ua_to_hpa(mem, ua, &hpa)))
|
||||
if (WARN_ON_ONCE(mm_iommu_ua_to_hpa(mem, ua, tbl->it_page_shift, &hpa)))
|
||||
return H_HARDWARE;
|
||||
|
||||
if (mm_iommu_mapped_inc(mem))
|
||||
|
|
|
@ -279,7 +279,8 @@ static long kvmppc_rm_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
|
|||
if (!mem)
|
||||
return H_TOO_HARD;
|
||||
|
||||
if (WARN_ON_ONCE_RM(mm_iommu_ua_to_hpa_rm(mem, ua, &hpa)))
|
||||
if (WARN_ON_ONCE_RM(mm_iommu_ua_to_hpa_rm(mem, ua, tbl->it_page_shift,
|
||||
&hpa)))
|
||||
return H_HARDWARE;
|
||||
|
||||
pua = (void *) vmalloc_to_phys(pua);
|
||||
|
@ -469,7 +470,8 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
|
|||
|
||||
mem = mm_iommu_lookup_rm(vcpu->kvm->mm, ua, IOMMU_PAGE_SIZE_4K);
|
||||
if (mem)
|
||||
prereg = mm_iommu_ua_to_hpa_rm(mem, ua, &tces) == 0;
|
||||
prereg = mm_iommu_ua_to_hpa_rm(mem, ua,
|
||||
IOMMU_PAGE_SHIFT_4K, &tces) == 0;
|
||||
}
|
||||
|
||||
if (!prereg) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/hugetlb.h>
|
||||
#include <linux/swap.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/pte-walk.h>
|
||||
|
||||
static DEFINE_MUTEX(mem_list_mutex);
|
||||
|
||||
|
@ -27,6 +28,7 @@ struct mm_iommu_table_group_mem_t {
|
|||
struct rcu_head rcu;
|
||||
unsigned long used;
|
||||
atomic64_t mapped;
|
||||
unsigned int pageshift;
|
||||
u64 ua; /* userspace address */
|
||||
u64 entries; /* number of entries in hpas[] */
|
||||
u64 *hpas; /* vmalloc'ed */
|
||||
|
@ -125,6 +127,8 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
|
|||
{
|
||||
struct mm_iommu_table_group_mem_t *mem;
|
||||
long i, j, ret = 0, locked_entries = 0;
|
||||
unsigned int pageshift;
|
||||
unsigned long flags;
|
||||
struct page *page = NULL;
|
||||
|
||||
mutex_lock(&mem_list_mutex);
|
||||
|
@ -159,6 +163,12 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
|
|||
goto unlock_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a starting point for a maximum page size calculation
|
||||
* we use @ua and @entries natural alignment to allow IOMMU pages
|
||||
* smaller than huge pages but still bigger than PAGE_SIZE.
|
||||
*/
|
||||
mem->pageshift = __ffs(ua | (entries << PAGE_SHIFT));
|
||||
mem->hpas = vzalloc(array_size(entries, sizeof(mem->hpas[0])));
|
||||
if (!mem->hpas) {
|
||||
kfree(mem);
|
||||
|
@ -199,6 +209,23 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
|
|||
}
|
||||
}
|
||||
populate:
|
||||
pageshift = PAGE_SHIFT;
|
||||
if (PageCompound(page)) {
|
||||
pte_t *pte;
|
||||
struct page *head = compound_head(page);
|
||||
unsigned int compshift = compound_order(head);
|
||||
|
||||
local_irq_save(flags); /* disables as well */
|
||||
pte = find_linux_pte(mm->pgd, ua, NULL, &pageshift);
|
||||
local_irq_restore(flags);
|
||||
|
||||
/* Double check it is still the same pinned page */
|
||||
if (pte && pte_page(*pte) == head &&
|
||||
pageshift == compshift)
|
||||
pageshift = max_t(unsigned int, pageshift,
|
||||
PAGE_SHIFT);
|
||||
}
|
||||
mem->pageshift = min(mem->pageshift, pageshift);
|
||||
mem->hpas[i] = page_to_pfn(page) << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
|
@ -349,7 +376,7 @@ struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
|
|||
EXPORT_SYMBOL_GPL(mm_iommu_find);
|
||||
|
||||
long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
|
||||
unsigned long ua, unsigned long *hpa)
|
||||
unsigned long ua, unsigned int pageshift, unsigned long *hpa)
|
||||
{
|
||||
const long entry = (ua - mem->ua) >> PAGE_SHIFT;
|
||||
u64 *va = &mem->hpas[entry];
|
||||
|
@ -357,6 +384,9 @@ long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
|
|||
if (entry >= mem->entries)
|
||||
return -EFAULT;
|
||||
|
||||
if (pageshift > mem->pageshift)
|
||||
return -EFAULT;
|
||||
|
||||
*hpa = *va | (ua & ~PAGE_MASK);
|
||||
|
||||
return 0;
|
||||
|
@ -364,7 +394,7 @@ long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
|
|||
EXPORT_SYMBOL_GPL(mm_iommu_ua_to_hpa);
|
||||
|
||||
long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
|
||||
unsigned long ua, unsigned long *hpa)
|
||||
unsigned long ua, unsigned int pageshift, unsigned long *hpa)
|
||||
{
|
||||
const long entry = (ua - mem->ua) >> PAGE_SHIFT;
|
||||
void *va = &mem->hpas[entry];
|
||||
|
@ -373,6 +403,9 @@ long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
|
|||
if (entry >= mem->entries)
|
||||
return -EFAULT;
|
||||
|
||||
if (pageshift > mem->pageshift)
|
||||
return -EFAULT;
|
||||
|
||||
pa = (void *) vmalloc_to_phys(va);
|
||||
if (!pa)
|
||||
return -EFAULT;
|
||||
|
|
|
@ -2734,7 +2734,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
|
|||
{
|
||||
int nr, dotted;
|
||||
unsigned long first_adr;
|
||||
unsigned long inst, last_inst = 0;
|
||||
unsigned int inst, last_inst = 0;
|
||||
unsigned char val[4];
|
||||
|
||||
dotted = 0;
|
||||
|
@ -2758,7 +2758,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr,
|
|||
dotted = 0;
|
||||
last_inst = inst;
|
||||
if (praddr)
|
||||
printf(REG" %.8lx", adr, inst);
|
||||
printf(REG" %.8x", adr, inst);
|
||||
printf("\t");
|
||||
dump_func(inst, adr);
|
||||
printf("\n");
|
||||
|
|
|
@ -457,17 +457,17 @@ static void tce_iommu_unuse_page(struct tce_container *container,
|
|||
}
|
||||
|
||||
static int tce_iommu_prereg_ua_to_hpa(struct tce_container *container,
|
||||
unsigned long tce, unsigned long size,
|
||||
unsigned long tce, unsigned long shift,
|
||||
unsigned long *phpa, struct mm_iommu_table_group_mem_t **pmem)
|
||||
{
|
||||
long ret = 0;
|
||||
struct mm_iommu_table_group_mem_t *mem;
|
||||
|
||||
mem = mm_iommu_lookup(container->mm, tce, size);
|
||||
mem = mm_iommu_lookup(container->mm, tce, 1ULL << shift);
|
||||
if (!mem)
|
||||
return -EINVAL;
|
||||
|
||||
ret = mm_iommu_ua_to_hpa(mem, tce, phpa);
|
||||
ret = mm_iommu_ua_to_hpa(mem, tce, shift, phpa);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -487,7 +487,7 @@ static void tce_iommu_unuse_page_v2(struct tce_container *container,
|
|||
if (!pua)
|
||||
return;
|
||||
|
||||
ret = tce_iommu_prereg_ua_to_hpa(container, *pua, IOMMU_PAGE_SIZE(tbl),
|
||||
ret = tce_iommu_prereg_ua_to_hpa(container, *pua, tbl->it_page_shift,
|
||||
&hpa, &mem);
|
||||
if (ret)
|
||||
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,
|
|||
entry + i);
|
||||
|
||||
ret = tce_iommu_prereg_ua_to_hpa(container,
|
||||
tce, IOMMU_PAGE_SIZE(tbl), &hpa, &mem);
|
||||
tce, tbl->it_page_shift, &hpa, &mem);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
|
|
Loading…
Reference in New Issue