diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 106 | ||||
-rw-r--r-- | arch/arm/kernel/entry-v7m.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/fiq.c | 23 | ||||
-rw-r--r-- | arch/arm/kernel/head-common.S | 1 | ||||
-rw-r--r-- | arch/arm/kernel/head-nommu.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/hyp-stub.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 20 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_cpu.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 49 | ||||
-rw-r--r-- | arch/arm/kernel/psci_smp.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 56 | ||||
-rw-r--r-- | arch/arm/kernel/signal.h | 12 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 28 | ||||
-rw-r--r-- | arch/arm/kernel/smp_tlb.c | 17 | ||||
-rw-r--r-- | arch/arm/kernel/smp_twd.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 46 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 17 |
21 files changed, 266 insertions, 151 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a39cfc2a1f90..9cbe70c8b0ef 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -357,7 +357,8 @@ ENDPROC(__pabt_svc) | |||
357 | .endm | 357 | .endm |
358 | 358 | ||
359 | .macro kuser_cmpxchg_check | 359 | .macro kuser_cmpxchg_check |
360 | #if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) | 360 | #if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ |
361 | !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) | ||
361 | #ifndef CONFIG_MMU | 362 | #ifndef CONFIG_MMU |
362 | #warning "NPTL on non MMU needs fixing" | 363 | #warning "NPTL on non MMU needs fixing" |
363 | #else | 364 | #else |
@@ -742,6 +743,18 @@ ENDPROC(__switch_to) | |||
742 | #endif | 743 | #endif |
743 | .endm | 744 | .endm |
744 | 745 | ||
746 | .macro kuser_pad, sym, size | ||
747 | .if (. - \sym) & 3 | ||
748 | .rept 4 - (. - \sym) & 3 | ||
749 | .byte 0 | ||
750 | .endr | ||
751 | .endif | ||
752 | .rept (\size - (. - \sym)) / 4 | ||
753 | .word 0xe7fddef1 | ||
754 | .endr | ||
755 | .endm | ||
756 | |||
757 | #ifdef CONFIG_KUSER_HELPERS | ||
745 | .align 5 | 758 | .align 5 |
746 | .globl __kuser_helper_start | 759 | .globl __kuser_helper_start |
747 | __kuser_helper_start: | 760 | __kuser_helper_start: |
@@ -832,18 +845,13 @@ kuser_cmpxchg64_fixup: | |||
832 | #error "incoherent kernel configuration" | 845 | #error "incoherent kernel configuration" |
833 | #endif | 846 | #endif |
834 | 847 | ||
835 | /* pad to next slot */ | 848 | kuser_pad __kuser_cmpxchg64, 64 |
836 | .rept (16 - (. - __kuser_cmpxchg64)/4) | ||
837 | .word 0 | ||
838 | .endr | ||
839 | |||
840 | .align 5 | ||
841 | 849 | ||
842 | __kuser_memory_barrier: @ 0xffff0fa0 | 850 | __kuser_memory_barrier: @ 0xffff0fa0 |
843 | smp_dmb arm | 851 | smp_dmb arm |
844 | usr_ret lr | 852 | usr_ret lr |
845 | 853 | ||
846 | .align 5 | 854 | kuser_pad __kuser_memory_barrier, 32 |
847 | 855 | ||
848 | __kuser_cmpxchg: @ 0xffff0fc0 | 856 | __kuser_cmpxchg: @ 0xffff0fc0 |
849 | 857 | ||
@@ -916,13 +924,14 @@ kuser_cmpxchg32_fixup: | |||
916 | 924 | ||
917 | #endif | 925 | #endif |
918 | 926 | ||
919 | .align 5 | 927 | kuser_pad __kuser_cmpxchg, 32 |
920 | 928 | ||
921 | __kuser_get_tls: @ 0xffff0fe0 | 929 | __kuser_get_tls: @ 0xffff0fe0 |
922 | ldr r0, [pc, #(16 - 8)] @ read TLS, set in kuser_get_tls_init | 930 | ldr r0, [pc, #(16 - 8)] @ read TLS, set in kuser_get_tls_init |
923 | usr_ret lr | 931 | usr_ret lr |
924 | mrc p15, 0, r0, c13, c0, 3 @ 0xffff0fe8 hardware TLS code | 932 | mrc p15, 0, r0, c13, c0, 3 @ 0xffff0fe8 hardware TLS code |
925 | .rep 4 | 933 | kuser_pad __kuser_get_tls, 16 |
934 | .rep 3 | ||
926 | .word 0 @ 0xffff0ff0 software TLS value, then | 935 | .word 0 @ 0xffff0ff0 software TLS value, then |
927 | .endr @ pad up to __kuser_helper_version | 936 | .endr @ pad up to __kuser_helper_version |
928 | 937 | ||
@@ -932,14 +941,16 @@ __kuser_helper_version: @ 0xffff0ffc | |||
932 | .globl __kuser_helper_end | 941 | .globl __kuser_helper_end |
933 | __kuser_helper_end: | 942 | __kuser_helper_end: |
934 | 943 | ||
944 | #endif | ||
945 | |||
935 | THUMB( .thumb ) | 946 | THUMB( .thumb ) |
936 | 947 | ||
937 | /* | 948 | /* |
938 | * Vector stubs. | 949 | * Vector stubs. |
939 | * | 950 | * |
940 | * This code is copied to 0xffff0200 so we can use branches in the | 951 | * This code is copied to 0xffff1000 so we can use branches in the |
941 | * vectors, rather than ldr's. Note that this code must not | 952 | * vectors, rather than ldr's. Note that this code must not exceed |
942 | * exceed 0x300 bytes. | 953 | * a page size. |
943 | * | 954 | * |
944 | * Common stub entry macro: | 955 | * Common stub entry macro: |
945 | * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC | 956 | * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC |
@@ -986,8 +997,17 @@ ENDPROC(vector_\name) | |||
986 | 1: | 997 | 1: |
987 | .endm | 998 | .endm |
988 | 999 | ||
989 | .globl __stubs_start | 1000 | .section .stubs, "ax", %progbits |
990 | __stubs_start: | 1001 | __stubs_start: |
1002 | @ This must be the first word | ||
1003 | .word vector_swi | ||
1004 | |||
1005 | vector_rst: | ||
1006 | ARM( swi SYS_ERROR0 ) | ||
1007 | THUMB( svc #0 ) | ||
1008 | THUMB( nop ) | ||
1009 | b vector_und | ||
1010 | |||
991 | /* | 1011 | /* |
992 | * Interrupt dispatcher | 1012 | * Interrupt dispatcher |
993 | */ | 1013 | */ |
@@ -1082,6 +1102,16 @@ __stubs_start: | |||
1082 | .align 5 | 1102 | .align 5 |
1083 | 1103 | ||
1084 | /*============================================================================= | 1104 | /*============================================================================= |
1105 | * Address exception handler | ||
1106 | *----------------------------------------------------------------------------- | ||
1107 | * These aren't too critical. | ||
1108 | * (they're not supposed to happen, and won't happen in 32-bit data mode). | ||
1109 | */ | ||
1110 | |||
1111 | vector_addrexcptn: | ||
1112 | b vector_addrexcptn | ||
1113 | |||
1114 | /*============================================================================= | ||
1085 | * Undefined FIQs | 1115 | * Undefined FIQs |
1086 | *----------------------------------------------------------------------------- | 1116 | *----------------------------------------------------------------------------- |
1087 | * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC | 1117 | * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC |
@@ -1094,45 +1124,19 @@ __stubs_start: | |||
1094 | vector_fiq: | 1124 | vector_fiq: |
1095 | subs pc, lr, #4 | 1125 | subs pc, lr, #4 |
1096 | 1126 | ||
1097 | /*============================================================================= | 1127 | .globl vector_fiq_offset |
1098 | * Address exception handler | 1128 | .equ vector_fiq_offset, vector_fiq |
1099 | *----------------------------------------------------------------------------- | ||
1100 | * These aren't too critical. | ||
1101 | * (they're not supposed to happen, and won't happen in 32-bit data mode). | ||
1102 | */ | ||
1103 | |||
1104 | vector_addrexcptn: | ||
1105 | b vector_addrexcptn | ||
1106 | |||
1107 | /* | ||
1108 | * We group all the following data together to optimise | ||
1109 | * for CPUs with separate I & D caches. | ||
1110 | */ | ||
1111 | .align 5 | ||
1112 | |||
1113 | .LCvswi: | ||
1114 | .word vector_swi | ||
1115 | |||
1116 | .globl __stubs_end | ||
1117 | __stubs_end: | ||
1118 | |||
1119 | .equ stubs_offset, __vectors_start + 0x200 - __stubs_start | ||
1120 | 1129 | ||
1121 | .globl __vectors_start | 1130 | .section .vectors, "ax", %progbits |
1122 | __vectors_start: | 1131 | __vectors_start: |
1123 | ARM( swi SYS_ERROR0 ) | 1132 | W(b) vector_rst |
1124 | THUMB( svc #0 ) | 1133 | W(b) vector_und |
1125 | THUMB( nop ) | 1134 | W(ldr) pc, __vectors_start + 0x1000 |
1126 | W(b) vector_und + stubs_offset | 1135 | W(b) vector_pabt |
1127 | W(ldr) pc, .LCvswi + stubs_offset | 1136 | W(b) vector_dabt |
1128 | W(b) vector_pabt + stubs_offset | 1137 | W(b) vector_addrexcptn |
1129 | W(b) vector_dabt + stubs_offset | 1138 | W(b) vector_irq |
1130 | W(b) vector_addrexcptn + stubs_offset | 1139 | W(b) vector_fiq |
1131 | W(b) vector_irq + stubs_offset | ||
1132 | W(b) vector_fiq + stubs_offset | ||
1133 | |||
1134 | .globl __vectors_end | ||
1135 | __vectors_end: | ||
1136 | 1140 | ||
1137 | .data | 1141 | .data |
1138 | 1142 | ||
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S index e00621f1403f..52b26432c9a9 100644 --- a/arch/arm/kernel/entry-v7m.S +++ b/arch/arm/kernel/entry-v7m.S | |||
@@ -49,7 +49,7 @@ __irq_entry: | |||
49 | mov r1, sp | 49 | mov r1, sp |
50 | stmdb sp!, {lr} | 50 | stmdb sp!, {lr} |
51 | @ routine called with r0 = irq number, r1 = struct pt_regs * | 51 | @ routine called with r0 = irq number, r1 = struct pt_regs * |
52 | bl nvic_do_IRQ | 52 | bl nvic_handle_irq |
53 | 53 | ||
54 | pop {lr} | 54 | pop {lr} |
55 | @ | 55 | @ |
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 2adda11f712f..fc7920288a3d 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c | |||
@@ -47,6 +47,11 @@ | |||
47 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
48 | #include <asm/traps.h> | 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 | static unsigned long no_fiq_insn; | 55 | static unsigned long no_fiq_insn; |
51 | 56 | ||
52 | /* Default reacquire function | 57 | /* Default reacquire function |
@@ -79,14 +84,13 @@ int show_fiq_list(struct seq_file *p, int prec) | |||
79 | 84 | ||
80 | void set_fiq_handler(void *start, unsigned int length) | 85 | void set_fiq_handler(void *start, unsigned int length) |
81 | { | 86 | { |
82 | #if defined(CONFIG_CPU_USE_DOMAINS) | 87 | void *base = vectors_page; |
83 | memcpy((void *)0xffff001c, start, length); | 88 | unsigned offset = FIQ_OFFSET; |
84 | #else | 89 | |
85 | memcpy(vectors_page + 0x1c, start, length); | 90 | memcpy(base + offset, start, length); |
86 | #endif | 91 | if (!cache_is_vipt_nonaliasing()) |
87 | flush_icache_range(0xffff001c, 0xffff001c + length); | 92 | flush_icache_range(base + offset, offset + length); |
88 | if (!vectors_high()) | 93 | flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); |
89 | flush_icache_range(0x1c, 0x1c + length); | ||
90 | } | 94 | } |
91 | 95 | ||
92 | int claim_fiq(struct fiq_handler *f) | 96 | int claim_fiq(struct fiq_handler *f) |
@@ -144,6 +148,7 @@ EXPORT_SYMBOL(disable_fiq); | |||
144 | 148 | ||
145 | void __init init_FIQ(int start) | 149 | void __init init_FIQ(int start) |
146 | { | 150 | { |
147 | no_fiq_insn = *(unsigned long *)0xffff001c; | 151 | unsigned offset = FIQ_OFFSET; |
152 | no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); | ||
148 | fiq_start = start; | 153 | fiq_start = start; |
149 | } | 154 | } |
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 76ab5ca50610..47cd974e57ea 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S | |||
@@ -149,7 +149,6 @@ ENDPROC(lookup_processor_type) | |||
149 | * r5 = proc_info pointer in physical address space | 149 | * r5 = proc_info pointer in physical address space |
150 | * r9 = cpuid (preserved) | 150 | * r9 = cpuid (preserved) |
151 | */ | 151 | */ |
152 | __CPUINIT | ||
153 | __lookup_processor_type: | 152 | __lookup_processor_type: |
154 | adr r3, __lookup_processor_type_data | 153 | adr r3, __lookup_processor_type_data |
155 | ldmia r3, {r4 - r6} | 154 | ldmia r3, {r4 - r6} |
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index 75f14cc3e073..14235ba64a90 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S | |||
@@ -87,7 +87,7 @@ ENTRY(stext) | |||
87 | ENDPROC(stext) | 87 | ENDPROC(stext) |
88 | 88 | ||
89 | #ifdef CONFIG_SMP | 89 | #ifdef CONFIG_SMP |
90 | __CPUINIT | 90 | .text |
91 | ENTRY(secondary_startup) | 91 | ENTRY(secondary_startup) |
92 | /* | 92 | /* |
93 | * Common entry point for secondary CPUs. | 93 | * Common entry point for secondary CPUs. |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 45e8935cae4e..2c7cc1e03473 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -343,7 +343,7 @@ __turn_mmu_on_loc: | |||
343 | .long __turn_mmu_on_end | 343 | .long __turn_mmu_on_end |
344 | 344 | ||
345 | #if defined(CONFIG_SMP) | 345 | #if defined(CONFIG_SMP) |
346 | __CPUINIT | 346 | .text |
347 | ENTRY(secondary_startup) | 347 | ENTRY(secondary_startup) |
348 | /* | 348 | /* |
349 | * Common entry point for secondary CPUs. | 349 | * Common entry point for secondary CPUs. |
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 1fd749ee4a1b..7b95de601357 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c | |||
@@ -1020,7 +1020,7 @@ out_mdbgen: | |||
1020 | cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu)); | 1020 | cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu)); |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | static int __cpuinit dbg_reset_notify(struct notifier_block *self, | 1023 | static int dbg_reset_notify(struct notifier_block *self, |
1024 | unsigned long action, void *cpu) | 1024 | unsigned long action, void *cpu) |
1025 | { | 1025 | { |
1026 | if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) | 1026 | if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) |
@@ -1029,7 +1029,7 @@ static int __cpuinit dbg_reset_notify(struct notifier_block *self, | |||
1029 | return NOTIFY_OK; | 1029 | return NOTIFY_OK; |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | static struct notifier_block __cpuinitdata dbg_reset_nb = { | 1032 | static struct notifier_block dbg_reset_nb = { |
1033 | .notifier_call = dbg_reset_notify, | 1033 | .notifier_call = dbg_reset_notify, |
1034 | }; | 1034 | }; |
1035 | 1035 | ||
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S index 4910232c4833..797b1a6a4906 100644 --- a/arch/arm/kernel/hyp-stub.S +++ b/arch/arm/kernel/hyp-stub.S | |||
@@ -56,8 +56,8 @@ ENTRY(__boot_cpu_mode) | |||
56 | ldr \reg3, [\reg2] | 56 | ldr \reg3, [\reg2] |
57 | ldr \reg1, [\reg2, \reg3] | 57 | ldr \reg1, [\reg2, \reg3] |
58 | cmp \mode, \reg1 @ matches primary CPU boot mode? | 58 | cmp \mode, \reg1 @ matches primary CPU boot mode? |
59 | orrne r7, r7, #BOOT_CPU_MODE_MISMATCH | 59 | orrne \reg1, \reg1, #BOOT_CPU_MODE_MISMATCH |
60 | strne r7, [r5, r6] @ record what happened and give up | 60 | strne \reg1, [\reg2, \reg3] @ record what happened and give up |
61 | .endm | 61 | .endm |
62 | 62 | ||
63 | #else /* ZIMAGE */ | 63 | #else /* ZIMAGE */ |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 4fb074c446bf..d7c82df69243 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <asm/mmu_context.h> | 15 | #include <asm/mmu_context.h> |
16 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
17 | #include <asm/mach-types.h> | 17 | #include <asm/mach-types.h> |
18 | #include <asm/smp_plat.h> | ||
18 | #include <asm/system_misc.h> | 19 | #include <asm/system_misc.h> |
19 | 20 | ||
20 | extern const unsigned char relocate_new_kernel[]; | 21 | extern const unsigned char relocate_new_kernel[]; |
@@ -39,6 +40,14 @@ int machine_kexec_prepare(struct kimage *image) | |||
39 | int i, err; | 40 | int i, err; |
40 | 41 | ||
41 | /* | 42 | /* |
43 | * Validate that if the current HW supports SMP, then the SW supports | ||
44 | * and implements CPU hotplug for the current HW. If not, we won't be | ||
45 | * able to kexec reliably, so fail the prepare operation. | ||
46 | */ | ||
47 | if (num_possible_cpus() > 1 && !platform_can_cpu_hotplug()) | ||
48 | return -EINVAL; | ||
49 | |||
50 | /* | ||
42 | * No segment at default ATAGs address. try to locate | 51 | * No segment at default ATAGs address. try to locate |
43 | * a dtb using magic. | 52 | * a dtb using magic. |
44 | */ | 53 | */ |
@@ -134,10 +143,13 @@ void machine_kexec(struct kimage *image) | |||
134 | unsigned long reboot_code_buffer_phys; | 143 | unsigned long reboot_code_buffer_phys; |
135 | void *reboot_code_buffer; | 144 | void *reboot_code_buffer; |
136 | 145 | ||
137 | if (num_online_cpus() > 1) { | 146 | /* |
138 | pr_err("kexec: error: multiple CPUs still online\n"); | 147 | * This can only happen if machine_shutdown() failed to disable some |
139 | return; | 148 | * CPU, and that can only happen if the checks in |
140 | } | 149 | * machine_kexec_prepare() were not correct. If this fails, we can't |
150 | * reliably kexec anyway, so BUG_ON is appropriate. | ||
151 | */ | ||
152 | BUG_ON(num_online_cpus() > 1); | ||
141 | 153 | ||
142 | page_list = image->head & PAGE_MASK; | 154 | page_list = image->head & PAGE_MASK; |
143 | 155 | ||
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index d9f5cd4e533f..e186ee1e63f6 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -53,7 +53,12 @@ armpmu_map_cache_event(const unsigned (*cache_map) | |||
53 | static int | 53 | static int |
54 | armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) | 54 | armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) |
55 | { | 55 | { |
56 | int mapping = (*event_map)[config]; | 56 | int mapping; |
57 | |||
58 | if (config >= PERF_COUNT_HW_MAX) | ||
59 | return -EINVAL; | ||
60 | |||
61 | mapping = (*event_map)[config]; | ||
57 | return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; | 62 | return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; |
58 | } | 63 | } |
59 | 64 | ||
@@ -253,6 +258,9 @@ validate_event(struct pmu_hw_events *hw_events, | |||
253 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | 258 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); |
254 | struct pmu *leader_pmu = event->group_leader->pmu; | 259 | struct pmu *leader_pmu = event->group_leader->pmu; |
255 | 260 | ||
261 | if (is_software_event(event)) | ||
262 | return 1; | ||
263 | |||
256 | if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF) | 264 | if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF) |
257 | return 1; | 265 | return 1; |
258 | 266 | ||
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 1f2740e3dbc0..aebe0e99c153 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c | |||
@@ -157,8 +157,8 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu) | |||
157 | * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading | 157 | * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading |
158 | * junk values out of them. | 158 | * junk values out of them. |
159 | */ | 159 | */ |
160 | static int __cpuinit cpu_pmu_notify(struct notifier_block *b, | 160 | static int cpu_pmu_notify(struct notifier_block *b, unsigned long action, |
161 | unsigned long action, void *hcpu) | 161 | void *hcpu) |
162 | { | 162 | { |
163 | if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) | 163 | if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) |
164 | return NOTIFY_DONE; | 164 | return NOTIFY_DONE; |
@@ -171,7 +171,7 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b, | |||
171 | return NOTIFY_OK; | 171 | return NOTIFY_OK; |
172 | } | 172 | } |
173 | 173 | ||
174 | static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = { | 174 | static struct notifier_block cpu_pmu_hotplug_notifier = { |
175 | .notifier_call = cpu_pmu_notify, | 175 | .notifier_call = cpu_pmu_notify, |
176 | }; | 176 | }; |
177 | 177 | ||
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index d3ca4f6915af..94f6b05f9e24 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -197,6 +197,7 @@ void machine_shutdown(void) | |||
197 | */ | 197 | */ |
198 | void machine_halt(void) | 198 | void machine_halt(void) |
199 | { | 199 | { |
200 | local_irq_disable(); | ||
200 | smp_send_stop(); | 201 | smp_send_stop(); |
201 | 202 | ||
202 | local_irq_disable(); | 203 | local_irq_disable(); |
@@ -211,6 +212,7 @@ void machine_halt(void) | |||
211 | */ | 212 | */ |
212 | void machine_power_off(void) | 213 | void machine_power_off(void) |
213 | { | 214 | { |
215 | local_irq_disable(); | ||
214 | smp_send_stop(); | 216 | smp_send_stop(); |
215 | 217 | ||
216 | if (pm_power_off) | 218 | if (pm_power_off) |
@@ -230,6 +232,7 @@ void machine_power_off(void) | |||
230 | */ | 232 | */ |
231 | void machine_restart(char *cmd) | 233 | void machine_restart(char *cmd) |
232 | { | 234 | { |
235 | local_irq_disable(); | ||
233 | smp_send_stop(); | 236 | smp_send_stop(); |
234 | 237 | ||
235 | arm_pm_restart(reboot_mode, cmd); | 238 | arm_pm_restart(reboot_mode, cmd); |
@@ -426,10 +429,11 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
426 | } | 429 | } |
427 | 430 | ||
428 | #ifdef CONFIG_MMU | 431 | #ifdef CONFIG_MMU |
432 | #ifdef CONFIG_KUSER_HELPERS | ||
429 | /* | 433 | /* |
430 | * The vectors page is always readable from user space for the | 434 | * The vectors page is always readable from user space for the |
431 | * atomic helpers and the signal restart code. Insert it into the | 435 | * atomic helpers. Insert it into the gate_vma so that it is visible |
432 | * gate_vma so that it is visible through ptrace and /proc/<pid>/mem. | 436 | * through ptrace and /proc/<pid>/mem. |
433 | */ | 437 | */ |
434 | static struct vm_area_struct gate_vma = { | 438 | static struct vm_area_struct gate_vma = { |
435 | .vm_start = 0xffff0000, | 439 | .vm_start = 0xffff0000, |
@@ -458,9 +462,48 @@ int in_gate_area_no_mm(unsigned long addr) | |||
458 | { | 462 | { |
459 | return in_gate_area(NULL, addr); | 463 | return in_gate_area(NULL, addr); |
460 | } | 464 | } |
465 | #define is_gate_vma(vma) ((vma) == &gate_vma) | ||
466 | #else | ||
467 | #define is_gate_vma(vma) 0 | ||
468 | #endif | ||
461 | 469 | ||
462 | const char *arch_vma_name(struct vm_area_struct *vma) | 470 | const char *arch_vma_name(struct vm_area_struct *vma) |
463 | { | 471 | { |
464 | return (vma == &gate_vma) ? "[vectors]" : NULL; | 472 | return is_gate_vma(vma) ? "[vectors]" : |
473 | (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ? | ||
474 | "[sigpage]" : NULL; | ||
475 | } | ||
476 | |||
477 | static struct page *signal_page; | ||
478 | extern struct page *get_signal_page(void); | ||
479 | |||
480 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | ||
481 | { | ||
482 | struct mm_struct *mm = current->mm; | ||
483 | unsigned long addr; | ||
484 | int ret; | ||
485 | |||
486 | if (!signal_page) | ||
487 | signal_page = get_signal_page(); | ||
488 | if (!signal_page) | ||
489 | return -ENOMEM; | ||
490 | |||
491 | down_write(&mm->mmap_sem); | ||
492 | addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); | ||
493 | if (IS_ERR_VALUE(addr)) { | ||
494 | ret = addr; | ||
495 | goto up_fail; | ||
496 | } | ||
497 | |||
498 | ret = install_special_mapping(mm, addr, PAGE_SIZE, | ||
499 | VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, | ||
500 | &signal_page); | ||
501 | |||
502 | if (ret == 0) | ||
503 | mm->context.sigpage = addr; | ||
504 | |||
505 | up_fail: | ||
506 | up_write(&mm->mmap_sem); | ||
507 | return ret; | ||
465 | } | 508 | } |
466 | #endif | 509 | #endif |
diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c index 219f1d73572a..70ded3fb42d9 100644 --- a/arch/arm/kernel/psci_smp.c +++ b/arch/arm/kernel/psci_smp.c | |||
@@ -46,8 +46,7 @@ | |||
46 | 46 | ||
47 | extern void secondary_startup(void); | 47 | extern void secondary_startup(void); |
48 | 48 | ||
49 | static int __cpuinit psci_boot_secondary(unsigned int cpu, | 49 | static int psci_boot_secondary(unsigned int cpu, struct task_struct *idle) |
50 | struct task_struct *idle) | ||
51 | { | 50 | { |
52 | if (psci_ops.cpu_on) | 51 | if (psci_ops.cpu_on) |
53 | return psci_ops.cpu_on(cpu_logical_map(cpu), | 52 | return psci_ops.cpu_on(cpu_logical_map(cpu), |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 63af9a7ae512..afc2489ee13b 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -836,6 +836,8 @@ static int __init meminfo_cmp(const void *_a, const void *_b) | |||
836 | void __init hyp_mode_check(void) | 836 | void __init hyp_mode_check(void) |
837 | { | 837 | { |
838 | #ifdef CONFIG_ARM_VIRT_EXT | 838 | #ifdef CONFIG_ARM_VIRT_EXT |
839 | sync_boot_mode(); | ||
840 | |||
839 | if (is_hyp_mode_available()) { | 841 | if (is_hyp_mode_available()) { |
840 | pr_info("CPU: All CPU(s) started in HYP mode.\n"); | 842 | pr_info("CPU: All CPU(s) started in HYP mode.\n"); |
841 | pr_info("CPU: Virtualization extensions available.\n"); | 843 | pr_info("CPU: Virtualization extensions available.\n"); |
@@ -971,6 +973,7 @@ static const char *hwcap_str[] = { | |||
971 | "vfpv4", | 973 | "vfpv4", |
972 | "idiva", | 974 | "idiva", |
973 | "idivt", | 975 | "idivt", |
976 | "vfpd32", | ||
974 | "lpae", | 977 | "lpae", |
975 | NULL | 978 | NULL |
976 | }; | 979 | }; |
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 1c16c35c271a..ab3304225272 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/random.h> | ||
11 | #include <linux/signal.h> | 12 | #include <linux/signal.h> |
12 | #include <linux/personality.h> | 13 | #include <linux/personality.h> |
13 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
@@ -15,12 +16,11 @@ | |||
15 | 16 | ||
16 | #include <asm/elf.h> | 17 | #include <asm/elf.h> |
17 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> |
19 | #include <asm/traps.h> | ||
18 | #include <asm/ucontext.h> | 20 | #include <asm/ucontext.h> |
19 | #include <asm/unistd.h> | 21 | #include <asm/unistd.h> |
20 | #include <asm/vfp.h> | 22 | #include <asm/vfp.h> |
21 | 23 | ||
22 | #include "signal.h" | ||
23 | |||
24 | /* | 24 | /* |
25 | * For ARM syscalls, we encode the syscall number into the instruction. | 25 | * For ARM syscalls, we encode the syscall number into the instruction. |
26 | */ | 26 | */ |
@@ -40,11 +40,13 @@ | |||
40 | #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) | 40 | #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) |
41 | #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) | 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 | MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, | 44 | MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, |
45 | MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, | 45 | MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static unsigned long signal_return_offset; | ||
49 | |||
48 | #ifdef CONFIG_CRUNCH | 50 | #ifdef CONFIG_CRUNCH |
49 | static int preserve_crunch_context(struct crunch_sigframe __user *frame) | 51 | static int preserve_crunch_context(struct crunch_sigframe __user *frame) |
50 | { | 52 | { |
@@ -400,14 +402,20 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, | |||
400 | __put_user(sigreturn_codes[idx+1], rc+1)) | 402 | __put_user(sigreturn_codes[idx+1], rc+1)) |
401 | return 1; | 403 | return 1; |
402 | 404 | ||
403 | if ((cpsr & MODE32_BIT) && !IS_ENABLED(CONFIG_ARM_MPU)) { | 405 | #ifdef CONFIG_MMU |
406 | if (cpsr & MODE32_BIT) { | ||
407 | struct mm_struct *mm = current->mm; | ||
408 | |||
404 | /* | 409 | /* |
405 | * 32-bit code can use the new high-page | 410 | * 32-bit code can use the signal return page |
406 | * signal return code support except when the MPU has | 411 | * except when the MPU has protected the vectors |
407 | * protected the vectors page from PL0 | 412 | * page from PL0 |
408 | */ | 413 | */ |
409 | retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb; | 414 | retcode = mm->context.sigpage + signal_return_offset + |
410 | } else { | 415 | (idx << 2) + thumb; |
416 | } else | ||
417 | #endif | ||
418 | { | ||
411 | /* | 419 | /* |
412 | * Ensure that the instruction cache sees | 420 | * Ensure that the instruction cache sees |
413 | * the return code written onto the stack. | 421 | * the return code written onto the stack. |
@@ -608,3 +616,33 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) | |||
608 | } while (thread_flags & _TIF_WORK_MASK); | 616 | } while (thread_flags & _TIF_WORK_MASK); |
609 | return 0; | 617 | return 0; |
610 | } | 618 | } |
619 | |||
620 | struct page *get_signal_page(void) | ||
621 | { | ||
622 | unsigned long ptr; | ||
623 | unsigned offset; | ||
624 | struct page *page; | ||
625 | void *addr; | ||
626 | |||
627 | page = alloc_pages(GFP_KERNEL, 0); | ||
628 | |||
629 | if (!page) | ||
630 | return NULL; | ||
631 | |||
632 | addr = page_address(page); | ||
633 | |||
634 | /* Give the signal return code some randomness */ | ||
635 | offset = 0x200 + (get_random_int() & 0x7fc); | ||
636 | signal_return_offset = offset; | ||
637 | |||
638 | /* | ||
639 | * Copy signal return handlers into the vector page, and | ||
640 | * set sigreturn to be a pointer to these. | ||
641 | */ | ||
642 | memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes)); | ||
643 | |||
644 | ptr = (unsigned long)addr + offset; | ||
645 | flush_icache_range(ptr, ptr + sizeof(sigreturn_codes)); | ||
646 | |||
647 | return page; | ||
648 | } | ||
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h deleted file mode 100644 index 5ff067b7c752..000000000000 --- a/arch/arm/kernel/signal.h +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
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]; | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index c5fb5469054b..2dc19349eb19 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -58,7 +58,7 @@ struct secondary_data secondary_data; | |||
58 | * control for which core is the next to come out of the secondary | 58 | * control for which core is the next to come out of the secondary |
59 | * boot "holding pen" | 59 | * boot "holding pen" |
60 | */ | 60 | */ |
61 | volatile int __cpuinitdata pen_release = -1; | 61 | volatile int pen_release = -1; |
62 | 62 | ||
63 | enum ipi_msg_type { | 63 | enum ipi_msg_type { |
64 | IPI_WAKEUP, | 64 | IPI_WAKEUP, |
@@ -86,7 +86,7 @@ static unsigned long get_arch_pgd(pgd_t *pgd) | |||
86 | return pgdir >> ARCH_PGD_SHIFT; | 86 | return pgdir >> ARCH_PGD_SHIFT; |
87 | } | 87 | } |
88 | 88 | ||
89 | int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | 89 | int __cpu_up(unsigned int cpu, struct task_struct *idle) |
90 | { | 90 | { |
91 | int ret; | 91 | int ret; |
92 | 92 | ||
@@ -138,13 +138,23 @@ void __init smp_init_cpus(void) | |||
138 | smp_ops.smp_init_cpus(); | 138 | smp_ops.smp_init_cpus(); |
139 | } | 139 | } |
140 | 140 | ||
141 | int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | 141 | int boot_secondary(unsigned int cpu, struct task_struct *idle) |
142 | { | 142 | { |
143 | if (smp_ops.smp_boot_secondary) | 143 | if (smp_ops.smp_boot_secondary) |
144 | return smp_ops.smp_boot_secondary(cpu, idle); | 144 | return smp_ops.smp_boot_secondary(cpu, idle); |
145 | return -ENOSYS; | 145 | return -ENOSYS; |
146 | } | 146 | } |
147 | 147 | ||
148 | int platform_can_cpu_hotplug(void) | ||
149 | { | ||
150 | #ifdef CONFIG_HOTPLUG_CPU | ||
151 | if (smp_ops.cpu_kill) | ||
152 | return 1; | ||
153 | #endif | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
148 | #ifdef CONFIG_HOTPLUG_CPU | 158 | #ifdef CONFIG_HOTPLUG_CPU |
149 | static void percpu_timer_stop(void); | 159 | static void percpu_timer_stop(void); |
150 | 160 | ||
@@ -170,7 +180,7 @@ static int platform_cpu_disable(unsigned int cpu) | |||
170 | /* | 180 | /* |
171 | * __cpu_disable runs on the processor to be shutdown. | 181 | * __cpu_disable runs on the processor to be shutdown. |
172 | */ | 182 | */ |
173 | int __cpuinit __cpu_disable(void) | 183 | int __cpu_disable(void) |
174 | { | 184 | { |
175 | unsigned int cpu = smp_processor_id(); | 185 | unsigned int cpu = smp_processor_id(); |
176 | int ret; | 186 | int ret; |
@@ -216,7 +226,7 @@ static DECLARE_COMPLETION(cpu_died); | |||
216 | * called on the thread which is asking for a CPU to be shutdown - | 226 | * called on the thread which is asking for a CPU to be shutdown - |
217 | * waits until shutdown has completed, or it is timed out. | 227 | * waits until shutdown has completed, or it is timed out. |
218 | */ | 228 | */ |
219 | void __cpuinit __cpu_die(unsigned int cpu) | 229 | void __cpu_die(unsigned int cpu) |
220 | { | 230 | { |
221 | if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) { | 231 | if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) { |
222 | pr_err("CPU%u: cpu didn't die\n", cpu); | 232 | pr_err("CPU%u: cpu didn't die\n", cpu); |
@@ -306,7 +316,7 @@ void __ref cpu_die(void) | |||
306 | * Called by both boot and secondaries to move global data into | 316 | * Called by both boot and secondaries to move global data into |
307 | * per-processor storage. | 317 | * per-processor storage. |
308 | */ | 318 | */ |
309 | static void __cpuinit smp_store_cpu_info(unsigned int cpuid) | 319 | static void smp_store_cpu_info(unsigned int cpuid) |
310 | { | 320 | { |
311 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); | 321 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); |
312 | 322 | ||
@@ -322,7 +332,7 @@ static void percpu_timer_setup(void); | |||
322 | * This is the secondary CPU boot entry. We're using this CPUs | 332 | * This is the secondary CPU boot entry. We're using this CPUs |
323 | * idle thread stack, but a set of temporary page tables. | 333 | * idle thread stack, but a set of temporary page tables. |
324 | */ | 334 | */ |
325 | asmlinkage void __cpuinit secondary_start_kernel(void) | 335 | asmlinkage void secondary_start_kernel(void) |
326 | { | 336 | { |
327 | struct mm_struct *mm = &init_mm; | 337 | struct mm_struct *mm = &init_mm; |
328 | unsigned int cpu; | 338 | unsigned int cpu; |
@@ -521,7 +531,7 @@ static void broadcast_timer_set_mode(enum clock_event_mode mode, | |||
521 | { | 531 | { |
522 | } | 532 | } |
523 | 533 | ||
524 | static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt) | 534 | static void broadcast_timer_setup(struct clock_event_device *evt) |
525 | { | 535 | { |
526 | evt->name = "dummy_timer"; | 536 | evt->name = "dummy_timer"; |
527 | evt->features = CLOCK_EVT_FEAT_ONESHOT | | 537 | evt->features = CLOCK_EVT_FEAT_ONESHOT | |
@@ -550,7 +560,7 @@ int local_timer_register(struct local_timer_ops *ops) | |||
550 | } | 560 | } |
551 | #endif | 561 | #endif |
552 | 562 | ||
553 | static void __cpuinit percpu_timer_setup(void) | 563 | static void percpu_timer_setup(void) |
554 | { | 564 | { |
555 | unsigned int cpu = smp_processor_id(); | 565 | unsigned int cpu = smp_processor_id(); |
556 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); | 566 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); |
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c index a98b62dca2fa..c2edfff573c2 100644 --- a/arch/arm/kernel/smp_tlb.c +++ b/arch/arm/kernel/smp_tlb.c | |||
@@ -70,23 +70,6 @@ static inline void ipi_flush_bp_all(void *ignored) | |||
70 | local_flush_bp_all(); | 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 | static void ipi_flush_tlb_a15_erratum(void *arg) | 73 | static void ipi_flush_tlb_a15_erratum(void *arg) |
91 | { | 74 | { |
92 | dmb(); | 75 | dmb(); |
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index f6fd1d4398c6..25956204ef23 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -187,7 +187,7 @@ core_initcall(twd_cpufreq_init); | |||
187 | 187 | ||
188 | #endif | 188 | #endif |
189 | 189 | ||
190 | static void __cpuinit twd_calibrate_rate(void) | 190 | static void twd_calibrate_rate(void) |
191 | { | 191 | { |
192 | unsigned long count; | 192 | unsigned long count; |
193 | u64 waitjiffies; | 193 | u64 waitjiffies; |
@@ -265,7 +265,7 @@ static void twd_get_clock(struct device_node *np) | |||
265 | /* | 265 | /* |
266 | * Setup the local clock events for a CPU. | 266 | * Setup the local clock events for a CPU. |
267 | */ | 267 | */ |
268 | static int __cpuinit twd_timer_setup(struct clock_event_device *clk) | 268 | static int twd_timer_setup(struct clock_event_device *clk) |
269 | { | 269 | { |
270 | struct clock_event_device **this_cpu_clk; | 270 | struct clock_event_device **this_cpu_clk; |
271 | int cpu = smp_processor_id(); | 271 | int cpu = smp_processor_id(); |
@@ -308,7 +308,7 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk) | |||
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | static struct local_timer_ops twd_lt_ops __cpuinitdata = { | 311 | static struct local_timer_ops twd_lt_ops = { |
312 | .setup = twd_timer_setup, | 312 | .setup = twd_timer_setup, |
313 | .stop = twd_timer_stop, | 313 | .stop = twd_timer_stop, |
314 | }; | 314 | }; |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index cab094c234ee..ab517fcce21b 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -35,8 +35,6 @@ | |||
35 | #include <asm/tls.h> | 35 | #include <asm/tls.h> |
36 | #include <asm/system_misc.h> | 36 | #include <asm/system_misc.h> |
37 | 37 | ||
38 | #include "signal.h" | ||
39 | |||
40 | static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; | 38 | static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; |
41 | 39 | ||
42 | void *vectors_page; | 40 | void *vectors_page; |
@@ -800,15 +798,26 @@ void __init trap_init(void) | |||
800 | return; | 798 | return; |
801 | } | 799 | } |
802 | 800 | ||
803 | static void __init kuser_get_tls_init(unsigned long vectors) | 801 | #ifdef CONFIG_KUSER_HELPERS |
802 | static void __init kuser_init(void *vectors) | ||
804 | { | 803 | { |
804 | extern char __kuser_helper_start[], __kuser_helper_end[]; | ||
805 | int kuser_sz = __kuser_helper_end - __kuser_helper_start; | ||
806 | |||
807 | memcpy(vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); | ||
808 | |||
805 | /* | 809 | /* |
806 | * vectors + 0xfe0 = __kuser_get_tls | 810 | * vectors + 0xfe0 = __kuser_get_tls |
807 | * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 | 811 | * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 |
808 | */ | 812 | */ |
809 | if (tls_emu || has_tls_reg) | 813 | if (tls_emu || has_tls_reg) |
810 | memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4); | 814 | memcpy(vectors + 0xfe0, vectors + 0xfe8, 4); |
811 | } | 815 | } |
816 | #else | ||
817 | static void __init kuser_init(void *vectors) | ||
818 | { | ||
819 | } | ||
820 | #endif | ||
812 | 821 | ||
813 | void __init early_trap_init(void *vectors_base) | 822 | void __init early_trap_init(void *vectors_base) |
814 | { | 823 | { |
@@ -816,33 +825,30 @@ void __init early_trap_init(void *vectors_base) | |||
816 | unsigned long vectors = (unsigned long)vectors_base; | 825 | unsigned long vectors = (unsigned long)vectors_base; |
817 | extern char __stubs_start[], __stubs_end[]; | 826 | extern char __stubs_start[], __stubs_end[]; |
818 | extern char __vectors_start[], __vectors_end[]; | 827 | extern char __vectors_start[], __vectors_end[]; |
819 | extern char __kuser_helper_start[], __kuser_helper_end[]; | 828 | unsigned i; |
820 | int kuser_sz = __kuser_helper_end - __kuser_helper_start; | ||
821 | 829 | ||
822 | vectors_page = vectors_base; | 830 | vectors_page = vectors_base; |
823 | 831 | ||
824 | /* | 832 | /* |
833 | * Poison the vectors page with an undefined instruction. This | ||
834 | * instruction is chosen to be undefined for both ARM and Thumb | ||
835 | * ISAs. The Thumb version is an undefined instruction with a | ||
836 | * branch back to the undefined instruction. | ||
837 | */ | ||
838 | for (i = 0; i < PAGE_SIZE / sizeof(u32); i++) | ||
839 | ((u32 *)vectors_base)[i] = 0xe7fddef1; | ||
840 | |||
841 | /* | ||
825 | * Copy the vectors, stubs and kuser helpers (in entry-armv.S) | 842 | * Copy the vectors, stubs and kuser helpers (in entry-armv.S) |
826 | * into the vector page, mapped at 0xffff0000, and ensure these | 843 | * into the vector page, mapped at 0xffff0000, and ensure these |
827 | * are visible to the instruction stream. | 844 | * are visible to the instruction stream. |
828 | */ | 845 | */ |
829 | memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); | 846 | memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); |
830 | memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); | 847 | memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start); |
831 | memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); | ||
832 | 848 | ||
833 | /* | 849 | kuser_init(vectors_base); |
834 | * Do processor specific fixups for the kuser helpers | ||
835 | */ | ||
836 | kuser_get_tls_init(vectors); | ||
837 | |||
838 | /* | ||
839 | * Copy signal return handlers into the vector page, and | ||
840 | * set sigreturn to be a pointer to these. | ||
841 | */ | ||
842 | memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), | ||
843 | sigreturn_codes, sizeof(sigreturn_codes)); | ||
844 | 850 | ||
845 | flush_icache_range(vectors, vectors + PAGE_SIZE); | 851 | flush_icache_range(vectors, vectors + PAGE_SIZE * 2); |
846 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); | 852 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); |
847 | #else /* ifndef CONFIG_CPU_V7M */ | 853 | #else /* ifndef CONFIG_CPU_V7M */ |
848 | /* | 854 | /* |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index fa25e4e425f6..7bcee5c9b604 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -148,6 +148,23 @@ SECTIONS | |||
148 | . = ALIGN(PAGE_SIZE); | 148 | . = ALIGN(PAGE_SIZE); |
149 | __init_begin = .; | 149 | __init_begin = .; |
150 | #endif | 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 | INIT_TEXT_SECTION(8) | 169 | INIT_TEXT_SECTION(8) |
153 | .exit.text : { | 170 | .exit.text : { |