diff options
| -rw-r--r-- | arch/arm/include/asm/uaccess.h | 4 | ||||
| -rw-r--r-- | arch/arm/kernel/process.c | 33 | ||||
| -rw-r--r-- | arch/arm/kernel/swp_emulate.c | 6 | ||||
| -rw-r--r-- | arch/arm/lib/uaccess_with_memcpy.c | 29 | ||||
| -rw-r--r-- | arch/arm/mm/context.c | 38 | ||||
| -rw-r--r-- | arch/arm/mm/init.c | 92 | ||||
| -rw-r--r-- | arch/arm/mm/proc-v7.S | 4 |
7 files changed, 138 insertions, 68 deletions
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 8cc85a4ebec2..35c9db857ebe 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h | |||
| @@ -510,10 +510,14 @@ __copy_to_user_std(void __user *to, const void *from, unsigned long n); | |||
| 510 | static inline unsigned long __must_check | 510 | static inline unsigned long __must_check |
| 511 | __copy_to_user(void __user *to, const void *from, unsigned long n) | 511 | __copy_to_user(void __user *to, const void *from, unsigned long n) |
| 512 | { | 512 | { |
| 513 | #ifndef CONFIG_UACCESS_WITH_MEMCPY | ||
| 513 | unsigned int __ua_flags = uaccess_save_and_enable(); | 514 | unsigned int __ua_flags = uaccess_save_and_enable(); |
| 514 | n = arm_copy_to_user(to, from, n); | 515 | n = arm_copy_to_user(to, from, n); |
| 515 | uaccess_restore(__ua_flags); | 516 | uaccess_restore(__ua_flags); |
| 516 | return n; | 517 | return n; |
| 518 | #else | ||
| 519 | return arm_copy_to_user(to, from, n); | ||
| 520 | #endif | ||
| 517 | } | 521 | } |
| 518 | 522 | ||
| 519 | extern unsigned long __must_check | 523 | extern unsigned long __must_check |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 7a7c4cea5523..4adfb46e3ee9 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
| @@ -95,6 +95,22 @@ void __show_regs(struct pt_regs *regs) | |||
| 95 | { | 95 | { |
| 96 | unsigned long flags; | 96 | unsigned long flags; |
| 97 | char buf[64]; | 97 | char buf[64]; |
| 98 | #ifndef CONFIG_CPU_V7M | ||
| 99 | unsigned int domain; | ||
| 100 | #ifdef CONFIG_CPU_SW_DOMAIN_PAN | ||
| 101 | /* | ||
| 102 | * Get the domain register for the parent context. In user | ||
| 103 | * mode, we don't save the DACR, so lets use what it should | ||
| 104 | * be. For other modes, we place it after the pt_regs struct. | ||
| 105 | */ | ||
| 106 | if (user_mode(regs)) | ||
| 107 | domain = DACR_UACCESS_ENABLE; | ||
| 108 | else | ||
| 109 | domain = *(unsigned int *)(regs + 1); | ||
| 110 | #else | ||
| 111 | domain = get_domain(); | ||
| 112 | #endif | ||
| 113 | #endif | ||
| 98 | 114 | ||
| 99 | show_regs_print_info(KERN_DEFAULT); | 115 | show_regs_print_info(KERN_DEFAULT); |
| 100 | 116 | ||
| @@ -123,21 +139,8 @@ void __show_regs(struct pt_regs *regs) | |||
| 123 | 139 | ||
| 124 | #ifndef CONFIG_CPU_V7M | 140 | #ifndef CONFIG_CPU_V7M |
| 125 | { | 141 | { |
| 126 | unsigned int domain = get_domain(); | ||
| 127 | const char *segment; | 142 | const char *segment; |
| 128 | 143 | ||
| 129 | #ifdef CONFIG_CPU_SW_DOMAIN_PAN | ||
| 130 | /* | ||
| 131 | * Get the domain register for the parent context. In user | ||
| 132 | * mode, we don't save the DACR, so lets use what it should | ||
| 133 | * be. For other modes, we place it after the pt_regs struct. | ||
| 134 | */ | ||
| 135 | if (user_mode(regs)) | ||
| 136 | domain = DACR_UACCESS_ENABLE; | ||
| 137 | else | ||
| 138 | domain = *(unsigned int *)(regs + 1); | ||
| 139 | #endif | ||
| 140 | |||
| 141 | if ((domain & domain_mask(DOMAIN_USER)) == | 144 | if ((domain & domain_mask(DOMAIN_USER)) == |
| 142 | domain_val(DOMAIN_USER, DOMAIN_NOACCESS)) | 145 | domain_val(DOMAIN_USER, DOMAIN_NOACCESS)) |
| 143 | segment = "none"; | 146 | segment = "none"; |
| @@ -163,11 +166,11 @@ void __show_regs(struct pt_regs *regs) | |||
| 163 | buf[0] = '\0'; | 166 | buf[0] = '\0'; |
| 164 | #ifdef CONFIG_CPU_CP15_MMU | 167 | #ifdef CONFIG_CPU_CP15_MMU |
| 165 | { | 168 | { |
| 166 | unsigned int transbase, dac = get_domain(); | 169 | unsigned int transbase; |
| 167 | asm("mrc p15, 0, %0, c2, c0\n\t" | 170 | asm("mrc p15, 0, %0, c2, c0\n\t" |
| 168 | : "=r" (transbase)); | 171 | : "=r" (transbase)); |
| 169 | snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x", | 172 | snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x", |
| 170 | transbase, dac); | 173 | transbase, domain); |
| 171 | } | 174 | } |
| 172 | #endif | 175 | #endif |
| 173 | asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl)); | 176 | asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl)); |
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c index 5b26e7efa9ea..c3fe769d7558 100644 --- a/arch/arm/kernel/swp_emulate.c +++ b/arch/arm/kernel/swp_emulate.c | |||
| @@ -36,10 +36,10 @@ | |||
| 36 | */ | 36 | */ |
| 37 | #define __user_swpX_asm(data, addr, res, temp, B) \ | 37 | #define __user_swpX_asm(data, addr, res, temp, B) \ |
| 38 | __asm__ __volatile__( \ | 38 | __asm__ __volatile__( \ |
| 39 | " mov %2, %1\n" \ | 39 | "0: ldrex"B" %2, [%3]\n" \ |
| 40 | "0: ldrex"B" %1, [%3]\n" \ | 40 | "1: strex"B" %0, %1, [%3]\n" \ |
| 41 | "1: strex"B" %0, %2, [%3]\n" \ | ||
| 42 | " cmp %0, #0\n" \ | 41 | " cmp %0, #0\n" \ |
| 42 | " moveq %1, %2\n" \ | ||
| 43 | " movne %0, %4\n" \ | 43 | " movne %0, %4\n" \ |
| 44 | "2:\n" \ | 44 | "2:\n" \ |
| 45 | " .section .text.fixup,\"ax\"\n" \ | 45 | " .section .text.fixup,\"ax\"\n" \ |
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index d72b90905132..588bbc288396 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/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) | |||
| 88 | static unsigned long noinline | 88 | static unsigned long noinline |
| 89 | __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) | 89 | __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) |
| 90 | { | 90 | { |
| 91 | unsigned long ua_flags; | ||
| 91 | int atomic; | 92 | int atomic; |
| 92 | 93 | ||
| 93 | if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { | 94 | if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { |
| @@ -118,7 +119,9 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) | |||
| 118 | if (tocopy > n) | 119 | if (tocopy > n) |
| 119 | tocopy = n; | 120 | tocopy = n; |
| 120 | 121 | ||
| 122 | ua_flags = uaccess_save_and_enable(); | ||
| 121 | memcpy((void *)to, from, tocopy); | 123 | memcpy((void *)to, from, tocopy); |
| 124 | uaccess_restore(ua_flags); | ||
| 122 | to += tocopy; | 125 | to += tocopy; |
| 123 | from += tocopy; | 126 | from += tocopy; |
| 124 | n -= tocopy; | 127 | n -= tocopy; |
| @@ -145,14 +148,21 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n) | |||
| 145 | * With frame pointer disabled, tail call optimization kicks in | 148 | * With frame pointer disabled, tail call optimization kicks in |
| 146 | * as well making this test almost invisible. | 149 | * as well making this test almost invisible. |
| 147 | */ | 150 | */ |
| 148 | if (n < 64) | 151 | if (n < 64) { |
| 149 | return __copy_to_user_std(to, from, n); | 152 | unsigned long ua_flags = uaccess_save_and_enable(); |
| 150 | return __copy_to_user_memcpy(to, from, n); | 153 | n = __copy_to_user_std(to, from, n); |
| 154 | uaccess_restore(ua_flags); | ||
| 155 | } else { | ||
| 156 | n = __copy_to_user_memcpy(to, from, n); | ||
| 157 | } | ||
| 158 | return n; | ||
| 151 | } | 159 | } |
| 152 | 160 | ||
| 153 | static unsigned long noinline | 161 | static unsigned long noinline |
| 154 | __clear_user_memset(void __user *addr, unsigned long n) | 162 | __clear_user_memset(void __user *addr, unsigned long n) |
| 155 | { | 163 | { |
| 164 | unsigned long ua_flags; | ||
| 165 | |||
| 156 | if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { | 166 | if (unlikely(segment_eq(get_fs(), KERNEL_DS))) { |
| 157 | memset((void *)addr, 0, n); | 167 | memset((void *)addr, 0, n); |
| 158 | return 0; | 168 | return 0; |
| @@ -175,7 +185,9 @@ __clear_user_memset(void __user *addr, unsigned long n) | |||
| 175 | if (tocopy > n) | 185 | if (tocopy > n) |
| 176 | tocopy = n; | 186 | tocopy = n; |
| 177 | 187 | ||
| 188 | ua_flags = uaccess_save_and_enable(); | ||
| 178 | memset((void *)addr, 0, tocopy); | 189 | memset((void *)addr, 0, tocopy); |
| 190 | uaccess_restore(ua_flags); | ||
| 179 | addr += tocopy; | 191 | addr += tocopy; |
| 180 | n -= tocopy; | 192 | n -= tocopy; |
| 181 | 193 | ||
| @@ -193,9 +205,14 @@ out: | |||
| 193 | unsigned long arm_clear_user(void __user *addr, unsigned long n) | 205 | unsigned long arm_clear_user(void __user *addr, unsigned long n) |
| 194 | { | 206 | { |
| 195 | /* See rational for this in __copy_to_user() above. */ | 207 | /* See rational for this in __copy_to_user() above. */ |
| 196 | if (n < 64) | 208 | if (n < 64) { |
| 197 | return __clear_user_std(addr, n); | 209 | unsigned long ua_flags = uaccess_save_and_enable(); |
| 198 | return __clear_user_memset(addr, n); | 210 | n = __clear_user_std(addr, n); |
| 211 | uaccess_restore(ua_flags); | ||
| 212 | } else { | ||
| 213 | n = __clear_user_memset(addr, n); | ||
| 214 | } | ||
| 215 | return n; | ||
| 199 | } | 216 | } |
| 200 | 217 | ||
| 201 | #if 0 | 218 | #if 0 |
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 845769e41332..c8c8b9ed02e0 100644 --- a/arch/arm/mm/context.c +++ b/ | |||
