Skip to content

Commit 4f3df2e

Browse files
committed
Merge tag 'powerpc-7.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Madhavan Srinivasan: - Fix KUAP warning in VMX usercopy path - Fix lockdep warning during PCI enumeration - Fix to move CMA reservations to arch_mm_preinit - Fix to check current->mm is alive before getting user callchain Thanks to Aboorva Devarajan, Christophe Leroy (CS GROUP), Dan Horák, Nicolin Chen, Nilay Shroff, Qiao Zhao, Ritesh Harjani (IBM), Saket Kumar Bhaskar, Sayali Patil, Shrikanth Hegde, Venkat Rao Bagalkote, and Viktor Malik. * tag 'powerpc-7.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/iommu: fix lockdep warning during PCI enumeration powerpc/selftests/copyloops: extend selftest to exercise __copy_tofrom_user_power7_vmx powerpc: fix KUAP warning in VMX usercopy path powerpc, perf: Check that current->mm is alive before getting user callchain powerpc/mem: Move CMA reservations to arch_mm_preinit
2 parents 13af67f + 82f73ef commit 4f3df2e

14 files changed

Lines changed: 107 additions & 77 deletions

File tree

arch/powerpc/include/asm/uaccess.h

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#define TASK_SIZE_MAX TASK_SIZE_USER64
1616
#endif
1717

18+
/* Threshold above which VMX copy path is used */
19+
#define VMX_COPY_THRESHOLD 3328
20+
1821
#include <asm-generic/access_ok.h>
1922

2023
/*
@@ -326,40 +329,62 @@ do { \
326329
extern unsigned long __copy_tofrom_user(void __user *to,
327330
const void __user *from, unsigned long size);
328331

329-
#ifdef __powerpc64__
330-
static inline unsigned long
331-
raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
332+
unsigned long __copy_tofrom_user_base(void __user *to,
333+
const void __user *from, unsigned long size);
334+
335+
unsigned long __copy_tofrom_user_power7_vmx(void __user *to,
336+
const void __user *from, unsigned long size);
337+
338+
static __always_inline bool will_use_vmx(unsigned long n)
339+
{
340+
return IS_ENABLED(CONFIG_ALTIVEC) && cpu_has_feature(CPU_FTR_VMX_COPY) &&
341+
n > VMX_COPY_THRESHOLD;
342+
}
343+
344+
static __always_inline unsigned long
345+
raw_copy_tofrom_user(void __user *to, const void __user *from,
346+
unsigned long n, unsigned long dir)
332347
{
333348
unsigned long ret;
334349

335-
barrier_nospec();
336-
allow_user_access(to, KUAP_READ_WRITE);
350+
if (will_use_vmx(n) && enter_vmx_usercopy()) {
351+
allow_user_access(to, dir);
352+
ret = __copy_tofrom_user_power7_vmx(to, from, n);
353+
prevent_user_access(dir);
354+
exit_vmx_usercopy();
355+
356+
if (unlikely(ret)) {
357+
allow_user_access(to, dir);
358+
ret = __copy_tofrom_user_base(to, from, n);
359+
prevent_user_access(dir);
360+
}
361+
return ret;
362+
}
363+
364+
allow_user_access(to, dir);
337365
ret = __copy_tofrom_user(to, from, n);
338-
prevent_user_access(KUAP_READ_WRITE);
366+
prevent_user_access(dir);
339367
return ret;
340368
}
341-
#endif /* __powerpc64__ */
342369

343-
static inline unsigned long raw_copy_from_user(void *to,
344-
const void __user *from, unsigned long n)
370+
#ifdef CONFIG_PPC64
371+
static inline unsigned long
372+
raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
345373
{
346-
unsigned long ret;
374+
barrier_nospec();
375+
return raw_copy_tofrom_user(to, from, n, KUAP_READ_WRITE);
376+
}
377+
#endif /* CONFIG_PPC64 */
347378

348-
allow_user_access(NULL, KUAP_READ);
349-
ret = __copy_tofrom_user((__force void __user *)to, from, n);
350-
prevent_user_access(KUAP_READ);
351-
return ret;
379+
static inline unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n)
380+
{
381+
return raw_copy_tofrom_user((__force void __user *)to, from, n, KUAP_READ);
352382
}
353383

