Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm

Pull ARM fixes from Russell King:
"I've thought long and hard about what to say for this pull request,
and I really can't work out anything sane to say to summarise much of
these commits. The problem is, for most of these are, yet again, lots
of small bits scattered around the place without any real overall
theme to them"

Most notable is probably the kuser page helper improvements.

* 'fixes' of git://git.linaro.org/people/rmk/linux-arm: (22 commits)
ARM: Add .text annotations where required after __CPUINIT removal
ARM: 7803/1: Fix deadlock scenario with smp_send_stop()
ARM: make vectors page inaccessible from userspace
ARM: move signal handlers into a vdso-like page
ARM: allow kuser helpers to be removed from the vector page
ARM: update FIQ support for relocation of vectors
ARM: use linker magic for vectors and vector stubs
ARM: move vector stubs
ARM: poison memory between kuser helpers
ARM: poison the vectors page
ARM: 7801/1: v6: prevent gcc 4.5 from reordering extended CP15 reads above is_smp() test
ARM: 7800/1: ARMv7-M: Fix name of NVIC handler function
ARM: Fix sorting of machine- initializers
ARM: 7791/1: a.out: remove partial a.out support
ARM: 7790/1: Fix deferred mm switch on VIVT processors
ARM: 7789/1: Do not run dummy_flush_tlb_a15_erratum() on non-Cortex-A15
ARM: 7787/1: virt: ensure visibility of __boot_cpu_mode
ARM: 7788/1: elf: fix lpae hwcap feature reporting in proc/cpuinfo
ARM: 7786/1: hyp: fix macro parameterisation
ARM: 7785/1: mm: restrict early_alloc to section-aligned memory
...

