diff options
| -rw-r--r-- | arch/arm/Kconfig.debug | 6 | ||||
| -rw-r--r-- | arch/arm/Makefile | 4 | ||||
| -rw-r--r-- | arch/arm/boot/compressed/head.S | 4 | ||||
| -rw-r--r-- | arch/arm/include/asm/assembler.h | 8 | ||||
| -rw-r--r-- | arch/arm/include/asm/memory.h | 3 | ||||
| -rw-r--r-- | arch/arm/include/asm/tlb.h | 4 | ||||
| -rw-r--r-- | arch/arm/include/asm/uaccess.h | 58 | ||||
| -rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 62 | ||||
| -rw-r--r-- | arch/arm/kernel/traps.c | 11 | ||||
| -rw-r--r-- | arch/arm/lib/delay.c | 1 | ||||
| -rw-r--r-- | arch/arm/lib/getuser.S | 23 | ||||
| -rw-r--r-- | arch/arm/lib/putuser.S | 6 | ||||
| -rw-r--r-- | arch/arm/mm/context.c | 7 | ||||
| -rw-r--r-- | arch/arm/mm/mm.h | 3 | ||||
| -rw-r--r-- | arch/arm/mm/mmu.c | 8 |
15 files changed, 151 insertions, 57 deletions
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index f15f82bf3a50..e968a52e4881 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
| @@ -356,15 +356,15 @@ choice | |||
| 356 | is nothing connected to read from the DCC. | 356 | is nothing connected to read from the DCC. |
| 357 | 357 | ||
| 358 | config DEBUG_SEMIHOSTING | 358 | config DEBUG_SEMIHOSTING |
| 359 | bool "Kernel low-level debug output via semihosting I" | 359 | bool "Kernel low-level debug output via semihosting I/O" |
| 360 | help | 360 | help |
| 361 | Semihosting enables code running on an ARM target to use | 361 | Semihosting enables code running on an ARM target to use |
| 362 | the I/O facilities on a host debugger/emulator through a | 362 | the I/O facilities on a host debugger/emulator through a |
| 363 | simple SVC calls. The host debugger or emulator must have | 363 | simple SVC call. The host debugger or emulator must have |
| 364 | semihosting enabled for the special svc call to be trapped | 364 | semihosting enabled for the special svc call to be trapped |
| 365 | otherwise the kernel will crash. | 365 | otherwise the kernel will crash. |
| 366 | 366 | ||
| 367 | This is known to work with OpenOCD, as wellas | 367 | This is known to work with OpenOCD, as well as |
| 368 | ARM's Fast Models, or any other controlling environment | 368 | ARM's Fast Models, or any other controlling environment |
| 369 | that implements semihosting. | 369 | that implements semihosting. |
| 370 | 370 | ||
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 30eae87ead6d..a051dfbdd7db 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
| @@ -284,10 +284,10 @@ zImage Image xipImage bootpImage uImage: vmlinux | |||
| 284 | zinstall uinstall install: vmlinux | 284 | zinstall uinstall install: vmlinux |
| 285 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ | 285 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ |
| 286 | 286 | ||
| 287 | %.dtb: | 287 | %.dtb: scripts |
| 288 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ | 288 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ |
| 289 | 289 | ||
| 290 | dtbs: | 290 | dtbs: scripts |
| 291 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ | 291 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ |
| 292 | 292 | ||
| 293 | # We use MRPROPER_FILES and CLEAN_FILES now | 293 | # We use MRPROPER_FILES and CLEAN_FILES now |
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index b8c64b80bafc..81769c1341fa 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
| @@ -659,10 +659,14 @@ __armv7_mmu_cache_on: | |||
| 659 | #ifdef CONFIG_CPU_ENDIAN_BE8 | 659 | #ifdef CONFIG_CPU_ENDIAN_BE8 |
| 660 | orr r0, r0, #1 << 25 @ big-endian page tables | 660 | orr r0, r0, #1 << 25 @ big-endian page tables |
| 661 | #endif | 661 | #endif |
| 662 | mrcne p15, 0, r6, c2, c0, 2 @ read ttb control reg | ||
| 662 | orrne r0, r0, #1 @ MMU enabled | 663 | orrne r0, r0, #1 @ MMU enabled |
| 663 | movne r1, #0xfffffffd @ domain 0 = client | 664 | movne r1, #0xfffffffd @ domain 0 = client |
| 665 | bic r6, r6, #1 << 31 @ 32-bit translation system | ||
| 666 | bic r6, r6, #3 << 0 @ use only ttbr0 | ||
| 664 | mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer | 667 | mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer |
| 665 | mcrne p15, 0, r1, c3, c0, 0 @ load domain access control | 668 | mcrne p15, 0, r1, c3, c0, 0 @ load domain access control |
| 669 | mcrne p15, 0, r6, c2, c0, 2 @ load ttb control | ||
| 666 | #endif | 670 | #endif |
| 667 | mcr p15, 0, r0, c7, c5, 4 @ ISB | 671 | mcr p15, 0, r0, c7, c5, 4 @ ISB |
| 668 | mcr p15, 0, r0, c1, c0, 0 @ load control register | 672 | mcr p15, 0, r0, c1, c0, 0 @ load control register |
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 03fb93621d0d..5c8b3bf4d825 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
| @@ -320,4 +320,12 @@ | |||
| 320 | .size \name , . - \name | 320 | .size \name , . - \name |
| 321 | .endm | 321 | .endm |
| 322 | 322 | ||
| 323 | .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req | ||
| 324 | #ifndef CONFIG_CPU_USE_DOMAINS | ||
| 325 | adds \tmp, \addr, #\size - 1 | ||
| 326 | sbcccs \tmp, \tmp, \limit | ||
| 327 | bcs \bad | ||
| 328 | #endif | ||
| 329 | .endm | ||
| 330 | |||
| 323 | #endif /* __ASM_ASSEMBLER_H__ */ | 331 | #endif /* __ASM_ASSEMBLER_H__ */ |
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index e965f1b560f1..5f6ddcc56452 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h | |||
| @@ -187,6 +187,7 @@ static inline unsigned long __phys_to_virt(unsigned long x) | |||
| 187 | #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) | 187 | #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) |
| 188 | #endif | 188 | #endif |
| 189 | #endif | 189 | #endif |
| 190 | #endif /* __ASSEMBLY__ */ | ||
| 190 | 191 | ||
| 191 | #ifndef PHYS_OFFSET | 192 | #ifndef PHYS_OFFSET |
| 192 | #ifdef PLAT_PHYS_OFFSET | 193 | #ifdef PLAT_PHYS_OFFSET |
| @@ -196,6 +197,8 @@ static inline unsigned long __phys_to_virt(unsigned long x) | |||
| 196 | #endif | 197 | #endif |
| 197 | #endif | 198 | #endif |
| 198 | 199 | ||
| 200 | #ifndef __ASSEMBLY__ | ||
| 201 | |||
| 199 | /* | 202 | /* |
| 200 | * PFNs are used to describe any physical page; this means | 203 | * PFNs are used to describe any physical page; this means |
| 201 | * PFN 0 == physical address 0. | 204 | * PFN 0 == physical address 0. |
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 314d4664eae7..99a19512ee26 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h | |||
| @@ -199,6 +199,9 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | |||
| 199 | { | 199 | { |
| 200 | pgtable_page_dtor(pte); | 200 | pgtable_page_dtor(pte); |
| 201 | 201 | ||
| 202 | #ifdef CONFIG_ARM_LPAE | ||
| 203 | tlb_add_flush(tlb, addr); | ||
| 204 | #else | ||
| 202 | /* | 205 | /* |
| 203 | * With the classic ARM MMU, a pte page has two corresponding pmd | 206 | * With the classic ARM MMU, a pte page has two corresponding pmd |
| 204 | * entries, each covering 1MB. | 207 | * entries, each covering 1MB. |
| @@ -206,6 +209,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | |||
| 206 | addr &= PMD_MASK; | 209 | addr &= PMD_MASK; |
| 207 | tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); | 210 | tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); |
| 208 | tlb_add_flush(tlb, addr + SZ_1M); | 211 | tlb_add_flush(tlb, addr + SZ_1M); |
| 212 | #endif | ||
| 209 | 213 | ||
| 210 | tlb_remove_page(tlb, pte); | 214 | tlb_remove_page(tlb, pte); |
| 211 | } | 215 | } |
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 479a6352e0b5..77bd79f2ffdb 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h | |||
| @@ -101,28 +101,39 @@ extern int __get_user_1(void *); | |||
| 101 | extern int __get_user_2(void *); | 101 | extern int __get_user_2(void *); |
| 102 | extern int __get_user_4(void *); | 102 | extern int __get_user_4(void *); |
| 103 | 103 | ||
| 104 | #define __get_user_x(__r2,__p,__e,__s,__i...) \ | 104 | #define __GUP_CLOBBER_1 "lr", "cc" |
| 105 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
| 106 | #define __GUP_CLOBBER_2 "ip", "lr", "cc" | ||
| 107 | #else | ||
| 108 | #define __GUP_CLOBBER_2 "lr", "cc" | ||
| 109 | #endif | ||
| 110 | #define __GUP_CLOBBER_4 "lr", "cc" | ||
| 111 | |||
| 112 | #define __get_user_x(__r2,__p,__e,__l,__s) \ | ||
| 105 | __asm__ __volatile__ ( \ | 113 | __asm__ __volatile__ ( \ |
| 106 | __asmeq("%0", "r0") __asmeq("%1", "r2") \ | 114 | __asmeq("%0", "r0") __asmeq("%1", "r2") \ |
| 115 | __asmeq("%3", "r1") \ | ||
| 107 | "bl __get_user_" #__s \ | 116 | "bl __get_user_" #__s \ |
| 108 | : "=&r" (__e), "=r" (__r2) \ | 117 | : "=&r" (__e), "=r" (__r2) \ |
| 109 | : "0" (__p) \ | 118 | : "0" (__p), "r" (__l) \ |
| 110 | : __i, "cc") | 119 | : __GUP_CLOBBER_##__s) |
| 111 | 120 | ||
| 112 | #define get_user(x,p) \ | 121 | #define __get_user_check(x,p) \ |
| 113 | ({ \ | 122 | ({ \ |
| 123 | unsigned long __limit = current_thread_info()->addr_limit - 1; \ | ||
| 114 | register const typeof(*(p)) __user *__p asm("r0") = (p);\ | 124 | register const typeof(*(p)) __user *__p asm("r0") = (p);\ |
| 115 | register unsigned long __r2 asm("r2"); \ | 125 | register unsigned long __r2 asm("r2"); \ |
| 126 | register unsigned long __l asm("r1") = __limit; \ | ||
| 116 | register int __e asm("r0"); \ | 127 | register int __e asm("r0"); \ |
| 117 | switch (sizeof(*(__p))) { \ | 128 | switch (sizeof(*(__p))) { \ |
| 118 | case 1: \ | 129 | case 1: \ |
| 119 | __get_user_x(__r2, __p, __e, 1, "lr"); \ | 130 | __get_user_x(__r2, __p, __e, __l, 1); \ |
| 120 | break; \ | 131 | break; \ |
| 121 | case 2: \ | 132 | case 2: \ |
| 122 | __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ | 133 | __get_user_x(__r2, __p, __e, __l, 2); \ |
| 123 | break; \ | 134 | break; \ |
| 124 | case 4: \ | 135 | case 4: \ |
| 125 | __get_user_x(__r2, __p, __e, 4, "lr"); \ | 136 | __get_user_x(__r2, __p, __e, __l, 4); \ |
| 126 | break; \ | 137 | break; \ |
| 127 | default: __e = __get_user_bad(); break; \ | 138 | default: __e = __get_user_bad(); break; \ |
| 128 | } \ | 139 | } \ |
| @@ -130,42 +141,57 @@ extern int __get_user_4(void *); | |||
| 130 | __e; \ | 141 | __e; \ |
| 131 | }) | 142 | }) |
| 132 | 143 | ||
| 144 | #define get_user(x,p) \ | ||
| 145 | ({ \ | ||
| 146 | might_fault(); \ | ||
| 147 | __get_user_check(x,p); \ | ||
| 148 | }) | ||
| 149 | |||
| 133 | extern int __put_user_1(void *, unsigned int); | 150 | extern int __put_user_1(void *, unsigned int); |
| 134 | extern int __put_user_2(void *, unsigned int); | 151 | extern int __put_user_2(void *, unsigned int); |
| 135 | extern int __put_user_4(void *, unsigned int); | 152 | extern int __put_user_4(void *, unsigned int); |
| 136 | extern int __put_user_8(void *, unsigned long long); | 153 | extern int __put_user_8(void *, unsigned long long); |
| 137 | 154 | ||
| 138 | #define __put_user_x(__r2,__p,__e,__s) \ | 155 | #define __put_user_x(__r2,__p,__e,__l,__s) \ |
| 139 | __asm__ __volatile__ ( \ | 156 | __asm__ __volatile__ ( \ |
| 140 | __asmeq("%0", "r0") __asmeq("%2", "r2") \ | 157 | __asmeq("%0", "r0") __asmeq("%2", "r2") \ |
| 158 | __asmeq("%3", "r1") \ | ||
| 141 | "bl __put_user_" #__s \ | 159 | "bl __put_user_" #__s \ |
| 142 | : "=&r" (__e) \ | 160 | : "=&r" (__e) \ |
| 143 | : "0" (__p), "r" (__r2) \ | 161 | : "0" (__p), "r" (__r2), "r" (__l) \ |
| 144 | : "ip", "lr", "cc") | 162 | : "ip", "lr", "cc") |
| 145 | 163 | ||
| 146 | #define put_user(x,p) \ | 164 | #define __put_user_check(x,p) \ |
| 147 | ({ \ | 165 | ({ \ |
| 166 | unsigned long __limit = current_thread_info()->addr_limit - 1; \ | ||
| 148 | register const typeof(*(p)) __r2 asm("r2") = (x); \ | 167 | register const typeof(*(p)) __r2 asm("r2") = (x); \ |
| 149 | register const typeof(*(p)) __user *__p asm("r0") = (p);\ | 168 | register const typeof(*(p)) __user *__p asm("r0") = (p);\ |
| 169 | register unsigned long __l asm("r1") = __limit; \ | ||
| 150 | register int __e asm("r0"); \ | 170 | register int __e asm("r0"); \ |
| 151 | switch (sizeof(*(__p))) { \ | 171 | switch (sizeof(*(__p))) { \ |
| 152 | case 1: \ | 172 | case 1: \ |
| 153 | __put_user_x(__r2, __p, __e, 1); \ | 173 | __put_user_x(__r2, __p, __e, __l, 1); \ |
| 154 | break; \ | 174 | break; \ |
| 155 | case 2: \ | 175 | case 2: \ |
| 156 | __put_user_x(__r2, __p, __e, 2); \ | 176 | __put_user_x(__r2, __p, __e, __l, 2); \ |
| 157 | break; \ | 177 | break; \ |
| 158 | case 4: \ | 178 | case 4: \ |
| 159 | __put_user_x(__r2, __p, __e, 4); \ | 179 | __put_user_x(__r2, __p, __e, __l, 4); \ |
| 160 | break; \ | 180 | break; \ |
| 161 | case 8: \ | 181 | case 8: \ |
| 162 | __put_user_x(__r2, __p, __e, 8); \ | 182 | __put_user_x(__r2, __p, __e, __l, 8); \ |
| 163 | break; \ | 183 | break; \ |
| 164 | default: __e = __put_user_bad(); break; \ | 184 | default: __e = __put_user_bad(); break; \ |
| 165 | } \ | 185 | } \ |
| 166 | __e; \ | 186 | __e; \ |
| 167 | }) | 187 | }) |
| 168 | 188 | ||
| 189 | #define put_user(x,p) \ | ||
| 190 | ({ \ | ||
| 191 | might_fault(); \ | ||
| 192 | __put_user_check(x,p); \ | ||
| 193 | }) | ||
| 194 | |||
| 169 | #else /* CONFIG_MMU */ | 195 | #else /* CONFIG_MMU */ |
| 170 | 196 | ||
| 171 | /* | 197 | /* |
| @@ -219,6 +245,7 @@ do { \ | |||
| 219 | unsigned long __gu_addr = (unsigned long)(ptr); \ | 245 | unsigned long __gu_addr = (unsigned long)(ptr); \ |
| 220 | unsigned long __gu_val; \ | 246 | unsigned long __gu_val; \ |
| 221 | __chk_user_ptr(ptr); \ | 247 | __chk_user_ptr(ptr); \ |
| 248 | might_fault(); \ | ||
| 222 | switch (sizeof(*(ptr))) { \ | 249 | switch (sizeof(*(ptr))) { \ |
| 223 | case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ | 250 | case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ |
| 224 | case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ | 251 | case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ |
| @@ -300,6 +327,7 @@ do { \ | |||
| 300 | unsigned long __pu_addr = (unsigned long)(ptr); \ | 327 | unsigned long __pu_addr = (unsigned long)(ptr); \ |
| 301 | __typeof__(*(ptr)) __pu_val = (x); \ | 328 | __typeof__(*(ptr)) __pu_val = (x); \ |
| 302 | __chk_user_ptr(ptr); \ | 329 | __chk_user_ptr(ptr); \ |
| 330 | might_fault(); \ | ||
| 303 | switch (sizeof(*(ptr))) { \ | 331 | switch (sizeof(*(ptr))) { \ |
| 304 | case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ | 332 | case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ |
| 305 | case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ | 333 | case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ |
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index ba386bd94107..281bf3301241 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c | |||
| @@ -159,6 +159,12 @@ static int debug_arch_supported(void) | |||
| 159 | arch >= ARM_DEBUG_ARCH_V7_1; | 159 | arch >= ARM_DEBUG_ARCH_V7_1; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | /* Can we determine the watchpoint access type from the fsr? */ | ||
| 163 | static int debug_exception_updates_fsr(void) | ||
| 164 | { | ||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 162 | /* Determine number of WRP registers available. */ | 168 | /* Determine number of WRP registers available. */ |
| 163 | static int get_num_wrp_resources(void) | 169 | static int get_num_wrp_resources(void) |
| 164 | { | 170 | { |
| @@ -604,13 +610,14 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) | |||
| 604 | /* Aligned */ | 610 | /* Aligned */ |
| 605 | break; | 611 | break; |
| 606 | case 1: | 612 | case 1: |
| 607 | /* Allow single byte watchpoint. */ | ||
| 608 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) | ||
| 609 | break; | ||
| 610 | case 2: | 613 | case 2: |
| 611 | /* Allow halfword watchpoints and breakpoints. */ | 614 | /* Allow halfword watchpoints and breakpoints. */ |
| 612 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) | 615 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) |
| 613 | break; | 616 | break; |
| 617 | case 3: | ||
| 618 | /* Allow single byte watchpoint. */ | ||
| 619 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) | ||
| 620 | break; | ||
| 614 | default: | 621 | default: |
| 615 | ret = -EINVAL; | 622 | ret = -EINVAL; |
| 616 | goto out; | 623 | goto out; |
| @@ -619,18 +626,35 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) | |||
| 619 | info->address &= ~alignment_mask; | 626 | info->address &= ~alignment_mask; |
| 620 | info->ctrl.len <<= offset; | 627 | info->ctrl.len <<= offset; |
| 621 | 628 | ||
| 622 | /* | 629 | if (!bp->overflow_handler) { |
| 623 | * Currently we rely on an overflow handler to take | 630 | /* |
| 624 | * care of single-stepping the breakpoint when it fires. | 631 | * Mismatch breakpoints are required for single-stepping |
| 625 | * In the case of userspace breakpoints on a core with V7 debug, | 632 | * breakpoints. |
| 626 | * we can use the mismatch feature as a poor-man's hardware | 633 | */ |
| 627 | * single-step, but this only works for per-task breakpoints. | 634 | if (!core_has_mismatch_brps()) |
| 628 | */ | 635 | return -EINVAL; |
| 629 | if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || | 636 | |
| 630 | !core_has_mismatch_brps() || !bp->hw.bp_target)) { | 637 | /* We don't allow mismatch breakpoints in kernel space. */ |
| 631 | pr_warning("overflow handler required but none found\n"); | 638 | if (arch_check_bp_in_kernelspace(bp)) |
| 632 | ret = -EINVAL; | 639 | return -EPERM; |
| 640 | |||
| 641 | /* | ||
| 642 | * Per-cpu breakpoints are not supported by our stepping | ||
| 643 | * mechanism. | ||
| 644 | */ | ||
| 645 | if (!bp->hw.bp_target) | ||
| 646 | return -EINVAL; | ||
| 647 | |||
| 648 | /* | ||
| 649 | * We only support specific access types if the fsr | ||
| 650 | * reports them. | ||
| 651 | */ | ||
| 652 | if (!debug_exception_updates_fsr() && | ||
| 653 | (info->ctrl.type == ARM_BREAKPOINT_LOAD || | ||
| 654 | info->ctrl.type == ARM_BREAKPOINT_STORE)) | ||
| 655 | return -EINVAL; | ||
| 633 | } | 656 | } |
| 657 | |||
| 634 | out: | 658 | out: |
| 635 | return ret; | 659 | return ret; |
| 636 | } | 660 | } |
| @@ -706,10 +730,12 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, | |||
| 706 | goto unlock; | 730 | goto unlock; |
| 707 | 731 | ||
| 708 | /* Check that the access type matches. */ | 732 | /* Check that the access type matches. */ |
| 709 | access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : | 733 | if (debug_exception_updates_fsr()) { |
| 710 | HW_BREAKPOINT_R; | 734 | access = (fsr & ARM_FSR_ACCESS_MASK) ? |
| 711 | if (!(access & hw_breakpoint_type(wp))) | 735 | HW_BREAKPOINT_W : HW_BREAKPOINT_R; |
| 712 | goto unlock; | 736 | if (!(access & hw_breakpoint_type(wp))) |
| 737 | goto unlock; | ||
| 738 | } | ||
| 713 | 739 | ||
| 714 | /* We have a winner. */ | 740 | /* We have a winner. */ |
| 715 | info->trigger = addr; | 741 | info->trigger = addr; |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index f7945218b8c6..b0179b89a04c 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
| @@ -420,20 +420,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
| 420 | #endif | 420 | #endif |
| 421 | instr = *(u32 *) pc; | 421 | instr = *(u32 *) pc; |
| 422 | } else if (thumb_mode(regs)) { | 422 | } else if (thumb_mode(regs)) { |
| 423 | get_user(instr, (u16 __user *)pc); | 423 | if (get_user(instr, (u16 __user *)pc)) |
| 424 | goto die_sig; | ||
| 424 | if (is_wide_instruction(instr)) { | 425 | if (is_wide_instruction(instr)) { |
| 425 | unsigned int instr2; | 426 | unsigned int instr2; |
| 426 | get_user(instr2, (u16 __user *)pc+1); | 427 | if (get_user(instr2, (u16 __user *)pc+1)) |
| 428 | goto die_sig; | ||
| 427 | instr <<= 16; | 429 | instr <<= 16; |
| 428 | instr |= instr2; | 430 | instr |= instr2; |
| 429 | } | 431 | } |
| 430 | } else { | 432 | } else if (get_user(instr, (u32 __user *)pc)) { |
| 431 | get_user(instr, (u32 __user *)pc); | 433 | goto die_sig; |
| 432 | } | 434 | } |
| 433 | 435 | ||
| 434 | if (call_undef_hook(regs, instr) == 0) | 436 | if (call_undef_hook(regs, instr) == 0) |
| 435 | return; | 437 | return; |
| 436 | 438 | ||
| 439 | die_sig: | ||
| 437 | #ifdef CONFIG_DEBUG_USER | 440 | #ifdef CONFIG_DEBUG_USER |
| 438 | if (user_debug & UDBG_UNDEFINED) { | 441 | if (user_debug & UDBG_UNDEFINED) { |
| 439 | printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", | 442 | printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", |
diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index d6dacc69254e..395d5fbb8fa2 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c | |||
| @@ -59,6 +59,7 @@ void __init init_current_timer_delay(unsigned long freq) | |||
| 59 | { | 59 | { |
| 60 | pr_info("Switching to timer-based delay loop\n"); | 60 | pr_info("Switching to timer-based delay loop\n"); |
| 61 | lpj_fine = freq / HZ; | 61 | lpj_fine = freq / HZ; |
| 62 | loops_per_jiffy = lpj_fine; | ||
| 62 | arm_delay_ops.delay = __timer_delay; | 63 | arm_delay_ops.delay = __timer_delay; |
| 63 | arm_delay_ops.const_udelay = __timer_const_udelay; | 64 | arm_delay_ops.const_udelay = __timer_const_udelay; |
| 64 | arm_delay_ops.udelay = __timer_udelay; | 65 | arm_delay_ops.udelay = __timer_udelay; |
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 11093a7c3e32..9b06bb41fca6 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S | |||
| @@ -16,8 +16,9 @@ | |||
| 16 | * __get_user_X | 16 | * __get_user_X |
| 17 | * | 17 | * |
| 18 | * Inputs: r0 contains the address | 18 | * Inputs: r0 contains the address |
| 19 | * r1 contains the address limit, which must be preserved | ||
| 19 | * Outputs: r0 is the error code | 20 | * Outputs: r0 is the error code |
| 20 | * r2, r3 contains the zero-extended value | 21 | * r2 contains the zero-extended value |
| 21 | * lr corrupted | 22 | * lr corrupted |
| 22 | * | 23 | * |
| 23 | * No other registers must be altered. (see <asm/uaccess.h> | 24 | * No other registers must be altered. (see <asm/uaccess.h> |
| @@ -27,33 +28,39 @@ | |||
| 27 | * Note also that it is intended that __get_user_bad is not global. | 28 | * Note also that it is intended that __get_user_bad is not global. |
| 28 | */ | 29 | */ |
| 29 | #include <linux/linkage.h> | 30 | #include <linux/linkage.h> |
| 31 | #include <asm/assembler.h> | ||
| 30 | #include <asm/errno.h> | 32 | #include <asm/errno.h> |
| 31 | #include <asm/domain.h> | 33 | #include <asm/domain.h> |
| 32 | 34 | ||
| 33 | ENTRY(__get_user_1) | 35 | ENTRY(__get_user_1) |
| 36 | check_uaccess r0, 1, r1, r2, __get_user_bad | ||
| 34 | 1: TUSER(ldrb) r2, [r0] | 37 | 1: TUSER(ldrb) r2, [r0] |
| 35 | mov r0, #0 | 38 | mov r0, #0 |
| 36 | mov pc, lr | 39 | mov pc, lr |
| 37 | ENDPROC(__get_user_1) | 40 | ENDPROC(__get_user_1) |
| 38 | 41 | ||
| 39 | ENTRY(__get_user_2) | 42 | ENTRY(__get_user_2) |
| 40 | #ifdef CONFIG_THUMB2_KERNEL | 43 | check_uaccess r0, 2, r1, r2, __get_user_bad |
| 41 | 2: TUSER(ldrb) r2, [r0] | 44 | #ifdef CONFIG_CPU_USE_DOMAINS |
| 42 | 3: TUSER(ldrb) r3, [r0, #1] | 45 | rb .req ip |
| 46 | 2: ldrbt r2, [r0], #1 | ||
| 47 | 3: ldrbt rb, [r0], #0 | ||
| 43 | #else | 48 | #else |
| 44 | 2: TUSER(ldrb) r2, [r0], #1 | 49 | rb .req r0 |
| 45 | 3: TUSER(ldrb) r3, [r0] | 50 | 2: ldrb r2, [r0] |
| 51 | 3: ldrb rb, [r0, #1] | ||
| 46 | #endif | 52 | #endif |
| 47 | #ifndef __ARMEB__ | 53 | #ifndef __ARMEB__ |
| 48 | orr r2, r2, r3, lsl #8 | 54 | orr r2, r2, rb, lsl #8 |
| 49 | #else | 55 | #else |
| 50 | orr r2, r3, r2, lsl #8 | 56 | orr r2, rb, r2, lsl #8 |
| 51 | #endif | 57 | #endif |
| 52 | mov r0, #0 | 58 | mov r0, #0 |
| 53 | mov pc, lr | 59 | mov pc, lr |
| 54 | ENDPROC(__get_user_2) | 60 | ENDPROC(__get_user_2) |
| 55 | 61 | ||
| 56 | ENTRY(__get_user_4) | 62 | ENTRY(__get_user_4) |
| 63 | check_uaccess r0, 4, r1, r2, __get_user_bad | ||
| 57 | 4: TUSER(ldr) r2, [r0] | 64 | 4: TUSER(ldr) r2, [r0] |
| 58 | mov r0, #0 | 65 | mov r0, #0 |
| 59 | mov pc, lr | 66 | mov pc, lr |
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 7db25990c589..3d73dcb959b0 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | * __put_user_X | 16 | * __put_user_X |
| 17 | * | 17 | * |
| 18 | * Inputs: r0 contains the address | 18 | * Inputs: r0 contains the address |
| 19 | * r1 contains the address limit, which must be preserved | ||
| 19 | * r2, r3 contains the value | 20 | * r2, r3 contains the value |
| 20 | * Outputs: r0 is the error code | 21 | * Outputs: r0 is the error code |
| 21 | * lr corrupted | 22 | * lr corrupted |
| @@ -27,16 +28,19 @@ | |||
| 27 | * Note also that it is intended that __put_user_bad is not global. | 28 | * Note also that it is intended that __put_user_bad is not global. |
| 28 | */ | 29 | */ |
| 29 | #include <linux/linkage.h> | 30 | #include <linux/linkage.h> |
| 31 | #include <asm/assembler.h> | ||
| 30 | #include <asm/errno.h> | 32 | #include <asm/errno.h> |
| 31 | #include <asm/domain.h> | 33 | #include <asm/domain.h> |
| 32 | 34 | ||
| 33 | ENTRY(__put_user_1) | 35 | ENTRY(__put_user_1) |
| 36 | check_uaccess r0, 1, r1, ip, __put_user_bad | ||
| 34 | 1: TUSER(strb) r2, [r0] | 37 | 1: TUSER(strb) r2, [r0] |
| 35 | mov r0, #0 | 38 | mov r0, #0 |
| 36 | mov pc, lr | 39 | mov pc, lr |
| 37 | ENDPROC(__put_user_1) | 40 | ENDPROC(__put_user_1) |
| 38 | 41 | ||
| 39 | ENTRY(__put_user_2) | 42 | ENTRY(__put_user_2) |
| 43 | check_uaccess r0, 2, r1, ip, __put_user_bad | ||
| 40 | mov ip, r2, lsr #8 | 44 | mov ip, r2, lsr #8 |
| 41 | #ifdef CONFIG_THUMB2_KERNEL | 45 | #ifdef CONFIG_THUMB2_KERNEL |
| 42 | #ifndef __ARMEB__ | 46 | #ifndef __ARMEB__ |
| @@ -60,12 +64,14 @@ ENTRY(__put_user_2) | |||
| 60 | ENDPROC(__put_user_2) | 64 | ENDPROC(__put_user_2) |
| 61 | 65 | ||
| 62 | ENTRY(__put_user_4) | 66 | ENTRY(__put_user_4) |
| 67 | check_uaccess r0, 4, r1, ip, __put_user_bad | ||
| 63 | 4: TUSER(str) r2, [r0] | 68 | 4: TUSER(str) r2, [r0] |
| 64 | mov r0, #0 | 69 | mov r0, #0 |
| 65 | mov pc, lr | 70 | mov pc, lr |
| 66 | ENDPROC(__put_user_4) | 71 | ENDPROC(__put_user_4) |
| 67 | 72 | ||
| 68 | ENTRY(__put_user_8) | 73 | ENTRY(__put_user_8) |
| 74 | check_uaccess r0, 8, r1, ip, __put_user_bad | ||
| 69 | #ifdef CONFIG_THUMB2_KERNEL | 75 | #ifdef CONFIG_THUMB2_KERNEL |
| 70 | 5: TUSER(str) r2, [r0] | 76 | 5: TUSER(str) r2, [r0] |
| 71 | 6: TUSER(str) r3, [r0, #4] | 77 | 6: TUSER(str) r3, [r0, #4] |
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c index 119bc52ab93e..4e07eec1270d 100644 --- a/arch/arm/mm/context.c +++ b/arch/arm/mm/context.c | |||
| @@ -63,10 +63,11 @@ static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd, | |||
| 63 | pid = task_pid_nr(thread->task) << ASID_BITS; | 63 | pid = task_pid_nr(thread->task) << ASID_BITS; |
| 64 | asm volatile( | 64 | asm volatile( |
| 65 | " mrc p15, 0, %0, c13, c0, 1\n" | 65 | " mrc p15, 0, %0, c13, c0, 1\n" |
| 66 | " bfi %1, %0, #0, %2\n" | 66 | " and %0, %0, %2\n" |
| 67 | " mcr p15, 0, %1, c13, c0, 1\n" | 67 | " orr %0, %0, %1\n" |
| 68 | " mcr p15, 0, %0, c13, c0, 1\n" | ||
| 68 | : "=r" (contextidr), "+r" (pid) | 69 | : "=r" (contextidr), "+r" (pid) |
| 69 | : "I" (ASID_BITS)); | 70 | : "I" (~ASID_MASK)); |
| 70 | isb(); | 71 | isb(); |
| 71 | 72 | ||
| 72 | return NOTIFY_OK; | 73 | return NOTIFY_OK; |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 6776160618ef..a8ee92da3544 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
| @@ -55,6 +55,9 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page | |||
| 55 | /* permanent static mappings from iotable_init() */ | 55 | /* permanent static mappings from iotable_init() */ |
| 56 | #define VM_ARM_STATIC_MAPPING 0x40000000 | 56 | #define VM_ARM_STATIC_MAPPING 0x40000000 |
| 57 | 57 | ||
| 58 | /* empty mapping */ | ||
| 59 | #define VM_ARM_EMPTY_MAPPING 0x20000000 | ||
| 60 | |||
| 58 | /* mapping type (attributes) for permanent static mappings */ | 61 | /* mapping type (attributes) for permanent static mappings */ |
| 59 | #define VM_ARM_MTYPE(mt) ((mt) << 20) | 62 | #define VM_ARM_MTYPE(mt) ((mt) << 20) |
| 60 | #define VM_ARM_MTYPE_MASK (0x1f << 20) | 63 | #define VM_ARM_MTYPE_MASK (0x1f << 20) |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4c2d0451e84a..c2fa21d0103e 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
| @@ -807,7 +807,7 @@ static void __init pmd_empty_section_gap(unsigned long addr) | |||
| 807 | vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); | 807 | vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); |
| 808 | vm->addr = (void *)addr; | 808 | vm->addr = (void *)addr; |
| 809 | vm->size = SECTION_SIZE; | 809 | vm->size = SECTION_SIZE; |
| 810 | vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; | 810 | vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING; |
| 811 | vm->caller = pmd_empty_section_gap; | 811 | vm->caller = pmd_empty_section_gap; |
| 812 | vm_area_add_early(vm); | 812 | vm_area_add_early(vm); |
| 813 | } | 813 | } |
| @@ -820,7 +820,7 @@ static void __init fill_pmd_gaps(void) | |||
| 820 | 820 | ||
| 821 | /* we're still single threaded hence no lock needed here */ | 821 | /* we're still single threaded hence no lock needed here */ |
| 822 | for (vm = vmlist; vm; vm = vm->next) { | 822 | for (vm = vmlist; vm; vm = vm->next) { |
| 823 | if (!(vm->flags & VM_ARM_STATIC_MAPPING)) | 823 | if (!(vm->flags & (VM_ARM_STATIC_MAPPING | VM_ARM_EMPTY_MAPPING))) |
| 824 | continue; | 824 | continue; |
| 825 | addr = (unsigned long)vm->addr; | 825 | addr = (unsigned long)vm->addr; |
| 826 | if (addr < next) | 826 | if (addr < next) |
| @@ -961,8 +961,8 @@ void __init sanity_check_meminfo(void) | |||
| 961 | * Check whether this memory bank would partially overlap | 961 | * Check whether this memory bank would partially overlap |
| 962 | * the vmalloc area. | 962 | * the vmalloc area. |
| 963 | */ | 963 | */ |
| 964 | if (__va(bank->start + bank->size) > vmalloc_min || | 964 | if (__va(bank->start + bank->size - 1) >= vmalloc_min || |
| 965 | __va(bank->start + bank->size) < __va(bank->start)) { | 965 | __va(bank->start + bank->size - 1) <= __va(bank->start)) { |
| 966 | unsigned long newsize = vmalloc_min - __va(bank->start); | 966 | unsigned long newsize = vmalloc_min - __va(bank->start); |
| 967 | printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " | 967 | printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx " |
| 968 | "to -%.8llx (vmalloc region overlap).\n", | 968 | "to -%.8llx (vmalloc region overlap).\n", |