354384
static inline unsigned long
355385
raw_copy_to_user(void __user *to, const void *from, unsigned long n)
356386
{
357-
unsigned long ret;
358-
359-
allow_user_access(to, KUAP_WRITE);
360-
ret = __copy_tofrom_user(to, (__force const void __user *)from, n);
361-
prevent_user_access(KUAP_WRITE);
362-
return ret;
387+
return raw_copy_tofrom_user(to, (__force const void __user *)from, n, KUAP_WRITE);
363388
}
364389

365390
unsigned long __arch_clear_user(void __user *addr, unsigned long size);

arch/powerpc/kernel/iommu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain,
11591159
struct device *dev,
11601160
struct iommu_domain *old)
11611161
{
1162-
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
1162+
struct iommu_domain *domain = iommu_driver_get_domain_for_dev(dev);
11631163
struct iommu_table_group *table_group;
11641164
struct iommu_group *grp;
11651165

arch/powerpc/kernel/setup-common.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#include <linux/of_irq.h>
3636
#include <linux/hugetlb.h>
3737
#include <linux/pgtable.h>
38-
#include <asm/kexec.h>
3938
#include <asm/io.h>
4039
#include <asm/paca.h>
4140
#include <asm/processor.h>
@@ -995,15 +994,6 @@ void __init setup_arch(char **cmdline_p)
995994

996995
initmem_init();
997996

998-
/*
999-
* Reserve large chunks of memory for use by CMA for kdump, fadump, KVM and
1000-
* hugetlb. These must be called after initmem_init(), so that
1001-
* pageblock_order is initialised.
1002-
*/
1003-
fadump_cma_init();
1004-
kdump_cma_reserve();
1005-
kvm_cma_reserve();
1006-
1007997
early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT);
1008998

1009999
if (ppc_md.setup_arch)

arch/powerpc/lib/copyuser_64.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,3 +562,4 @@ exc; std r10,32(3)
562562
li r5,4096
563563
b .Ldst_aligned
564564
EXPORT_SYMBOL(__copy_tofrom_user)
565+
EXPORT_SYMBOL(__copy_tofrom_user_base)

arch/powerpc/lib/copyuser_power7.S

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,9 @@
55
*
66
* Author: Anton Blanchard <anton@au.ibm.com>
77
*/
8+
#include <linux/export.h>
89
#include <asm/ppc_asm.h>
910

10-
#ifndef SELFTEST_CASE
11-
/* 0 == don't use VMX, 1 == use VMX */
12-
#define SELFTEST_CASE 0
13-
#endif
14-
1511
#ifdef __BIG_ENDIAN__
1612
#define LVS(VRT,RA,RB) lvsl VRT,RA,RB
1713
#define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRA,VRB,VRC
@@ -47,10 +43,14 @@
4743
ld r15,STK_REG(R15)(r1)
4844
ld r14,STK_REG(R14)(r1)
4945
.Ldo_err3:
50-
bl CFUNC(exit_vmx_usercopy)
46+
ld r6,STK_REG(R31)(r1) /* original destination pointer */
47+
ld r5,STK_REG(R29)(r1) /* original number of bytes */
48+
subf r7,r6,r3 /* #bytes copied */
49+
subf r3,r7,r5 /* #bytes not copied in r3 */
5150
ld r0,STACKFRAMESIZE+16(r1)
5251
mtlr r0
53-
b .Lexit
52+
addi r1,r1,STACKFRAMESIZE
53+
blr
5454
#endif /* CONFIG_ALTIVEC */
5555

5656
.Ldo_err2:
@@ -74,20 +74,13 @@
7474

7575
_GLOBAL(__copy_tofrom_user_power7)
7676
cmpldi r5,16
77-
cmpldi cr1,r5,3328
7877

7978
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
8079
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
8180
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
8281

8382
blt .Lshort_copy
8483

85-
#ifdef CONFIG_ALTIVEC
86-
test_feature = SELFTEST_CASE
87-
BEGIN_FTR_SECTION
88-
bgt cr1,.Lvmx_copy
89-
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
90-
#endif
9184

9285
.Lnonvmx_copy:
9386
/* Get the source 8B aligned */
@@ -263,23 +256,14 @@ err1; stb r0,0(r3)
263256
15: li r3,0
264257
blr
265258

