diff options
Diffstat (limited to 'kernel/arch/arm/lib')
-rw-r--r-- | kernel/arch/arm/lib/call_with_stack.S | 2 | ||||
-rw-r--r-- | kernel/arch/arm/lib/clear_user.S | 10 | ||||
-rw-r--r-- | kernel/arch/arm/lib/copy_from_user.S | 6 | ||||
-rw-r--r-- | kernel/arch/arm/lib/copy_to_user.S | 6 | ||||
-rw-r--r-- | kernel/arch/arm/lib/csumpartialcopyuser.S | 14 | ||||
-rw-r--r-- | kernel/arch/arm/lib/lib1funcs.S | 4 | ||||
-rw-r--r-- | kernel/arch/arm/lib/memcpy.S | 2 | ||||
-rw-r--r-- | kernel/arch/arm/lib/memset.S | 2 | ||||
-rw-r--r-- | kernel/arch/arm/lib/uaccess_with_memcpy.c | 35 |
9 files changed, 60 insertions, 21 deletions
diff --git a/kernel/arch/arm/lib/call_with_stack.S b/kernel/arch/arm/lib/call_with_stack.S index ed1a42181..bf3a40889 100644 --- a/kernel/arch/arm/lib/call_with_stack.S +++ b/kernel/arch/arm/lib/call_with_stack.S @@ -35,7 +35,7 @@ ENTRY(call_with_stack) mov r2, r0 mov r0, r1 - adr lr, BSYM(1f) + badr lr, 1f ret r2 1: ldr lr, [sp] diff --git a/kernel/arch/arm/lib/clear_user.S b/kernel/arch/arm/lib/clear_user.S index 1710fd7db..e936352cc 100644 --- a/kernel/arch/arm/lib/clear_user.S +++ b/kernel/arch/arm/lib/clear_user.S @@ -9,17 +9,20 @@ */ #include <linux/linkage.h> #include <asm/assembler.h> +#include <asm/unwind.h> .text -/* Prototype: int __clear_user(void *addr, size_t sz) +/* Prototype: unsigned long arm_clear_user(void *addr, size_t sz) * Purpose : clear some user memory * Params : addr - user memory address to clear * : sz - number of bytes to clear * Returns : number of bytes NOT cleared */ ENTRY(__clear_user_std) -WEAK(__clear_user) +WEAK(arm_clear_user) +UNWIND(.fnstart) +UNWIND(.save {r1, lr}) stmfd sp!, {r1, lr} mov r2, #0 cmp r1, #4 @@ -44,7 +47,8 @@ WEAK(__clear_user) USER( strnebt r2, [r0]) mov r0, #0 ldmfd sp!, {r1, pc} -ENDPROC(__clear_user) +UNWIND(.fnend) +ENDPROC(arm_clear_user) ENDPROC(__clear_user_std) .pushsection .text.fixup,"ax" diff --git a/kernel/arch/arm/lib/copy_from_user.S b/kernel/arch/arm/lib/copy_from_user.S index 7a235b995..1512bebfb 100644 --- a/kernel/arch/arm/lib/copy_from_user.S +++ b/kernel/arch/arm/lib/copy_from_user.S @@ -17,7 +17,7 @@ /* * Prototype: * - * size_t __copy_from_user(void *to, const void *from, size_t n) + * size_t arm_copy_from_user(void *to, const void *from, size_t n) * * Purpose: * @@ -89,11 +89,11 @@ .text -ENTRY(__copy_from_user) +ENTRY(arm_copy_from_user) #include "copy_template.S" -ENDPROC(__copy_from_user) +ENDPROC(arm_copy_from_user) .pushsection .fixup,"ax" .align 0 diff --git a/kernel/arch/arm/lib/copy_to_user.S b/kernel/arch/arm/lib/copy_to_user.S index 9648b0675..caf5019d8 100644 --- a/kernel/arch/arm/lib/copy_to_user.S +++ b/kernel/arch/arm/lib/copy_to_user.S @@ -17,7 +17,7 @@ /* * Prototype: * - * size_t __copy_to_user(void *to, const void *from, size_t n) + * size_t arm_copy_to_user(void *to, const void *from, size_t n) * * Purpose: * @@ -93,11 +93,11 @@ .text ENTRY(__copy_to_user_std) -WEAK(__copy_to_user) +WEAK(arm_copy_to_user) #include "copy_template.S" -ENDPROC(__copy_to_user) +ENDPROC(arm_copy_to_user) ENDPROC(__copy_to_user_std) .pushsection .text.fixup,"ax" diff --git a/kernel/arch/arm/lib/csumpartialcopyuser.S b/kernel/arch/arm/lib/csumpartialcopyuser.S index 1d0957e61..1712f132b 100644 --- a/kernel/arch/arm/lib/csumpartialcopyuser.S +++ b/kernel/arch/arm/lib/csumpartialcopyuser.S @@ -17,6 +17,19 @@ .text +#ifdef CONFIG_CPU_SW_DOMAIN_PAN + .macro save_regs + mrc p15, 0, ip, c3, c0, 0 + stmfd sp!, {r1, r2, r4 - r8, ip, lr} + uaccess_enable ip + .endm + + .macro load_regs + ldmfd sp!, {r1, r2, r4 - r8, ip, lr} + mcr p15, 0, ip, c3, c0, 0 + ret lr + .endm +#else .macro save_regs stmfd sp!, {r1, r2, r4 - r8, lr} .endm @@ -24,6 +37,7 @@ .macro load_regs ldmfd sp!, {r1, r2, r4 - r8, pc} .endm +#endif .macro load1b, reg1 ldrusr \reg1, r0, 1 diff --git a/kernel/arch/arm/lib/lib1funcs.S b/kernel/arch/arm/lib/lib1funcs.S index 947567ff6..af2267f6a 100644 --- a/kernel/arch/arm/lib/lib1funcs.S +++ b/kernel/arch/arm/lib/lib1funcs.S @@ -167,7 +167,7 @@ Boston, MA 02111-1307, USA. */ #endif - @ Perform all needed substractions to keep only the reminder. + @ Perform all needed subtractions to keep only the reminder. @ Do comparisons in batch of 4 first. subs \order, \order, #3 @ yes, 3 is intended here blt 2f @@ -189,7 +189,7 @@ Boston, MA 02111-1307, USA. */ teqne \dividend, #0 beq 5f - @ Either 1, 2 or 3 comparison/substractions are left. + @ Either 1, 2 or 3 comparison/subtractions are left. 2: cmn \order, #2 blt 4f beq 3f diff --git a/kernel/arch/arm/lib/memcpy.S b/kernel/arch/arm/lib/memcpy.S index 7797e81e4..64111bd44 100644 --- a/kernel/arch/arm/lib/memcpy.S +++ b/kernel/arch/arm/lib/memcpy.S @@ -61,8 +61,10 @@ /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ +ENTRY(mmiocpy) ENTRY(memcpy) #include "copy_template.S" ENDPROC(memcpy) +ENDPROC(mmiocpy) diff --git a/kernel/arch/arm/lib/memset.S b/kernel/arch/arm/lib/memset.S index a4ee97b5a..3c65e3bd7 100644 --- a/kernel/arch/arm/lib/memset.S +++ b/kernel/arch/arm/lib/memset.S @@ -16,6 +16,7 @@ .text .align 5 +ENTRY(mmioset) ENTRY(memset) UNWIND( .fnstart ) ands r3, r0, #3 @ 1 unaligned? @@ -133,3 +134,4 @@ UNWIND( .fnstart ) b 1b UNWIND( .fnend ) ENDPROC(memset) +ENDPROC(mmioset) diff --git a/kernel/arch/arm/lib/uaccess_with_memcpy.c b/kernel/arch/arm/lib/uaccess_with_memcpy.c index 3e58d7100..588bbc288 100644 --- a/kernel/arch/arm/lib/uaccess_with_memcpy.c +++ b/kernel/arch/arm/lib/uaccess_with_memcpy.c @@ -88,6 +88,7 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp) static unsigned long noinline __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) { + unsigned long ua_flags; int atomic; if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { @@ -96,7 +97,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) } /* the mmap semaphore is taken only if not in an atomic context */ - atomic = in_atomic(); + atomic = faulthandler_disabled(); if (!atomic) down_read(¤t->mm->mmap_sem); @@ -118,7 +119,9 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) if (tocopy > n) tocopy = n; + ua_flags = uaccess_save_and_enable(); memcpy((void *)to, from, tocopy); + uaccess_restore(ua_flags); to += tocopy; from += tocopy; n -= tocopy; @@ -136,7 +139,7 @@ out: } unsigned long -__copy_to_user(void __user *to, const void *from, unsigned long n) +arm_copy_to_user(void __user *to, const void *from, unsigned long n) { /* * This test is stubbed out of the main function above to keep @@ -145,14 +148,21 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) * With frame pointer disabled, tail call optimization kicks in * as well making this test almost invisible. */ - if (n < 64) - return __copy_to_user_std(to, from, n); - return __copy_to_user_memcpy(to, from, n); + if (n < 64) { + unsigned long ua_flags = uaccess_save_and_enable(); + n = __copy_to_user_std(to, from, n); + uaccess_restore(ua_flags); + } else { + n = __copy_to_user_memcpy(to, from, n); + } + return n; } static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) { + unsigned long ua_flags; + if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { memset((void *)addr, 0, n); return 0; @@ -175,7 +185,9 @@ __clear_user_memset(void __user *addr, unsigned long n) if (tocopy > n) tocopy = n; + ua_flags = uaccess_save_and_enable(); memset((void *)addr, 0, tocopy); + uaccess_restore(ua_flags); addr += tocopy; n -= tocopy; @@ -190,12 +202,17 @@ out: return n; } -unsigned long __clear_user(void __user *addr, unsigned long n) +unsigned long arm_clear_user(void __user *addr, unsigned long n) { /* See rational for this in __copy_to_user() above. */ - if (n < 64) - return __clear_user_std(addr, n); - return __clear_user_memset(addr, n); + if (n < 64) { + unsigned long ua_flags = uaccess_save_and_enable(); + n = __clear_user_std(addr, n); + uaccess_restore(ua_flags); + } else { + n = __clear_user_memset(addr, n); + } + return n; } #if 0 |