+386 -235
+2 -2
arch/arm/Kconfig
··· 20 20 select GENERIC_STRNCPY_FROM_USER 21 21 select GENERIC_STRNLEN_USER 22 22 select HARDIRQS_SW_RESEND 23 - select HAVE_AOUT 24 23 select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL 25 24 select HAVE_ARCH_KGDB 26 25 select HAVE_ARCH_SECCOMP_FILTER ··· 217 218 default DRAM_BASE if REMAP_VECTORS_TO_RAM 218 219 default 0x00000000 219 220 help 220 - The base address of exception vectors. 221 + The base address of exception vectors. This must be two pages 222 + in size. 221 223 222 224 config ARM_PATCH_PHYS_VIRT 223 225 bool "Patch physical to virtual translations at runtime" if EMBEDDED
+12 -2
arch/arm/Kconfig.debug
··· 804 804 805 805 config DEBUG_UNCOMPRESS 806 806 bool 807 - default y if ARCH_MULTIPLATFORM && DEBUG_LL && \ 808 - !DEBUG_OMAP2PLUS_UART && \ 807 + depends on ARCH_MULTIPLATFORM 808 + default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \ 809 809 !DEBUG_TEGRA_UART 810 + help 811 + This option influences the normal decompressor output for 812 + multiplatform kernels. Normally, multiplatform kernels disable 813 + decompressor output because it is not possible to know where to 814 + send the decompressor output. 815 + 816 + When this option is set, the selected DEBUG_LL output method 817 + will be re-used for normal decompressor output on multiplatform 818 + kernels. 819 + 810 820 811 821 config UNCOMPRESS_INCLUDE 812 822 string
+10 -10
arch/arm/Makefile
··· 153 153 machine-$(CONFIG_ARCH_DOVE) += dove 154 154 machine-$(CONFIG_ARCH_EBSA110) += ebsa110 155 155 machine-$(CONFIG_ARCH_EP93XX) += ep93xx 156 + machine-$(CONFIG_ARCH_EXYNOS) += exynos 156 157 machine-$(CONFIG_ARCH_GEMINI) += gemini 157 158 machine-$(CONFIG_ARCH_HIGHBANK) += highbank 158 159 machine-$(CONFIG_ARCH_INTEGRATOR) += integrator ··· 161 160 machine-$(CONFIG_ARCH_IOP32X) += iop32x 162 161 machine-$(CONFIG_ARCH_IOP33X) += iop33x 163 162 machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx 163 + machine-$(CONFIG_ARCH_KEYSTONE) += keystone 164 164 machine-$(CONFIG_ARCH_KIRKWOOD) += kirkwood 165 165 machine-$(CONFIG_ARCH_KS8695) += ks8695 166 166 machine-$(CONFIG_ARCH_LPC32XX) += lpc32xx 167 167 machine-$(CONFIG_ARCH_MMP) += mmp 168 168 machine-$(CONFIG_ARCH_MSM) += msm 169 169 machine-$(CONFIG_ARCH_MV78XX0) += mv78xx0 170 + machine-$(CONFIG_ARCH_MVEBU) += mvebu 170 171 machine-$(CONFIG_ARCH_MXC) += imx 171 172 machine-$(CONFIG_ARCH_MXS) += mxs 172 - machine-$(CONFIG_ARCH_MVEBU) += mvebu 173 173 machine-$(CONFIG_ARCH_NETX) += netx 174 174 machine-$(CONFIG_ARCH_NOMADIK) += nomadik 175 175 machine-$(CONFIG_ARCH_NSPIRE) += nspire ··· 178 176 machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 179 177 machine-$(CONFIG_ARCH_ORION5X) += orion5x 180 178 machine-$(CONFIG_ARCH_PICOXCELL) += picoxcell 181 - machine-$(CONFIG_ARCH_SIRF) += prima2 182 179 machine-$(CONFIG_ARCH_PXA) += pxa 183 180 machine-$(CONFIG_ARCH_REALVIEW) += realview 184 181 machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip ··· 187 186 machine-$(CONFIG_ARCH_S5P64X0) += s5p64x0 188 187 machine-$(CONFIG_ARCH_S5PC100) += s5pc100 189 188 machine-$(CONFIG_ARCH_S5PV210) += s5pv210 190 - machine-$(CONFIG_ARCH_EXYNOS) += exynos 191 189 machine-$(CONFIG_ARCH_SA1100) += sa1100 192 190 machine-$(CONFIG_ARCH_SHARK) += shark 193 191 machine-$(CONFIG_ARCH_SHMOBILE) += shmobile 192 + machine-$(CONFIG_ARCH_SIRF) += prima2 193 + machine-$(CONFIG_ARCH_SOCFPGA) += socfpga 194 + machine-$(CONFIG_ARCH_STI) += sti 195 + machine-$(CONFIG_ARCH_SUNXI) += sunxi 194 196 machine-$(CONFIG_ARCH_TEGRA) += tegra 195 197 machine-$(CONFIG_ARCH_U300) += u300 196 198 machine-$(CONFIG_ARCH_U8500) += ux500 197 199 machine-$(CONFIG_ARCH_VERSATILE) += versatile 198 200 machine-$(CONFIG_ARCH_VEXPRESS) += vexpress 201 + machine-$(CONFIG_ARCH_VIRT) += virt 199 202 machine-$(CONFIG_ARCH_VT8500) += vt8500 200 203 machine-$(CONFIG_ARCH_W90X900) += w90x900 201 - machine-$(CONFIG_FOOTBRIDGE) += footbridge 202 - machine-$(CONFIG_ARCH_SOCFPGA) += socfpga 203 - machine-$(CONFIG_PLAT_SPEAR) += spear 204 - machine-$(CONFIG_ARCH_STI) += sti 205 - machine-$(CONFIG_ARCH_VIRT) += virt 206 204 machine-$(CONFIG_ARCH_ZYNQ) += zynq 207 - machine-$(CONFIG_ARCH_SUNXI) += sunxi 208 - machine-$(CONFIG_ARCH_KEYSTONE) += keystone 205 + machine-$(CONFIG_FOOTBRIDGE) += footbridge 206 + machine-$(CONFIG_PLAT_SPEAR) += spear 209 207 210 208 # Platform directory name. This list is sorted alphanumerically 211 209 # by CONFIG_* macro name.
-45
arch/arm/include/asm/a.out-core.h
··· 1 - /* a.out coredump register dumper 2 - * 3 - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 4 - * Written by David Howells (dhowells@redhat.com) 5 - * 6 - * This program is free software; you can redistribute it and/or 7 - * modify it under the terms of the GNU General Public Licence 8 - * as published by the Free Software Foundation; either version 9 - * 2 of the Licence, or (at your option) any later version. 10 - */ 11 - 12 - #ifndef _ASM_A_OUT_CORE_H 13 - #define _ASM_A_OUT_CORE_H 14 - 15 - #ifdef __KERNEL__ 16 - 17 - #include <linux/user.h> 18 - #include <linux/elfcore.h> 19 - 20 - /* 21 - * fill in the user structure for an a.out core dump 22 - */ 23 - static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) 24 - { 25 - struct task_struct *tsk = current; 26 - 27 - dump->magic = CMAGIC; 28 - dump->start_code = tsk->mm->start_code; 29 - dump->start_stack = regs->ARM_sp & ~(PAGE_SIZE - 1); 30 - 31 - dump->u_tsize = (tsk->mm->end_code - tsk->mm->start_code) >> PAGE_SHIFT; 32 - dump->u_dsize = (tsk->mm->brk - tsk->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT; 33 - dump->u_ssize = 0; 34 - 35 - memset(dump->u_debugreg, 0, sizeof(dump->u_debugreg)); 36 - 37 - if (dump->start_stack < 0x04000000) 38 - dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT; 39 - 40 - dump->regs = *regs; 41 - dump->u_fpvalid = dump_fpu (regs, &dump->u_fp); 42 - } 43 - 44 - #endif /* __KERNEL__ */ 45 - #endif /* _ASM_A_OUT_CORE_H */
+6 -1
arch/arm/include/asm/cputype.h
··· 89 89 __val; \ 90 90 }) 91 91 92 + /* 93 + * The memory clobber prevents gcc 4.5 from reordering the mrc before 94 + * any is_smp() tests, which can cause undefined instruction aborts on 95 + * ARM1136 r0 due to the missing extended CP15 registers. 96 + */ 92 97 #define read_cpuid_ext(ext_reg) \ 93 98 ({ \ 94 99 unsigned int __val; \ 95 100 asm("mrc p15, 0, %0, c0, " ext_reg \ 96 101 : "=r" (__val) \ 97 102 : \ 98 - : "cc"); \ 103 + : "memory"); \ 99 104 __val; \ 100 105 }) 101 106
+4
arch/arm/include/asm/elf.h
··· 130 130 extern unsigned long arch_randomize_brk(struct mm_struct *mm); 131 131 #define arch_randomize_brk arch_randomize_brk 132 132 133 + #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 134 + struct linux_binprm; 135 + int arch_setup_additional_pages(struct linux_binprm *, int); 136 + 133 137 #endif
+3
arch/arm/include/asm/mmu.h
··· 6 6 typedef struct { 7 7 #ifdef CONFIG_CPU_HAS_ASID 8 8 atomic64_t id; 9 + #else 10 + int switch_pending; 9 11 #endif 10 12 unsigned int vmalloc_seq; 13 + unsigned long sigpage; 11 14 } mm_context_t; 12 15 13 16 #ifdef CONFIG_CPU_HAS_ASID
+16 -4
arch/arm/include/asm/mmu_context.h
··· 56 56 * on non-ASID CPUs, the old mm will remain valid until the 57 57 * finish_arch_post_lock_switch() call. 58 58 */ 59 - set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM); 59 + mm->context.switch_pending = 1; 60 60 else 61 61 cpu_switch_mm(mm->pgd, mm); 62 62 } ··· 65 65 finish_arch_post_lock_switch 66 66 static inline void finish_arch_post_lock_switch(void) 67 67 { 68 - if (test_and_clear_thread_flag(TIF_SWITCH_MM)) { 69 - struct mm_struct *mm = current->mm; 70 - cpu_switch_mm(mm->pgd, mm); 68 + struct mm_struct *mm = current->mm; 69 + 70 + if (mm && mm->context.switch_pending) { 71 + /* 72 + * Preemption must be disabled during cpu_switch_mm() as we 73 + * have some stateful cache flush implementations. Check 74 + * switch_pending again in case we were preempted and the 75 + * switch to this mm was already done. 76 + */ 77 + preempt_disable(); 78 + if (mm->context.switch_pending) { 79 + mm->context.switch_pending = 0; 80 + cpu_switch_mm(mm->pgd, mm); 81 + } 82 + preempt_enable_no_resched(); 71 83 } 72 84 } 73 85
+2
arch/arm/include/asm/page.h
··· 142 142 #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) 143 143 extern void copy_page(void *to, const void *from); 144 144 145 + #ifdef CONFIG_KUSER_HELPERS 145 146 #define __HAVE_ARCH_GATE_AREA 1 147 + #endif 146 148 147 149 #ifdef CONFIG_ARM_LPAE 148 150 #include <asm/pgtable-3level-types.h>
-4
arch/arm/include/asm/processor.h
··· 54 54 55 55 #define start_thread(regs,pc,sp) \ 56 56 ({ \ 57 - unsigned long *stack = (unsigned long *)sp; \ 58 57 memset(regs->uregs, 0, sizeof(regs->uregs)); \ 59 58 if (current->personality & ADDR_LIMIT_32BIT) \ 60 59 regs->ARM_cpsr = USR_MODE; \ ··· 64 65 regs->ARM_cpsr |= PSR_ENDSTATE; \ 65 66 regs->ARM_pc = pc & ~1; /* pc */ \ 66 67 regs->ARM_sp = sp; /* sp */ \ 67 - regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ 68 - regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ 69 - regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ 70 68 nommu_start_thread(regs); \ 71 69 }) 72 70
-1
arch/arm/include/asm/thread_info.h
··· 156 156 #define TIF_USING_IWMMXT 17 157 157 #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ 158 158 #define TIF_RESTORE_SIGMASK 20 159 - #define TIF_SWITCH_MM 22 /* deferred switch_mm */ 160 159 161 160 #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) 162 161 #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+16
arch/arm/include/asm/tlbflush.h
··· 443 443 isb(); 444 444 } 445 445 446 + #include <asm/cputype.h> 446 447 #ifdef CONFIG_ARM_ERRATA_798181 448 + static inline int erratum_a15_798181(void) 449 + { 450 + unsigned int midr = read_cpuid_id(); 451 + 452 + /* Cortex-A15 r0p0..r3p2 affected */ 453 + if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2) 454 + return 0; 455 + return 1; 456 + } 457 + 447 458 static inline void dummy_flush_tlb_a15_erratum(void) 448 459 { 449 460 /* ··· 464 453 dsb(); 465 454 } 466 455 #else 456 + static inline int erratum_a15_798181(void) 457 + { 458 + return 0; 459 + } 460 + 467 461 static inline void dummy_flush_tlb_a15_erratum(void) 468 462 { 469 463 }
+12
arch/arm/include/asm/virt.h
··· 29 29 #define BOOT_CPU_MODE_MISMATCH PSR_N_BIT 30 30 31 31 #ifndef __ASSEMBLY__ 32 + #include <asm/cacheflush.h> 32 33 33 34 #ifdef CONFIG_ARM_VIRT_EXT 34 35 /* ··· 42 41 */ 43 42 extern int __boot_cpu_mode; 44 43 44 + static inline void sync_boot_mode(void) 45 + { 46 + /* 47 + * As secondaries write to __boot_cpu_mode with caches disabled, we 48 + * must flush the corresponding cache entries to ensure the visibility 49 + * of their writes. 50 + */ 51 + sync_cache_r(&__boot_cpu_mode); 52 + } 53 + 45 54 void __hyp_set_vectors(unsigned long phys_vector_base); 46 55 unsigned long __hyp_get_vectors(void); 47 56 #else 48 57 #define __boot_cpu_mode (SVC_MODE) 58 + #define sync_boot_mode() 49 59 #endif 50 60 51 61 #ifndef ZIMAGE
-1
arch/arm/include/uapi/asm/Kbuild
··· 1 1 # UAPI Header export list 2 2 include include/uapi/asm-generic/Kbuild.asm 3 3 4 - header-y += a.out.h 5 4 header-y += byteorder.h 6 5 header-y += fcntl.h 7 6 header-y += hwcap.h
-34
arch/arm/include/uapi/asm/a.out.h
··· 1 - #ifndef __ARM_A_OUT_H__ 2 - #define __ARM_A_OUT_H__ 3 - 4 - #include <linux/personality.h> 5 - #include <linux/types.h> 6 - 7 - struct exec 8 - { 9 - __u32 a_info; /* Use macros N_MAGIC, etc for access */ 10 - __u32 a_text; /* length of text, in bytes */ 11 - __u32 a_data; /* length of data, in bytes */ 12 - __u32 a_bss; /* length of uninitialized data area for file, in bytes */ 13 - __u32 a_syms; /* length of symbol table data in file, in bytes */ 14 - __u32 a_entry; /* start address */ 15 - __u32 a_trsize; /* length of relocation info for text, in bytes */ 16 - __u32 a_drsize; /* length of relocation info for data, in bytes */ 17 - }; 18 - 19 - /* 20 - * This is always the same 21 - */ 22 - #define N_TXTADDR(a) (0x00008000) 23 - 24 - #define N_TRSIZE(a) ((a).a_trsize) 25 - #define N_DRSIZE(a) ((a).a_drsize) 26 - #define N_SYMSIZE(a) ((a).a_syms) 27 - 28 - #define M_ARM 103 29 - 30 - #ifndef LIBRARY_START_TEXT 31 - #define LIBRARY_START_TEXT (0x00c00000) 32 - #endif 33 - 34 - #endif /* __A_OUT_GNU_H__ */
+53 -50
arch/arm/kernel/entry-armv.S
··· 742 742 #endif 743 743 .endm 744 744 745 + .macro kuser_pad, sym, size 746 + .if (. - \sym) & 3 747 + .rept 4 - (. - \sym) & 3 748 + .byte 0 749 + .endr 750 + .endif 751 + .rept (\size - (. - \sym)) / 4 752 + .word 0xe7fddef1 753 + .endr 754 + .endm 755 + 756 + #ifdef CONFIG_KUSER_HELPERS 745 757 .align 5 746 758 .globl __kuser_helper_start 747 759 __kuser_helper_start: ··· 844 832 #error "incoherent kernel configuration" 845 833 #endif 846 834 847 - /* pad to next slot */ 848 - .rept (16 - (. - __kuser_cmpxchg64)/4) 849 - .word 0 850 - .endr 851 - 852 - .align 5 835 + kuser_pad __kuser_cmpxchg64, 64 853 836 854 837 __kuser_memory_barrier: @ 0xffff0fa0 855 838 smp_dmb arm 856 839 usr_ret lr 857 840 858 - .align 5 841 + kuser_pad __kuser_memory_barrier, 32 859 842 860 843 __kuser_cmpxchg: @ 0xffff0fc0 861 844 ··· 923 916 924 917 #endif 925 918 926 - .align 5 919 + kuser_pad __kuser_cmpxchg, 32 927 920 928 921 __kuser_get_tls: @ 0xffff0fe0 929 922 ldr r0, [pc, #(16 - 8)] @ read TLS, set in kuser_get_tls_init 930 923 usr_ret lr 931 924 mrc p15, 0, r0, c13, c0, 3 @ 0xffff0fe8 hardware TLS code 932 - .rep 4 925 + kuser_pad __kuser_get_tls, 16 926 + .rep 3 933 927 .word 0 @ 0xffff0ff0 software TLS value, then 934 928 .endr @ pad up to __kuser_helper_version 935 929 ··· 940 932 .globl __kuser_helper_end 941 933 __kuser_helper_end: 942 934 935 + #endif 936 + 943 937 THUMB( .thumb ) 944 938 945 939 /* 946 940 * Vector stubs. 947 941 * 948 - * This code is copied to 0xffff0200 so we can use branches in the 949 - * vectors, rather than ldr's. Note that this code must not 950 - * exceed 0x300 bytes. 942 + * This code is copied to 0xffff1000 so we can use branches in the 943 + * vectors, rather than ldr's. Note that this code must not exceed 944 + * a page size. 951 945 * 952 946 * Common stub entry macro: 953 947 * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC ··· 996 986 1: 997 987 .endm 998 988 999 - .globl __stubs_start 989 + .section .stubs, "ax", %progbits 1000 990 __stubs_start: 991 + @ This must be the first word 992 + .word vector_swi 993 + 994 + vector_rst: 995 + ARM( swi SYS_ERROR0 ) 996 + THUMB( svc #0 ) 997 + THUMB( nop ) 998 + b vector_und 999 + 1001 1000 /* 1002 1001 * Interrupt dispatcher 1003 1002 */ ··· 1101 1082 .align 5 1102 1083 1103 1084 /*============================================================================= 1085 + * Address exception handler 1086 + *----------------------------------------------------------------------------- 1087 + * These aren't too critical. 1088 + * (they're not supposed to happen, and won't happen in 32-bit data mode). 1089 + */ 1090 + 1091 + vector_addrexcptn: 1092 + b vector_addrexcptn 1093 + 1094 + /*============================================================================= 1104 1095 * Undefined FIQs 1105 1096 *----------------------------------------------------------------------------- 1106 1097 * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC ··· 1123 1094 vector_fiq: 1124 1095 subs pc, lr, #4 1125 1096 1126 - /*============================================================================= 1127 - * Address exception handler 1128 - *----------------------------------------------------------------------------- 1129 - * These aren't too critical. 1130 - * (they're not supposed to happen, and won't happen in 32-bit data mode). 1131 - */ 1097 + .globl vector_fiq_offset 1098 + .equ vector_fiq_offset, vector_fiq 1132 1099 1133 - vector_addrexcptn: 1134 - b vector_addrexcptn 1135 - 1136 - /* 1137 - * We group all the following data together to optimise 1138 - * for CPUs with separate I & D caches. 1139 - */ 1140 - .align 5 1141 - 1142 - .LCvswi: 1143 - .word vector_swi 1144 - 1145 - .globl __stubs_end 1146 - __stubs_end: 1147 - 1148 - .equ stubs_offset, __vectors_start + 0x200 - __stubs_start 1149 - 1150 - .globl __vectors_start 1100 + .section .vectors, "ax", %progbits 1151 1101 __vectors_start: 1152 - ARM( swi SYS_ERROR0 ) 1153 - THUMB( svc #0 ) 1154 - THUMB( nop ) 1155 - W(b) vector_und + stubs_offset 1156 - W(ldr) pc, .LCvswi + stubs_offset 1157 - W(b) vector_pabt + stubs_offset 1158 - W(b) vector_dabt + stubs_offset 1159 - W(b) vector_addrexcptn + stubs_offset 1160 - W(b) vector_irq + stubs_offset 1161 - W(b) vector_fiq + stubs_offset 1162 - 1163 - .globl __vectors_end 1164 - __vectors_end: 1102 + W(b) vector_rst 1103 + W(b) vector_und 1104 + W(ldr) pc, __vectors_start + 0x1000 1105 + W(b) vector_pabt 1106 + W(b) vector_dabt 1107 + W(b) vector_addrexcptn 1108 + W(b) vector_irq 1109 + W(b) vector_fiq 1165 1110 1166 1111 .data 1167 1112
+1 -1
arch/arm/kernel/entry-v7m.S
··· 49 49 mov r1, sp 50 50 stmdb sp!, {lr} 51 51 @ routine called with r0 = irq number, r1 = struct pt_regs * 52 - bl nvic_do_IRQ 52 + bl nvic_handle_irq 53 53 54 54 pop {lr} 55 55 @
+14 -5
arch/arm/kernel/fiq.c
··· 47 47 #include <asm/irq.h> 48 48 #include <asm/traps.h> 49 49 50 + #define FIQ_OFFSET ({ \ 51 + extern void *vector_fiq_offset; \ 52 + (unsigned)&vector_fiq_offset; \ 53 + }) 54 + 50 55 static unsigned long no_fiq_insn; 51 56 52 57 /* Default reacquire function ··· 85 80 void set_fiq_handler(void *start, unsigned int length) 86 81 { 87 82 #if defined(CONFIG_CPU_USE_DOMAINS) 88 - memcpy((void *)0xffff001c, start, length); 83 + void *base = (void *)0xffff0000; 89 84 #else 90 - memcpy(vectors_page + 0x1c, start, length); 85 + void *base = vectors_page; 91 86 #endif 92 - flush_icache_range(0xffff001c, 0xffff001c + length); 87 + unsigned offset = FIQ_OFFSET; 88 + 89 + memcpy(base + offset, start, length); 90 + flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); 93 91 if (!vectors_high()) 94 - flush_icache_range(0x1c, 0x1c + length); 92 + flush_icache_range(offset, offset + length); 95 93 } 96 94 97 95 int claim_fiq(struct fiq_handler *f) ··· 152 144 153 145 void __init init_FIQ(int start) 154 146 { 155 - no_fiq_insn = *(unsigned long *)0xffff001c; 147 + unsigned offset = FIQ_OFFSET; 148 + no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); 156 149 fiq_start = start; 157 150 }
+1
arch/arm/kernel/head-nommu.S
··· 87 87 ENDPROC(stext) 88 88 89 89 #ifdef CONFIG_SMP 90 + .text 90 91 ENTRY(secondary_startup) 91 92 /* 92 93 * Common entry point for secondary CPUs.
+1
arch/arm/kernel/head.S
··· 343 343 .long __turn_mmu_on_end 344 344 345 345 #if defined(CONFIG_SMP) 346 + .text 346 347 ENTRY(secondary_startup) 347 348 /* 348 349 * Common entry point for secondary CPUs.
+2 -2
arch/arm/kernel/hyp-stub.S
··· 56 56 ldr \reg3, [\reg2] 57 57 ldr \reg1, [\reg2, \reg3] 58 58 cmp \mode, \reg1 @ matches primary CPU boot mode? 59 - orrne r7, r7, #BOOT_CPU_MODE_MISMATCH 60 - strne r7, [r5, r6] @ record what happened and give up 59 + orrne \reg1, \reg1, #BOOT_CPU_MODE_MISMATCH 60 + strne \reg1, [\reg2, \reg3] @ record what happened and give up 61 61 .endm 62 62 63 63 #else /* ZIMAGE */
+45 -3
arch/arm/kernel/process.c
··· 197 197 */ 198 198 void machine_halt(void) 199 199 { 200 + local_irq_disable(); 200 201 smp_send_stop(); 201 202 202 203 local_irq_disable(); ··· 212 211 */ 213 212 void machine_power_off(void) 214 213 { 214 + local_irq_disable(); 215 215 smp_send_stop(); 216 216 217 217 if (pm_power_off) ··· 232 230 */ 233 231 void machine_restart(char *cmd) 234 232 { 233 + local_irq_disable(); 235 234 smp_send_stop(); 236 235 237 236 arm_pm_restart(reboot_mode, cmd); ··· 429 426 } 430 427 431 428 #ifdef CONFIG_MMU 429 + #ifdef CONFIG_KUSER_HELPERS 432 430 /* 433 431 * The vectors page is always readable from user space for the 434 - * atomic helpers and the signal restart code. Insert it into the 435 - * gate_vma so that it is visible through ptrace and /proc/<pid>/mem. 432 + * atomic helpers. Insert it into the gate_vma so that it is visible 433 + * through ptrace and /proc/<pid>/mem. 436 434 */ 437 435 static struct vm_area_struct gate_vma = { 438 436 .vm_start = 0xffff0000, ··· 462 458 { 463 459 return in_gate_area(NULL, addr); 464 460 } 461 + #define is_gate_vma(vma) ((vma) = &gate_vma) 462 + #else 463 + #define is_gate_vma(vma) 0 464 + #endif 465 465 466 466 const char *arch_vma_name(struct vm_area_struct *vma) 467 467 { 468 - return (vma == &gate_vma) ? "[vectors]" : NULL; 468 + return is_gate_vma(vma) ? "[vectors]" : 469 + (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ? 470 + "[sigpage]" : NULL; 471 + } 472 + 473 + extern struct page *get_signal_page(void); 474 + 475 + int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 476 + { 477 + struct mm_struct *mm = current->mm; 478 + struct page *page; 479 + unsigned long addr; 480 + int ret; 481 + 482 + page = get_signal_page(); 483 + if (!page) 484 + return -ENOMEM; 485 + 486 + down_write(&mm->mmap_sem); 487 + addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); 488 + if (IS_ERR_VALUE(addr)) { 489 + ret = addr; 490 + goto up_fail; 491 + } 492 + 493 + ret = install_special_mapping(mm, addr, PAGE_SIZE, 494 + VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, 495 + &page); 496 + 497 + if (ret == 0) 498 + mm->context.sigpage = addr; 499 + 500 + up_fail: 501 + up_write(&mm->mmap_sem); 502 + return ret; 469 503 } 470 504 #endif
+3
arch/arm/kernel/setup.c
··· 836 836 void __init hyp_mode_check(void) 837 837 { 838 838 #ifdef CONFIG_ARM_VIRT_EXT 839 + sync_boot_mode(); 840 + 839 841 if (is_hyp_mode_available()) { 840 842 pr_info("CPU: All CPU(s) started in HYP mode.\n"); 841 843 pr_info("CPU: Virtualization extensions available.\n"); ··· 973 971 "vfpv4", 974 972 "idiva", 975 973 "idivt", 974 + "vfpd32", 976 975 "lpae", 977 976 NULL 978 977 };
+45 -7
arch/arm/kernel/signal.c
··· 8 8 * published by the Free Software Foundation. 9 9 */ 10 10 #include <linux/errno.h> 11 + #include <linux/random.h> 11 12 #include <linux/signal.h> 12 13 #include <linux/personality.h> 13 14 #include <linux/uaccess.h> ··· 16 15 17 16 #include <asm/elf.h> 18 17 #include <asm/cacheflush.h> 18 + #include <asm/traps.h> 19 19 #include <asm/ucontext.h> 20 20 #include <asm/unistd.h> 21 21 #include <asm/vfp.h> 22 - 23 - #include "signal.h" 24 22 25 23 /* 26 24 * For ARM syscalls, we encode the syscall number into the instruction. ··· 40 40 #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) 41 41 #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) 42 42 43 - const unsigned long sigreturn_codes[7] = { 43 + static const unsigned long sigreturn_codes[7] = { 44 44 MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, 45 45 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, 46 46 }; 47 + 48 + static unsigned long signal_return_offset; 47 49 48 50 #ifdef CONFIG_CRUNCH 49 51 static int preserve_crunch_context(struct crunch_sigframe __user *frame) ··· 403 401 return 1; 404 402 405 403 if ((cpsr & MODE32_BIT) && !IS_ENABLED(CONFIG_ARM_MPU)) { 404 + struct mm_struct *mm = current->mm; 405 + 406 406 /* 407 - * 32-bit code can use the new high-page 408 - * signal return code support except when the MPU has 409 - * protected the vectors page from PL0 407 + * 32-bit code can use the signal return page 408 + * except when the MPU has protected the vectors 409 + * page from PL0 410 410 */ 411 - retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb; 411 + retcode = mm->context.sigpage + signal_return_offset + 412 + (idx << 2) + thumb; 412 413 } else { 413 414 /* 414 415 * Ensure that the instruction cache sees ··· 612 607 thread_flags = current_thread_info()->flags; 613 608 } while (thread_flags & _TIF_WORK_MASK); 614 609 return 0; 610 + } 611 + 612 + static struct page *signal_page; 613 + 614 + struct page *get_signal_page(void) 615 + { 616 + if (!signal_page) { 617 + unsigned long ptr; 618 + unsigned offset; 619 + void *addr; 620 + 621 + signal_page = alloc_pages(GFP_KERNEL, 0); 622 + 623 + if (!signal_page) 624 + return NULL; 625 + 626 + addr = page_address(signal_page); 627 + 628 + /* Give the signal return code some randomness */ 629 + offset = 0x200 + (get_random_int() & 0x7fc); 630 + signal_return_offset = offset; 631 + 632 + /* 633 + * Copy signal return handlers into the vector page, and 634 + * set sigreturn to be a pointer to these. 635 + */ 636 + memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes)); 637 + 638 + ptr = (unsigned long)addr + offset; 639 + flush_icache_range(ptr, ptr + sizeof(sigreturn_codes)); 640 + } 641 + 642 + return signal_page; 615 643 }
-12
arch/arm/kernel/signal.h
··· 1 - /* 2 - * linux/arch/arm/kernel/signal.h 3 - * 4 - * Copyright (C) 2005-2009 Russell King. 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation. 9 - */ 10 - #define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500) 11 - 12 - extern const unsigned long sigreturn_codes[7];
-17
arch/arm/kernel/smp_tlb.c
··· 70 70 local_flush_bp_all(); 71 71 } 72 72 73 - #ifdef CONFIG_ARM_ERRATA_798181 74 - static int erratum_a15_798181(void) 75 - { 76 - unsigned int midr = read_cpuid_id(); 77 - 78 - /* Cortex-A15 r0p0..r3p2 affected */ 79 - if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2) 80 - return 0; 81 - return 1; 82 - } 83 - #else 84 - static int erratum_a15_798181(void) 85 - { 86 - return 0; 87 - } 88 - #endif 89 - 90 73 static void ipi_flush_tlb_a15_erratum(void *arg) 91 74 { 92 75 dmb();
+26 -20
arch/arm/kernel/traps.c
··· 35 35 #include <asm/tls.h> 36 36 #include <asm/system_misc.h> 37 37 38 - #include "signal.h" 39 - 40 38 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; 41 39 42 40 void *vectors_page; ··· 798 800 return; 799 801 } 800 802 801 - static void __init kuser_get_tls_init(unsigned long vectors) 803 + #ifdef CONFIG_KUSER_HELPERS 804 + static void __init kuser_init(void *vectors) 802 805 { 806 + extern char __kuser_helper_start[], __kuser_helper_end[]; 807 + int kuser_sz = __kuser_helper_end - __kuser_helper_start; 808 + 809 + memcpy(vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); 810 + 803 811 /* 804 812 * vectors + 0xfe0 = __kuser_get_tls 805 813 * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 806 814 */ 807 815 if (tls_emu || has_tls_reg) 808 - memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4); 816 + memcpy(vectors + 0xfe0, vectors + 0xfe8, 4); 809 817 } 818 + #else 819 + static void __init kuser_init(void *vectors) 820 + { 821 + } 822 + #endif 810 823 811 824 void __init early_trap_init(void *vectors_base) 812 825 { ··· 825 816 unsigned long vectors = (unsigned long)vectors_base; 826 817 extern char __stubs_start[], __stubs_end[]; 827 818 extern char __vectors_start[], __vectors_end[]; 828 - extern char __kuser_helper_start[], __kuser_helper_end[]; 829 - int kuser_sz = __kuser_helper_end - __kuser_helper_start; 819 + unsigned i; 830 820 831 821 vectors_page = vectors_base; 822 + 823 + /* 824 + * Poison the vectors page with an undefined instruction. This 825 + * instruction is chosen to be undefined for both ARM and Thumb 826 + * ISAs. The Thumb version is an undefined instruction with a 827 + * branch back to the undefined instruction. 828 + */ 829 + for (i = 0; i < PAGE_SIZE / sizeof(u32); i++) 830 + ((u32 *)vectors_base)[i] = 0xe7fddef1; 832 831 833 832 /* 834 833 * Copy the vectors, stubs and kuser helpers (in entry-armv.S) ··· 844 827 * are visible to the instruction stream. 845 828 */ 846 829 memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); 847 - memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); 848 - memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); 830 + memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start); 849 831 850 - /* 851 - * Do processor specific fixups for the kuser helpers 852 - */ 853 - kuser_get_tls_init(vectors); 832 + kuser_init(vectors_base); 854 833 855 - /* 856 - * Copy signal return handlers into the vector page, and 857 - * set sigreturn to be a pointer to these. 858 - */ 859 - memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), 860 - sigreturn_codes, sizeof(sigreturn_codes)); 861 - 862 - flush_icache_range(vectors, vectors + PAGE_SIZE); 834 + flush_icache_range(vectors, vectors + PAGE_SIZE * 2); 863 835 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); 864 836 #else /* ifndef CONFIG_CPU_V7M */ 865 837 /*
+17
arch/arm/kernel/vmlinux.lds.S
··· 148 148 . = ALIGN(PAGE_SIZE); 149 149 __init_begin = .; 150 150 #endif 151 + /* 152 + * The vectors and stubs are relocatable code, and the 153 + * only thing that matters is their relative offsets 154 + */ 155 + __vectors_start = .; 156 + .vectors 0 : AT(__vectors_start) { 157 + *(.vectors) 158 + } 159 + . = __vectors_start + SIZEOF(.vectors); 160 + __vectors_end = .; 161 + 162 + __stubs_start = .; 163 + .stubs 0x1000 : AT(__stubs_start) { 164 + *(.stubs) 165 + } 166 + . = __stubs_start + SIZEOF(.stubs); 167 + __stubs_end = .; 151 168 152 169 INIT_TEXT_SECTION(8) 153 170 .exit.text : {
+34
arch/arm/mm/Kconfig
··· 421 421 select CPU_USE_DOMAINS if MMU 422 422 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP 423 423 select TLS_REG_EMUL if SMP || !MMU 424 + select NEED_KUSER_HELPERS 424 425 425 426 config CPU_32v4 426 427 bool 427 428 select CPU_USE_DOMAINS if MMU 428 429 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP 429 430 select TLS_REG_EMUL if SMP || !MMU 431 + select NEED_KUSER_HELPERS 430 432 431 433 config CPU_32v4T 432 434 bool 433 435 select CPU_USE_DOMAINS if MMU 434 436 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP 435 437 select TLS_REG_EMUL if SMP || !MMU 438 + select NEED_KUSER_HELPERS 436 439 437 440 config CPU_32v5 438 441 bool 439 442 select CPU_USE_DOMAINS if MMU 440 443 select NEEDS_SYSCALL_FOR_CMPXCHG if SMP 441 444 select TLS_REG_EMUL if SMP || !MMU 445 + select NEED_KUSER_HELPERS 442 446 443 447 config CPU_32v6 444 448 bool ··· 780 776 781 777 config TLS_REG_EMUL 782 778 bool 779 + select NEED_KUSER_HELPERS 783 780 help 784 781 An SMP system using a pre-ARMv6 processor (there are apparently 785 782 a few prototypes like that in existence) and therefore access to ··· 788 783 789 784 config NEEDS_SYSCALL_FOR_CMPXCHG 790 785 bool 786 + select NEED_KUSER_HELPERS 791 787 help 792 788 SMP on a pre-ARMv6 processor? Well OK then. 793 789 Forget about fast user space cmpxchg support. 794 790 It is just not possible. 791 + 792 + config NEED_KUSER_HELPERS 793 + bool 794 + 795 + config KUSER_HELPERS 796 + bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS 797 + default y 798 + help 799 + Warning: disabling this option may break user programs. 800 + 801 + Provide kuser helpers in the vector page. The kernel provides 802 + helper code to userspace in read only form at a fixed location 803 + in the high vector page to allow userspace to be independent of 804 + the CPU type fitted to the system. This permits binaries to be 805 + run on ARMv4 through to ARMv7 without modification. 806 + 807 + However, the fixed address nature of these helpers can be used 808 + by ROP (return orientated programming) authors when creating 809 + exploits. 810 + 811 + If all of the binaries and libraries which run on your platform 812 + are built specifically for your platform, and make no use of 813 + these helpers, then you can turn this option off. However, 814 + when such an binary or library is run, it will receive a SIGILL 815 + signal, which will terminate the program. 816 + 817 + Say N here only if you are absolutely certain that you do not 818 + need these helpers; otherwise, the safe option is to say Y. 795 819 796 820 config DMA_CACHE_RWFO 797 821 bool "Enable read/write for ownership DMA cache maintenance"
+2 -1
arch/arm/mm/context.c
··· 245 245 if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) { 246 246 local_flush_bp_all(); 247 247 local_flush_tlb_all(); 248 - dummy_flush_tlb_a15_erratum(); 248 + if (erratum_a15_798181()) 249 + dummy_flush_tlb_a15_erratum(); 249 250 } 250 251 251 252 atomic64_set(&per_cpu(active_asids, cpu), asid);
+51 -6
arch/arm/mm/mmu.c
··· 989 989 990 990 void __init sanity_check_meminfo(void) 991 991 { 992 + phys_addr_t memblock_limit = 0; 992 993 int i, j, highmem = 0; 993 994 phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; 994 995 ··· 1053 1052 bank->size = size_limit; 1054 1053 } 1055 1054 #endif 1056 - if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit) 1057 - arm_lowmem_limit = bank->start + bank->size; 1055 + if (!bank->highmem) { 1056 + phys_addr_t bank_end = bank->start + bank->size; 1058 1057 1058 + if (bank_end > arm_lowmem_limit) 1059 + arm_lowmem_limit = bank_end; 1060 + 1061 + /* 1062 + * Find the first non-section-aligned page, and point 1063 + * memblock_limit at it. This relies on rounding the 1064 + * limit down to be section-aligned, which happens at 1065 + * the end of this function. 1066 + * 1067 + * With this algorithm, the start or end of almost any 1068 + * bank can be non-section-aligned. The only exception 1069 + * is that the start of the bank 0 must be section- 1070 + * aligned, since otherwise memory would need to be 1071 + * allocated when mapping the start of bank 0, which 1072 + * occurs before any free memory is mapped. 1073 + */ 1074 + if (!memblock_limit) { 1075 + if (!IS_ALIGNED(bank->start, SECTION_SIZE)) 1076 + memblock_limit = bank->start; 1077 + else if (!IS_ALIGNED(bank_end, SECTION_SIZE)) 1078 + memblock_limit = bank_end; 1079 + } 1080 + } 1059 1081 j++; 1060 1082 } 1061 1083 #ifdef CONFIG_HIGHMEM ··· 1103 1079 #endif 1104 1080 meminfo.nr_banks = j; 1105 1081 high_memory = __va(arm_lowmem_limit - 1) + 1; 1106 - memblock_set_current_limit(arm_lowmem_limit); 1082 + 1083 + /* 1084 + * Round the memblock limit down to a section size. This 1085 + * helps to ensure that we will allocate memory from the 1086 + * last full section, which should be mapped. 1087 + */ 1088 + if (memblock_limit) 1089 + memblock_limit = round_down(memblock_limit, SECTION_SIZE); 1090 + if (!memblock_limit) 1091 + memblock_limit = arm_lowmem_limit; 1092 + 1093 + memblock_set_current_limit(memblock_limit); 1107 1094 } 1108 1095 1109 1096 static inline void prepare_page_table(void) ··· 1195 1160 /* 1196 1161 * Allocate the vector page early. 1197 1162 */ 1198 - vectors = early_alloc(PAGE_SIZE); 1163 + vectors = early_alloc(PAGE_SIZE * 2); 1199 1164 1200 1165 early_trap_init(vectors); 1201 1166 ··· 1240 1205 map.pfn = __phys_to_pfn(virt_to_phys(vectors)); 1241 1206 map.virtual = 0xffff0000; 1242 1207 map.length = PAGE_SIZE; 1208 + #ifdef CONFIG_KUSER_HELPERS 1243 1209 map.type = MT_HIGH_VECTORS; 1210 + #else 1211 + map.type = MT_LOW_VECTORS; 1212 + #endif 1244 1213 create_mapping(&map); 1245 1214 1246 1215 if (!vectors_high()) { 1247 1216 map.virtual = 0; 1217 + map.length = PAGE_SIZE * 2; 1248 1218 map.type = MT_LOW_VECTORS; 1249 1219 create_mapping(&map); 1250 1220 } 1221 + 1222 + /* Now create a kernel read-only mapping */ 1223 + map.pfn += 1; 1224 + map.virtual = 0xffff0000 + PAGE_SIZE; 1225 + map.length = PAGE_SIZE; 1226 + map.type = MT_LOW_VECTORS; 1227 + create_mapping(&map); 1251 1228 1252 1229 /* 1253 1230 * Ask the machine support to map in the statically mapped devices. ··· 1322 1275 void __init paging_init(struct machine_desc *mdesc) 1323 1276 { 1324 1277 void *zero_page; 1325 - 1326 - memblock_set_current_limit(arm_lowmem_limit); 1327 1278 1328 1279 build_mem_type_table(); 1329 1280 prepare_page_table();
+1 -1
arch/arm/mm/proc-v7-2level.S
··· 110 110 ARM( str r3, [r0, #2048]! ) 111 111 THUMB( add r0, r0, #2048 ) 112 112 THUMB( str r3, [r0] ) 113 - ALT_SMP(mov pc,lr) 113 + ALT_SMP(W(nop)) 114 114 ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte 115 115 #endif 116 116 mov pc, lr
+1 -1
arch/arm/mm/proc-v7-3level.S
··· 81 81 tst r3, #1 << (55 - 32) @ L_PTE_DIRTY 82 82 orreq r2, #L_PTE_RDONLY 83 83 1: strd r2, r3, [r0] 84 - ALT_SMP(mov pc, lr) 84 + ALT_SMP(W(nop)) 85 85 ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte 86 86 #endif 87 87 mov pc, lr
+6 -5
arch/arm/mm/proc-v7.S
··· 75 75 ENDPROC(cpu_v7_do_idle) 76 76 77 77 ENTRY(cpu_v7_dcache_clean_area) 78 - ALT_SMP(mov pc, lr) @ MP extensions imply L1 PTW 79 - ALT_UP(W(nop)) 80 - dcache_line_size r2, r3 81 - 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 78 + ALT_SMP(W(nop)) @ MP extensions imply L1 PTW 79 + ALT_UP_B(1f) 80 + mov pc, lr 81 + 1: dcache_line_size r2, r3 82 + 2: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 82 83 add r0, r0, r2 83 84 subs r1, r1, r2 84 - bhi 1b 85 + bhi 2b 85 86 dsb 86 87 mov pc, lr 87 88 ENDPROC(cpu_v7_dcache_clean_area)