266-
.Lunwind_stack_nonvmx_copy:
267-
addi r1,r1,STACKFRAMESIZE
268-
b .Lnonvmx_copy
269-
270-
.Lvmx_copy:
271259
#ifdef CONFIG_ALTIVEC
260+
_GLOBAL(__copy_tofrom_user_power7_vmx)
272261
mflr r0
273262
std r0,16(r1)
274263
stdu r1,-STACKFRAMESIZE(r1)
275-
bl CFUNC(enter_vmx_usercopy)
276-
cmpwi cr1,r3,0
277-
ld r0,STACKFRAMESIZE+16(r1)
278-
ld r3,STK_REG(R31)(r1)
279-
ld r4,STK_REG(R30)(r1)
280-
ld r5,STK_REG(R29)(r1)
281-
mtlr r0
282264

265+
std r3,STK_REG(R31)(r1)
266+
std r5,STK_REG(R29)(r1)
283267
/*
284268
* We prefetch both the source and destination using enhanced touch
285269
* instructions. We use a stream ID of 0 for the load side and
@@ -300,8 +284,6 @@ err1; stb r0,0(r3)
300284

301285
DCBT_SETUP_STREAMS(r6, r7, r9, r10, r8)
302286

303-
beq cr1,.Lunwind_stack_nonvmx_copy
304-
305287
/*
306288
* If source and destination are not relatively aligned we use a
307289
* slower permute loop.
@@ -478,7 +460,8 @@ err3; lbz r0,0(r4)
478460
err3; stb r0,0(r3)
479461

480462
15: addi r1,r1,STACKFRAMESIZE
481-
b CFUNC(exit_vmx_usercopy) /* tail call optimise */
463+
li r3,0
464+
blr
482465

483466
.Lvmx_unaligned_copy:
484467
/* Get the destination 16B aligned */
@@ -681,5 +664,7 @@ err3; lbz r0,0(r4)
681664
err3; stb r0,0(r3)
682665

683666
15: addi r1,r1,STACKFRAMESIZE
684-
b CFUNC(exit_vmx_usercopy) /* tail call optimise */
667+
li r3,0
668+
blr
669+
EXPORT_SYMBOL(__copy_tofrom_user_power7_vmx)
685670
#endif /* CONFIG_ALTIVEC */

arch/powerpc/lib/vmx-helper.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ int enter_vmx_usercopy(void)
2727

2828
return 1;
2929
}
30+
EXPORT_SYMBOL(enter_vmx_usercopy);
3031

3132
/*
3233
* This function must return 0 because we tail call optimise when calling
@@ -49,6 +50,7 @@ int exit_vmx_usercopy(void)
4950
set_dec(1);
5051
return 0;
5152
}
53+
EXPORT_SYMBOL(exit_vmx_usercopy);
5254

5355
int enter_vmx_ops(void)
5456
{

arch/powerpc/mm/mem.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
#include <asm/setup.h>
3131
#include <asm/fixmap.h>
3232

33+
#include <asm/fadump.h>
34+
#include <asm/kexec.h>
35+
#include <asm/kvm_ppc.h>
36+
3337
#include <mm/mmu_decl.h>
3438

3539
unsigned long long memory_limit __initdata;
@@ -268,6 +272,16 @@ void __init paging_init(void)
268272

269273
void __init arch_mm_preinit(void)
270274
{
275+
276+
/*
277+
* Reserve large chunks of memory for use by CMA for kdump, fadump, KVM
278+
* and hugetlb. These must be called after pageblock_order is
279+
* initialised.
280+
*/
281+
fadump_cma_init();
282+
kdump_cma_reserve();
283+
kvm_cma_reserve();
284+
271285
/*
272286
* book3s is limited to 16 page sizes due to encoding this in
273287
* a 4-bit field for slices.

arch/powerpc/perf/callchain.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
103103
void
104104
perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
105105
{
106+
perf_callchain_store(entry, perf_arch_instruction_pointer(regs));
107+
108+
if (!current->mm)
109+
return;
110+
106111
if (!is_32bit_task())
107112
perf_callchain_user_64(entry, regs);
108113
else

arch/powerpc/perf/callchain_32.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
142142
next_ip = perf_arch_instruction_pointer(regs);
143143
lr = regs->link;
144144
sp = regs->gpr[1];
145-
perf_callchain_store(entry, next_ip);
146145

147146
while (entry->nr < entry->max_stack) {
148147
fp = (unsigned int __user *) (unsigned long) sp;

arch/powerpc/perf/callchain_64.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
7777
next_ip = perf_arch_instruction_pointer(regs);
7878
lr = regs->link;
7979
sp = regs->gpr[1];
80-
perf_callchain_store(entry, next_ip);
8180

8281
while (entry->nr < entry->max_stack) {
8382
fp = (unsigned long __user *) sp;

0 commit comments

Comments
 (0)