diff options
Diffstat (limited to 'arch')
439 files changed, 27879 insertions, 3316 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 72f2fa189cc5..a62965d057f6 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -222,6 +222,19 @@ config HAVE_PERF_EVENTS_NMI | |||
222 | subsystem. Also has support for calculating CPU cycle events | 222 | subsystem. Also has support for calculating CPU cycle events |
223 | to determine how many clock cycles in a given period. | 223 | to determine how many clock cycles in a given period. |
224 | 224 | ||
225 | config HAVE_PERF_REGS | ||
226 | bool | ||
227 | help | ||
228 | Support selective register dumps for perf events. This includes | ||
229 | bit-mapping of each registers and a unique architecture id. | ||
230 | |||
231 | config HAVE_PERF_USER_STACK_DUMP | ||
232 | bool | ||
233 | help | ||
234 | Support user stack dumps for perf event samples. This needs | ||
235 | access to the user stack pointer which is not unified across | ||
236 | architectures. | ||
237 | |||
225 | config HAVE_ARCH_JUMP_LABEL | 238 | config HAVE_ARCH_JUMP_LABEL |
226 | bool | 239 | bool |
227 | 240 | ||
@@ -281,4 +294,23 @@ config SECCOMP_FILTER | |||
281 | 294 | ||
282 | See Documentation/prctl/seccomp_filter.txt for details. | 295 | See Documentation/prctl/seccomp_filter.txt for details. |
283 | 296 | ||
297 | config HAVE_RCU_USER_QS | ||
298 | bool | ||
299 | help | ||
300 | Provide kernel entry/exit hooks necessary for userspace | ||
301 | RCU extended quiescent state. Syscalls need to be wrapped inside | ||
302 | rcu_user_exit()-rcu_user_enter() through the slow path using | ||
303 | TIF_NOHZ flag. Exceptions handlers must be wrapped as well. Irqs | ||
304 | are already protected inside rcu_irq_enter/rcu_irq_exit() but | ||
305 | preemption or signal handling on irq exit still need to be protected. | ||
306 | |||
307 | config HAVE_VIRT_CPU_ACCOUNTING | ||
308 | bool | ||
309 | |||
310 | config HAVE_IRQ_TIME_ACCOUNTING | ||
311 | bool | ||
312 | help | ||
313 | Archs need to ensure they use a high enough resolution clock to | ||
314 | support irq time accounting and then call enable_sched_clock_irqtime(). | ||
315 | |||
284 | source "kernel/gcov/Kconfig" | 316 | source "kernel/gcov/Kconfig" |
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index d6fde98b74b3..83638aa096d5 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
29 | #include <linux/console.h> | 29 | #include <linux/console.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/rcupdate.h> | ||
31 | 32 | ||
32 | #include <asm/reg.h> | 33 | #include <asm/reg.h> |
33 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
@@ -54,9 +55,12 @@ cpu_idle(void) | |||
54 | /* FIXME -- EV6 and LCA45 know how to power down | 55 | /* FIXME -- EV6 and LCA45 know how to power down |
55 | the CPU. */ | 56 | the CPU. */ |
56 | 57 | ||
58 | rcu_idle_enter(); | ||
57 | while (!need_resched()) | 59 | while (!need_resched()) |
58 | cpu_relax(); | 60 | cpu_relax(); |
59 | schedule(); | 61 | |
62 | rcu_idle_exit(); | ||
63 | schedule_preempt_disabled(); | ||
60 | } | 64 | } |
61 | } | 65 | } |
62 | 66 | ||
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 35ddc02bfa4a..a41ad90a97a6 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c | |||
@@ -166,6 +166,7 @@ smp_callin(void) | |||
166 | DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n", | 166 | DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n", |
167 | cpuid, current, current->active_mm)); | 167 | cpuid, current, current->active_mm)); |
168 | 168 | ||
169 | preempt_disable(); | ||
169 | /* Do nothing. */ | 170 | /* Do nothing. */ |
170 | cpu_idle(); | 171 | cpu_idle(); |
171 | } | 172 | } |
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..bc67cbff3944 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S | |||
@@ -653,16 +653,21 @@ __armv7_mmu_cache_on: | |||
653 | mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs | 653 | mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs |
654 | #endif | 654 | #endif |
655 | mrc p15, 0, r0, c1, c0, 0 @ read control reg | 655 | mrc p15, 0, r0, c1, c0, 0 @ read control reg |
656 | bic r0, r0, #1 << 28 @ clear SCTLR.TRE | ||
656 | orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement | 657 | orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement |
657 | orr r0, r0, #0x003c @ write buffer | 658 | orr r0, r0, #0x003c @ write buffer |
658 | #ifdef CONFIG_MMU | 659 | #ifdef CONFIG_MMU |
659 | #ifdef CONFIG_CPU_ENDIAN_BE8 | 660 | #ifdef CONFIG_CPU_ENDIAN_BE8 |
660 | orr r0, r0, #1 << 25 @ big-endian page tables | 661 | orr r0, r0, #1 << 25 @ big-endian page tables |
661 | #endif | 662 | #endif |
663 | mrcne p15, 0, r6, c2, c0, 2 @ read ttb control reg | ||
662 | orrne r0, r0, #1 @ MMU enabled | 664 | orrne r0, r0, #1 @ MMU enabled |
663 | movne r1, #0xfffffffd @ domain 0 = client | 665 | movne r1, #0xfffffffd @ domain 0 = client |
666 | bic r6, r6, #1 << 31 @ 32-bit translation system | ||
667 | bic r6, r6, #3 << 0 @ use only ttbr0 | ||
664 | mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer | 668 | mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer |
665 | mcrne p15, 0, r1, c3, c0, 0 @ load domain access control | 669 | mcrne p15, 0, r1, c3, c0, 0 @ load domain access control |
670 | mcrne p15, 0, r6, c2, c0, 2 @ load ttb control | ||
666 | #endif | 671 | #endif |
667 | mcr p15, 0, r0, c7, c5, 4 @ ISB | 672 | mcr p15, 0, r0, c7, c5, 4 @ ISB |
668 | mcr p15, 0, r0, c1, c0, 0 @ load control register | 673 | mcr p15, 0, r0, c1, c0, 0 @ load control register |
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index 66389c1c6f62..7c95f76398de 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi | |||
@@ -104,6 +104,7 @@ | |||
104 | #gpio-cells = <2>; | 104 | #gpio-cells = <2>; |
105 | gpio-controller; | 105 | gpio-controller; |
106 | interrupt-controller; | 106 | interrupt-controller; |
107 | #interrupt-cells = <2>; | ||
107 | }; | 108 | }; |
108 | 109 | ||
109 | pioB: gpio@fffff600 { | 110 | pioB: gpio@fffff600 { |
@@ -113,6 +114,7 @@ | |||
113 | #gpio-cells = <2>; | 114 | #gpio-cells = <2>; |
114 | gpio-controller; | 115 | gpio-controller; |
115 | interrupt-controller; | 116 | interrupt-controller; |
117 | #interrupt-cells = <2>; | ||
116 | }; | 118 | }; |
117 | 119 | ||
118 | pioC: gpio@fffff800 { | 120 | pioC: gpio@fffff800 { |
@@ -122,6 +124,7 @@ | |||
122 | #gpio-cells = <2>; | 124 | #gpio-cells = <2>; |
123 | gpio-controller; | 125 | gpio-controller; |
124 | interrupt-controller; | 126 | interrupt-controller; |
127 | #interrupt-cells = <2>; | ||
125 | }; | 128 | }; |
126 | 129 | ||
127 | dbgu: serial@fffff200 { | 130 | dbgu: serial@fffff200 { |
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi index b460d6ce9eb5..195019b7ca0e 100644 --- a/arch/arm/boot/dts/at91sam9263.dtsi +++ b/arch/arm/boot/dts/at91sam9263.dtsi | |||
@@ -95,6 +95,7 @@ | |||
95 | #gpio-cells = <2>; | 95 | #gpio-cells = <2>; |
96 | gpio-controller; | 96 | gpio-controller; |
97 | interrupt-controller; | 97 | interrupt-controller; |
98 | #interrupt-cells = <2>; | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | pioB: gpio@fffff400 { | 101 | pioB: gpio@fffff400 { |
@@ -104,6 +105,7 @@ | |||
104 | #gpio-cells = <2>; | 105 | #gpio-cells = <2>; |
105 | gpio-controller; | 106 | gpio-controller; |
106 | interrupt-controller; | 107 | interrupt-controller; |
108 | #interrupt-cells = <2>; | ||
107 | }; | 109 | }; |
108 | 110 | ||
109 | pioC: gpio@fffff600 { | 111 | pioC: gpio@fffff600 { |
@@ -113,6 +115,7 @@ | |||
113 | #gpio-cells = <2>; | 115 | #gpio-cells = <2>; |
114 | gpio-controller; | 116 | gpio-controller; |
115 | interrupt-controller; | 117 | interrupt-controller; |
118 | #interrupt-cells = <2>; | ||
116 | }; | 119 | }; |
117 | 120 | ||
118 | pioD: gpio@fffff800 { | 121 | pioD: gpio@fffff800 { |
@@ -122,6 +125,7 @@ | |||
122 | #gpio-cells = <2>; | 125 | #gpio-cells = <2>; |
123 | gpio-controller; | 126 | gpio-controller; |
124 | interrupt-controller; | 127 | interrupt-controller; |
128 | #interrupt-cells = <2>; | ||
125 | }; | 129 | }; |
126 | 130 | ||
127 | pioE: gpio@fffffa00 { | 131 | pioE: gpio@fffffa00 { |
@@ -131,6 +135,7 @@ | |||
131 | #gpio-cells = <2>; | 135 | #gpio-cells = <2>; |
132 | gpio-controller; | 136 | gpio-controller; |
133 | interrupt-controller; | 137 | interrupt-controller; |
138 | #interrupt-cells = <2>; | ||
134 | }; | 139 | }; |
135 | 140 | ||
136 | dbgu: serial@ffffee00 { | 141 | dbgu: serial@ffffee00 { |
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index bafa8806fc17..63751b1e744b 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi | |||
@@ -113,6 +113,7 @@ | |||
113 | #gpio-cells = <2>; | 113 | #gpio-cells = <2>; |
114 | gpio-controller; | 114 | gpio-controller; |
115 | interrupt-controller; | 115 | interrupt-controller; |
116 | #interrupt-cells = <2>; | ||
116 | }; | 117 | }; |
117 | 118 | ||
118 | pioB: gpio@fffff400 { | 119 | pioB: gpio@fffff400 { |
@@ -122,6 +123,7 @@ | |||
122 | #gpio-cells = <2>; | 123 | #gpio-cells = <2>; |
123 | gpio-controller; | 124 | gpio-controller; |
124 | interrupt-controller; | 125 | interrupt-controller; |
126 | #interrupt-cells = <2>; | ||
125 | }; | 127 | }; |
126 | 128 | ||
127 | pioC: gpio@fffff600 { | 129 | pioC: gpio@fffff600 { |
@@ -131,6 +133,7 @@ | |||
131 | #gpio-cells = <2>; | 133 | #gpio-cells = <2>; |
132 | gpio-controller; | 134 | gpio-controller; |
133 | interrupt-controller; | 135 | interrupt-controller; |
136 | #interrupt-cells = <2>; | ||
134 | }; | 137 | }; |
135 | 138 | ||
136 | pioD: gpio@fffff800 { | 139 | pioD: gpio@fffff800 { |
@@ -140,6 +143,7 @@ | |||
140 | #gpio-cells = <2>; | 143 | #gpio-cells = <2>; |
141 | gpio-controller; | 144 | gpio-controller; |
142 | interrupt-controller; | 145 | interrupt-controller; |
146 | #interrupt-cells = <2>; | ||
143 | }; | 147 | }; |
144 | 148 | ||
145 | pioE: gpio@fffffa00 { | 149 | pioE: gpio@fffffa00 { |
@@ -149,6 +153,7 @@ | |||
149 | #gpio-cells = <2>; | 153 | #gpio-cells = <2>; |
150 | gpio-controller; | 154 | gpio-controller; |
151 | interrupt-controller; | 155 | interrupt-controller; |
156 | #interrupt-cells = <2>; | ||
152 | }; | 157 | }; |
153 | 158 | ||
154 | dbgu: serial@ffffee00 { | 159 | dbgu: serial@ffffee00 { |
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi index bfac0dfc332c..ef9336ae9614 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/at91sam9n12.dtsi | |||
@@ -107,6 +107,7 @@ | |||
107 | #gpio-cells = <2>; | 107 | #gpio-cells = <2>; |
108 | gpio-controller; | 108 | gpio-controller; |
109 | interrupt-controller; | 109 | interrupt-controller; |
110 | #interrupt-cells = <2>; | ||
110 | }; | 111 | }; |
111 | 112 | ||
112 | pioB: gpio@fffff600 { | 113 | pioB: gpio@fffff600 { |
@@ -116,6 +117,7 @@ | |||
116 | #gpio-cells = <2>; | 117 | #gpio-cells = <2>; |
117 | gpio-controller; | 118 | gpio-controller; |
118 | interrupt-controller; | 119 | interrupt-controller; |
120 | #interrupt-cells = <2>; | ||
119 | }; | 121 | }; |
120 | 122 | ||
121 | pioC: gpio@fffff800 { | 123 | pioC: gpio@fffff800 { |
@@ -125,6 +127,7 @@ | |||
125 | #gpio-cells = <2>; | 127 | #gpio-cells = <2>; |
126 | gpio-controller; | 128 | gpio-controller; |
127 | interrupt-controller; | 129 | interrupt-controller; |
130 | #interrupt-cells = <2>; | ||
128 | }; | 131 | }; |
129 | 132 | ||
130 | pioD: gpio@fffffa00 { | 133 | pioD: gpio@fffffa00 { |
@@ -134,6 +137,7 @@ | |||
134 | #gpio-cells = <2>; | 137 | #gpio-cells = <2>; |
135 | gpio-controller; | 138 | gpio-controller; |
136 | interrupt-controller; | 139 | interrupt-controller; |
140 | #interrupt-cells = <2>; | ||
137 | }; | 141 | }; |
138 | 142 | ||
139 | dbgu: serial@fffff200 { | 143 | dbgu: serial@fffff200 { |
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 4a18c393b136..8a387a8d61b7 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi | |||
@@ -115,6 +115,7 @@ | |||
115 | #gpio-cells = <2>; | 115 | #gpio-cells = <2>; |
116 | gpio-controller; | 116 | gpio-controller; |
117 | interrupt-controller; | 117 | interrupt-controller; |
118 | #interrupt-cells = <2>; | ||
118 | }; | 119 | }; |
119 | 120 | ||
120 | pioB: gpio@fffff600 { | 121 | pioB: gpio@fffff600 { |
@@ -124,6 +125,7 @@ | |||
124 | #gpio-cells = <2>; | 125 | #gpio-cells = <2>; |
125 | gpio-controller; | 126 | gpio-controller; |
126 | interrupt-controller; | 127 | interrupt-controller; |
128 | #interrupt-cells = <2>; | ||
127 | }; | 129 | }; |
128 | 130 | ||
129 | pioC: gpio@fffff800 { | 131 | pioC: gpio@fffff800 { |
@@ -133,6 +135,7 @@ | |||
133 | #gpio-cells = <2>; | 135 | #gpio-cells = <2>; |
134 | gpio-controller; | 136 | gpio-controller; |
135 | interrupt-controller; | 137 | interrupt-controller; |
138 | #interrupt-cells = <2>; | ||
136 | }; | 139 | }; |
137 | 140 | ||
138 | pioD: gpio@fffffa00 { | 141 | pioD: gpio@fffffa00 { |
@@ -142,6 +145,7 @@ | |||
142 | #gpio-cells = <2>; | 145 | #gpio-cells = <2>; |
143 | gpio-controller; | 146 | gpio-controller; |
144 | interrupt-controller; | 147 | interrupt-controller; |
148 | #interrupt-cells = <2>; | ||
145 | }; | 149 | }; |
146 | 150 | ||
147 | dbgu: serial@fffff200 { | 151 | dbgu: serial@fffff200 { |
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/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 0cab47d4a83f..2fde5fd1acce 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h | |||
@@ -404,6 +404,7 @@ | |||
404 | #define __NR_setns (__NR_SYSCALL_BASE+375) | 404 | #define __NR_setns (__NR_SYSCALL_BASE+375) |
405 | #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) | 405 | #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) |
406 | #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) | 406 | #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) |
407 | /* 378 for kcmp */ | ||
407 | 408 | ||
408 | /* | 409 | /* |
409 | * The following SWIs are ARM private. | 410 | * The following SWIs are ARM private. |
@@ -483,6 +484,7 @@ | |||
483 | */ | 484 | */ |
484 | #define __IGNORE_fadvise64_64 | 485 | #define __IGNORE_fadvise64_64 |
485 | #define __IGNORE_migrate_pages | 486 | #define __IGNORE_migrate_pages |
487 | #define __IGNORE_kcmp | ||
486 | 488 | ||
487 | #endif /* __KERNEL__ */ | 489 | #endif /* __KERNEL__ */ |
488 | #endif /* __ASM_ARM_UNISTD_H */ | 490 | #endif /* __ASM_ARM_UNISTD_H */ |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 463ff4a0ec8a..e337879595e5 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -387,6 +387,7 @@ | |||
387 | /* 375 */ CALL(sys_setns) | 387 | /* 375 */ CALL(sys_setns) |
388 | CALL(sys_process_vm_readv) | 388 | CALL(sys_process_vm_readv) |
389 | CALL(sys_process_vm_writev) | 389 | CALL(sys_process_vm_writev) |
390 | CALL(sys_ni_syscall) /* reserved for sys_kcmp */ | ||
390 | #ifndef syscalls_counted | 391 | #ifndef syscalls_counted |
391 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls | 392 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls |
392 | #define syscalls_counted | 393 | #define syscalls_counted |
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/smp_twd.c b/arch/arm/kernel/smp_twd.c index fef42b21cecb..e1f906989bb8 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
14 | #include <linux/cpufreq.h> | ||
15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
16 | #include <linux/device.h> | 15 | #include <linux/device.h> |
17 | #include <linux/err.h> | 16 | #include <linux/err.h> |
@@ -96,7 +95,52 @@ static void twd_timer_stop(struct clock_event_device *clk) | |||
96 | disable_percpu_irq(clk->irq); | 95 | disable_percpu_irq(clk->irq); |
97 | } | 96 | } |
98 | 97 | ||
99 | #ifdef CONFIG_CPU_FREQ | 98 | #ifdef CONFIG_COMMON_CLK |
99 | |||
100 | /* | ||
101 | * Updates clockevent frequency when the cpu frequency changes. | ||
102 | * Called on the cpu that is changing frequency with interrupts disabled. | ||
103 | */ | ||
104 | static void twd_update_frequency(void *new_rate) | ||
105 | { | ||
106 | twd_timer_rate = *((unsigned long *) new_rate); | ||
107 | |||
108 | clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); | ||
109 | } | ||
110 | |||
111 | static int twd_rate_change(struct notifier_block *nb, | ||
112 | unsigned long flags, void *data) | ||
113 | { | ||
114 | struct clk_notifier_data *cnd = data; | ||
115 | |||
116 | /* | ||
117 | * The twd clock events must be reprogrammed to account for the new | ||
118 | * frequency. The timer is local to a cpu, so cross-call to the | ||
119 | * changing cpu. | ||
120 | */ | ||
121 | if (flags == POST_RATE_CHANGE) | ||
122 | smp_call_function(twd_update_frequency, | ||
123 | (void *)&cnd->new_rate, 1); | ||
124 | |||
125 | return NOTIFY_OK; | ||
126 | } | ||
127 | |||
128 | static struct notifier_block twd_clk_nb = { | ||
129 | .notifier_call = twd_rate_change, | ||
130 | }; | ||
131 | |||
132 | static int twd_clk_init(void) | ||
133 | { | ||
134 | if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) | ||
135 | return clk_notifier_register(twd_clk, &twd_clk_nb); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | core_initcall(twd_clk_init); | ||
140 | |||
141 | #elif defined (CONFIG_CPU_FREQ) | ||
142 | |||
143 | #include <linux/cpufreq.h> | ||
100 | 144 | ||
101 | /* | 145 | /* |
102 | * Updates clockevent frequency when the cpu frequency changes. | 146 | * Updates clockevent frequency when the cpu frequency changes. |
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/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c index fdd8cc87c9fe..d20d4795f4ea 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/arch/arm/mach-imx/clk-imx25.c | |||
@@ -222,10 +222,8 @@ int __init mx25_clocks_init(void) | |||
222 | clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0"); | 222 | clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0"); |
223 | clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0"); | 223 | clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0"); |
224 | clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0"); | 224 | clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0"); |
225 | clk_register_clkdev(clk[ssi1_ipg_per], "per", "imx-ssi.0"); | 225 | clk_register_clkdev(clk[ssi1_ipg], NULL, "imx-ssi.0"); |
226 | clk_register_clkdev(clk[ssi1_ipg], "ipg", "imx-ssi.0"); | 226 | clk_register_clkdev(clk[ssi2_ipg], NULL, "imx-ssi.1"); |
227 | clk_register_clkdev(clk[ssi2_ipg_per], "per", "imx-ssi.1"); | ||
228 | clk_register_clkdev(clk[ssi2_ipg], "ipg", "imx-ssi.1"); | ||
229 | clk_register_clkdev(clk[esdhc1_ipg_per], "per", "sdhci-esdhc-imx25.0"); | 227 | clk_register_clkdev(clk[esdhc1_ipg_per], "per", "sdhci-esdhc-imx25.0"); |
230 | clk_register_clkdev(clk[esdhc1_ipg], "ipg", "sdhci-esdhc-imx25.0"); | 228 | clk_register_clkdev(clk[esdhc1_ipg], "ipg", "sdhci-esdhc-imx25.0"); |
231 | clk_register_clkdev(clk[esdhc1_ahb], "ahb", "sdhci-esdhc-imx25.0"); | 229 | clk_register_clkdev(clk[esdhc1_ahb], "ahb", "sdhci-esdhc-imx25.0"); |
@@ -243,6 +241,6 @@ int __init mx25_clocks_init(void) | |||
243 | clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma"); | 241 | clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma"); |
244 | clk_register_clkdev(clk[iim_ipg], "iim", NULL); | 242 | clk_register_clkdev(clk[iim_ipg], "iim", NULL); |
245 | 243 | ||
246 | mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54); | 244 | mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), MX25_INT_GPT1); |
247 | return 0; | 245 | return 0; |
248 | } | 246 | } |
diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index c6422fb10bae..65fb8bcd86cb 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c | |||
@@ -230,10 +230,8 @@ int __init mx35_clocks_init() | |||
230 | clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); | 230 | clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); |
231 | clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1"); | 231 | clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1"); |
232 | clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma"); | 232 | clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma"); |
233 | clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.0"); | 233 | clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0"); |
234 | clk_register_clkdev(clk[ssi1_div_post], "per", "imx-ssi.0"); | 234 | clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1"); |
235 | clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.1"); | ||
236 | clk_register_clkdev(clk[ssi2_div_post], "per", "imx-ssi.1"); | ||
237 | /* i.mx35 has the i.mx21 type uart */ | 235 | /* i.mx35 has the i.mx21 type uart */ |
238 | clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); | 236 | clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); |
239 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0"); | 237 | clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0"); |
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c index 2c6ab3273f9e..5985ed1b8c98 100644 --- a/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/arch/arm/mach-imx/mach-armadillo5x0.c | |||
@@ -526,7 +526,8 @@ static void __init armadillo5x0_init(void) | |||
526 | imx31_add_mxc_nand(&armadillo5x0_nand_board_info); | 526 | imx31_add_mxc_nand(&armadillo5x0_nand_board_info); |
527 | 527 | ||
528 | /* set NAND page size to 2k if not configured via boot mode pins */ | 528 | /* set NAND page size to 2k if not configured via boot mode pins */ |
529 | __raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR); | 529 | __raw_writel(__raw_readl(mx3_ccm_base + MXC_CCM_RCSR) | |
530 | (1 << 30), mx3_ccm_base + MXC_CCM_RCSR); | ||
530 | 531 | ||
531 | /* RTC */ | 532 | /* RTC */ |
532 | /* Get RTC IRQ and register the chip */ | 533 | /* Get RTC IRQ and register the chip */ |
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 8dabfe81d07c..ff886e01a0b0 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c | |||
@@ -261,7 +261,7 @@ static void __init apx4devkit_init(void) | |||
261 | enable_clk_enet_out(); | 261 | enable_clk_enet_out(); |
262 | 262 | ||
263 | if (IS_BUILTIN(CONFIG_PHYLIB)) | 263 | if (IS_BUILTIN(CONFIG_PHYLIB)) |
264 | phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK, | 264 | phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, |
265 | apx4devkit_phy_fixup); | 265 | apx4devkit_phy_fixup); |
266 | 266 | ||
267 | mxsfb_pdata.mode_list = apx4devkit_video_modes; | 267 | mxsfb_pdata.mode_list = apx4devkit_video_modes; |
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index fcd4e85c4ddc..346fd26f3aa6 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -232,10 +232,11 @@ config MACH_OMAP3_PANDORA | |||
232 | select OMAP_PACKAGE_CBB | 232 | select OMAP_PACKAGE_CBB |
233 | select REGULATOR_FIXED_VOLTAGE if REGULATOR | 233 | select REGULATOR_FIXED_VOLTAGE if REGULATOR |
234 | 234 | ||
235 | config MACH_OMAP3_TOUCHBOOK | 235 | config MACH_TOUCHBOOK |
236 | bool "OMAP3 Touch Book" | 236 | bool "OMAP3 Touch Book" |
237 | depends on ARCH_OMAP3 | 237 | depends on ARCH_OMAP3 |
238 | default y | 238 | default y |
239 | select OMAP_PACKAGE_CBB | ||
239 | 240 | ||
240 | config MACH_OMAP_3430SDP | 241 | config MACH_OMAP_3430SDP |
241 | bool "OMAP 3430 SDP board" | 242 | bool "OMAP 3430 SDP board" |
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index f6a24b3f9c4f..34c2c7f59f0a 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -255,7 +255,7 @@ obj-$(CONFIG_MACH_OMAP_3630SDP) += board-zoom-display.o | |||
255 | obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o | 255 | obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o |
256 | obj-$(CONFIG_MACH_CM_T3517) += board-cm-t3517.o | 256 | obj-$(CONFIG_MACH_CM_T3517) += board-cm-t3517.o |
257 | obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o | 257 | obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o |
258 | obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o | 258 | obj-$(CONFIG_MACH_TOUCHBOOK) += board-omap3touchbook.o |
259 | obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o | 259 | obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o |
260 | obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o | 260 | obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o |
261 | 261 | ||
diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c index 25bbcc7ca4dc..ae27de8899a6 100644 --- a/arch/arm/mach-omap2/clock33xx_data.c +++ b/arch/arm/mach-omap2/clock33xx_data.c | |||
@@ -1036,13 +1036,13 @@ static struct omap_clk am33xx_clks[] = { | |||
1036 | CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX), | 1036 | CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX), |
1037 | CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX), | 1037 | CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX), |
1038 | CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX), | 1038 | CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX), |
1039 | CLK(NULL, "gpt1_fck", &timer1_fck, CK_AM33XX), | 1039 | CLK(NULL, "timer1_fck", &timer1_fck, CK_AM33XX), |
1040 | CLK(NULL, "gpt2_fck", &timer2_fck, CK_AM33XX), | 1040 | CLK(NULL, "timer2_fck", &timer2_fck, CK_AM33XX), |
1041 | CLK(NULL, "gpt3_fck", &timer3_fck, CK_AM33XX), | 1041 | CLK(NULL, "timer3_fck", &timer3_fck, CK_AM33XX), |
1042 | CLK(NULL, "gpt4_fck", &timer4_fck, CK_AM33XX), | 1042 | CLK(NULL, "timer4_fck", &timer4_fck, CK_AM33XX), |
1043 | CLK(NULL, "gpt5_fck", &timer5_fck, CK_AM33XX), | 1043 | CLK(NULL, "timer5_fck", &timer5_fck, CK_AM33XX), |
1044 | CLK(NULL, "gpt6_fck", &timer6_fck, CK_AM33XX), | 1044 | CLK(NULL, "timer6_fck", &timer6_fck, CK_AM33XX), |
1045 | CLK(NULL, "gpt7_fck", &timer7_fck, CK_AM33XX), | 1045 | CLK(NULL, "timer7_fck", &timer7_fck, CK_AM33XX), |
1046 | CLK(NULL, "usbotg_fck", &usbotg_fck, CK_AM33XX), | 1046 | CLK(NULL, "usbotg_fck", &usbotg_fck, CK_AM33XX), |
1047 | CLK(NULL, "ieee5000_fck", &ieee5000_fck, CK_AM33XX), | 1047 | CLK(NULL, "ieee5000_fck", &ieee5000_fck, CK_AM33XX), |
1048 | CLK(NULL, "wdt1_fck", &wdt1_fck, CK_AM33XX), | 1048 | CLK(NULL, "wdt1_fck", &wdt1_fck, CK_AM33XX), |
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index a0d68dbecfa3..f99e65cfb862 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | |||
@@ -241,6 +241,52 @@ static void omap3_clkdm_deny_idle(struct clockdomain *clkdm) | |||
241 | _clkdm_del_autodeps(clkdm); | 241 | _clkdm_del_autodeps(clkdm); |
242 | } | 242 | } |
243 | 243 | ||
244 | static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm) | ||
245 | { | ||
246 | bool hwsup = false; | ||
247 | |||
248 | if (!clkdm->clktrctrl_mask) | ||
249 | return 0; | ||
250 | |||
251 | hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
252 | clkdm->clktrctrl_mask); | ||
253 | |||
254 | if (hwsup) { | ||
255 | /* Disable HW transitions when we are changing deps */ | ||
256 | _disable_hwsup(clkdm); | ||
257 | _clkdm_add_autodeps(clkdm); | ||
258 | _enable_hwsup(clkdm); | ||
259 | } else { | ||
260 | if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) | ||
261 | omap3_clkdm_wakeup(clkdm); | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm) | ||
268 | { | ||
269 | bool hwsup = false; | ||
270 | |||
271 | if (!clkdm->clktrctrl_mask) | ||
272 | return 0; | ||
273 | |||
274 | hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, | ||
275 | clkdm->clktrctrl_mask); | ||
276 | |||
277 | if (hwsup) { | ||
278 | /* Disable HW transitions when we are changing deps */ | ||
279 | _disable_hwsup(clkdm); | ||
280 | _clkdm_del_autodeps(clkdm); | ||
281 | _enable_hwsup(clkdm); | ||
282 | } else { | ||
283 | if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP) | ||
284 | omap3_clkdm_sleep(clkdm); | ||
285 | } | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
244 | struct clkdm_ops omap2_clkdm_operations = { | 290 | struct clkdm_ops omap2_clkdm_operations = { |
245 | .clkdm_add_wkdep = omap2_clkdm_add_wkdep, | 291 | .clkdm_add_wkdep = omap2_clkdm_add_wkdep, |
246 | .clkdm_del_wkdep = omap2_clkdm_del_wkdep, | 292 | .clkdm_del_wkdep = omap2_clkdm_del_wkdep, |
@@ -267,6 +313,6 @@ struct clkdm_ops omap3_clkdm_operations = { | |||
267 | .clkdm_wakeup = omap3_clkdm_wakeup, | 313 | .clkdm_wakeup = omap3_clkdm_wakeup, |
268 | .clkdm_allow_idle = omap3_clkdm_allow_idle, | 314 | .clkdm_allow_idle = omap3_clkdm_allow_idle, |
269 | .clkdm_deny_idle = omap3_clkdm_deny_idle, | 315 | .clkdm_deny_idle = omap3_clkdm_deny_idle, |
270 | .clkdm_clk_enable = omap2_clkdm_clk_enable, | 316 | .clkdm_clk_enable = omap3xxx_clkdm_clk_enable, |
271 | .clkdm_clk_disable = omap2_clkdm_clk_disable, | 317 | .clkdm_clk_disable = omap3xxx_clkdm_clk_disable, |
272 | }; | 318 | }; |
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index 766338fe4d34..975f6bda0e0b 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h | |||
@@ -67,6 +67,7 @@ | |||
67 | #define OMAP3430_EN_IVA2_DPLL_MASK (0x7 << 0) | 67 | #define OMAP3430_EN_IVA2_DPLL_MASK (0x7 << 0) |
68 | 68 | ||
69 | /* CM_IDLEST_IVA2 */ | 69 | /* CM_IDLEST_IVA2 */ |
70 | #define OMAP3430_ST_IVA2_SHIFT 0 | ||
70 | #define OMAP3430_ST_IVA2_MASK (1 << 0) | 71 | #define OMAP3430_ST_IVA2_MASK (1 << 0) |
71 | 72 | ||
72 | /* CM_IDLEST_PLL_IVA2 */ | 73 | /* CM_IDLEST_PLL_IVA2 */ |
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 05fdebfaa195..330d4c6e746b 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c | |||
@@ -46,7 +46,7 @@ | |||
46 | static void __iomem *wakeupgen_base; | 46 | static void __iomem *wakeupgen_base; |
47 | static void __iomem *sar_base; | 47 | static void __iomem *sar_base; |
48 | static DEFINE_SPINLOCK(wakeupgen_lock); | 48 | static DEFINE_SPINLOCK(wakeupgen_lock); |
49 | static unsigned int irq_target_cpu[NR_IRQS]; | 49 | static unsigned int irq_target_cpu[MAX_IRQS]; |
50 | static unsigned int irq_banks = MAX_NR_REG_BANKS; | 50 | static unsigned int irq_banks = MAX_NR_REG_BANKS; |
51 | static unsigned int max_irqs = MAX_IRQS; | 51 | static unsigned int max_irqs = MAX_IRQS; |
52 | static unsigned int omap_secure_apis; | 52 | static unsigned int omap_secure_apis; |
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 6ca8e519968d..37afbd173c2c 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -1889,6 +1889,7 @@ static int _enable(struct omap_hwmod *oh) | |||
1889 | _enable_sysc(oh); | 1889 | _enable_sysc(oh); |
1890 | } | 1890 | } |
1891 | } else { | 1891 | } else { |
1892 | _omap4_disable_module(oh); | ||
1892 | _disable_clocks(oh); | 1893 | _disable_clocks(oh); |
1893 | pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", | 1894 | pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n", |
1894 | oh->name, r); | 1895 | oh->name, r); |
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index c9e38200216b..ce7e6068768f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | |||
@@ -100,9 +100,9 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = { | |||
100 | 100 | ||
101 | /* IVA2 (IVA2) */ | 101 | /* IVA2 (IVA2) */ |
102 | static struct omap_hwmod_rst_info omap3xxx_iva_resets[] = { | 102 | static struct omap_hwmod_rst_info omap3xxx_iva_resets[] = { |
103 | { .name = "logic", .rst_shift = 0 }, | 103 | { .name = "logic", .rst_shift = 0, .st_shift = 8 }, |
104 | { .name = "seq0", .rst_shift = 1 }, | 104 | { .name = "seq0", .rst_shift = 1, .st_shift = 9 }, |
105 | { .name = "seq1", .rst_shift = 2 }, | 105 | { .name = "seq1", .rst_shift = 2, .st_shift = 10 }, |
106 | }; | 106 | }; |
107 | 107 | ||
108 | static struct omap_hwmod omap3xxx_iva_hwmod = { | 108 | static struct omap_hwmod omap3xxx_iva_hwmod = { |
@@ -112,6 +112,15 @@ static struct omap_hwmod omap3xxx_iva_hwmod = { | |||
112 | .rst_lines = omap3xxx_iva_resets, | 112 | .rst_lines = omap3xxx_iva_resets, |
113 | .rst_lines_cnt = ARRAY_SIZE(omap3xxx_iva_resets), | 113 | .rst_lines_cnt = ARRAY_SIZE(omap3xxx_iva_resets), |
114 | .main_clk = "iva2_ck", | 114 | .main_clk = "iva2_ck", |
115 | .prcm = { | ||
116 | .omap2 = { | ||
117 | .module_offs = OMAP3430_IVA2_MOD, | ||
118 | .prcm_reg_id = 1, | ||
119 | .module_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT, | ||
120 | .idlest_reg_id = 1, | ||
121 | .idlest_idle_bit = OMAP3430_ST_IVA2_SHIFT, | ||
122 | } | ||
123 | }, | ||
115 | }; | 124 | }; |
116 | 125 | ||
117 | /* timer class */ | 126 | /* timer class */ |
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 242aee498ceb..afb60917a948 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c | |||
@@ -4210,7 +4210,7 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__iva = { | |||
4210 | }; | 4210 | }; |
4211 | 4211 | ||
4212 | /* dsp -> sl2if */ | 4212 | /* dsp -> sl2if */ |
4213 | static struct omap_hwmod_ocp_if omap44xx_dsp__sl2if = { | 4213 | static struct omap_hwmod_ocp_if __maybe_unused omap44xx_dsp__sl2if = { |
4214 | .master = &omap44xx_dsp_hwmod, | 4214 | .master = &omap44xx_dsp_hwmod, |
4215 | .slave = &omap44xx_sl2if_hwmod, | 4215 | .slave = &omap44xx_sl2if_hwmod, |
4216 | .clk = "dpll_iva_m5x2_ck", | 4216 | .clk = "dpll_iva_m5x2_ck", |
@@ -4828,7 +4828,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = { | |||
4828 | }; | 4828 | }; |
4829 | 4829 | ||
4830 | /* iva -> sl2if */ | 4830 | /* iva -> sl2if */ |
4831 | static struct omap_hwmod_ocp_if omap44xx_iva__sl2if = { | 4831 | static struct omap_hwmod_ocp_if __maybe_unused omap44xx_iva__sl2if = { |
4832 | .master = &omap44xx_iva_hwmod, | 4832 | .master = &omap44xx_iva_hwmod, |
4833 | .slave = &omap44xx_sl2if_hwmod, | 4833 | .slave = &omap44xx_sl2if_hwmod, |
4834 | .clk = "dpll_iva_m5x2_ck", | 4834 | .clk = "dpll_iva_m5x2_ck", |
@@ -5362,7 +5362,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__scrm = { | |||
5362 | }; | 5362 | }; |
5363 | 5363 | ||
5364 | /* l3_main_2 -> sl2if */ | 5364 | /* l3_main_2 -> sl2if */ |
5365 | static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sl2if = { | 5365 | static struct omap_hwmod_ocp_if __maybe_unused omap44xx_l3_main_2__sl2if = { |
5366 | .master = &omap44xx_l3_main_2_hwmod, | 5366 | .master = &omap44xx_l3_main_2_hwmod, |
5367 | .slave = &omap44xx_sl2if_hwmod, | 5367 | .slave = &omap44xx_sl2if_hwmod, |
5368 | .clk = "l3_div_ck", | 5368 | .clk = "l3_div_ck", |
@@ -6032,7 +6032,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { | |||
6032 | &omap44xx_l4_abe__dmic, | 6032 | &omap44xx_l4_abe__dmic, |
6033 | &omap44xx_l4_abe__dmic_dma, | 6033 | &omap44xx_l4_abe__dmic_dma, |
6034 | &omap44xx_dsp__iva, | 6034 | &omap44xx_dsp__iva, |
6035 | &omap44xx_dsp__sl2if, | 6035 | /* &omap44xx_dsp__sl2if, */ |
6036 | &omap44xx_l4_cfg__dsp, | 6036 | &omap44xx_l4_cfg__dsp, |
6037 | &omap44xx_l3_main_2__dss, | 6037 | &omap44xx_l3_main_2__dss, |
6038 | &omap44xx_l4_per__dss, | 6038 | &omap44xx_l4_per__dss, |
@@ -6068,7 +6068,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { | |||
6068 | &omap44xx_l4_per__i2c4, | 6068 | &omap44xx_l4_per__i2c4, |
6069 | &omap44xx_l3_main_2__ipu, | 6069 | &omap44xx_l3_main_2__ipu, |
6070 | &omap44xx_l3_main_2__iss, | 6070 | &omap44xx_l3_main_2__iss, |
6071 | &omap44xx_iva__sl2if, | 6071 | /* &omap44xx_iva__sl2if, */ |
6072 | &omap44xx_l3_main_2__iva, | 6072 | &omap44xx_l3_main_2__iva, |
6073 | &omap44xx_l4_wkup__kbd, | 6073 | &omap44xx_l4_wkup__kbd, |
6074 | &omap44xx_l4_cfg__mailbox, | 6074 | &omap44xx_l4_cfg__mailbox, |
@@ -6099,7 +6099,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { | |||
6099 | &omap44xx_l4_cfg__cm_core, | 6099 | &omap44xx_l4_cfg__cm_core, |
6100 | &omap44xx_l4_wkup__prm, | 6100 | &omap44xx_l4_wkup__prm, |
6101 | &omap44xx_l4_wkup__scrm, | 6101 | &omap44xx_l4_wkup__scrm, |
6102 | &omap44xx_l3_main_2__sl2if, | 6102 | /* &omap44xx_l3_main_2__sl2if, */ |
6103 | &omap44xx_l4_abe__slimbus1, | 6103 | &omap44xx_l4_abe__slimbus1, |
6104 | &omap44xx_l4_abe__slimbus1_dma, | 6104 | &omap44xx_l4_abe__slimbus1_dma, |
6105 | &omap44xx_l4_per__slimbus2, | 6105 | &omap44xx_l4_per__slimbus2, |
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 2ff6d41ec6c6..2ba4f57dda86 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -260,6 +260,7 @@ static u32 notrace dmtimer_read_sched_clock(void) | |||
260 | return 0; | 260 | return 0; |
261 | } | 261 | } |
262 | 262 | ||
263 | #ifdef CONFIG_OMAP_32K_TIMER | ||
263 | /* Setup free-running counter for clocksource */ | 264 | /* Setup free-running counter for clocksource */ |
264 | static int __init omap2_sync32k_clocksource_init(void) | 265 | static int __init omap2_sync32k_clocksource_init(void) |
265 | { | 266 | { |
@@ -299,6 +300,12 @@ static int __init omap2_sync32k_clocksource_init(void) | |||
299 | 300 | ||
300 | return ret; | 301 | return ret; |
301 | } | 302 | } |
303 | #else | ||
304 | static inline int omap2_sync32k_clocksource_init(void) | ||
305 | { | ||
306 | return -ENODEV; | ||
307 | } | ||
308 | #endif | ||
302 | 309 | ||
303 | static void __init omap2_gptimer_clocksource_init(int gptimer_id, | 310 | static void __init omap2_gptimer_clocksource_init(int gptimer_id, |
304 | const char *fck_source) | 311 | const char *fck_source) |
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 410291c67666..a6cd14ab1e4e 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c | |||
@@ -204,6 +204,13 @@ void __init orion5x_wdt_init(void) | |||
204 | void __init orion5x_init_early(void) | 204 | void __init orion5x_init_early(void) |
205 | { | 205 | { |
206 | orion_time_set_base(TIMER_VIRT_BASE); | 206 | orion_time_set_base(TIMER_VIRT_BASE); |
207 | |||
208 | /* | ||
209 | * Some Orion5x devices allocate their coherent buffers from atomic | ||
210 | * context. Increase size of atomic coherent pool to make sure such | ||
211 | * the allocations won't fail. | ||
212 | */ | ||
213 | init_dma_coherent_pool_size(SZ_1M); | ||
207 | } | 214 | } |
208 | 215 | ||
209 | int orion5x_tclk; | 216 | int orion5x_tclk; |
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index 53b7ea92c32c..3b8a0171c3cb 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c | |||
@@ -346,11 +346,11 @@ static struct resource sh_mmcif_resources[] = { | |||
346 | .flags = IORESOURCE_MEM, | 346 | .flags = IORESOURCE_MEM, |
347 | }, | 347 | }, |
348 | [1] = { | 348 | [1] = { |
349 | .start = gic_spi(141), | 349 | .start = gic_spi(140), |
350 | .flags = IORESOURCE_IRQ, | 350 | .flags = IORESOURCE_IRQ, |
351 | }, | 351 | }, |
352 | [2] = { | 352 | [2] = { |
353 | .start = gic_spi(140), | 353 | .start = gic_spi(141), |
354 | .flags = IORESOURCE_IRQ, | 354 | .flags = IORESOURCE_IRQ, |
355 | }, | 355 | }, |
356 | }; | 356 | }; |
diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c index b7344beec102..94486e7e9dfd 100644 --- a/arch/arm/mach-tegra/board-harmony-power.c +++ b/arch/arm/mach-tegra/board-harmony-power.c | |||
@@ -67,6 +67,13 @@ static struct regulator_init_data ldo0_data = { | |||
67 | }, \ | 67 | }, \ |
68 | } | 68 | } |
69 | 69 | ||
70 | static struct regulator_init_data sys_data = { | ||
71 | .supply_regulator = "vdd_5v0", | ||
72 | .constraints = { | ||
73 | .name = "vdd_sys", | ||
74 | }, | ||
75 | }; | ||
76 | |||
70 | HARMONY_REGULATOR_INIT(sm0, "vdd_sm0", "vdd_sys", 725, 1500, 1); | 77 | HARMONY_REGULATOR_INIT(sm0, "vdd_sm0", "vdd_sys", 725, 1500, 1); |
71 | HARMONY_REGULATOR_INIT(sm1, "vdd_sm1", "vdd_sys", 725, 1500, 1); | 78 | HARMONY_REGULATOR_INIT(sm1, "vdd_sm1", "vdd_sys", 725, 1500, 1); |
72 | HARMONY_REGULATOR_INIT(sm2, "vdd_sm2", "vdd_sys", 3000, 4550, 1); | 79 | HARMONY_REGULATOR_INIT(sm2, "vdd_sm2", "vdd_sys", 3000, 4550, 1); |
@@ -74,7 +81,7 @@ HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500, 1); | |||
74 | HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500, 0); | 81 | HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500, 0); |
75 | HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300, 1); | 82 | HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300, 1); |
76 | HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475, 1); | 83 | HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475, 1); |
77 | HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL, 1250, 3300, 1); | 84 | HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", "vdd_sys", 1250, 3300, 1); |
78 | HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300, 0); | 85 | HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300, 0); |
79 | HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300, 0); | 86 | HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300, 0); |
80 | HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300, 0); | 87 | HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300, 0); |
@@ -88,6 +95,7 @@ HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300, 1); | |||
88 | } | 95 | } |
89 | 96 | ||
90 | static struct tps6586x_subdev_info tps_devs[] = { | 97 | static struct tps6586x_subdev_info tps_devs[] = { |
98 | TPS_REG(SYS, &sys_data), | ||
91 | TPS_REG(SM_0, &sm0_data), | 99 | TPS_REG(SM_0, &sm0_data), |
92 | TPS_REG(SM_1, &sm1_data), | 100 | TPS_REG(SM_1, &sm1_data), |
93 | TPS_REG(SM_2, &sm2_data), | 101 | TPS_REG(SM_2, &sm2_data), |
@@ -120,7 +128,7 @@ static struct i2c_board_info __initdata harmony_regulators[] = { | |||
120 | 128 | ||
121 | int __init harmony_regulator_init(void) | 129 | int __init harmony_regulator_init(void) |
122 | { | 130 | { |
123 | regulator_register_always_on(0, "vdd_sys", | 131 | regulator_register_always_on(0, "vdd_5v0", |
124 | NULL, 0, 5000000); | 132 | NULL, 0, 5000000); |
125 | 133 | ||
126 | if (machine_is_harmony()) { | 134 | if (machine_is_harmony()) { |
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/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 051204fc4617..13f555d62491 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -346,6 +346,8 @@ static int __init atomic_pool_init(void) | |||
346 | (unsigned)pool->size / 1024); | 346 | (unsigned)pool->size / 1024); |
347 | return 0; | 347 | return 0; |
348 | } | 348 | } |
349 | |||
350 | kfree(pages); | ||
349 | no_pages: | 351 | no_pages: |
350 | kfree(bitmap); | 352 | kfree(bitmap); |
351 | no_bitmap: | 353 | no_bitmap: |
@@ -489,7 +491,7 @@ static bool __in_atomic_pool(void *start, size_t size) | |||
489 | void *pool_start = pool->vaddr; | 491 | void *pool_start = pool->vaddr; |
490 | void *pool_end = pool->vaddr + pool->size; | 492 | void *pool_end = pool->vaddr + pool->size; |
491 | 493 | ||
492 | if (start < pool_start || start > pool_end) | 494 | if (start < pool_start || start >= pool_end) |
493 | return false; | 495 | return false; |
494 | 496 | ||
495 | if (end <= pool_end) | 497 | if (end <= pool_end) |
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", |
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h index 627d94f1b010..ec466400a200 100644 --- a/arch/arm/plat-mxc/include/mach/mx25.h +++ b/arch/arm/plat-mxc/include/mach/mx25.h | |||
@@ -98,6 +98,7 @@ | |||
98 | #define MX25_INT_UART1 (NR_IRQS_LEGACY + 45) | 98 | #define MX25_INT_UART1 (NR_IRQS_LEGACY + 45) |
99 | #define MX25_INT_GPIO2 (NR_IRQS_LEGACY + 51) | 99 | #define MX25_INT_GPIO2 (NR_IRQS_LEGACY + 51) |
100 | #define MX25_INT_GPIO1 (NR_IRQS_LEGACY + 52) | 100 | #define MX25_INT_GPIO1 (NR_IRQS_LEGACY + 52) |
101 | #define MX25_INT_GPT1 (NR_IRQS_LEGACY + 54) | ||
101 | #define MX25_INT_FEC (NR_IRQS_LEGACY + 57) | 102 | #define MX25_INT_FEC (NR_IRQS_LEGACY + 57) |
102 | 103 | ||
103 | #define MX25_DMA_REQ_SSI2_RX1 22 | 104 | #define MX25_DMA_REQ_SSI2_RX1 22 |
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 766181cb5c95..024f3b08db29 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c | |||
@@ -68,6 +68,7 @@ | |||
68 | 68 | ||
69 | static unsigned long omap_sram_start; | 69 | static unsigned long omap_sram_start; |
70 | static void __iomem *omap_sram_base; | 70 | static void __iomem *omap_sram_base; |
71 | static unsigned long omap_sram_skip; | ||
71 | static unsigned long omap_sram_size; | 72 | static unsigned long omap_sram_size; |
72 | static void __iomem *omap_sram_ceil; | 73 | static void __iomem *omap_sram_ceil; |
73 | 74 | ||
@@ -106,6 +107,7 @@ static int is_sram_locked(void) | |||
106 | */ | 107 | */ |
107 | static void __init omap_detect_sram(void) | 108 | static void __init omap_detect_sram(void) |
108 | { | 109 | { |
110 | omap_sram_skip = SRAM_BOOTLOADER_SZ; | ||
109 | if (cpu_class_is_omap2()) { | 111 | if (cpu_class_is_omap2()) { |
110 | if (is_sram_locked()) { | 112 | if (is_sram_locked()) { |
111 | if (cpu_is_omap34xx()) { | 113 | if (cpu_is_omap34xx()) { |
@@ -113,6 +115,7 @@ static void __init omap_detect_sram(void) | |||
113 | if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) || | 115 | if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) || |
114 | (omap_type() == OMAP2_DEVICE_TYPE_SEC)) { | 116 | (omap_type() == OMAP2_DEVICE_TYPE_SEC)) { |
115 | omap_sram_size = 0x7000; /* 28K */ | 117 | omap_sram_size = 0x7000; /* 28K */ |
118 | omap_sram_skip += SZ_16K; | ||
116 | } else { | 119 | } else { |
117 | omap_sram_size = 0x8000; /* 32K */ | 120 | omap_sram_size = 0x8000; /* 32K */ |
118 | } | 121 | } |
@@ -175,8 +178,10 @@ static void __init omap_map_sram(void) | |||
175 | return; | 178 | return; |
176 | 179 | ||
177 | #ifdef CONFIG_OMAP4_ERRATA_I688 | 180 | #ifdef CONFIG_OMAP4_ERRATA_I688 |
181 | if (cpu_is_omap44xx()) { | ||
178 | omap_sram_start += PAGE_SIZE; | 182 | omap_sram_start += PAGE_SIZE; |
179 | omap_sram_size -= SZ_16K; | 183 | omap_sram_size -= SZ_16K; |
184 | } | ||
180 | #endif | 185 | #endif |
181 | if (cpu_is_omap34xx()) { | 186 | if (cpu_is_omap34xx()) { |
182 | /* | 187 | /* |
@@ -203,8 +208,8 @@ static void __init omap_map_sram(void) | |||
203 | * Looks like we need to preserve some bootloader code at the | 208 | * Looks like we need to preserve some bootloader code at the |
204 | * beginning of SRAM for jumping to flash for reboot to work... | 209 | * beginning of SRAM for jumping to flash for reboot to work... |
205 | */ | 210 | */ |
206 | memset_io(omap_sram_base + SRAM_BOOTLOADER_SZ, 0, | 211 | memset_io(omap_sram_base + omap_sram_skip, 0, |
207 | omap_sram_size - SRAM_BOOTLOADER_SZ); | 212 | omap_sram_size - omap_sram_skip); |
208 | } | 213 | } |
209 | 214 | ||
210 | /* | 215 | /* |
@@ -218,7 +223,7 @@ void *omap_sram_push_address(unsigned long size) | |||
218 | { | 223 | { |
219 | unsigned long available, new_ceil = (unsigned long)omap_sram_ceil; | 224 | unsigned long available, new_ceil = (unsigned long)omap_sram_ceil; |
220 | 225 | ||
221 | available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ); | 226 | available = omap_sram_ceil - (omap_sram_base + omap_sram_skip); |
222 | 227 | ||
223 | if (size > available) { | 228 | if (size > available) { |
224 | pr_err("Not enough space in SRAM\n"); | 229 | pr_err("Not enough space in SRAM\n"); |
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c index 65c5eca475e7..d1116e2dfbea 100644 --- a/arch/arm/plat-samsung/clock.c +++ b/arch/arm/plat-samsung/clock.c | |||
@@ -144,6 +144,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
144 | 144 | ||
145 | int clk_set_rate(struct clk *clk, unsigned long rate) | 145 | int clk_set_rate(struct clk *clk, unsigned long rate) |
146 | { | 146 | { |
147 | unsigned long flags; | ||
147 | int ret; | 148 | int ret; |
148 | 149 | ||
149 | if (IS_ERR(clk)) | 150 | if (IS_ERR(clk)) |
@@ -159,9 +160,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
159 | if (clk->ops == NULL || clk->ops->set_rate == NULL) | 160 | if (clk->ops == NULL || clk->ops->set_rate == NULL) |
160 | return -EINVAL; | 161 | return -EINVAL; |
161 | 162 | ||
162 | spin_lock(&clocks_lock); | 163 | spin_lock_irqsave(&clocks_lock, flags); |
163 | ret = (clk->ops->set_rate)(clk, rate); | 164 | ret = (clk->ops->set_rate)(clk, rate); |
164 | spin_unlock(&clocks_lock); | 165 | spin_unlock_irqrestore(&clocks_lock, flags); |
165 | 166 | ||
166 | return ret; | 167 | return ret; |
167 | } | 168 | } |
@@ -173,17 +174,18 @@ struct clk *clk_get_parent(struct clk *clk) | |||
173 | 174 | ||
174 | int clk_set_parent(struct clk *clk, struct clk *parent) | 175 | int clk_set_parent(struct clk *clk, struct clk *parent) |
175 | { | 176 | { |
177 | unsigned long flags; | ||
176 | int ret = 0; | 178 | int ret = 0; |
177 | 179 | ||
178 | if (IS_ERR(clk)) | 180 | if (IS_ERR(clk)) |
179 | return -EINVAL; | 181 | return -EINVAL; |
180 | 182 | ||
181 | spin_lock(&clocks_lock); | 183 | spin_lock_irqsave(&clocks_lock, flags); |
182 | 184 | ||
183 | if (clk->ops && clk->ops->set_parent) | 185 | if (clk->ops && clk->ops->set_parent) |
184 | ret = (clk->ops->set_parent)(clk, parent); | 186 | ret = (clk->ops->set_parent)(clk, parent); |
185 | 187 | ||
186 | spin_unlock(&clocks_lock); | 188 | spin_unlock_irqrestore(&clocks_lock, flags); |
187 | 189 | ||
188 | return ret; | 190 | return ret; |
189 | } | 191 | } |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig new file mode 100644 index 000000000000..767ba5685454 --- /dev/null +++ b/arch/arm64/Kconfig | |||
@@ -0,0 +1,222 @@ | |||
1 | config ARM64 | ||
2 | def_bool y | ||
3 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | ||
4 | select GENERIC_CLOCKEVENTS | ||
5 | select GENERIC_HARDIRQS_NO_DEPRECATED | ||
6 | select GENERIC_IOMAP | ||
7 | select GENERIC_IRQ_PROBE | ||
8 | select GENERIC_IRQ_SHOW | ||
9 | select GENERIC_SMP_IDLE_THREAD | ||
10 | select GENERIC_TIME_VSYSCALL | ||
11 | select HARDIRQS_SW_RESEND | ||
12 | select HAVE_ARCH_TRACEHOOK | ||
13 | select HAVE_DMA_API_DEBUG | ||
14 | select HAVE_DMA_ATTRS | ||
15 | select HAVE_GENERIC_DMA_COHERENT | ||
16 | select HAVE_GENERIC_HARDIRQS | ||
17 | select HAVE_HW_BREAKPOINT if PERF_EVENTS | ||
18 | select HAVE_IRQ_WORK | ||
19 | select HAVE_MEMBLOCK | ||
20 | select HAVE_PERF_EVENTS | ||
21 | select HAVE_SPARSE_IRQ | ||
22 | select IRQ_DOMAIN | ||
23 | select NO_BOOTMEM | ||
24 | select OF | ||
25 | select OF_EARLY_FLATTREE | ||
26 | select PERF_USE_VMALLOC | ||
27 | select RTC_LIB | ||
28 | select SPARSE_IRQ | ||
29 | help | ||
30 | ARM 64-bit (AArch64) Linux support. | ||
31 | |||
32 | config 64BIT | ||
33 | def_bool y | ||
34 | |||
35 | config ARCH_PHYS_ADDR_T_64BIT | ||
36 | def_bool y | ||
37 | |||
38 | config MMU | ||
39 | def_bool y | ||
40 | |||
41 | config NO_IOPORT | ||
42 | def_bool y | ||
43 | |||
44 | config STACKTRACE_SUPPORT | ||
45 | def_bool y | ||
46 | |||
47 | config LOCKDEP_SUPPORT | ||
48 | def_bool y | ||
49 | |||
50 | config TRACE_IRQFLAGS_SUPPORT | ||
51 | def_bool y | ||
52 | |||
53 | config GENERIC_LOCKBREAK | ||
54 | def_bool y | ||
55 | depends on SMP && PREEMPT | ||
56 | |||
57 | config RWSEM_GENERIC_SPINLOCK | ||
58 | def_bool y | ||
59 | |||
60 | config GENERIC_HWEIGHT | ||
61 | def_bool y | ||
62 | |||
63 | config GENERIC_CSUM | ||
64 | def_bool y | ||
65 | |||
66 | config GENERIC_CALIBRATE_DELAY | ||
67 | def_bool y | ||
68 | |||
69 | config ZONE_DMA32 | ||
70 | def_bool y | ||
71 | |||
72 | config ARCH_DMA_ADDR_T_64BIT | ||
73 | def_bool y | ||
74 | |||
75 | config NEED_DMA_MAP_STATE | ||
76 | def_bool y | ||
77 | |||
78 | config NEED_SG_DMA_LENGTH | ||
79 | def_bool y | ||
80 | |||
81 | config SWIOTLB | ||
82 | def_bool y | ||
83 | |||
84 | config IOMMU_HELPER | ||
85 | def_bool SWIOTLB | ||
86 | |||
87 | source "init/Kconfig" | ||
88 | |||
89 | source "kernel/Kconfig.freezer" | ||
90 | |||
91 | menu "System Type" | ||
92 | |||
93 | endmenu | ||
94 | |||
95 | menu "Bus support" | ||
96 | |||
97 | config ARM_AMBA | ||
98 | bool | ||
99 | |||
100 | endmenu | ||
101 | |||
102 | menu "Kernel Features" | ||
103 | |||
104 | source "kernel/time/Kconfig" | ||
105 | |||
106 | config ARM64_64K_PAGES | ||
107 | bool "Enable 64KB pages support" | ||
108 | help | ||
109 | This feature enables 64KB pages support (4KB by default) | ||
110 | allowing only two levels of page tables and faster TLB | ||
111 | look-up. AArch32 emulation is not available when this feature | ||
112 | is enabled. | ||
113 | |||
114 | config SMP | ||
115 | bool "Symmetric Multi-Processing" | ||
116 | select USE_GENERIC_SMP_HELPERS | ||
117 | help | ||
118 | This enables support for systems with more than one CPU. If | ||
119 | you say N here, the kernel will run on single and | ||
120 | multiprocessor machines, but will use only one CPU of a | ||
121 | multiprocessor machine. If you say Y here, the kernel will run | ||
122 | on many, but not all, single processor machines. On a single | ||
123 | processor machine, the kernel will run faster if you say N | ||
124 | here. | ||
125 | |||
126 | If you don't know what to do here, say N. | ||
127 | |||
128 | config NR_CPUS | ||
129 | int "Maximum number of CPUs (2-32)" | ||
130 | range 2 32 | ||
131 | depends on SMP | ||
132 | default "4" | ||
133 | |||
134 | source kernel/Kconfig.preempt | ||
135 | |||
136 | config HZ | ||
137 | int | ||
138 | default 100 | ||
139 | |||
140 | config ARCH_HAS_HOLES_MEMORYMODEL | ||
141 | def_bool y if SPARSEMEM | ||
142 | |||
143 | config ARCH_SPARSEMEM_ENABLE | ||
144 | def_bool y | ||
145 | select SPARSEMEM_VMEMMAP_ENABLE | ||
146 | |||
147 | config ARCH_SPARSEMEM_DEFAULT | ||
148 | def_bool ARCH_SPARSEMEM_ENABLE | ||
149 | |||
150 | config ARCH_SELECT_MEMORY_MODEL | ||
151 | def_bool ARCH_SPARSEMEM_ENABLE | ||
152 | |||
153 | config HAVE_ARCH_PFN_VALID | ||
154 | def_bool ARCH_HAS_HOLES_MEMORYMODEL || !SPARSEMEM | ||
155 | |||
156 | config HW_PERF_EVENTS | ||
157 | bool "Enable hardware performance counter support for perf events" | ||
158 | depends on PERF_EVENTS | ||
159 | default y | ||
160 | help | ||
161 | Enable hardware performance counter support for perf events. If | ||
162 | disabled, perf events will use software events only. | ||
163 | |||
164 | source "mm/Kconfig" | ||
165 | |||
166 | endmenu | ||
167 | |||
168 | menu "Boot options" | ||
169 | |||
170 | config CMDLINE | ||
171 | string "Default kernel command string" | ||
172 | default "" | ||
173 | help | ||
174 | Provide a set of default command-line options at build time by | ||
175 | entering them here. As a minimum, you should specify the the | ||
176 | root device (e.g. root=/dev/nfs). | ||
177 | |||
178 | config CMDLINE_FORCE | ||
179 | bool "Always use the default kernel command string" | ||
180 | help | ||
181 | Always use the default kernel command string, even if the boot | ||
182 | loader passes other arguments to the kernel. | ||
183 | This is useful if you cannot or don't want to change the | ||
184 | command-line options your boot loader passes to the kernel. | ||
185 | |||
186 | endmenu | ||
187 | |||
188 | menu "Userspace binary formats" | ||
189 | |||
190 | source "fs/Kconfig.binfmt" | ||
191 | |||
192 | config COMPAT | ||
193 | bool "Kernel support for 32-bit EL0" | ||
194 | depends on !ARM64_64K_PAGES | ||
195 | select COMPAT_BINFMT_ELF | ||
196 | help | ||
197 | This option enables support for a 32-bit EL0 running under a 64-bit | ||
198 | kernel at EL1. AArch32-specific components such as system calls, | ||
199 | the user helper functions, VFP support and the ptrace interface are | ||
200 | handled appropriately by the kernel. | ||
201 | |||
202 | If you want to execute 32-bit userspace applications, say Y. | ||
203 | |||
204 | config SYSVIPC_COMPAT | ||
205 | def_bool y | ||
206 | depends on COMPAT && SYSVIPC | ||
207 | |||
208 | endmenu | ||
209 | |||
210 | source "net/Kconfig" | ||
211 | |||
212 | source "drivers/Kconfig" | ||
213 | |||
214 | source "fs/Kconfig" | ||
215 | |||
216 | source "arch/arm64/Kconfig.debug" | ||
217 | |||
218 | source "security/Kconfig" | ||
219 | |||
220 | source "crypto/Kconfig" | ||
221 | |||
222 | source "lib/Kconfig" | ||
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug new file mode 100644 index 000000000000..d7553f2bda66 --- /dev/null +++ b/arch/arm64/Kconfig.debug | |||
@@ -0,0 +1,27 @@ | |||
1 | menu "Kernel hacking" | ||
2 | |||
3 | source "lib/Kconfig.debug" | ||
4 | |||
5 | config FRAME_POINTER | ||
6 | bool | ||
7 | default y | ||
8 | |||
9 | config DEBUG_ERRORS | ||
10 | bool "Verbose kernel error messages" | ||
11 | depends on DEBUG_KERNEL | ||
12 | help | ||
13 | This option controls verbose debugging information which can be | ||
14 | printed when the kernel detects an internal error. This debugging | ||
15 | information is useful to kernel hackers when tracking down problems, | ||
16 | but mostly meaningless to other people. It's safe to say Y unless | ||
17 | you are concerned with the code size or don't want to see these | ||
18 | messages. | ||
19 | |||
20 | config DEBUG_STACK_USAGE | ||
21 | bool "Enable stack utilization instrumentation" | ||
22 | depends on DEBUG_KERNEL | ||
23 | help | ||
24 | Enables the display of the minimum amount of free stack which each | ||
25 | task has ever had available in the sysrq-T output. | ||
26 | |||
27 | endmenu | ||
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile new file mode 100644 index 000000000000..364191f3be43 --- /dev/null +++ b/arch/arm64/Makefile | |||
@@ -0,0 +1,71 @@ | |||
1 | # | ||
2 | # arch/arm64/Makefile | ||
3 | # | ||
4 | # This file is included by the global makefile so that you can add your own | ||
5 | # architecture-specific flags and dependencies. | ||
6 | # | ||
7 | # This file is subject to the terms and conditions of the GNU General Public | ||
8 | # License. See the file "COPYING" in the main directory of this archive | ||
9 | # for more details. | ||
10 | # | ||
11 | # Copyright (C) 1995-2001 by Russell King | ||
12 | |||
13 | LDFLAGS_vmlinux :=-p --no-undefined -X | ||
14 | CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) | ||
15 | OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S | ||
16 | GZFLAGS :=-9 | ||
17 | |||
18 | LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) | ||
19 | |||
20 | KBUILD_DEFCONFIG := defconfig | ||
21 | |||
22 | KBUILD_CFLAGS += -mgeneral-regs-only | ||
23 | KBUILD_CPPFLAGS += -mlittle-endian | ||
24 | AS += -EL | ||
25 | LD += -EL | ||
26 | |||
27 | comma = , | ||
28 | |||
29 | CHECKFLAGS += -D__aarch64__ | ||
30 | |||
31 | # Default value | ||
32 | head-y := arch/arm64/kernel/head.o | ||
33 | |||
34 | # The byte offset of the kernel image in RAM from the start of RAM. | ||
35 | TEXT_OFFSET := 0x00080000 | ||
36 | |||
37 | export TEXT_OFFSET GZFLAGS | ||
38 | |||
39 | core-y += arch/arm64/kernel/ arch/arm64/mm/ | ||
40 | libs-y := arch/arm64/lib/ $(libs-y) | ||
41 | libs-y += $(LIBGCC) | ||
42 | |||
43 | # Default target when executing plain make | ||
44 | KBUILD_IMAGE := Image.gz | ||
45 | |||
46 | all: $(KBUILD_IMAGE) | ||
47 | |||
48 | boot := arch/arm64/boot | ||
49 | |||
50 | Image Image.gz: vmlinux | ||
51 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ | ||
52 | |||
53 | zinstall install: vmlinux | ||
54 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ | ||
55 | |||
56 | %.dtb: | ||
57 | $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ | ||
58 | |||
59 | # We use MRPROPER_FILES and CLEAN_FILES now | ||
60 | archclean: | ||
61 | $(Q)$(MAKE) $(clean)=$(boot) | ||
62 | |||
63 | define archhelp | ||
64 | echo '* Image.gz - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)' | ||
65 | echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' | ||
66 | echo ' install - Install uncompressed kernel' | ||
67 | echo ' zinstall - Install compressed kernel' | ||
68 | echo ' Install using (your) ~/bin/installkernel or' | ||
69 | echo ' (distribution) /sbin/installkernel or' | ||
70 | echo ' install to $$(INSTALL_PATH) and run lilo' | ||
71 | endef | ||
diff --git a/arch/arm64/boot/.gitignore b/arch/arm64/boot/.gitignore new file mode 100644 index 000000000000..8dab0bb6ae66 --- /dev/null +++ b/arch/arm64/boot/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | Image | ||
2 | Image.gz | ||
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile new file mode 100644 index 000000000000..eca209b2b0bf --- /dev/null +++ b/arch/arm64/boot/Makefile | |||
@@ -0,0 +1,36 @@ | |||
1 | # | ||
2 | # arch/arm64/boot/Makefile | ||
3 | # | ||
4 | # This file is included by the global makefile so that you can add your own | ||
5 | # architecture-specific flags and dependencies. | ||
6 | # | ||
7 | # This file is subject to the terms and conditions of the GNU General Public | ||
8 | # License. See the file "COPYING" in the main directory of this archive | ||
9 | # for more details. | ||
10 | # | ||
11 | # Copyright (C) 2012, ARM Ltd. | ||
12 | # Author: Will Deacon <will.deacon@arm.com> | ||
13 | # | ||
14 | # Based on the ia64 boot/Makefile. | ||
15 | # | ||
16 | |||
17 | targets := Image Image.gz | ||
18 | |||
19 | $(obj)/Image: vmlinux FORCE | ||
20 | $(call if_changed,objcopy) | ||
21 | |||
22 | $(obj)/Image.gz: $(obj)/Image FORCE | ||
23 | $(call if_changed,gzip) | ||
24 | |||
25 | $(obj)/%.dtb: $(src)/dts/%.dts | ||
26 | $(call cmd,dtc) | ||
27 | |||
28 | install: $(obj)/Image | ||
29 | $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ | ||
30 | $(obj)/Image System.map "$(INSTALL_PATH)" | ||
31 | |||
32 | zinstall: $(obj)/Image.gz | ||
33 | $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ | ||
34 | $(obj)/Image.gz System.map "$(INSTALL_PATH)" | ||
35 | |||
36 | clean-files += *.dtb | ||
diff --git a/arch/arm64/boot/install.sh b/arch/arm64/boot/install.sh new file mode 100644 index 000000000000..12ed78aa6f0c --- /dev/null +++ b/arch/arm64/boot/install.sh | |||
@@ -0,0 +1,46 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # arch/arm64/boot/install.sh | ||
4 | # | ||
5 | # This file is subject to the terms and conditions of the GNU General Public | ||
6 | # License. See the file "COPYING" in the main directory of this archive | ||
7 | # for more details. | ||
8 | # | ||
9 | # Copyright (C) 1995 by Linus Torvalds | ||
10 | # | ||
11 | # Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin | ||
12 | # Adapted from code in arch/i386/boot/install.sh by Russell King | ||
13 | # | ||
14 | # "make install" script for the AArch64 Linux port | ||
15 | # | ||
16 | # Arguments: | ||
17 | # $1 - kernel version | ||
18 | # $2 - kernel image file | ||
19 | # $3 - kernel map file | ||
20 | # $4 - default install path (blank if root directory) | ||
21 | # | ||
22 | |||
23 | # User may have a custom install script | ||
24 | if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi | ||
25 | if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi | ||
26 | |||
27 | if [ "$(basename $2)" = "Image.gz" ]; then | ||
28 | # Compressed install | ||
29 | echo "Installing compressed kernel" | ||
30 | base=vmlinuz | ||
31 | else | ||
32 | # Normal install | ||
33 | echo "Installing normal kernel" | ||
34 | base=vmlinux | ||
35 | fi | ||
36 | |||
37 | if [ -f $4/$base-$1 ]; then | ||
38 | mv $4/$base-$1 $4/$base-$1.old | ||
39 | fi | ||
40 | cat $2 > $4/$base-$1 | ||
41 | |||
42 | # Install system map file | ||
43 | if [ -f $4/System.map-$1 ]; then | ||
44 | mv $4/System.map-$1 $4/System.map-$1.old | ||
45 | fi | ||
46 | cp $3 $4/System.map-$1 | ||
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig new file mode 100644 index 000000000000..9212c7880da7 --- /dev/null +++ b/arch/arm64/configs/defconfig | |||
@@ -0,0 +1,85 @@ | |||
1 | CONFIG_EXPERIMENTAL=y | ||
2 | # CONFIG_LOCALVERSION_AUTO is not set | ||
3 | # CONFIG_SWAP is not set | ||
4 | CONFIG_SYSVIPC=y | ||
5 | CONFIG_POSIX_MQUEUE=y | ||
6 | CONFIG_BSD_PROCESS_ACCT=y | ||
7 | CONFIG_BSD_PROCESS_ACCT_V3=y | ||
8 | CONFIG_NO_HZ=y | ||
9 | CONFIG_HIGH_RES_TIMERS=y | ||
10 | CONFIG_IKCONFIG=y | ||
11 | CONFIG_IKCONFIG_PROC=y | ||
12 | CONFIG_LOG_BUF_SHIFT=14 | ||
13 | # CONFIG_UTS_NS is not set | ||
14 | # CONFIG_IPC_NS is not set | ||
15 | # CONFIG_PID_NS is not set | ||
16 | # CONFIG_NET_NS is not set | ||
17 | CONFIG_SCHED_AUTOGROUP=y | ||
18 | CONFIG_BLK_DEV_INITRD=y | ||
19 | CONFIG_KALLSYMS_ALL=y | ||
20 | # CONFIG_COMPAT_BRK is not set | ||
21 | CONFIG_PROFILING=y | ||
22 | CONFIG_MODULES=y | ||
23 | CONFIG_MODULE_UNLOAD=y | ||
24 | # CONFIG_BLK_DEV_BSG is not set | ||
25 | # CONFIG_IOSCHED_DEADLINE is not set | ||
26 | CONFIG_SMP=y | ||
27 | CONFIG_PREEMPT_VOLUNTARY=y | ||
28 | CONFIG_CMDLINE="console=ttyAMA0" | ||
29 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
30 | CONFIG_COMPAT=y | ||
31 | CONFIG_NET=y | ||
32 | CONFIG_PACKET=y | ||
33 | CONFIG_UNIX=y | ||
34 | CONFIG_INET=y | ||
35 | CONFIG_IP_PNP=y | ||
36 | CONFIG_IP_PNP_DHCP=y | ||
37 | CONFIG_IP_PNP_BOOTP=y | ||
38 | # CONFIG_INET_LRO is not set | ||
39 | # CONFIG_IPV6 is not set | ||
40 | # CONFIG_WIRELESS is not set | ||
41 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
42 | CONFIG_DEVTMPFS=y | ||
43 | # CONFIG_BLK_DEV is not set | ||
44 | CONFIG_SCSI=y | ||
45 | # CONFIG_SCSI_PROC_FS is not set | ||
46 | CONFIG_BLK_DEV_SD=y | ||
47 | # CONFIG_SCSI_LOWLEVEL is not set | ||
48 | CONFIG_NETDEVICES=y | ||
49 | CONFIG_MII=y | ||
50 | # CONFIG_WLAN is not set | ||
51 | CONFIG_INPUT_EVDEV=y | ||
52 | # CONFIG_SERIO_I8042 is not set | ||
53 | # CONFIG_SERIO_SERPORT is not set | ||
54 | CONFIG_LEGACY_PTY_COUNT=16 | ||
55 | # CONFIG_HW_RANDOM is not set | ||
56 | # CONFIG_HWMON is not set | ||
57 | CONFIG_FB=y | ||
58 | # CONFIG_VGA_CONSOLE is not set | ||
59 | CONFIG_FRAMEBUFFER_CONSOLE=y | ||
60 | CONFIG_LOGO=y | ||
61 | # CONFIG_LOGO_LINUX_MONO is not set | ||
62 | # CONFIG_LOGO_LINUX_VGA16 is not set | ||
63 | # CONFIG_USB_SUPPORT is not set | ||
64 | # CONFIG_IOMMU_SUPPORT is not set | ||
65 | CONFIG_EXT2_FS=y | ||
66 | CONFIG_EXT3_FS=y | ||
67 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
68 | # CONFIG_EXT3_FS_XATTR is not set | ||
69 | CONFIG_FUSE_FS=y | ||
70 | CONFIG_CUSE=y | ||
71 | CONFIG_VFAT_FS=y | ||
72 | CONFIG_TMPFS=y | ||
73 | # CONFIG_MISC_FILESYSTEMS is not set | ||
74 | CONFIG_NFS_FS=y | ||
75 | CONFIG_ROOT_NFS=y | ||
76 | CONFIG_NLS_CODEPAGE_437=y | ||
77 | CONFIG_NLS_ISO8859_1=y | ||
78 | CONFIG_MAGIC_SYSRQ=y | ||
79 | CONFIG_DEBUG_FS=y | ||
80 | CONFIG_DEBUG_KERNEL=y | ||
81 | # CONFIG_SCHED_DEBUG is not set | ||
82 | CONFIG_DEBUG_INFO=y | ||
83 | # CONFIG_FTRACE is not set | ||
84 | CONFIG_ATOMIC64_SELFTEST=y | ||
85 | CONFIG_DEBUG_ERRORS=y | ||
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild new file mode 100644 index 000000000000..35924a542d43 --- /dev/null +++ b/arch/arm64/include/asm/Kbuild | |||
@@ -0,0 +1,51 @@ | |||
1 | include include/asm-generic/Kbuild.asm | ||
2 | |||
3 | header-y += hwcap.h | ||
4 | |||
5 | generic-y += bug.h | ||
6 | generic-y += bugs.h | ||
7 | generic-y += checksum.h | ||
8 | generic-y += cputime.h | ||
9 | generic-y += current.h | ||
10 | generic-y += delay.h | ||
11 | generic-y += div64.h | ||
12 | generic-y += dma.h | ||
13 | generic-y += emergency-restart.h | ||
14 | generic-y += errno.h | ||
15 | generic-y += ftrace.h | ||
16 | generic-y += hw_irq.h | ||
17 | generic-y += ioctl.h | ||
18 | generic-y += ioctls.h | ||
19 | generic-y += ipcbuf.h | ||
20 | generic-y += irq_regs.h | ||
21 | generic-y += kdebug.h | ||
22 | generic-y += kmap_types.h | ||
23 | generic-y += linkage.h | ||
24 | generic-y += local.h | ||
25 | generic-y += local64.h | ||
26 | generic-y += mman.h | ||
27 | generic-y += msgbuf.h | ||
28 | generic-y += mutex.h | ||
29 | generic-y += pci.h | ||
30 | generic-y += percpu.h | ||
31 | generic-y += poll.h | ||
32 | generic-y += posix_types.h | ||
33 | generic-y += resource.h | ||
34 | generic-y += scatterlist.h | ||
35 | generic-y += sections.h | ||
36 | generic-y += segment.h | ||
37 | generic-y += sembuf.h | ||
38 | generic-y += serial.h | ||
39 | generic-y += shmbuf.h | ||
40 | generic-y += sizes.h | ||
41 | generic-y += socket.h | ||
42 | generic-y += sockios.h | ||
43 | generic-y += string.h | ||
44 | generic-y += switch_to.h | ||
45 | generic-y += swab.h | ||
46 | generic-y += termbits.h | ||
47 | generic-y += termios.h | ||
48 | generic-y += topology.h | ||
49 | generic-y += types.h | ||
50 | generic-y += unaligned.h | ||
51 | generic-y += user.h | ||
diff --git a/arch/arm64/include/asm/arm_generic.h b/arch/arm64/include/asm/arm_generic.h new file mode 100644 index 000000000000..e4cec9d30f27 --- /dev/null +++ b/arch/arm64/include/asm/arm_generic.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * arch/arm64/include/asm/arm_generic.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * Author: Marc Zyngier <marc.zyngier@arm.com> | ||
6 | * | ||
7 | * This program is free software: you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_ARM_GENERIC_H | ||
20 | #define __ASM_ARM_GENERIC_H | ||
21 | |||
22 | #include <linux/clocksource.h> | ||
23 | |||
24 | #define ARCH_TIMER_CTRL_ENABLE (1 << 0) | ||
25 | #define ARCH_TIMER_CTRL_IMASK (1 << 1) | ||
26 | #define ARCH_TIMER_CTRL_ISTATUS (1 << 2) | ||
27 | |||
28 | #define ARCH_TIMER_REG_CTRL 0 | ||
29 | #define ARCH_TIMER_REG_FREQ 1 | ||
30 | #define ARCH_TIMER_REG_TVAL 2 | ||
31 | |||
32 | static inline void arch_timer_reg_write(int reg, u32 val) | ||
33 | { | ||
34 | switch (reg) { | ||
35 | case ARCH_TIMER_REG_CTRL: | ||
36 | asm volatile("msr cntp_ctl_el0, %0" : : "r" (val)); | ||
37 | break; | ||
38 | case ARCH_TIMER_REG_TVAL: | ||
39 | asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); | ||
40 | break; | ||
41 | default: | ||
42 | BUILD_BUG(); | ||
43 | } | ||
44 | |||
45 | isb(); | ||
46 | } | ||
47 | |||
48 | static inline u32 arch_timer_reg_read(int reg) | ||
49 | { | ||
50 | u32 val; | ||
51 | |||
52 | switch (reg) { | ||
53 | case ARCH_TIMER_REG_CTRL: | ||
54 | asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val)); | ||
55 | break; | ||
56 | case ARCH_TIMER_REG_FREQ: | ||
57 | asm volatile("mrs %0, cntfrq_el0" : "=r" (val)); | ||
58 | break; | ||
59 | case ARCH_TIMER_REG_TVAL: | ||
60 | asm volatile("mrs %0, cntp_tval_el0" : "=r" (val)); | ||
61 | break; | ||
62 | default: | ||
63 | BUILD_BUG(); | ||
64 | } | ||
65 | |||
66 | return val; | ||
67 | } | ||
68 | |||
69 | static inline void __cpuinit arch_counter_enable_user_access(void) | ||
70 | { | ||
71 | u32 cntkctl; | ||
72 | |||
73 | /* Disable user access to the timers and the virtual counter. */ | ||
74 | asm volatile("mrs %0, cntkctl_el1" : "=r" (cntkctl)); | ||
75 | cntkctl &= ~((3 << 8) | (1 << 1)); | ||
76 | |||
77 | /* Enable user access to the physical counter and frequency. */ | ||
78 | cntkctl |= 1; | ||
79 | asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); | ||
80 | } | ||
81 | |||
82 | static inline cycle_t arch_counter_get_cntpct(void) | ||
83 | { | ||
84 | cycle_t cval; | ||
85 | |||
86 | asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); | ||
87 | |||
88 | return cval; | ||
89 | } | ||
90 | |||
91 | static inline cycle_t arch_counter_get_cntvct(void) | ||
92 | { | ||
93 | cycle_t cval; | ||
94 | |||
95 | asm volatile("mrs %0, cntvct_el0" : "=r" (cval)); | ||
96 | |||
97 | return cval; | ||
98 | } | ||
99 | |||
100 | #endif | ||
diff --git a/arch/arm64/include/asm/asm-offsets.h b/arch/arm64/include/asm/asm-offsets.h new file mode 100644 index 000000000000..d370ee36a182 --- /dev/null +++ b/arch/arm64/include/asm/asm-offsets.h | |||
@@ -0,0 +1 @@ | |||
#include <generated/asm-offsets.h> | |||
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h new file mode 100644 index 000000000000..da2a13e8f1e6 --- /dev/null +++ b/arch/arm64/include/asm/assembler.h | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/assembler.h | ||
3 | * | ||
4 | * Copyright (C) 1996-2000 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASSEMBLY__ | ||
20 | #error "Only include this from assembly code" | ||
21 | #endif | ||
22 | |||
23 | #include <asm/ptrace.h> | ||
24 | |||
25 | /* | ||
26 | * Stack pushing/popping (register pairs only). Equivalent to store decrement | ||
27 | * before, load increment after. | ||
28 | */ | ||
29 | .macro push, xreg1, xreg2 | ||
30 | stp \xreg1, \xreg2, [sp, #-16]! | ||
31 | .endm | ||
32 | |||
33 | .macro pop, xreg1, xreg2 | ||
34 | ldp \xreg1, \xreg2, [sp], #16 | ||
35 | .endm | ||
36 | |||
37 | /* | ||
38 | * Enable and disable interrupts. | ||
39 | */ | ||
40 | .macro disable_irq | ||
41 | msr daifset, #2 | ||
42 | .endm | ||
43 | |||
44 | .macro enable_irq | ||
45 | msr daifclr, #2 | ||
46 | .endm | ||
47 | |||
48 | /* | ||
49 | * Save/disable and restore interrupts. | ||
50 | */ | ||
51 | .macro save_and_disable_irqs, olddaif | ||
52 | mrs \olddaif, daif | ||
53 | disable_irq | ||
54 | .endm | ||
55 | |||
56 | .macro restore_irqs, olddaif | ||
57 | msr daif, \olddaif | ||
58 | .endm | ||
59 | |||
60 | /* | ||
61 | * Enable and disable debug exceptions. | ||
62 | */ | ||
63 | .macro disable_dbg | ||
64 | msr daifset, #8 | ||
65 | .endm | ||
66 | |||
67 | .macro enable_dbg | ||
68 | msr daifclr, #8 | ||
69 | .endm | ||
70 | |||
71 | .macro disable_step, tmp | ||
72 | mrs \tmp, mdscr_el1 | ||
73 | bic \tmp, \tmp, #1 | ||
74 | msr mdscr_el1, \tmp | ||
75 | .endm | ||
76 | |||
77 | .macro enable_step, tmp | ||
78 | mrs \tmp, mdscr_el1 | ||
79 | orr \tmp, \tmp, #1 | ||
80 | msr mdscr_el1, \tmp | ||
81 | .endm | ||
82 | |||
83 | .macro enable_dbg_if_not_stepping, tmp | ||
84 | mrs \tmp, mdscr_el1 | ||
85 | tbnz \tmp, #1, 9990f | ||
86 | enable_dbg | ||
87 | 9990: | ||
88 | .endm | ||
89 | |||
90 | /* | ||
91 | * SMP data memory barrier | ||
92 | */ | ||
93 | .macro smp_dmb, opt | ||
94 | #ifdef CONFIG_SMP | ||
95 | dmb \opt | ||
96 | #endif | ||
97 | .endm | ||
98 | |||
99 | #define USER(l, x...) \ | ||
100 | 9999: x; \ | ||
101 | .section __ex_table,"a"; \ | ||
102 | .align 3; \ | ||
103 | .quad 9999b,l; \ | ||
104 | .previous | ||
105 | |||
106 | /* | ||
107 | * Register aliases. | ||
108 | */ | ||
109 | lr .req x30 // link register | ||
diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h new file mode 100644 index 000000000000..407717ba060e --- /dev/null +++ b/arch/arm64/include/asm/atomic.h | |||
@@ -0,0 +1,305 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/atomic.h | ||
3 | * | ||
4 | * Copyright (C) 1996 Russell King. | ||
5 | * Copyright (C) 2002 Deep Blue Solutions Ltd. | ||
6 | * Copyright (C) 2012 ARM Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | #ifndef __ASM_ATOMIC_H | ||
21 | #define __ASM_ATOMIC_H | ||
22 | |||
23 | #include <linux/compiler.h> | ||
24 | #include <linux/types.h> | ||
25 | |||
26 | #include <asm/barrier.h> | ||
27 | #include <asm/cmpxchg.h> | ||
28 | |||
29 | #define ATOMIC_INIT(i) { (i) } | ||
30 | |||
31 | #ifdef __KERNEL__ | ||
32 | |||
33 | /* | ||
34 | * On ARM, ordinary assignment (str instruction) doesn't clear the local | ||
35 | * strex/ldrex monitor on some implementations. The reason we can use it for | ||
36 | * atomic_set() is the clrex or dummy strex done on every exception return. | ||
37 | */ | ||
38 | #define atomic_read(v) (*(volatile int *)&(v)->counter) | ||
39 | #define atomic_set(v,i) (((v)->counter) = (i)) | ||
40 | |||
41 | /* | ||
42 | * AArch64 UP and SMP safe atomic ops. We use load exclusive and | ||
43 | * store exclusive to ensure that these are atomic. We may loop | ||
44 | * to ensure that the update happens. | ||
45 | */ | ||
46 | static inline void atomic_add(int i, atomic_t *v) | ||
47 | { | ||
48 | unsigned long tmp; | ||
49 | int result; | ||
50 | |||
51 | asm volatile("// atomic_add\n" | ||
52 | "1: ldxr %w0, [%3]\n" | ||
53 | " add %w0, %w0, %w4\n" | ||
54 | " stxr %w1, %w0, [%3]\n" | ||
55 | " cbnz %w1, 1b" | ||
56 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
57 | : "r" (&v->counter), "Ir" (i) | ||
58 | : "cc"); | ||
59 | } | ||
60 | |||
61 | static inline int atomic_add_return(int i, atomic_t *v) | ||
62 | { | ||
63 | unsigned long tmp; | ||
64 | int result; | ||
65 | |||
66 | asm volatile("// atomic_add_return\n" | ||
67 | "1: ldaxr %w0, [%3]\n" | ||
68 | " add %w0, %w0, %w4\n" | ||
69 | " stlxr %w1, %w0, [%3]\n" | ||
70 | " cbnz %w1, 1b" | ||
71 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
72 | : "r" (&v->counter), "Ir" (i) | ||
73 | : "cc"); | ||
74 | |||
75 | return result; | ||
76 | } | ||
77 | |||
78 | static inline void atomic_sub(int i, atomic_t *v) | ||
79 | { | ||
80 | unsigned long tmp; | ||
81 | int result; | ||
82 | |||
83 | asm volatile("// atomic_sub\n" | ||
84 | "1: ldxr %w0, [%3]\n" | ||
85 | " sub %w0, %w0, %w4\n" | ||
86 | " stxr %w1, %w0, [%3]\n" | ||
87 | " cbnz %w1, 1b" | ||
88 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
89 | : "r" (&v->counter), "Ir" (i) | ||
90 | : "cc"); | ||
91 | } | ||
92 | |||
93 | static inline int atomic_sub_return(int i, atomic_t *v) | ||
94 | { | ||
95 | unsigned long tmp; | ||
96 | int result; | ||
97 | |||
98 | asm volatile("// atomic_sub_return\n" | ||
99 | "1: ldaxr %w0, [%3]\n" | ||
100 | " sub %w0, %w0, %w4\n" | ||
101 | " stlxr %w1, %w0, [%3]\n" | ||
102 | " cbnz %w1, 1b" | ||
103 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
104 | : "r" (&v->counter), "Ir" (i) | ||
105 | : "cc"); | ||
106 | |||
107 | return result; | ||
108 | } | ||
109 | |||
110 | static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) | ||
111 | { | ||
112 | unsigned long tmp; | ||
113 | int oldval; | ||
114 | |||
115 | asm volatile("// atomic_cmpxchg\n" | ||
116 | "1: ldaxr %w1, [%3]\n" | ||
117 | " cmp %w1, %w4\n" | ||
118 | " b.ne 2f\n" | ||
119 | " stlxr %w0, %w5, [%3]\n" | ||
120 | " cbnz %w0, 1b\n" | ||
121 | "2:" | ||
122 | : "=&r" (tmp), "=&r" (oldval), "+o" (ptr->counter) | ||
123 | : "r" (&ptr->counter), "Ir" (old), "r" (new) | ||
124 | : "cc"); | ||
125 | |||
126 | return oldval; | ||
127 | } | ||
128 | |||
129 | static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) | ||
130 | { | ||
131 | unsigned long tmp, tmp2; | ||
132 | |||
133 | asm volatile("// atomic_clear_mask\n" | ||
134 | "1: ldxr %0, [%3]\n" | ||
135 | " bic %0, %0, %4\n" | ||
136 | " stxr %w1, %0, [%3]\n" | ||
137 | " cbnz %w1, 1b" | ||
138 | : "=&r" (tmp), "=&r" (tmp2), "+o" (*addr) | ||
139 | : "r" (addr), "Ir" (mask) | ||
140 | : "cc"); | ||
141 | } | ||
142 | |||
143 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | ||
144 | |||
145 | static inline int __atomic_add_unless(atomic_t *v, int a, int u) | ||
146 | { | ||
147 | int c, old; | ||
148 | |||
149 | c = atomic_read(v); | ||
150 | while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) | ||
151 | c = old; | ||
152 | return c; | ||
153 | } | ||
154 | |||
155 | #define atomic_inc(v) atomic_add(1, v) | ||
156 | #define atomic_dec(v) atomic_sub(1, v) | ||
157 | |||
158 | #define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) | ||
159 | #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) | ||
160 | #define atomic_inc_return(v) (atomic_add_return(1, v)) | ||
161 | #define atomic_dec_return(v) (atomic_sub_return(1, v)) | ||
162 | #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) | ||
163 | |||
164 | #define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0) | ||
165 | |||
166 | #define smp_mb__before_atomic_dec() smp_mb() | ||
167 | #define smp_mb__after_atomic_dec() smp_mb() | ||
168 | #define smp_mb__before_atomic_inc() smp_mb() | ||
169 | #define smp_mb__after_atomic_inc() smp_mb() | ||
170 | |||
171 | /* | ||
172 | * 64-bit atomic operations. | ||
173 | */ | ||
174 | #define ATOMIC64_INIT(i) { (i) } | ||
175 | |||
176 | #define atomic64_read(v) (*(volatile long long *)&(v)->counter) | ||
177 | #define atomic64_set(v,i) (((v)->counter) = (i)) | ||
178 | |||
179 | static inline void atomic64_add(u64 i, atomic64_t *v) | ||
180 | { | ||
181 | long result; | ||
182 | unsigned long tmp; | ||
183 | |||
184 | asm volatile("// atomic64_add\n" | ||
185 | "1: ldxr %0, [%3]\n" | ||
186 | " add %0, %0, %4\n" | ||
187 | " stxr %w1, %0, [%3]\n" | ||
188 | " cbnz %w1, 1b" | ||
189 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
190 | : "r" (&v->counter), "Ir" (i) | ||
191 | : "cc"); | ||
192 | } | ||
193 | |||
194 | static inline long atomic64_add_return(long i, atomic64_t *v) | ||
195 | { | ||
196 | long result; | ||
197 | unsigned long tmp; | ||
198 | |||
199 | asm volatile("// atomic64_add_return\n" | ||
200 | "1: ldaxr %0, [%3]\n" | ||
201 | " add %0, %0, %4\n" | ||
202 | " stlxr %w1, %0, [%3]\n" | ||
203 | " cbnz %w1, 1b" | ||
204 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
205 | : "r" (&v->counter), "Ir" (i) | ||
206 | : "cc"); | ||
207 | |||
208 | return result; | ||
209 | } | ||
210 | |||
211 | static inline void atomic64_sub(u64 i, atomic64_t *v) | ||
212 | { | ||
213 | long result; | ||
214 | unsigned long tmp; | ||
215 | |||
216 | asm volatile("// atomic64_sub\n" | ||
217 | "1: ldxr %0, [%3]\n" | ||
218 | " sub %0, %0, %4\n" | ||
219 | " stxr %w1, %0, [%3]\n" | ||
220 | " cbnz %w1, 1b" | ||
221 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
222 | : "r" (&v->counter), "Ir" (i) | ||
223 | : "cc"); | ||
224 | } | ||
225 | |||
226 | static inline long atomic64_sub_return(long i, atomic64_t *v) | ||
227 | { | ||
228 | long result; | ||
229 | unsigned long tmp; | ||
230 | |||
231 | asm volatile("// atomic64_sub_return\n" | ||
232 | "1: ldaxr %0, [%3]\n" | ||
233 | " sub %0, %0, %4\n" | ||
234 | " stlxr %w1, %0, [%3]\n" | ||
235 | " cbnz %w1, 1b" | ||
236 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
237 | : "r" (&v->counter), "Ir" (i) | ||
238 | : "cc"); | ||
239 | |||
240 | return result; | ||
241 | } | ||
242 | |||
243 | static inline long atomic64_cmpxchg(atomic64_t *ptr, long old, long new) | ||
244 | { | ||
245 | long oldval; | ||
246 | unsigned long res; | ||
247 | |||
248 | asm volatile("// atomic64_cmpxchg\n" | ||
249 | "1: ldaxr %1, [%3]\n" | ||
250 | " cmp %1, %4\n" | ||
251 | " b.ne 2f\n" | ||
252 | " stlxr %w0, %5, [%3]\n" | ||
253 | " cbnz %w0, 1b\n" | ||
254 | "2:" | ||
255 | : "=&r" (res), "=&r" (oldval), "+o" (ptr->counter) | ||
256 | : "r" (&ptr->counter), "Ir" (old), "r" (new) | ||
257 | : "cc"); | ||
258 | |||
259 | return oldval; | ||
260 | } | ||
261 | |||
262 | #define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) | ||
263 | |||
264 | static inline long atomic64_dec_if_positive(atomic64_t *v) | ||
265 | { | ||
266 | long result; | ||
267 | unsigned long tmp; | ||
268 | |||
269 | asm volatile("// atomic64_dec_if_positive\n" | ||
270 | "1: ldaxr %0, [%3]\n" | ||
271 | " subs %0, %0, #1\n" | ||
272 | " b.mi 2f\n" | ||
273 | " stlxr %w1, %0, [%3]\n" | ||
274 | " cbnz %w1, 1b\n" | ||
275 | "2:" | ||
276 | : "=&r" (result), "=&r" (tmp), "+o" (v->counter) | ||
277 | : "r" (&v->counter) | ||
278 | : "cc"); | ||
279 | |||
280 | return result; | ||
281 | } | ||
282 | |||
283 | static inline int atomic64_add_unless(atomic64_t *v, long a, long u) | ||
284 | { | ||
285 | long c, old; | ||
286 | |||
287 | c = atomic64_read(v); | ||
288 | while (c != u && (old = atomic64_cmpxchg((v), c, c + a)) != c) | ||
289 | c = old; | ||
290 | |||
291 | return c != u; | ||
292 | } | ||
293 | |||
294 | #define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0) | ||
295 | #define atomic64_inc(v) atomic64_add(1LL, (v)) | ||
296 | #define atomic64_inc_return(v) atomic64_add_return(1LL, (v)) | ||
297 | #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) | ||
298 | #define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0) | ||
299 | #define atomic64_dec(v) atomic64_sub(1LL, (v)) | ||
300 | #define atomic64_dec_return(v) atomic64_sub_return(1LL, (v)) | ||
301 | #define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) | ||
302 | #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL) | ||
303 | |||
304 | #endif | ||
305 | #endif | ||
diff --git a/arch/arm64/include/asm/auxvec.h b/arch/arm64/include/asm/auxvec.h new file mode 100644 index 000000000000..22d6d8885854 --- /dev/null +++ b/arch/arm64/include/asm/auxvec.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_AUXVEC_H | ||
17 | #define __ASM_AUXVEC_H | ||
18 | |||
19 | /* vDSO location */ | ||
20 | #define AT_SYSINFO_EHDR 33 | ||
21 | |||
22 | #endif | ||
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h new file mode 100644 index 000000000000..d4a63338a53c --- /dev/null +++ b/arch/arm64/include/asm/barrier.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/barrier.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_BARRIER_H | ||
19 | #define __ASM_BARRIER_H | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | |||
23 | #define sev() asm volatile("sev" : : : "memory") | ||
24 | #define wfe() asm volatile("wfe" : : : "memory") | ||
25 | #define wfi() asm volatile("wfi" : : : "memory") | ||
26 | |||
27 | #define isb() asm volatile("isb" : : : "memory") | ||
28 | #define dsb() asm volatile("dsb sy" : : : "memory") | ||
29 | |||
30 | #define mb() dsb() | ||
31 | #define rmb() asm volatile("dsb ld" : : : "memory") | ||
32 | #define wmb() asm volatile("dsb st" : : : "memory") | ||
33 | |||
34 | #ifndef CONFIG_SMP | ||
35 | #define smp_mb() barrier() | ||
36 | #define smp_rmb() barrier() | ||
37 | #define smp_wmb() barrier() | ||
38 | #else | ||
39 | #define smp_mb() asm volatile("dmb ish" : : : "memory") | ||
40 | #define smp_rmb() asm volatile("dmb ishld" : : : "memory") | ||
41 | #define smp_wmb() asm volatile("dmb ishst" : : : "memory") | ||
42 | #endif | ||
43 | |||
44 | #define read_barrier_depends() do { } while(0) | ||
45 | #define smp_read_barrier_depends() do { } while(0) | ||
46 | |||
47 | #define set_mb(var, value) do { var = value; smp_mb(); } while (0) | ||
48 | #define nop() asm volatile("nop"); | ||
49 | |||
50 | #endif /* __ASSEMBLY__ */ | ||
51 | |||
52 | #endif /* __ASM_BARRIER_H */ | ||
diff --git a/arch/arm64/include/asm/bitops.h b/arch/arm64/include/asm/bitops.h new file mode 100644 index 000000000000..5e693073b030 --- /dev/null +++ b/arch/arm64/include/asm/bitops.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_BITOPS_H | ||
17 | #define __ASM_BITOPS_H | ||
18 | |||
19 | #include <linux/compiler.h> | ||
20 | |||
21 | #include <asm/barrier.h> | ||
22 | |||
23 | /* | ||
24 | * clear_bit may not imply a memory barrier | ||
25 | */ | ||
26 | #ifndef smp_mb__before_clear_bit | ||
27 | #define smp_mb__before_clear_bit() smp_mb() | ||
28 | #define smp_mb__after_clear_bit() smp_mb() | ||
29 | #endif | ||
30 | |||
31 | #ifndef _LINUX_BITOPS_H | ||
32 | #error only <linux/bitops.h> can be included directly | ||
33 | #endif | ||
34 | |||
35 | #include <asm-generic/bitops/builtin-__ffs.h> | ||
36 | #include <asm-generic/bitops/builtin-ffs.h> | ||
37 | #include <asm-generic/bitops/builtin-__fls.h> | ||
38 | #include <asm-generic/bitops/builtin-fls.h> | ||
39 | |||
40 | #include <asm-generic/bitops/ffz.h> | ||
41 | #include <asm-generic/bitops/fls64.h> | ||
42 | #include <asm-generic/bitops/find.h> | ||
43 | |||
44 | #include <asm-generic/bitops/sched.h> | ||
45 | #include <asm-generic/bitops/hweight.h> | ||
46 | #include <asm-generic/bitops/lock.h> | ||
47 | |||
48 | #include <asm-generic/bitops/atomic.h> | ||
49 | #include <asm-generic/bitops/non-atomic.h> | ||
50 | #include <asm-generic/bitops/le.h> | ||
51 | #include <asm-generic/bitops/ext2-atomic.h> | ||
52 | |||
53 | #endif /* __ASM_BITOPS_H */ | ||
diff --git a/arch/arm64/include/asm/bitsperlong.h b/arch/arm64/include/asm/bitsperlong.h new file mode 100644 index 000000000000..fce9c2924fa3 --- /dev/null +++ b/arch/arm64/include/asm/bitsperlong.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_BITSPERLONG_H | ||
17 | #define __ASM_BITSPERLONG_H | ||
18 | |||
19 | #define __BITS_PER_LONG 64 | ||
20 | |||
21 | #include <asm-generic/bitsperlong.h> | ||
22 | |||
23 | #endif /* __ASM_BITSPERLONG_H */ | ||
diff --git a/arch/arm64/include/asm/byteorder.h b/arch/arm64/include/asm/byteorder.h new file mode 100644 index 000000000000..2b92046aafc5 --- /dev/null +++ b/arch/arm64/include/asm/byteorder.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_BYTEORDER_H | ||
17 | #define __ASM_BYTEORDER_H | ||
18 | |||
19 | #include <linux/byteorder/little_endian.h> | ||
20 | |||
21 | #endif /* __ASM_BYTEORDER_H */ | ||
diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h new file mode 100644 index 000000000000..390308a67f0d --- /dev/null +++ b/arch/arm64/include/asm/cache.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_CACHE_H | ||
17 | #define __ASM_CACHE_H | ||
18 | |||
19 | #define L1_CACHE_SHIFT 6 | ||
20 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | ||
21 | |||
22 | /* | ||
23 | * Memory returned by kmalloc() may be used for DMA, so we must make | ||
24 | * sure that all such allocations are cache aligned. Otherwise, | ||
25 | * unrelated code may cause parts of the buffer to be read into the | ||
26 | * cache before the transfer is done, causing old data to be seen by | ||
27 | * the CPU. | ||
28 | */ | ||
29 | #define ARCH_DMA_MINALIGN L1_CACHE_BYTES | ||
30 | #define ARCH_SLAB_MINALIGN 8 | ||
31 | |||
32 | #endif | ||
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h new file mode 100644 index 000000000000..aa3132ab7f29 --- /dev/null +++ b/arch/arm64/include/asm/cacheflush.h | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/cacheflush.h | ||
3 | * | ||
4 | * Copyright (C) 1999-2002 Russell King. | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_CACHEFLUSH_H | ||
20 | #define __ASM_CACHEFLUSH_H | ||
21 | |||
22 | #include <linux/mm.h> | ||
23 | |||
24 | /* | ||
25 | * This flag is used to indicate that the page pointed to by a pte is clean | ||
26 | * and does not require cleaning before returning it to the user. | ||
27 | */ | ||
28 | #define PG_dcache_clean PG_arch_1 | ||
29 | |||
30 | /* | ||
31 | * MM Cache Management | ||
32 | * =================== | ||
33 | * | ||
34 | * The arch/arm64/mm/cache.S implements these methods. | ||
35 | * | ||
36 | * Start addresses are inclusive and end addresses are exclusive; start | ||
37 | * addresses should be rounded down, end addresses up. | ||
38 | * | ||
39 | * See Documentation/cachetlb.txt for more information. Please note that | ||
40 | * the implementation assumes non-aliasing VIPT D-cache and (aliasing) | ||
41 | * VIPT or ASID-tagged VIVT I-cache. | ||
42 | * | ||
43 | * flush_cache_all() | ||
44 | * | ||
45 | * Unconditionally clean and invalidate the entire cache. | ||
46 | * | ||
47 | * flush_cache_mm(mm) | ||
48 | * | ||
49 | * Clean and invalidate all user space cache entries | ||
50 | * before a change of page tables. | ||
51 | * | ||
52 | * flush_icache_range(start, end) | ||
53 | * | ||
54 | * Ensure coherency between the I-cache and the D-cache in the | ||
55 | * region described by start, end. | ||
56 | * - start - virtual start address | ||
57 | * - end - virtual end address | ||
58 | * | ||
59 | * __flush_cache_user_range(start, end) | ||
60 | * | ||
61 | * Ensure coherency between the I-cache and the D-cache in the | ||
62 | * region described by start, end. | ||
63 | * - start - virtual start address | ||
64 | * - end - virtual end address | ||
65 | * | ||
66 | * __flush_dcache_area(kaddr, size) | ||
67 | * | ||
68 | * Ensure that the data held in page is written back. | ||
69 | * - kaddr - page address | ||
70 | * - size - region size | ||
71 | */ | ||
72 | extern void flush_cache_all(void); | ||
73 | extern void flush_cache_mm(struct mm_struct *mm); | ||
74 | extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); | ||
75 | extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); | ||
76 | extern void flush_icache_range(unsigned long start, unsigned long end); | ||
77 | extern void __flush_dcache_area(void *addr, size_t len); | ||
78 | extern void __flush_cache_user_range(unsigned long start, unsigned long end); | ||
79 | |||
80 | /* | ||
81 | * Copy user data from/to a page which is mapped into a different | ||
82 | * processes address space. Really, we want to allow our "user | ||
83 | * space" model to handle this. | ||
84 | */ | ||
85 | extern void copy_to_user_page(struct vm_area_struct *, struct page *, | ||
86 | unsigned long, void *, const void *, unsigned long); | ||
87 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | ||
88 | do { \ | ||
89 | memcpy(dst, src, len); \ | ||
90 | } while (0) | ||
91 | |||
92 | #define flush_cache_dup_mm(mm) flush_cache_mm(mm) | ||
93 | |||
94 | /* | ||
95 | * flush_dcache_page is used when the kernel has written to the page | ||
96 | * cache page at virtual address page->virtual. | ||
97 | * | ||
98 | * If this page isn't mapped (ie, page_mapping == NULL), or it might | ||
99 | * have userspace mappings, then we _must_ always clean + invalidate | ||
100 | * the dcache entries associated with the kernel mapping. | ||
101 | * | ||
102 | * Otherwise we can defer the operation, and clean the cache when we are | ||
103 | * about to change to user space. This is the same method as used on SPARC64. | ||
104 | * See update_mmu_cache for the user space part. | ||
105 | */ | ||
106 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | ||
107 | extern void flush_dcache_page(struct page *); | ||
108 | |||
109 | static inline void __flush_icache_all(void) | ||
110 | { | ||
111 | asm("ic ialluis"); | ||
112 | } | ||
113 | |||
114 | #define flush_dcache_mmap_lock(mapping) \ | ||
115 | spin_lock_irq(&(mapping)->tree_lock) | ||
116 | #define flush_dcache_mmap_unlock(mapping) \ | ||
117 | spin_unlock_irq(&(mapping)->tree_lock) | ||
118 | |||
119 | #define flush_icache_user_range(vma,page,addr,len) \ | ||
120 | flush_dcache_page(page) | ||
121 | |||
122 | /* | ||
123 | * We don't appear to need to do anything here. In fact, if we did, we'd | ||
124 | * duplicate cache flushing elsewhere performed by flush_dcache_page(). | ||
125 | */ | ||
126 | #define flush_icache_page(vma,page) do { } while (0) | ||
127 | |||
128 | /* | ||
129 | * flush_cache_vmap() is used when creating mappings (eg, via vmap, | ||
130 | * vmalloc, ioremap etc) in kernel space for pages. On non-VIPT | ||
131 | * caches, since the direct-mappings of these pages may contain cached | ||
132 | * data, we need to do a full cache flush to ensure that writebacks | ||
133 | * don't corrupt data placed into these pages via the new mappings. | ||
134 | */ | ||
135 | static inline void flush_cache_vmap(unsigned long start, unsigned long end) | ||
136 | { | ||
137 | /* | ||
138 | * set_pte_at() called from vmap_pte_range() does not | ||
139 | * have a DSB after cleaning the cache line. | ||
140 | */ | ||
141 | dsb(); | ||
142 | } | ||
143 | |||
144 | static inline void flush_cache_vunmap(unsigned long start, unsigned long end) | ||
145 | { | ||
146 | } | ||
147 | |||
148 | #endif | ||
diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h new file mode 100644 index 000000000000..85f5f511352a --- /dev/null +++ b/arch/arm64/include/asm/cachetype.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_CACHETYPE_H | ||
17 | #define __ASM_CACHETYPE_H | ||
18 | |||
19 | #include <asm/cputype.h> | ||
20 | |||
21 | #define CTR_L1IP_SHIFT 14 | ||
22 | #define CTR_L1IP_MASK 3 | ||
23 | |||
24 | #define ICACHE_POLICY_RESERVED 0 | ||
25 | #define ICACHE_POLICY_AIVIVT 1 | ||
26 | #define ICACHE_POLICY_VIPT 2 | ||
27 | #define ICACHE_POLICY_PIPT 3 | ||
28 | |||
29 | static inline u32 icache_policy(void) | ||
30 | { | ||
31 | return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK; | ||
32 | } | ||
33 | |||
34 | /* | ||
35 | * Whilst the D-side always behaves as PIPT on AArch64, aliasing is | ||
36 | * permitted in the I-cache. | ||
37 | */ | ||
38 | static inline int icache_is_aliasing(void) | ||
39 | { | ||
40 | return icache_policy() != ICACHE_POLICY_PIPT; | ||
41 | } | ||
42 | |||
43 | static inline int icache_is_aivivt(void) | ||
44 | { | ||
45 | return icache_policy() == ICACHE_POLICY_AIVIVT; | ||
46 | } | ||
47 | |||
48 | #endif /* __ASM_CACHETYPE_H */ | ||
diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h new file mode 100644 index 000000000000..e0e65b069d9e --- /dev/null +++ b/arch/arm64/include/asm/cmpxchg.h | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/cmpxchg.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_CMPXCHG_H | ||
19 | #define __ASM_CMPXCHG_H | ||
20 | |||
21 | #include <linux/bug.h> | ||
22 | |||
23 | #include <asm/barrier.h> | ||
24 | |||
25 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) | ||
26 | { | ||
27 | unsigned long ret, tmp; | ||
28 | |||
29 | switch (size) { | ||
30 | case 1: | ||
31 | asm volatile("// __xchg1\n" | ||
32 | "1: ldaxrb %w0, [%3]\n" | ||
33 | " stlxrb %w1, %w2, [%3]\n" | ||
34 | " cbnz %w1, 1b\n" | ||
35 | : "=&r" (ret), "=&r" (tmp) | ||
36 | : "r" (x), "r" (ptr) | ||
37 | : "memory", "cc"); | ||
38 | break; | ||
39 | case 2: | ||
40 | asm volatile("// __xchg2\n" | ||
41 | "1: ldaxrh %w0, [%3]\n" | ||
42 | " stlxrh %w1, %w2, [%3]\n" | ||
43 | " cbnz %w1, 1b\n" | ||
44 | : "=&r" (ret), "=&r" (tmp) | ||
45 | : "r" (x), "r" (ptr) | ||
46 | : "memory", "cc"); | ||
47 | break; | ||
48 | case 4: | ||
49 | asm volatile("// __xchg4\n" | ||
50 | "1: ldaxr %w0, [%3]\n" | ||
51 | " stlxr %w1, %w2, [%3]\n" | ||
52 | " cbnz %w1, 1b\n" | ||
53 | : "=&r" (ret), "=&r" (tmp) | ||
54 | : "r" (x), "r" (ptr) | ||
55 | : "memory", "cc"); | ||
56 | break; | ||
57 | case 8: | ||
58 | asm volatile("// __xchg8\n" | ||
59 | "1: ldaxr %0, [%3]\n" | ||
60 | " stlxr %w1, %2, [%3]\n" | ||
61 | " cbnz %w1, 1b\n" | ||
62 | : "=&r" (ret), "=&r" (tmp) | ||
63 | : "r" (x), "r" (ptr) | ||
64 | : "memory", "cc"); | ||
65 | break; | ||
66 | default: | ||
67 | BUILD_BUG(); | ||
68 | } | ||
69 | |||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | #define xchg(ptr,x) \ | ||
74 | ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | ||
75 | |||
76 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | ||
77 | unsigned long new, int size) | ||
78 | { | ||
79 | unsigned long oldval = 0, res; | ||
80 | |||
81 | switch (size) { | ||
82 | case 1: | ||
83 | do { | ||
84 | asm volatile("// __cmpxchg1\n" | ||
85 | " ldxrb %w1, [%2]\n" | ||
86 | " mov %w0, #0\n" | ||
87 | " cmp %w1, %w3\n" | ||
88 | " b.ne 1f\n" | ||
89 | " stxrb %w0, %w4, [%2]\n" | ||
90 | "1:\n" | ||
91 | : "=&r" (res), "=&r" (oldval) | ||
92 | : "r" (ptr), "Ir" (old), "r" (new) | ||
93 | : "cc"); | ||
94 | } while (res); | ||
95 | break; | ||
96 | |||
97 | case 2: | ||
98 | do { | ||
99 | asm volatile("// __cmpxchg2\n" | ||
100 | " ldxrh %w1, [%2]\n" | ||
101 | " mov %w0, #0\n" | ||
102 | " cmp %w1, %w3\n" | ||
103 | " b.ne 1f\n" | ||
104 | " stxrh %w0, %w4, [%2]\n" | ||
105 | "1:\n" | ||
106 | : "=&r" (res), "=&r" (oldval) | ||
107 | : "r" (ptr), "Ir" (old), "r" (new) | ||
108 | : "memory", "cc"); | ||
109 | } while (res); | ||
110 | break; | ||
111 | |||
112 | case 4: | ||
113 | do { | ||
114 | asm volatile("// __cmpxchg4\n" | ||
115 | " ldxr %w1, [%2]\n" | ||
116 | " mov %w0, #0\n" | ||
117 | " cmp %w1, %w3\n" | ||
118 | " b.ne 1f\n" | ||
119 | " stxr %w0, %w4, [%2]\n" | ||
120 | "1:\n" | ||
121 | : "=&r" (res), "=&r" (oldval) | ||
122 | : "r" (ptr), "Ir" (old), "r" (new) | ||
123 | : "cc"); | ||
124 | } while (res); | ||
125 | break; | ||
126 | |||
127 | case 8: | ||
128 | do { | ||
129 | asm volatile("// __cmpxchg8\n" | ||
130 | " ldxr %1, [%2]\n" | ||
131 | " mov %w0, #0\n" | ||
132 | " cmp %1, %3\n" | ||
133 | " b.ne 1f\n" | ||
134 | " stxr %w0, %4, [%2]\n" | ||
135 | "1:\n" | ||
136 | : "=&r" (res), "=&r" (oldval) | ||
137 | : "r" (ptr), "Ir" (old), "r" (new) | ||
138 | : "cc"); | ||
139 | } while (res); | ||
140 | break; | ||
141 | |||
142 | default: | ||
143 | BUILD_BUG(); | ||
144 | } | ||
145 | |||
146 | return oldval; | ||
147 | } | ||
148 | |||
149 | static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old, | ||
150 | unsigned long new, int size) | ||
151 | { | ||
152 | unsigned long ret; | ||
153 | |||
154 | smp_mb(); | ||
155 | ret = __cmpxchg(ptr, old, new, size); | ||
156 | smp_mb(); | ||
157 | |||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | #define cmpxchg(ptr,o,n) \ | ||
162 | ((__typeof__(*(ptr)))__cmpxchg_mb((ptr), \ | ||
163 | (unsigned long)(o), \ | ||
164 | (unsigned long)(n), \ | ||
165 | sizeof(*(ptr)))) | ||
166 | |||
167 | #define cmpxchg_local(ptr,o,n) \ | ||
168 | ((__typeof__(*(ptr)))__cmpxchg((ptr), \ | ||
169 | (unsigned long)(o), \ | ||
170 | (unsigned long)(n), \ | ||
171 | sizeof(*(ptr)))) | ||
172 | |||
173 | #endif /* __ASM_CMPXCHG_H */ | ||
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h new file mode 100644 index 000000000000..a670a33ad736 --- /dev/null +++ b/arch/arm64/include/asm/compat.h | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_COMPAT_H | ||
17 | #define __ASM_COMPAT_H | ||
18 | #ifdef __KERNEL__ | ||
19 | #ifdef CONFIG_COMPAT | ||
20 | |||
21 | /* | ||
22 | * Architecture specific compatibility types | ||
23 | */ | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/sched.h> | ||
26 | |||
27 | #define COMPAT_USER_HZ 100 | ||
28 | #define COMPAT_UTS_MACHINE "armv8l\0\0" | ||
29 | |||
30 | typedef u32 compat_size_t; | ||
31 | typedef s32 compat_ssize_t; | ||
32 | typedef s32 compat_time_t; | ||
33 | typedef s32 compat_clock_t; | ||
34 | typedef s32 compat_pid_t; | ||
35 | typedef u32 __compat_uid_t; | ||
36 | typedef u32 __compat_gid_t; | ||
37 | typedef u32 __compat_uid32_t; | ||
38 | typedef u32 __compat_gid32_t; | ||
39 | typedef u32 compat_mode_t; | ||
40 | typedef u32 compat_ino_t; | ||
41 | typedef u32 compat_dev_t; | ||
42 | typedef s32 compat_off_t; | ||
43 | typedef s64 compat_loff_t; | ||
44 | typedef s16 compat_nlink_t; | ||
45 | typedef u16 compat_ipc_pid_t; | ||
46 | typedef s32 compat_daddr_t; | ||
47 | typedef u32 compat_caddr_t; | ||
48 | typedef __kernel_fsid_t compat_fsid_t; | ||
49 | typedef s32 compat_key_t; | ||
50 | typedef s32 compat_timer_t; | ||
51 | |||
52 | typedef s32 compat_int_t; | ||
53 | typedef s32 compat_long_t; | ||
54 | typedef s64 compat_s64; | ||
55 | typedef u32 compat_uint_t; | ||
56 | typedef u32 compat_ulong_t; | ||
57 | typedef u64 compat_u64; | ||
58 | |||
59 | struct compat_timespec { | ||
60 | compat_time_t tv_sec; | ||
61 | s32 tv_nsec; | ||
62 | }; | ||
63 | |||
64 | struct compat_timeval { | ||
65 | compat_time_t tv_sec; | ||
66 | s32 tv_usec; | ||
67 | }; | ||
68 | |||
69 | struct compat_stat { | ||
70 | compat_dev_t st_dev; | ||
71 | compat_ino_t st_ino; | ||
72 | compat_mode_t st_mode; | ||
73 | compat_nlink_t st_nlink; | ||
74 | __compat_uid32_t st_uid; | ||
75 | __compat_gid32_t st_gid; | ||
76 | compat_dev_t st_rdev; | ||
77 | compat_off_t st_size; | ||
78 | compat_off_t st_blksize; | ||
79 | compat_off_t st_blocks; | ||
80 | compat_time_t st_atime; | ||
81 | u32 st_atime_nsec; | ||
82 | compat_time_t st_mtime; | ||
83 | u32 st_mtime_nsec; | ||
84 | compat_time_t st_ctime; | ||
85 | u32 st_ctime_nsec; | ||
86 | u32 __unused4[2]; | ||
87 | }; | ||
88 | |||
89 | struct compat_flock { | ||
90 | short l_type; | ||
91 | short l_whence; | ||
92 | compat_off_t l_start; | ||
93 | compat_off_t l_len; | ||
94 | compat_pid_t l_pid; | ||
95 | }; | ||
96 | |||
97 | #define F_GETLK64 12 /* using 'struct flock64' */ | ||
98 | #define F_SETLK64 13 | ||
99 | #define F_SETLKW64 14 | ||
100 | |||
101 | struct compat_flock64 { | ||
102 | short l_type; | ||
103 | short l_whence; | ||
104 | compat_loff_t l_start; | ||
105 | compat_loff_t l_len; | ||
106 | compat_pid_t l_pid; | ||
107 | }; | ||
108 | |||
109 | struct compat_statfs { | ||
110 | int f_type; | ||
111 | int f_bsize; | ||
112 | int f_blocks; | ||
113 | int f_bfree; | ||
114 | int f_bavail; | ||
115 | int f_files; | ||
116 | int f_ffree; | ||
117 | compat_fsid_t f_fsid; | ||
118 | int f_namelen; /* SunOS ignores this field. */ | ||
119 | int f_frsize; | ||
120 | int f_flags; | ||
121 | int f_spare[4]; | ||
122 | }; | ||
123 | |||
124 | #define COMPAT_RLIM_INFINITY 0xffffffff | ||
125 | |||
126 | typedef u32 compat_old_sigset_t; | ||
127 | |||
128 | #define _COMPAT_NSIG 64 | ||
129 | #define _COMPAT_NSIG_BPW 32 | ||
130 | |||
131 | typedef u32 compat_sigset_word; | ||
132 | |||
133 | #define COMPAT_OFF_T_MAX 0x7fffffff | ||
134 | #define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL | ||
135 | |||
136 | /* | ||
137 | * A pointer passed in from user mode. This should not | ||
138 | * be used for syscall parameters, just declare them | ||
139 | * as pointers because the syscall entry code will have | ||
140 | * appropriately converted them already. | ||
141 | */ | ||
142 | typedef u32 compat_uptr_t; | ||
143 | |||
144 | static inline void __user *compat_ptr(compat_uptr_t uptr) | ||
145 | { | ||
146 | return (void __user *)(unsigned long)uptr; | ||
147 | } | ||
148 | |||
149 | static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
150 | { | ||
151 | return (u32)(unsigned long)uptr; | ||
152 | } | ||
153 | |||
154 | static inline void __user *arch_compat_alloc_user_space(long len) | ||
155 | { | ||
156 | struct pt_regs *regs = task_pt_regs(current); | ||
157 | return (void __user *)regs->compat_sp - len; | ||
158 | } | ||
159 | |||
160 | struct compat_ipc64_perm { | ||
161 | compat_key_t key; | ||
162 | __compat_uid32_t uid; | ||
163 | __compat_gid32_t gid; | ||
164 | __compat_uid32_t cuid; | ||
165 | __compat_gid32_t cgid; | ||
166 | unsigned short mode; | ||
167 | unsigned short __pad1; | ||
168 | unsigned short seq; | ||
169 | unsigned short __pad2; | ||
170 | compat_ulong_t unused1; | ||
171 | compat_ulong_t unused2; | ||
172 | }; | ||
173 | |||
174 | struct compat_semid64_ds { | ||
175 | struct compat_ipc64_perm sem_perm; | ||
176 | compat_time_t sem_otime; | ||
177 | compat_ulong_t __unused1; | ||
178 | compat_time_t sem_ctime; | ||
179 | compat_ulong_t __unused2; | ||
180 | compat_ulong_t sem_nsems; | ||
181 | compat_ulong_t __unused3; | ||
182 | compat_ulong_t __unused4; | ||
183 | }; | ||
184 | |||
185 | struct compat_msqid64_ds { | ||
186 | struct compat_ipc64_perm msg_perm; | ||
187 | compat_time_t msg_stime; | ||
188 | compat_ulong_t __unused1; | ||
189 | compat_time_t msg_rtime; | ||
190 | compat_ulong_t __unused2; | ||
191 | compat_time_t msg_ctime; | ||
192 | compat_ulong_t __unused3; | ||
193 | compat_ulong_t msg_cbytes; | ||
194 | compat_ulong_t msg_qnum; | ||
195 | compat_ulong_t msg_qbytes; | ||
196 | compat_pid_t msg_lspid; | ||
197 | compat_pid_t msg_lrpid; | ||
198 | compat_ulong_t __unused4; | ||
199 | compat_ulong_t __unused5; | ||
200 | }; | ||
201 | |||
202 | struct compat_shmid64_ds { | ||
203 | struct compat_ipc64_perm shm_perm; | ||
204 | compat_size_t shm_segsz; | ||
205 | compat_time_t shm_atime; | ||
206 | compat_ulong_t __unused1; | ||
207 | compat_time_t shm_dtime; | ||
208 | compat_ulong_t __unused2; | ||
209 | compat_time_t shm_ctime; | ||
210 | compat_ulong_t __unused3; | ||
211 | compat_pid_t shm_cpid; | ||
212 | compat_pid_t shm_lpid; | ||
213 | compat_ulong_t shm_nattch; | ||
214 | compat_ulong_t __unused4; | ||
215 | compat_ulong_t __unused5; | ||
216 | }; | ||
217 | |||
218 | static inline int is_compat_task(void) | ||
219 | { | ||
220 | return test_thread_flag(TIF_32BIT); | ||
221 | } | ||
222 | |||
223 | static inline int is_compat_thread(struct thread_info *thread) | ||
224 | { | ||
225 | return test_ti_thread_flag(thread, TIF_32BIT); | ||
226 | } | ||
227 | |||
228 | #else /* !CONFIG_COMPAT */ | ||
229 | |||
230 | static inline int is_compat_task(void) | ||
231 | { | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static inline int is_compat_thread(struct thread_info *thread) | ||
236 | { | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | #endif /* CONFIG_COMPAT */ | ||
241 | #endif /* __KERNEL__ */ | ||
242 | #endif /* __ASM_COMPAT_H */ | ||
diff --git a/arch/arm64/include/asm/compiler.h b/arch/arm64/include/asm/compiler.h new file mode 100644 index 000000000000..ee35fd0f2236 --- /dev/null +++ b/arch/arm64/include/asm/compiler.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/compiler.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_COMPILER_H | ||
19 | #define __ASM_COMPILER_H | ||
20 | |||
21 | /* | ||
22 | * This is used to ensure the compiler did actually allocate the register we | ||
23 | * asked it for some inline assembly sequences. Apparently we can't trust the | ||
24 | * compiler from one version to another so a bit of paranoia won't hurt. This | ||
25 | * string is meant to be concatenated with the inline asm string and will | ||
26 | * cause compilation to stop on mismatch. (for details, see gcc PR 15089) | ||
27 | */ | ||
28 | #define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" | ||
29 | |||
30 | #endif /* __ASM_COMPILER_H */ | ||
diff --git a/arch/arm64/include/asm/cputable.h b/arch/arm64/include/asm/cputable.h new file mode 100644 index 000000000000..e3bd983d3661 --- /dev/null +++ b/arch/arm64/include/asm/cputable.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * arch/arm64/include/asm/cputable.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_CPUTABLE_H | ||
19 | #define __ASM_CPUTABLE_H | ||
20 | |||
21 | struct cpu_info { | ||
22 | unsigned int cpu_id_val; | ||
23 | unsigned int cpu_id_mask; | ||
24 | const char *cpu_name; | ||
25 | unsigned long (*cpu_setup)(void); | ||
26 | }; | ||
27 | |||
28 | extern struct cpu_info *lookup_processor_type(unsigned int); | ||
29 | |||
30 | #endif | ||
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h new file mode 100644 index 000000000000..ef54125e6c1e --- /dev/null +++ b/arch/arm64/include/asm/cputype.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_CPUTYPE_H | ||
17 | #define __ASM_CPUTYPE_H | ||
18 | |||
19 | #define ID_MIDR_EL1 "midr_el1" | ||
20 | #define ID_CTR_EL0 "ctr_el0" | ||
21 | |||
22 | #define ID_AA64PFR0_EL1 "id_aa64pfr0_el1" | ||
23 | #define ID_AA64DFR0_EL1 "id_aa64dfr0_el1" | ||
24 | #define ID_AA64AFR0_EL1 "id_aa64afr0_el1" | ||
25 | #define ID_AA64ISAR0_EL1 "id_aa64isar0_el1" | ||
26 | #define ID_AA64MMFR0_EL1 "id_aa64mmfr0_el1" | ||
27 | |||
28 | #define read_cpuid(reg) ({ \ | ||
29 | u64 __val; \ | ||
30 | asm("mrs %0, " reg : "=r" (__val)); \ | ||
31 | __val; \ | ||
32 | }) | ||
33 | |||
34 | /* | ||
35 | * The CPU ID never changes at run time, so we might as well tell the | ||
36 | * compiler that it's constant. Use this function to read the CPU ID | ||
37 | * rather than directly reading processor_id or read_cpuid() directly. | ||
38 | */ | ||
39 | static inline u32 __attribute_const__ read_cpuid_id(void) | ||
40 | { | ||
41 | return read_cpuid(ID_MIDR_EL1); | ||
42 | } | ||
43 | |||
44 | static inline u32 __attribute_const__ read_cpuid_cachetype(void) | ||
45 | { | ||
46 | return read_cpuid(ID_CTR_EL0); | ||
47 | } | ||
48 | |||
49 | #endif | ||
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h new file mode 100644 index 000000000000..7eaa0b302493 --- /dev/null +++ b/arch/arm64/include/asm/debug-monitors.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_DEBUG_MONITORS_H | ||
17 | #define __ASM_DEBUG_MONITORS_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | #define DBG_ESR_EVT(x) (((x) >> 27) & 0x7) | ||
22 | |||
23 | /* AArch64 */ | ||
24 | #define DBG_ESR_EVT_HWBP 0x0 | ||
25 | #define DBG_ESR_EVT_HWSS 0x1 | ||
26 | #define DBG_ESR_EVT_HWWP 0x2 | ||
27 | #define DBG_ESR_EVT_BRK 0x6 | ||
28 | |||
29 | enum debug_el { | ||
30 | DBG_ACTIVE_EL0 = 0, | ||
31 | DBG_ACTIVE_EL1, | ||
32 | }; | ||
33 | |||
34 | /* AArch32 */ | ||
35 | #define DBG_ESR_EVT_BKPT 0x4 | ||
36 | #define DBG_ESR_EVT_VECC 0x5 | ||
37 | |||
38 | #define AARCH32_BREAK_ARM 0x07f001f0 | ||
39 | #define AARCH32_BREAK_THUMB 0xde01 | ||
40 | #define AARCH32_BREAK_THUMB2_LO 0xf7f0 | ||
41 | #define AARCH32_BREAK_THUMB2_HI 0xa000 | ||
42 | |||
43 | #ifndef __ASSEMBLY__ | ||
44 | struct task_struct; | ||
45 | |||
46 | #define local_dbg_save(flags) \ | ||
47 | do { \ | ||
48 | typecheck(unsigned long, flags); \ | ||
49 | asm volatile( \ | ||
50 | "mrs %0, daif // local_dbg_save\n" \ | ||
51 | "msr daifset, #8" \ | ||
52 | : "=r" (flags) : : "memory"); \ | ||
53 | } while (0) | ||
54 | |||
55 | #define local_dbg_restore(flags) \ | ||
56 | do { \ | ||
57 | typecheck(unsigned long, flags); \ | ||
58 | asm volatile( \ | ||
59 | "msr daif, %0 // local_dbg_restore\n" \ | ||
60 | : : "r" (flags) : "memory"); \ | ||
61 | } while (0) | ||
62 | |||
63 | #define DBG_ARCH_ID_RESERVED 0 /* In case of ptrace ABI updates. */ | ||
64 | |||
65 | u8 debug_monitors_arch(void); | ||
66 | |||
67 | void enable_debug_monitors(enum debug_el el); | ||
68 | void disable_debug_monitors(enum debug_el el); | ||
69 | |||
70 | void user_rewind_single_step(struct task_struct *task); | ||
71 | void user_fastforward_single_step(struct task_struct *task); | ||
72 | |||
73 | void kernel_enable_single_step(struct pt_regs *regs); | ||
74 | void kernel_disable_single_step(void); | ||
75 | int kernel_active_single_step(void); | ||
76 | |||
77 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
78 | int reinstall_suspended_bps(struct pt_regs *regs); | ||
79 | #else | ||
80 | static inline int reinstall_suspended_bps(struct pt_regs *regs) | ||
81 | { | ||
82 | return -ENODEV; | ||
83 | } | ||
84 | #endif | ||
85 | |||
86 | #endif /* __ASSEMBLY */ | ||
87 | #endif /* __KERNEL__ */ | ||
88 | #endif /* __ASM_DEBUG_MONITORS_H */ | ||
diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h new file mode 100644 index 000000000000..0d8453c755a8 --- /dev/null +++ b/arch/arm64/include/asm/device.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_DEVICE_H | ||
17 | #define __ASM_DEVICE_H | ||
18 | |||
19 | struct dev_archdata { | ||
20 | struct dma_map_ops *dma_ops; | ||
21 | }; | ||
22 | |||
23 | struct pdev_archdata { | ||
24 | }; | ||
25 | |||
26 | #endif | ||
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h new file mode 100644 index 000000000000..538f4b44db5d --- /dev/null +++ b/arch/arm64/include/asm/dma-mapping.h | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_DMA_MAPPING_H | ||
17 | #define __ASM_DMA_MAPPING_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/vmalloc.h> | ||
23 | |||
24 | #include <asm-generic/dma-coherent.h> | ||
25 | |||
26 | #define ARCH_HAS_DMA_GET_REQUIRED_MASK | ||
27 | |||
28 | extern struct dma_map_ops *dma_ops; | ||
29 | |||
30 | static inline struct dma_map_ops *get_dma_ops(struct device *dev) | ||
31 | { | ||
32 | if (unlikely(!dev) || !dev->archdata.dma_ops) | ||
33 | return dma_ops; | ||
34 | else | ||
35 | return dev->archdata.dma_ops; | ||
36 | } | ||
37 | |||
38 | #include <asm-generic/dma-mapping-common.h> | ||
39 | |||
40 | static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) | ||
41 | { | ||
42 | return (dma_addr_t)paddr; | ||
43 | } | ||
44 | |||
45 | static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr) | ||
46 | { | ||
47 | return (phys_addr_t)dev_addr; | ||
48 | } | ||
49 | |||
50 | static inline int dma_mapping_error(struct device *dev, dma_addr_t dev_addr) | ||
51 | { | ||
52 | struct dma_map_ops *ops = get_dma_ops(dev); | ||
53 | return ops->mapping_error(dev, dev_addr); | ||
54 | } | ||
55 | |||
56 | static inline int dma_supported(struct device *dev, u64 mask) | ||
57 | { | ||
58 | struct dma_map_ops *ops = get_dma_ops(dev); | ||
59 | return ops->dma_supported(dev, mask); | ||
60 | } | ||
61 | |||
62 | static inline int dma_set_mask(struct device *dev, u64 mask) | ||
63 | { | ||
64 | if (!dev->dma_mask || !dma_supported(dev, mask)) | ||
65 | return -EIO; | ||
66 | *dev->dma_mask = mask; | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) | ||
72 | { | ||
73 | if (!dev->dma_mask) | ||
74 | return 0; | ||
75 | |||
76 | return addr + size - 1 <= *dev->dma_mask; | ||
77 | } | ||
78 | |||
79 | static inline void dma_mark_clean(void *addr, size_t size) | ||
80 | { | ||
81 | } | ||
82 | |||
83 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, | ||
84 | dma_addr_t *dma_handle, gfp_t flags) | ||
85 | { | ||
86 | struct dma_map_ops *ops = get_dma_ops(dev); | ||
87 | void *vaddr; | ||
88 | |||
89 | if (dma_alloc_from_coherent(dev, size, dma_handle, &vaddr)) | ||
90 | return vaddr; | ||
91 | |||
92 | vaddr = ops->alloc(dev, size, dma_handle, flags, NULL); | ||
93 | debug_dma_alloc_coherent(dev, size, *dma_handle, vaddr); | ||
94 | return vaddr; | ||
95 | } | ||
96 | |||
97 | static inline void dma_free_coherent(struct device *dev, size_t size, | ||
98 | void *vaddr, dma_addr_t dev_addr) | ||
99 | { | ||
100 | struct dma_map_ops *ops = get_dma_ops(dev); | ||
101 | |||
102 | if (dma_release_from_coherent(dev, get_order(size), vaddr)) | ||
103 | return; | ||
104 | |||
105 | debug_dma_free_coherent(dev, size, vaddr, dev_addr); | ||
106 | ops->free(dev, size, vaddr, dev_addr, NULL); | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * There is no dma_cache_sync() implementation, so just return NULL here. | ||
111 | */ | ||
112 | static inline void *dma_alloc_noncoherent(struct device *dev, size_t size, | ||
113 | dma_addr_t *handle, gfp_t flags) | ||
114 | { | ||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | static inline void dma_free_noncoherent(struct device *dev, size_t size, | ||
119 | void *cpu_addr, dma_addr_t handle) | ||
120 | { | ||
121 | } | ||
122 | |||
123 | #endif /* __KERNEL__ */ | ||
124 | #endif /* __ASM_DMA_MAPPING_H */ | ||
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h new file mode 100644 index 000000000000..cf284649dfcb --- /dev/null +++ b/arch/arm64/include/asm/elf.h | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_ELF_H | ||
17 | #define __ASM_ELF_H | ||
18 | |||
19 | #include <asm/hwcap.h> | ||
20 | |||
21 | /* | ||
22 | * ELF register definitions.. | ||
23 | */ | ||
24 | #include <asm/ptrace.h> | ||
25 | #include <asm/user.h> | ||
26 | |||
27 | typedef unsigned long elf_greg_t; | ||
28 | typedef unsigned long elf_freg_t[3]; | ||
29 | |||
30 | #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) | ||
31 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | ||
32 | |||
33 | typedef struct user_fp elf_fpregset_t; | ||
34 | |||
35 | #define EM_AARCH64 183 | ||
36 | |||
37 | /* | ||
38 | * AArch64 static relocation types. | ||
39 | */ | ||
40 | |||
41 | /* Miscellaneous. */ | ||
42 | #define R_ARM_NONE 0 | ||
43 | #define R_AARCH64_NONE 256 | ||
44 | |||
45 | /* Data. */ | ||
46 | #define R_AARCH64_ABS64 257 | ||
47 | #define R_AARCH64_ABS32 258 | ||
48 | #define R_AARCH64_ABS16 259 | ||
49 | #define R_AARCH64_PREL64 260 | ||
50 | #define R_AARCH64_PREL32 261 | ||
51 | #define R_AARCH64_PREL16 262 | ||
52 | |||
53 | /* Instructions. */ | ||
54 | #define R_AARCH64_MOVW_UABS_G0 263 | ||
55 | #define R_AARCH64_MOVW_UABS_G0_NC 264 | ||
56 | #define R_AARCH64_MOVW_UABS_G1 265 | ||
57 | #define R_AARCH64_MOVW_UABS_G1_NC 266 | ||
58 | #define R_AARCH64_MOVW_UABS_G2 267 | ||
59 | #define R_AARCH64_MOVW_UABS_G2_NC 268 | ||
60 | #define R_AARCH64_MOVW_UABS_G3 269 | ||
61 | |||
62 | #define R_AARCH64_MOVW_SABS_G0 270 | ||
63 | #define R_AARCH64_MOVW_SABS_G1 271 | ||
64 | #define R_AARCH64_MOVW_SABS_G2 272 | ||
65 | |||
66 | #define R_AARCH64_LD_PREL_LO19 273 | ||
67 | #define R_AARCH64_ADR_PREL_LO21 274 | ||
68 | #define R_AARCH64_ADR_PREL_PG_HI21 275 | ||
69 | #define R_AARCH64_ADR_PREL_PG_HI21_NC 276 | ||
70 | #define R_AARCH64_ADD_ABS_LO12_NC 277 | ||
71 | #define R_AARCH64_LDST8_ABS_LO12_NC 278 | ||
72 | |||
73 | #define R_AARCH64_TSTBR14 279 | ||
74 | #define R_AARCH64_CONDBR19 280 | ||
75 | #define R_AARCH64_JUMP26 282 | ||
76 | #define R_AARCH64_CALL26 283 | ||
77 | #define R_AARCH64_LDST16_ABS_LO12_NC 284 | ||
78 | #define R_AARCH64_LDST32_ABS_LO12_NC 285 | ||
79 | #define R_AARCH64_LDST64_ABS_LO12_NC 286 | ||
80 | #define R_AARCH64_LDST128_ABS_LO12_NC 299 | ||
81 | |||
82 | #define R_AARCH64_MOVW_PREL_G0 287 | ||
83 | #define R_AARCH64_MOVW_PREL_G0_NC 288 | ||
84 | #define R_AARCH64_MOVW_PREL_G1 289 | ||
85 | #define R_AARCH64_MOVW_PREL_G1_NC 290 | ||
86 | #define R_AARCH64_MOVW_PREL_G2 291 | ||
87 | #define R_AARCH64_MOVW_PREL_G2_NC 292 | ||
88 | #define R_AARCH64_MOVW_PREL_G3 293 | ||
89 | |||
90 | |||
91 | /* | ||
92 | * These are used to set parameters in the core dumps. | ||
93 | */ | ||
94 | #define ELF_CLASS ELFCLASS64 | ||
95 | #define ELF_DATA ELFDATA2LSB | ||
96 | #define ELF_ARCH EM_AARCH64 | ||
97 | |||
98 | #define ELF_PLATFORM_SIZE 16 | ||
99 | #define ELF_PLATFORM ("aarch64") | ||
100 | |||
101 | /* | ||
102 | * This is used to ensure we don't load something for the wrong architecture. | ||
103 | */ | ||
104 | #define elf_check_arch(x) ((x)->e_machine == EM_AARCH64) | ||
105 | |||
106 | #define elf_read_implies_exec(ex,stk) (stk != EXSTACK_DISABLE_X) | ||
107 | |||
108 | #define CORE_DUMP_USE_REGSET | ||
109 | #define ELF_EXEC_PAGESIZE PAGE_SIZE | ||
110 | |||
111 | /* | ||
112 | * This is the location that an ET_DYN program is loaded if exec'ed. Typical | ||
113 | * use of this is to invoke "./ld.so someprog" to test out a new version of | ||
114 | * the loader. We need to make sure that it is out of the way of the program | ||
115 | * that it will "exec", and that there is sufficient room for the brk. | ||
116 | */ | ||
117 | extern unsigned long randomize_et_dyn(unsigned long base); | ||
118 | #define ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_64 / 3)) | ||
119 | |||
120 | /* | ||
121 | * When the program starts, a1 contains a pointer to a function to be | ||
122 | * registered with atexit, as per the SVR4 ABI. A value of 0 means we have no | ||
123 | * such handler. | ||
124 | */ | ||
125 | #define ELF_PLAT_INIT(_r, load_addr) (_r)->regs[0] = 0 | ||
126 | |||
127 | #define SET_PERSONALITY(ex) clear_thread_flag(TIF_32BIT); | ||
128 | |||
129 | #define ARCH_DLINFO \ | ||
130 | do { \ | ||
131 | NEW_AUX_ENT(AT_SYSINFO_EHDR, \ | ||
132 | (elf_addr_t)current->mm->context.vdso); \ | ||
133 | } while (0) | ||
134 | |||
135 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES | ||
136 | struct linux_binprm; | ||
137 | extern int arch_setup_additional_pages(struct linux_binprm *bprm, | ||
138 | int uses_interp); | ||
139 | |||
140 | /* 1GB of VA */ | ||
141 | #ifdef CONFIG_COMPAT | ||
142 | #define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \ | ||
143 | 0x7ff >> (PAGE_SHIFT - 12) : \ | ||
144 | 0x3ffff >> (PAGE_SHIFT - 12)) | ||
145 | #else | ||
146 | #define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12)) | ||
147 | #endif | ||
148 | |||
149 | struct mm_struct; | ||
150 | extern unsigned long arch_randomize_brk(struct mm_struct *mm); | ||
151 | #define arch_randomize_brk arch_randomize_brk | ||
152 | |||
153 | #ifdef CONFIG_COMPAT | ||
154 | #define EM_ARM 40 | ||
155 | #define COMPAT_ELF_PLATFORM ("v8l") | ||
156 | |||
157 | #define COMPAT_ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_32 / 3)) | ||
158 | |||
159 | /* AArch32 registers. */ | ||
160 | #define COMPAT_ELF_NGREG 18 | ||
161 | typedef unsigned int compat_elf_greg_t; | ||
162 | typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; | ||
163 | |||
164 | /* AArch32 EABI. */ | ||
165 | #define EF_ARM_EABI_MASK 0xff000000 | ||
166 | #define compat_elf_check_arch(x) (((x)->e_machine == EM_ARM) && \ | ||
167 | ((x)->e_flags & EF_ARM_EABI_MASK)) | ||
168 | |||
169 | #define compat_start_thread compat_start_thread | ||
170 | #define COMPAT_SET_PERSONALITY(ex) set_thread_flag(TIF_32BIT); | ||
171 | #define COMPAT_ARCH_DLINFO | ||
172 | extern int aarch32_setup_vectors_page(struct linux_binprm *bprm, | ||
173 | int uses_interp); | ||
174 | #define compat_arch_setup_additional_pages \ | ||
175 | aarch32_setup_vectors_page | ||
176 | |||
177 | #endif /* CONFIG_COMPAT */ | ||
178 | |||
179 | #endif | ||
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h new file mode 100644 index 000000000000..ac63519b7b90 --- /dev/null +++ b/arch/arm64/include/asm/exception.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/exception.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_EXCEPTION_H | ||
19 | #define __ASM_EXCEPTION_H | ||
20 | |||
21 | #define __exception __attribute__((section(".exception.text"))) | ||
22 | |||
23 | #endif /* __ASM_EXCEPTION_H */ | ||
diff --git a/arch/arm64/include/asm/exec.h b/arch/arm64/include/asm/exec.h new file mode 100644 index 000000000000..db0563c23482 --- /dev/null +++ b/arch/arm64/include/asm/exec.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/exec.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_EXEC_H | ||
19 | #define __ASM_EXEC_H | ||
20 | |||
21 | extern unsigned long arch_align_stack(unsigned long sp); | ||
22 | |||
23 | #endif /* __ASM_EXEC_H */ | ||
diff --git a/arch/arm64/include/asm/fb.h b/arch/arm64/include/asm/fb.h new file mode 100644 index 000000000000..adb88a64b2fe --- /dev/null +++ b/arch/arm64/include/asm/fb.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_FB_H_ | ||
17 | #define __ASM_FB_H_ | ||
18 | |||
19 | #include <linux/fb.h> | ||
20 | #include <linux/fs.h> | ||
21 | #include <asm/page.h> | ||
22 | |||
23 | static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, | ||
24 | unsigned long off) | ||
25 | { | ||
26 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | ||
27 | } | ||
28 | |||
29 | static inline int fb_is_primary_device(struct fb_info *info) | ||
30 | { | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | #endif /* __ASM_FB_H_ */ | ||
diff --git a/arch/arm64/include/asm/fcntl.h b/arch/arm64/include/asm/fcntl.h new file mode 100644 index 000000000000..cd2e630c235e --- /dev/null +++ b/arch/arm64/include/asm/fcntl.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_FCNTL_H | ||
17 | #define __ASM_FCNTL_H | ||
18 | |||
19 | /* | ||
20 | * Using our own definitions for AArch32 (compat) support. | ||
21 | */ | ||
22 | #define O_DIRECTORY 040000 /* must be a directory */ | ||
23 | #define O_NOFOLLOW 0100000 /* don't follow links */ | ||
24 | #define O_DIRECT 0200000 /* direct disk access hint - currently ignored */ | ||
25 | #define O_LARGEFILE 0400000 | ||
26 | |||
27 | #include <asm-generic/fcntl.h> | ||
28 | |||
29 | #endif | ||
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h new file mode 100644 index 000000000000..b42fab9f62a9 --- /dev/null +++ b/arch/arm64/include/asm/fpsimd.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_FP_H | ||
17 | #define __ASM_FP_H | ||
18 | |||
19 | #include <asm/ptrace.h> | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | |||
23 | /* | ||
24 | * FP/SIMD storage area has: | ||
25 | * - FPSR and FPCR | ||
26 | * - 32 128-bit data registers | ||
27 | * | ||
28 | * Note that user_fp forms a prefix of this structure, which is relied | ||
29 | * upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must | ||
30 | * form a prefix of struct fpsimd_state. | ||
31 | */ | ||
32 | struct fpsimd_state { | ||
33 | union { | ||
34 | struct user_fpsimd_state user_fpsimd; | ||
35 | struct { | ||
36 | __uint128_t vregs[32]; | ||
37 | u32 fpsr; | ||
38 | u32 fpcr; | ||
39 | }; | ||
40 | }; | ||
41 | }; | ||
42 | |||
43 | #if defined(__KERNEL__) && defined(CONFIG_COMPAT) | ||
44 | /* Masks for extracting the FPSR and FPCR from the FPSCR */ | ||
45 | #define VFP_FPSCR_STAT_MASK 0xf800009f | ||
46 | #define VFP_FPSCR_CTRL_MASK 0x07f79f00 | ||
47 | /* | ||
48 | * The VFP state has 32x64-bit registers and a single 32-bit | ||
49 | * control/status register. | ||
50 | */ | ||
51 | #define VFP_STATE_SIZE ((32 * 8) + 4) | ||
52 | #endif | ||
53 | |||
54 | struct task_struct; | ||
55 | |||
56 | extern void fpsimd_save_state(struct fpsimd_state *state); | ||
57 | extern void fpsimd_load_state(struct fpsimd_state *state); | ||
58 | |||
59 | extern void fpsimd_thread_switch(struct task_struct *next); | ||
60 | extern void fpsimd_flush_thread(void); | ||
61 | |||
62 | #endif | ||
63 | |||
64 | #endif | ||
diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h new file mode 100644 index 000000000000..3468ae8439fa --- /dev/null +++ b/arch/arm64/include/asm/futex.h | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_FUTEX_H | ||
17 | #define __ASM_FUTEX_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | #include <linux/futex.h> | ||
22 | #include <linux/uaccess.h> | ||
23 | #include <asm/errno.h> | ||
24 | |||
25 | #define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg) \ | ||
26 | asm volatile( \ | ||
27 | "1: ldaxr %w1, %2\n" \ | ||
28 | insn "\n" \ | ||
29 | "2: stlxr %w3, %w0, %2\n" \ | ||
30 | " cbnz %w3, 1b\n" \ | ||
31 | "3:\n" \ | ||
32 | " .pushsection .fixup,\"ax\"\n" \ | ||
33 | "4: mov %w0, %w5\n" \ | ||
34 | " b 3b\n" \ | ||
35 | " .popsection\n" \ | ||
36 | " .pushsection __ex_table,\"a\"\n" \ | ||
37 | " .align 3\n" \ | ||
38 | " .quad 1b, 4b, 2b, 4b\n" \ | ||
39 | " .popsection\n" \ | ||
40 | : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp) \ | ||
41 | : "r" (oparg), "Ir" (-EFAULT) \ | ||
42 | : "cc") | ||
43 | |||
44 | static inline int | ||
45 | futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) | ||
46 | { | ||
47 | int op = (encoded_op >> 28) & 7; | ||
48 | int cmp = (encoded_op >> 24) & 15; | ||
49 | int oparg = (encoded_op << 8) >> 20; | ||
50 | int cmparg = (encoded_op << 20) >> 20; | ||
51 | int oldval = 0, ret, tmp; | ||
52 | |||
53 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | ||
54 | oparg = 1 << oparg; | ||
55 | |||
56 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) | ||
57 | return -EFAULT; | ||
58 | |||
59 | pagefault_disable(); /* implies preempt_disable() */ | ||
60 | |||
61 | switch (op) { | ||
62 | case FUTEX_OP_SET: | ||
63 | __futex_atomic_op("mov %w0, %w4", | ||
64 | ret, oldval, uaddr, tmp, oparg); | ||
65 | break; | ||
66 | case FUTEX_OP_ADD: | ||
67 | __futex_atomic_op("add %w0, %w1, %w4", | ||
68 | ret, oldval, uaddr, tmp, oparg); | ||
69 | break; | ||
70 | case FUTEX_OP_OR: | ||
71 | __futex_atomic_op("orr %w0, %w1, %w4", | ||
72 | ret, oldval, uaddr, tmp, oparg); | ||
73 | break; | ||
74 | case FUTEX_OP_ANDN: | ||
75 | __futex_atomic_op("and %w0, %w1, %w4", | ||
76 | ret, oldval, uaddr, tmp, ~oparg); | ||
77 | break; | ||
78 | case FUTEX_OP_XOR: | ||
79 | __futex_atomic_op("eor %w0, %w1, %w4", | ||
80 | ret, oldval, uaddr, tmp, oparg); | ||
81 | break; | ||
82 | default: | ||
83 | ret = -ENOSYS; | ||
84 | } | ||
85 | |||
86 | pagefault_enable(); /* subsumes preempt_enable() */ | ||
87 | |||
88 | if (!ret) { | ||
89 | switch (cmp) { | ||
90 | case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; | ||
91 | case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; | ||
92 | case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; | ||
93 | case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; | ||
94 | case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; | ||
95 | case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; | ||
96 | default: ret = -ENOSYS; | ||
97 | } | ||
98 | } | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | static inline int | ||
103 | futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, | ||
104 | u32 oldval, u32 newval) | ||
105 | { | ||
106 | int ret = 0; | ||
107 | u32 val, tmp; | ||
108 | |||
109 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) | ||
110 | return -EFAULT; | ||
111 | |||
112 | asm volatile("// futex_atomic_cmpxchg_inatomic\n" | ||
113 | "1: ldaxr %w1, %2\n" | ||
114 | " sub %w3, %w1, %w4\n" | ||
115 | " cbnz %w3, 3f\n" | ||
116 | "2: stlxr %w3, %w5, %2\n" | ||
117 | " cbnz %w3, 1b\n" | ||
118 | "3:\n" | ||
119 | " .pushsection .fixup,\"ax\"\n" | ||
120 | "4: mov %w0, %w6\n" | ||
121 | " b 3b\n" | ||
122 | " .popsection\n" | ||
123 | " .pushsection __ex_table,\"a\"\n" | ||
124 | " .align 3\n" | ||
125 | " .quad 1b, 4b, 2b, 4b\n" | ||
126 | " .popsection\n" | ||
127 | : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp) | ||
128 | : "r" (oldval), "r" (newval), "Ir" (-EFAULT) | ||
129 | : "cc", "memory"); | ||
130 | |||
131 | *uval = val; | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | #endif /* __KERNEL__ */ | ||
136 | #endif /* __ASM_FUTEX_H */ | ||
diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h new file mode 100644 index 000000000000..507546353d62 --- /dev/null +++ b/arch/arm64/include/asm/hardirq.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_HARDIRQ_H | ||
17 | #define __ASM_HARDIRQ_H | ||
18 | |||
19 | #include <linux/cache.h> | ||
20 | #include <linux/threads.h> | ||
21 | #include <asm/irq.h> | ||
22 | |||
23 | #define NR_IPI 4 | ||
24 | |||
25 | typedef struct { | ||
26 | unsigned int __softirq_pending; | ||
27 | #ifdef CONFIG_SMP | ||
28 | unsigned int ipi_irqs[NR_IPI]; | ||
29 | #endif | ||
30 | } ____cacheline_aligned irq_cpustat_t; | ||
31 | |||
32 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ | ||
33 | |||
34 | #define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++ | ||
35 | #define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member) | ||
36 | |||
37 | #ifdef CONFIG_SMP | ||
38 | u64 smp_irq_stat_cpu(unsigned int cpu); | ||
39 | #define arch_irq_stat_cpu smp_irq_stat_cpu | ||
40 | #endif | ||
41 | |||
42 | #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 | ||
43 | |||
44 | static inline void ack_bad_irq(unsigned int irq) | ||
45 | { | ||
46 | extern unsigned long irq_err_count; | ||
47 | irq_err_count++; | ||
48 | } | ||
49 | |||
50 | extern void handle_IRQ(unsigned int, struct pt_regs *); | ||
51 | |||
52 | #endif /* __ASM_HARDIRQ_H */ | ||
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h new file mode 100644 index 000000000000..d064047612b1 --- /dev/null +++ b/arch/arm64/include/asm/hw_breakpoint.h | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_HW_BREAKPOINT_H | ||
17 | #define __ASM_HW_BREAKPOINT_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | struct arch_hw_breakpoint_ctrl { | ||
22 | u32 __reserved : 19, | ||
23 | len : 8, | ||
24 | type : 2, | ||
25 | privilege : 2, | ||
26 | enabled : 1; | ||
27 | }; | ||
28 | |||
29 | struct arch_hw_breakpoint { | ||
30 | u64 address; | ||
31 | u64 trigger; | ||
32 | struct arch_hw_breakpoint_ctrl ctrl; | ||
33 | }; | ||
34 | |||
35 | static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl) | ||
36 | { | ||
37 | return (ctrl.len << 5) | (ctrl.type << 3) | (ctrl.privilege << 1) | | ||
38 | ctrl.enabled; | ||
39 | } | ||
40 | |||
41 | static inline void decode_ctrl_reg(u32 reg, | ||
42 | struct arch_hw_breakpoint_ctrl *ctrl) | ||
43 | { | ||
44 | ctrl->enabled = reg & 0x1; | ||
45 | reg >>= 1; | ||
46 | ctrl->privilege = reg & 0x3; | ||
47 | reg >>= 2; | ||
48 | ctrl->type = reg & 0x3; | ||
49 | reg >>= 2; | ||
50 | ctrl->len = reg & 0xff; | ||
51 | } | ||
52 | |||
53 | /* Breakpoint */ | ||
54 | #define ARM_BREAKPOINT_EXECUTE 0 | ||
55 | |||
56 | /* Watchpoints */ | ||
57 | #define ARM_BREAKPOINT_LOAD 1 | ||
58 | #define ARM_BREAKPOINT_STORE 2 | ||
59 | #define AARCH64_ESR_ACCESS_MASK (1 << 6) | ||
60 | |||
61 | /* Privilege Levels */ | ||
62 | #define AARCH64_BREAKPOINT_EL1 1 | ||
63 | #define AARCH64_BREAKPOINT_EL0 2 | ||
64 | |||
65 | /* Lengths */ | ||
66 | #define ARM_BREAKPOINT_LEN_1 0x1 | ||
67 | #define ARM_BREAKPOINT_LEN_2 0x3 | ||
68 | #define ARM_BREAKPOINT_LEN_4 0xf | ||
69 | #define ARM_BREAKPOINT_LEN_8 0xff | ||
70 | |||
71 | /* Kernel stepping */ | ||
72 | #define ARM_KERNEL_STEP_NONE 0 | ||
73 | #define ARM_KERNEL_STEP_ACTIVE 1 | ||
74 | #define ARM_KERNEL_STEP_SUSPEND 2 | ||
75 | |||
76 | /* | ||
77 | * Limits. | ||
78 | * Changing these will require modifications to the register accessors. | ||
79 | */ | ||
80 | #define ARM_MAX_BRP 16 | ||
81 | #define ARM_MAX_WRP 16 | ||
82 | #define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP) | ||
83 | |||
84 | /* Virtual debug register bases. */ | ||
85 | #define AARCH64_DBG_REG_BVR 0 | ||
86 | #define AARCH64_DBG_REG_BCR (AARCH64_DBG_REG_BVR + ARM_MAX_BRP) | ||
87 | #define AARCH64_DBG_REG_WVR (AARCH64_DBG_REG_BCR + ARM_MAX_BRP) | ||
88 | #define AARCH64_DBG_REG_WCR (AARCH64_DBG_REG_WVR + ARM_MAX_WRP) | ||
89 | |||
90 | /* Debug register names. */ | ||
91 | #define AARCH64_DBG_REG_NAME_BVR "bvr" | ||
92 | #define AARCH64_DBG_REG_NAME_BCR "bcr" | ||
93 | #define AARCH64_DBG_REG_NAME_WVR "wvr" | ||
94 | #define AARCH64_DBG_REG_NAME_WCR "wcr" | ||
95 | |||
96 | /* Accessor macros for the debug registers. */ | ||
97 | #define AARCH64_DBG_READ(N, REG, VAL) do {\ | ||
98 | asm volatile("mrs %0, dbg" REG #N "_el1" : "=r" (VAL));\ | ||
99 | } while (0) | ||
100 | |||
101 | #define AARCH64_DBG_WRITE(N, REG, VAL) do {\ | ||
102 | asm volatile("msr dbg" REG #N "_el1, %0" :: "r" (VAL));\ | ||
103 | } while (0) | ||
104 | |||
105 | struct task_struct; | ||
106 | struct notifier_block; | ||
107 | struct perf_event; | ||
108 | struct pmu; | ||
109 | |||
110 | extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, | ||
111 | int *gen_len, int *gen_type); | ||
112 | extern int arch_check_bp_in_kernelspace(struct perf_event *bp); | ||
113 | extern int arch_validate_hwbkpt_settings(struct perf_event *bp); | ||
114 | extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, | ||
115 | unsigned long val, void *data); | ||
116 | |||
117 | extern int arch_install_hw_breakpoint(struct perf_event *bp); | ||
118 | extern void arch_uninstall_hw_breakpoint(struct perf_event *bp); | ||
119 | extern void hw_breakpoint_pmu_read(struct perf_event *bp); | ||
120 | extern int hw_breakpoint_slots(int type); | ||
121 | |||
122 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
123 | extern void hw_breakpoint_thread_switch(struct task_struct *next); | ||
124 | extern void ptrace_hw_copy_thread(struct task_struct *task); | ||
125 | #else | ||
126 | static inline void hw_breakpoint_thread_switch(struct task_struct *next) | ||
127 | { | ||
128 | } | ||
129 | static inline void ptrace_hw_copy_thread(struct task_struct *task) | ||
130 | { | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | extern struct pmu perf_ops_bp; | ||
135 | |||
136 | #endif /* __KERNEL__ */ | ||
137 | #endif /* __ASM_BREAKPOINT_H */ | ||
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h new file mode 100644 index 000000000000..f8190ba45a3e --- /dev/null +++ b/arch/arm64/include/asm/hwcap.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_HWCAP_H | ||
17 | #define __ASM_HWCAP_H | ||
18 | |||
19 | /* | ||
20 | * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP | ||
21 | */ | ||
22 | #define HWCAP_FP (1 << 0) | ||
23 | #define HWCAP_ASIMD (1 << 1) | ||
24 | |||
25 | #define COMPAT_HWCAP_HALF (1 << 1) | ||
26 | #define COMPAT_HWCAP_THUMB (1 << 2) | ||
27 | #define COMPAT_HWCAP_FAST_MULT (1 << 4) | ||
28 | #define COMPAT_HWCAP_VFP (1 << 6) | ||
29 | #define COMPAT_HWCAP_EDSP (1 << 7) | ||
30 | #define COMPAT_HWCAP_NEON (1 << 12) | ||
31 | #define COMPAT_HWCAP_VFPv3 (1 << 13) | ||
32 | #define COMPAT_HWCAP_TLS (1 << 15) | ||
33 | #define COMPAT_HWCAP_VFPv4 (1 << 16) | ||
34 | #define COMPAT_HWCAP_IDIVA (1 << 17) | ||
35 | #define COMPAT_HWCAP_IDIVT (1 << 18) | ||
36 | #define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) | ||
37 | |||
38 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) | ||
39 | /* | ||
40 | * This yields a mask that user programs can use to figure out what | ||
41 | * instruction set this cpu supports. | ||
42 | */ | ||
43 | #define ELF_HWCAP (elf_hwcap) | ||
44 | #define COMPAT_ELF_HWCAP (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\ | ||
45 | COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ | ||
46 | COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\ | ||
47 | COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ | ||
48 | COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV) | ||
49 | |||
50 | extern unsigned int elf_hwcap; | ||
51 | #endif | ||
52 | |||
53 | #endif | ||
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h new file mode 100644 index 000000000000..74a2a7d304a9 --- /dev/null +++ b/arch/arm64/include/asm/io.h | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/io.h | ||
3 | * | ||
4 | * Copyright (C) 1996-2000 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_IO_H | ||
20 | #define __ASM_IO_H | ||
21 | |||
22 | #ifdef __KERNEL__ | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | |||
26 | #include <asm/byteorder.h> | ||
27 | #include <asm/barrier.h> | ||
28 | #include <asm/pgtable.h> | ||
29 | |||
30 | /* | ||
31 | * Generic IO read/write. These perform native-endian accesses. | ||
32 | */ | ||
33 | static inline void __raw_writeb(u8 val, volatile void __iomem *addr) | ||
34 | { | ||
35 | asm volatile("strb %w0, [%1]" : : "r" (val), "r" (addr)); | ||
36 | } | ||
37 | |||
38 | static inline void __raw_writew(u16 val, volatile void __iomem *addr) | ||
39 | { | ||
40 | asm volatile("strh %w0, [%1]" : : "r" (val), "r" (addr)); | ||
41 | } | ||
42 | |||
43 | static inline void __raw_writel(u32 val, volatile void __iomem *addr) | ||
44 | { | ||
45 | asm volatile("str %w0, [%1]" : : "r" (val), "r" (addr)); | ||
46 | } | ||
47 | |||
48 | static inline void __raw_writeq(u64 val, volatile void __iomem *addr) | ||
49 | { | ||
50 | asm volatile("str %0, [%1]" : : "r" (val), "r" (addr)); | ||
51 | } | ||
52 | |||
53 | static inline u8 __raw_readb(const volatile void __iomem *addr) | ||
54 | { | ||
55 | u8 val; | ||
56 | asm volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr)); | ||
57 | return val; | ||
58 | } | ||
59 | |||
60 | static inline u16 __raw_readw(const volatile void __iomem *addr) | ||
61 | { | ||
62 | u16 val; | ||
63 | asm volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr)); | ||
64 | return val; | ||
65 | } | ||
66 | |||
67 | static inline u32 __raw_readl(const volatile void __iomem *addr) | ||
68 | { | ||
69 | u32 val; | ||
70 | asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr)); | ||
71 | return val; | ||
72 | } | ||
73 | |||
74 | static inline u64 __raw_readq(const volatile void __iomem *addr) | ||
75 | { | ||
76 | u64 val; | ||
77 | asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr)); | ||
78 | return val; | ||
79 | } | ||
80 | |||
81 | /* IO barriers */ | ||
82 | #define __iormb() rmb() | ||
83 | #define __iowmb() wmb() | ||
84 | |||
85 | #define mmiowb() do { } while (0) | ||
86 | |||
87 | /* | ||
88 | * Relaxed I/O memory access primitives. These follow the Device memory | ||
89 | * ordering rules but do not guarantee any ordering relative to Normal memory | ||
90 | * accesses. | ||
91 | */ | ||
92 | #define readb_relaxed(c) ({ u8 __v = __raw_readb(c); __v; }) | ||
93 | #define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; }) | ||
94 | #define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; }) | ||
95 | |||
96 | #define writeb_relaxed(v,c) ((void)__raw_writeb((v),(c))) | ||
97 | #define writew_relaxed(v,c) ((void)__raw_writew((__force u16)cpu_to_le16(v),(c))) | ||
98 | #define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) | ||
99 | |||
100 | /* | ||
101 | * I/O memory access primitives. Reads are ordered relative to any | ||
102 | * following Normal memory access. Writes are ordered relative to any prior | ||
103 | * Normal memory access. | ||
104 | */ | ||
105 | #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) | ||
106 | #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) | ||
107 | #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) | ||
108 | |||
109 | #define writeb(v,c) ({ __iowmb(); writeb_relaxed((v),(c)); }) | ||
110 | #define writew(v,c) ({ __iowmb(); writew_relaxed((v),(c)); }) | ||
111 | #define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c)); }) | ||
112 | |||
113 | /* | ||
114 | * I/O port access primitives. | ||
115 | */ | ||
116 | #define IO_SPACE_LIMIT 0xffff | ||
117 | #define PCI_IOBASE ((void __iomem *)0xffffffbbfffe0000UL) | ||
118 | |||
119 | static inline u8 inb(unsigned long addr) | ||
120 | { | ||
121 | return readb(addr + PCI_IOBASE); | ||
122 | } | ||
123 | |||
124 | static inline u16 inw(unsigned long addr) | ||
125 | { | ||
126 | return readw(addr + PCI_IOBASE); | ||
127 | } | ||
128 | |||
129 | static inline u32 inl(unsigned long addr) | ||
130 | { | ||
131 | return readl(addr + PCI_IOBASE); | ||
132 | } | ||
133 | |||
134 | static inline void outb(u8 b, unsigned long addr) | ||
135 | { | ||
136 | writeb(b, addr + PCI_IOBASE); | ||
137 | } | ||
138 | |||
139 | static inline void outw(u16 b, unsigned long addr) | ||
140 | { | ||
141 | writew(b, addr + PCI_IOBASE); | ||
142 | } | ||
143 | |||
144 | static inline void outl(u32 b, unsigned long addr) | ||
145 | { | ||
146 | writel(b, addr + PCI_IOBASE); | ||
147 | } | ||
148 | |||
149 | #define inb_p(addr) inb(addr) | ||
150 | #define inw_p(addr) inw(addr) | ||
151 | #define inl_p(addr) inl(addr) | ||
152 | |||
153 | #define outb_p(x, addr) outb((x), (addr)) | ||
154 | #define outw_p(x, addr) outw((x), (addr)) | ||
155 | #define outl_p(x, addr) outl((x), (addr)) | ||
156 | |||
157 | static inline void insb(unsigned long addr, void *buffer, int count) | ||
158 | { | ||
159 | u8 *buf = buffer; | ||
160 | while (count--) | ||
161 | *buf++ = __raw_readb(addr + PCI_IOBASE); | ||
162 | } | ||
163 | |||
164 | static inline void insw(unsigned long addr, void *buffer, int count) | ||
165 | { | ||
166 | u16 *buf = buffer; | ||
167 | while (count--) | ||
168 | *buf++ = __raw_readw(addr + PCI_IOBASE); | ||
169 | } | ||
170 | |||
171 | static inline void insl(unsigned long addr, void *buffer, int count) | ||
172 | { | ||
173 | u32 *buf = buffer; | ||
174 | while (count--) | ||
175 | *buf++ = __raw_readl(addr + PCI_IOBASE); | ||
176 | } | ||
177 | |||
178 | static inline void outsb(unsigned long addr, const void *buffer, int count) | ||
179 | { | ||
180 | const u8 *buf = buffer; | ||
181 | while (count--) | ||
182 | __raw_writeb(*buf++, addr + PCI_IOBASE); | ||
183 | } | ||
184 | |||
185 | static inline void outsw(unsigned long addr, const void *buffer, int count) | ||
186 | { | ||
187 | const u16 *buf = buffer; | ||
188 | while (count--) | ||
189 | __raw_writew(*buf++, addr + PCI_IOBASE); | ||
190 | } | ||
191 | |||
192 | static inline void outsl(unsigned long addr, const void *buffer, int count) | ||
193 | { | ||
194 | const u32 *buf = buffer; | ||
195 | while (count--) | ||
196 | __raw_writel(*buf++, addr + PCI_IOBASE); | ||
197 | } | ||
198 | |||
199 | #define insb_p(port,to,len) insb(port,to,len) | ||
200 | #define insw_p(port,to,len) insw(port,to,len) | ||
201 | #define insl_p(port,to,len) insl(port,to,len) | ||
202 | |||
203 | #define outsb_p(port,from,len) outsb(port,from,len) | ||
204 | #define outsw_p(port,from,len) outsw(port,from,len) | ||
205 | #define outsl_p(port,from,len) outsl(port,from,len) | ||
206 | |||
207 | /* | ||
208 | * String version of I/O memory access operations. | ||
209 | */ | ||
210 | extern void __memcpy_fromio(void *, const volatile void __iomem *, size_t); | ||
211 | extern void __memcpy_toio(volatile void __iomem *, const void *, size_t); | ||
212 | extern void __memset_io(volatile void __iomem *, int, size_t); | ||
213 | |||
214 | #define memset_io(c,v,l) __memset_io((c),(v),(l)) | ||
215 | #define memcpy_fromio(a,c,l) __memcpy_fromio((a),(c),(l)) | ||
216 | #define memcpy_toio(c,a,l) __memcpy_toio((c),(a),(l)) | ||
217 | |||
218 | /* | ||
219 | * I/O memory mapping functions. | ||
220 | */ | ||
221 | extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot); | ||
222 | extern void __iounmap(volatile void __iomem *addr); | ||
223 | |||
224 | #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY) | ||
225 | #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) | ||
226 | #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC)) | ||
227 | |||
228 | #define ioremap(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE) | ||
229 | #define ioremap_nocache(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE) | ||
230 | #define ioremap_wc(addr, size) __ioremap((addr), (size), PROT_NORMAL_NC) | ||
231 | #define iounmap __iounmap | ||
232 | |||
233 | #define ARCH_HAS_IOREMAP_WC | ||
234 | #include <asm-generic/iomap.h> | ||
235 | |||
236 | /* | ||
237 | * More restrictive address range checking than the default implementation | ||
238 | * (PHYS_OFFSET and PHYS_MASK taken into account). | ||
239 | */ | ||
240 | #define ARCH_HAS_VALID_PHYS_ADDR_RANGE | ||
241 | extern int valid_phys_addr_range(unsigned long addr, size_t size); | ||
242 | extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); | ||
243 | |||
244 | extern int devmem_is_allowed(unsigned long pfn); | ||
245 | |||
246 | /* | ||
247 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem | ||
248 | * access | ||
249 | */ | ||
250 | #define xlate_dev_mem_ptr(p) __va(p) | ||
251 | |||
252 | /* | ||
253 | * Convert a virtual cached pointer to an uncached pointer | ||
254 | */ | ||
255 | #define xlate_dev_kmem_ptr(p) p | ||
256 | |||
257 | #endif /* __KERNEL__ */ | ||
258 | #endif /* __ASM_IO_H */ | ||
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h new file mode 100644 index 000000000000..a4e1cad3202a --- /dev/null +++ b/arch/arm64/include/asm/irq.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __ASM_IRQ_H | ||
2 | #define __ASM_IRQ_H | ||
3 | |||
4 | #include <asm-generic/irq.h> | ||
5 | |||
6 | extern void (*handle_arch_irq)(struct pt_regs *); | ||
7 | |||
8 | #endif | ||
diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h new file mode 100644 index 000000000000..aa11943b8502 --- /dev/null +++ b/arch/arm64/include/asm/irqflags.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_IRQFLAGS_H | ||
17 | #define __ASM_IRQFLAGS_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | #include <asm/ptrace.h> | ||
22 | |||
23 | /* | ||
24 | * CPU interrupt mask handling. | ||
25 | */ | ||
26 | static inline unsigned long arch_local_irq_save(void) | ||
27 | { | ||
28 | unsigned long flags; | ||
29 | asm volatile( | ||
30 | "mrs %0, daif // arch_local_irq_save\n" | ||
31 | "msr daifset, #2" | ||
32 | : "=r" (flags) | ||
33 | : | ||
34 | : "memory"); | ||
35 | return flags; | ||
36 | } | ||
37 | |||
38 | static inline void arch_local_irq_enable(void) | ||
39 | { | ||
40 | asm volatile( | ||
41 | "msr daifclr, #2 // arch_local_irq_enable" | ||
42 | : | ||
43 | : | ||
44 | : "memory"); | ||
45 | } | ||
46 | |||
47 | static inline void arch_local_irq_disable(void) | ||
48 | { | ||
49 | asm volatile( | ||
50 | "msr daifset, #2 // arch_local_irq_disable" | ||
51 | : | ||
52 | : | ||
53 | : "memory"); | ||
54 | } | ||
55 | |||
56 | #define local_fiq_enable() asm("msr daifclr, #1" : : : "memory") | ||
57 | #define local_fiq_disable() asm("msr daifset, #1" : : : "memory") | ||
58 | |||
59 | /* | ||
60 | * Save the current interrupt enable state. | ||
61 | */ | ||
62 | static inline unsigned long arch_local_save_flags(void) | ||
63 | { | ||
64 | unsigned long flags; | ||
65 | asm volatile( | ||
66 | "mrs %0, daif // arch_local_save_flags" | ||
67 | : "=r" (flags) | ||
68 | : | ||
69 | : "memory"); | ||
70 | return flags; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * restore saved IRQ state | ||
75 | */ | ||
76 | static inline void arch_local_irq_restore(unsigned long flags) | ||
77 | { | ||
78 | asm volatile( | ||
79 | "msr daif, %0 // arch_local_irq_restore" | ||
80 | : | ||
81 | : "r" (flags) | ||
82 | : "memory"); | ||
83 | } | ||
84 | |||
85 | static inline int arch_irqs_disabled_flags(unsigned long flags) | ||
86 | { | ||
87 | return flags & PSR_I_BIT; | ||
88 | } | ||
89 | |||
90 | #endif | ||
91 | #endif | ||
diff --git a/arch/arm64/include/asm/memblock.h b/arch/arm64/include/asm/memblock.h new file mode 100644 index 000000000000..6afeed2467f1 --- /dev/null +++ b/arch/arm64/include/asm/memblock.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_MEMBLOCK_H | ||
17 | #define __ASM_MEMBLOCK_H | ||
18 | |||
19 | extern void arm64_memblock_init(void); | ||
20 | |||
21 | #endif | ||
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h new file mode 100644 index 000000000000..1cac16a001cb --- /dev/null +++ b/arch/arm64/include/asm/memory.h | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/memory.h | ||
3 | * | ||
4 | * Copyright (C) 2000-2002 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | * | ||
19 | * Note: this file should not be included by non-asm/.h files | ||
20 | */ | ||
21 | #ifndef __ASM_MEMORY_H | ||
22 | #define __ASM_MEMORY_H | ||
23 | |||
24 | #include <linux/compiler.h> | ||
25 | #include <linux/const.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <asm/sizes.h> | ||
28 | |||
29 | /* | ||
30 | * Allow for constants defined here to be used from assembly code | ||
31 | * by prepending the UL suffix only with actual C code compilation. | ||
32 | */ | ||
33 | #define UL(x) _AC(x, UL) | ||
34 | |||
35 | /* | ||
36 | * PAGE_OFFSET - the virtual address of the start of the kernel image. | ||
37 | * VA_BITS - the maximum number of bits for virtual addresses. | ||
38 | * TASK_SIZE - the maximum size of a user space task. | ||
39 | * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area. | ||
40 | * The module space lives between the addresses given by TASK_SIZE | ||
41 | * and PAGE_OFFSET - it must be within 128MB of the kernel text. | ||
42 | */ | ||
43 | #define PAGE_OFFSET UL(0xffffffc000000000) | ||
44 | #define MODULES_END (PAGE_OFFSET) | ||
45 | #define MODULES_VADDR (MODULES_END - SZ_64M) | ||
46 | #define VA_BITS (39) | ||
47 | #define TASK_SIZE_64 (UL(1) << VA_BITS) | ||
48 | |||
49 | #ifdef CONFIG_COMPAT | ||
50 | #define TASK_SIZE_32 UL(0x100000000) | ||
51 | #define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \ | ||
52 | TASK_SIZE_32 : TASK_SIZE_64) | ||
53 | #else | ||
54 | #define TASK_SIZE TASK_SIZE_64 | ||
55 | #endif /* CONFIG_COMPAT */ | ||
56 | |||
57 | #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 4)) | ||
58 | |||
59 | #if TASK_SIZE_64 > MODULES_VADDR | ||
60 | #error Top of 64-bit user space clashes with start of module space | ||
61 | #endif | ||
62 | |||
63 | /* | ||
64 | * Physical vs virtual RAM address space conversion. These are | ||
65 | * private definitions which should NOT be used outside memory.h | ||
66 | * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. | ||
67 | */ | ||
68 | #define __virt_to_phys(x) (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET)) | ||
69 | #define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET)) | ||
70 | |||
71 | /* | ||
72 | * Convert a physical address to a Page Frame Number and back | ||
73 | */ | ||
74 | #define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT)) | ||
75 | #define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) | ||
76 | |||
77 | /* | ||
78 | * Convert a page to/from a physical address | ||
79 | */ | ||
80 | #define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page))) | ||
81 | #define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys))) | ||
82 | |||
83 | /* | ||
84 | * Memory types available. | ||
85 | */ | ||
86 | #define MT_DEVICE_nGnRnE 0 | ||
87 | #define MT_DEVICE_nGnRE 1 | ||
88 | #define MT_DEVICE_GRE 2 | ||
89 | #define MT_NORMAL_NC 3 | ||
90 | #define MT_NORMAL 4 | ||
91 | |||
92 | #ifndef __ASSEMBLY__ | ||
93 | |||
94 | extern phys_addr_t memstart_addr; | ||
95 | /* PHYS_OFFSET - the physical address of the start of memory. */ | ||
96 | #define PHYS_OFFSET ({ memstart_addr; }) | ||
97 | |||
98 | /* | ||
99 | * PFNs are used to describe any physical page; this means | ||
100 | * PFN 0 == physical address 0. | ||
101 | * | ||
102 | * This is the PFN of the first RAM page in the kernel | ||
103 | * direct-mapped view. We assume this is the first page | ||
104 | * of RAM in the mem_map as well. | ||
105 | */ | ||
106 | #define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT) | ||
107 | |||
108 | /* | ||
109 | * Note: Drivers should NOT use these. They are the wrong | ||
110 | * translation for translating DMA addresses. Use the driver | ||
111 | * DMA support - see dma-mapping.h. | ||
112 | */ | ||
113 | static inline phys_addr_t virt_to_phys(const volatile void *x) | ||
114 | { | ||
115 | return __virt_to_phys((unsigned long)(x)); | ||
116 | } | ||
117 | |||
118 | static inline void *phys_to_virt(phys_addr_t x) | ||
119 | { | ||
120 | return (void *)(__phys_to_virt(x)); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Drivers should NOT use these either. | ||
125 | */ | ||
126 | #define __pa(x) __virt_to_phys((unsigned long)(x)) | ||
127 | #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) | ||
128 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | ||
129 | |||
130 | /* | ||
131 | * virt_to_page(k) convert a _valid_ virtual address to struct page * | ||
132 | * virt_addr_valid(k) indicates whether a virtual address is valid | ||
133 | */ | ||
134 | #define ARCH_PFN_OFFSET PHYS_PFN_OFFSET | ||
135 | |||
136 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | ||
137 | #define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ | ||
138 | ((void *)(kaddr) < (void *)high_memory)) | ||
139 | |||
140 | #endif | ||
141 | |||
142 | #include <asm-generic/memory_model.h> | ||
143 | |||
144 | #endif | ||
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h new file mode 100644 index 000000000000..d4f7fd5b9e33 --- /dev/null +++ b/arch/arm64/include/asm/mmu.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_MMU_H | ||
17 | #define __ASM_MMU_H | ||
18 | |||
19 | typedef struct { | ||
20 | unsigned int id; | ||
21 | raw_spinlock_t id_lock; | ||
22 | void *vdso; | ||
23 | } mm_context_t; | ||
24 | |||
25 | #define ASID(mm) ((mm)->context.id & 0xffff) | ||
26 | |||
27 | extern void paging_init(void); | ||
28 | extern void setup_mm_for_reboot(void); | ||
29 | |||
30 | #endif | ||
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h new file mode 100644 index 000000000000..f68465dee026 --- /dev/null +++ b/arch/arm64/include/asm/mmu_context.h | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/mmu_context.h | ||
3 | * | ||
4 | * Copyright (C) 1996 Russell King. | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_MMU_CONTEXT_H | ||
20 | #define __ASM_MMU_CONTEXT_H | ||
21 | |||
22 | #include <linux/compiler.h> | ||
23 | #include <linux/sched.h> | ||
24 | |||
25 | #include <asm/cacheflush.h> | ||
26 | #include <asm/proc-fns.h> | ||
27 | #include <asm-generic/mm_hooks.h> | ||
28 | #include <asm/cputype.h> | ||
29 | #include <asm/pgtable.h> | ||
30 | |||
31 | #define MAX_ASID_BITS 16 | ||
32 | |||
33 | extern unsigned int cpu_last_asid; | ||
34 | |||
35 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm); | ||
36 | void __new_context(struct mm_struct *mm); | ||
37 | |||
38 | /* | ||
39 | * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0. | ||
40 | */ | ||
41 | static inline void cpu_set_reserved_ttbr0(void) | ||
42 | { | ||
43 | unsigned long ttbr = page_to_phys(empty_zero_page); | ||
44 | |||
45 | asm( | ||
46 | " msr ttbr0_el1, %0 // set TTBR0\n" | ||
47 | " isb" | ||
48 | : | ||
49 | : "r" (ttbr)); | ||
50 | } | ||
51 | |||
52 | static inline void switch_new_context(struct mm_struct *mm) | ||
53 | { | ||
54 | unsigned long flags; | ||
55 | |||
56 | __new_context(mm); | ||
57 | |||
58 | local_irq_save(flags); | ||
59 | cpu_switch_mm(mm->pgd, mm); | ||
60 | local_irq_restore(flags); | ||
61 | } | ||
62 | |||
63 | static inline void check_and_switch_context(struct mm_struct *mm, | ||
64 | struct task_struct *tsk) | ||
65 | { | ||
66 | /* | ||
67 | * Required during context switch to avoid speculative page table | ||
68 | * walking with the wrong TTBR. | ||
69 | */ | ||
70 | cpu_set_reserved_ttbr0(); | ||
71 | |||
72 | if (!((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS)) | ||
73 | /* | ||
74 | * The ASID is from the current generation, just switch to the | ||
75 | * new pgd. This condition is only true for calls from | ||
76 | * context_switch() and interrupts are already disabled. | ||
77 | */ | ||
78 | cpu_switch_mm(mm->pgd, mm); | ||
79 | else if (irqs_disabled()) | ||
80 | /* | ||
81 | * Defer the new ASID allocation until after the context | ||
82 | * switch critical region since __new_context() cannot be | ||
83 | * called with interrupts disabled. | ||
84 | */ | ||
85 | set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM); | ||
86 | else | ||
87 | /* | ||
88 | * That is a direct call to switch_mm() or activate_mm() with | ||
89 | * interrupts enabled and a new context. | ||
90 | */ | ||
91 | switch_new_context(mm); | ||
92 | } | ||
93 | |||
94 | #define init_new_context(tsk,mm) (__init_new_context(tsk,mm),0) | ||
95 | #define destroy_context(mm) do { } while(0) | ||
96 | |||
97 | #define finish_arch_post_lock_switch \ | ||
98 | finish_arch_post_lock_switch | ||
99 | static inline void finish_arch_post_lock_switch(void) | ||
100 | { | ||
101 | if (test_and_clear_thread_flag(TIF_SWITCH_MM)) { | ||
102 | struct mm_struct *mm = current->mm; | ||
103 | unsigned long flags; | ||
104 | |||
105 | __new_context(mm); | ||
106 | |||
107 | local_irq_save(flags); | ||
108 | cpu_switch_mm(mm->pgd, mm); | ||
109 | local_irq_restore(flags); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * This is called when "tsk" is about to enter lazy TLB mode. | ||
115 | * | ||
116 | * mm: describes the currently active mm context | ||
117 | * tsk: task which is entering lazy tlb | ||
118 | * cpu: cpu number which is entering lazy tlb | ||
119 | * | ||
120 | * tsk->mm will be NULL | ||
121 | */ | ||
122 | static inline void | ||
123 | enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | ||
124 | { | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * This is the actual mm switch as far as the scheduler | ||
129 | * is concerned. No registers are touched. We avoid | ||
130 | * calling the CPU specific function when the mm hasn't | ||
131 | * actually changed. | ||
132 | */ | ||
133 | static inline void | ||
134 | switch_mm(struct mm_struct *prev, struct mm_struct *next, | ||
135 | struct task_struct *tsk) | ||
136 | { | ||
137 | unsigned int cpu = smp_processor_id(); | ||
138 | |||
139 | #ifdef CONFIG_SMP | ||
140 | /* check for possible thread migration */ | ||
141 | if (!cpumask_empty(mm_cpumask(next)) && | ||
142 | !cpumask_test_cpu(cpu, mm_cpumask(next))) | ||
143 | __flush_icache_all(); | ||
144 | #endif | ||
145 | if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) | ||
146 | check_and_switch_context(next, tsk); | ||
147 | } | ||
148 | |||
149 | #define deactivate_mm(tsk,mm) do { } while (0) | ||
150 | #define activate_mm(prev,next) switch_mm(prev, next, NULL) | ||
151 | |||
152 | #endif | ||
diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h new file mode 100644 index 000000000000..e80e232b730e --- /dev/null +++ b/arch/arm64/include/asm/module.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_MODULE_H | ||
17 | #define __ASM_MODULE_H | ||
18 | |||
19 | #include <asm-generic/module.h> | ||
20 | |||
21 | #define MODULE_ARCH_VERMAGIC "aarch64" | ||
22 | |||
23 | #endif /* __ASM_MODULE_H */ | ||
diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h new file mode 100644 index 000000000000..46bf66628b6a --- /dev/null +++ b/arch/arm64/include/asm/page.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/page.h | ||
3 | * | ||
4 | * Copyright (C) 1995-2003 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_PAGE_H | ||
20 | #define __ASM_PAGE_H | ||
21 | |||
22 | /* PAGE_SHIFT determines the page size */ | ||
23 | #ifdef CONFIG_ARM64_64K_PAGES | ||
24 | #define PAGE_SHIFT 16 | ||
25 | #else | ||
26 | #define PAGE_SHIFT 12 | ||
27 | #endif | ||
28 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) | ||
29 | #define PAGE_MASK (~(PAGE_SIZE-1)) | ||
30 | |||
31 | /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ | ||
32 | #define __HAVE_ARCH_GATE_AREA 1 | ||
33 | |||
34 | #ifndef __ASSEMBLY__ | ||
35 | |||
36 | #ifdef CONFIG_ARM64_64K_PAGES | ||
37 | #include <asm/pgtable-2level-types.h> | ||
38 | #else | ||
39 | #include <asm/pgtable-3level-types.h> | ||
40 | #endif | ||
41 | |||
42 | extern void __cpu_clear_user_page(void *p, unsigned long user); | ||
43 | extern void __cpu_copy_user_page(void *to, const void *from, | ||
44 | unsigned long user); | ||
45 | extern void copy_page(void *to, const void *from); | ||
46 | extern void clear_page(void *to); | ||
47 | |||
48 | #define clear_user_page(addr,vaddr,pg) __cpu_clear_user_page(addr, vaddr) | ||
49 | #define copy_user_page(to,from,vaddr,pg) __cpu_copy_user_page(to, from, vaddr) | ||
50 | |||
51 | typedef struct page *pgtable_t; | ||
52 | |||
53 | #ifdef CONFIG_HAVE_ARCH_PFN_VALID | ||
54 | extern int pfn_valid(unsigned long); | ||
55 | #endif | ||
56 | |||
57 | #include <asm/memory.h> | ||
58 | |||
59 | #endif /* !__ASSEMBLY__ */ | ||
60 | |||
61 | #define VM_DATA_DEFAULT_FLAGS \ | ||
62 | (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ | ||
63 | VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
64 | |||
65 | #include <asm-generic/getorder.h> | ||
66 | |||
67 | #endif | ||
diff --git a/arch/arm64/include/asm/param.h b/arch/arm64/include/asm/param.h new file mode 100644 index 000000000000..8e3a281d448a --- /dev/null +++ b/arch/arm64/include/asm/param.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_PARAM_H | ||
17 | #define __ASM_PARAM_H | ||
18 | |||
19 | #define EXEC_PAGESIZE 65536 | ||
20 | |||
21 | #include <asm-generic/param.h> | ||
22 | |||
23 | #endif | ||
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h new file mode 100644 index 000000000000..a6fffd511c5e --- /dev/null +++ b/arch/arm64/include/asm/perf_event.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #ifndef __ASM_PERF_EVENT_H | ||
18 | #define __ASM_PERF_EVENT_H | ||
19 | |||
20 | /* It's quiet around here... */ | ||
21 | |||
22 | #endif | ||
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h new file mode 100644 index 000000000000..f214069ec5d5 --- /dev/null +++ b/arch/arm64/include/asm/pgalloc.h | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/pgalloc.h | ||
3 | * | ||
4 | * Copyright (C) 2000-2001 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_PGALLOC_H | ||
20 | #define __ASM_PGALLOC_H | ||
21 | |||
22 | #include <asm/pgtable-hwdef.h> | ||
23 | #include <asm/processor.h> | ||
24 | #include <asm/cacheflush.h> | ||
25 | #include <asm/tlbflush.h> | ||
26 | |||
27 | #define check_pgt_cache() do { } while (0) | ||
28 | |||
29 | #ifndef CONFIG_ARM64_64K_PAGES | ||
30 | |||
31 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
32 | { | ||
33 | return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); | ||
34 | } | ||
35 | |||
36 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | ||
37 | { | ||
38 | BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); | ||
39 | free_page((unsigned long)pmd); | ||
40 | } | ||
41 | |||
42 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | ||
43 | { | ||
44 | set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); | ||
45 | } | ||
46 | |||
47 | #endif /* CONFIG_ARM64_64K_PAGES */ | ||
48 | |||
49 | extern pgd_t *pgd_alloc(struct mm_struct *mm); | ||
50 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | ||
51 | |||
52 | #define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) | ||
53 | |||
54 | static inline pte_t * | ||
55 | pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) | ||
56 | { | ||
57 | return (pte_t *)__get_free_page(PGALLOC_GFP); | ||
58 | } | ||
59 | |||
60 | static inline pgtable_t | ||
61 | pte_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
62 | { | ||
63 | struct page *pte; | ||
64 | |||
65 | pte = alloc_pages(PGALLOC_GFP, 0); | ||
66 | if (pte) | ||
67 | pgtable_page_ctor(pte); | ||
68 | |||
69 | return pte; | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Free a PTE table. | ||
74 | */ | ||
75 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | ||
76 | { | ||
77 | if (pte) | ||
78 | free_page((unsigned long)pte); | ||
79 | } | ||
80 | |||
81 | static inline void pte_free(struct mm_struct *mm, pgtable_t pte) | ||
82 | { | ||
83 | pgtable_page_dtor(pte); | ||
84 | __free_page(pte); | ||
85 | } | ||
86 | |||
87 | static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, | ||
88 | pmdval_t prot) | ||
89 | { | ||
90 | set_pmd(pmdp, __pmd(pte | prot)); | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * Populate the pmdp entry with a pointer to the pte. This pmd is part | ||
95 | * of the mm address space. | ||
96 | */ | ||
97 | static inline void | ||
98 | pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | ||
99 | { | ||
100 | /* | ||
101 | * The pmd must be loaded with the physical address of the PTE table | ||
102 | */ | ||
103 | __pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE); | ||
104 | } | ||
105 | |||
106 | static inline void | ||
107 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) | ||
108 | { | ||
109 | __pmd_populate(pmdp, page_to_phys(ptep), PMD_TYPE_TABLE); | ||
110 | } | ||
111 | #define pmd_pgtable(pmd) pmd_page(pmd) | ||
112 | |||
113 | #endif | ||
diff --git a/arch/arm64/include/asm/pgtable-2level-hwdef.h b/arch/arm64/include/asm/pgtable-2level-hwdef.h new file mode 100644 index 000000000000..0a8ed3f94e93 --- /dev/null +++ b/arch/arm64/include/asm/pgtable-2level-hwdef.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_PGTABLE_2LEVEL_HWDEF_H | ||
17 | #define __ASM_PGTABLE_2LEVEL_HWDEF_H | ||
18 | |||
19 | /* | ||
20 | * With LPAE and 64KB pages, there are 2 levels of page tables. Each level has | ||
21 | * 8192 entries of 8 bytes each, occupying a 64KB page. Levels 0 and 1 are not | ||
22 | * used. The 2nd level table (PGD for Linux) can cover a range of 4TB, each | ||
23 | * entry representing 512MB. The user and kernel address spaces are limited to | ||
24 | * 512GB and therefore we only use 1024 entries in the PGD. | ||
25 | */ | ||
26 | #define PTRS_PER_PTE 8192 | ||
27 | #define PTRS_PER_PGD 1024 | ||
28 | |||
29 | /* | ||
30 | * PGDIR_SHIFT determines the size a top-level page table entry can map. | ||
31 | */ | ||
32 | #define PGDIR_SHIFT 29 | ||
33 | #define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) | ||
34 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
35 | |||
36 | /* | ||
37 | * section address mask and size definitions. | ||
38 | */ | ||
39 | #define SECTION_SHIFT 29 | ||
40 | #define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT) | ||
41 | #define SECTION_MASK (~(SECTION_SIZE-1)) | ||
42 | |||
43 | #endif | ||
diff --git a/arch/arm64/include/asm/pgtable-2level-types.h b/arch/arm64/include/asm/pgtable-2level-types.h new file mode 100644 index 000000000000..3c3ca7d361e4 --- /dev/null +++ b/arch/arm64/include/asm/pgtable-2level-types.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_PGTABLE_2LEVEL_TYPES_H | ||
17 | #define __ASM_PGTABLE_2LEVEL_TYPES_H | ||
18 | |||
19 | typedef u64 pteval_t; | ||
20 | typedef u64 pgdval_t; | ||
21 | typedef pgdval_t pmdval_t; | ||
22 | |||
23 | #undef STRICT_MM_TYPECHECKS | ||
24 | |||
25 | #ifdef STRICT_MM_TYPECHECKS | ||
26 | |||
27 | /* | ||
28 | * These are used to make use of C type-checking.. | ||
29 | */ | ||
30 | typedef struct { pteval_t pte; } pte_t; | ||
31 | typedef struct { pgdval_t pgd; } pgd_t; | ||
32 | typedef struct { pteval_t pgprot; } pgprot_t; | ||
33 | |||
34 | #define pte_val(x) ((x).pte) | ||
35 | #define pgd_val(x) ((x).pgd) | ||
36 | #define pgprot_val(x) ((x).pgprot) | ||
37 | |||
38 | #define __pte(x) ((pte_t) { (x) } ) | ||
39 | #define __pgd(x) ((pgd_t) { (x) } ) | ||
40 | #define __pgprot(x) ((pgprot_t) { (x) } ) | ||
41 | |||
42 | #else /* !STRICT_MM_TYPECHECKS */ | ||
43 | |||
44 | typedef pteval_t pte_t; | ||
45 | typedef pgdval_t pgd_t; | ||
46 | typedef pteval_t pgprot_t; | ||
47 | |||
48 | #define pte_val(x) (x) | ||
49 | #define pgd_val(x) (x) | ||
50 | #define pgprot_val(x) (x) | ||
51 | |||
52 | #define __pte(x) (x) | ||
53 | #define __pgd(x) (x) | ||
54 | #define __pgprot(x) (x) | ||
55 | |||
56 | #endif /* STRICT_MM_TYPECHECKS */ | ||
57 | |||
58 | #include <asm-generic/pgtable-nopmd.h> | ||
59 | |||
60 | #endif /* __ASM_PGTABLE_2LEVEL_TYPES_H */ | ||
diff --git a/arch/arm64/include/asm/pgtable-3level-hwdef.h b/arch/arm64/include/asm/pgtable-3level-hwdef.h new file mode 100644 index 000000000000..3dbf941d7767 --- /dev/null +++ b/arch/arm64/include/asm/pgtable-3level-hwdef.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_PGTABLE_3LEVEL_HWDEF_H | ||
17 | #define __ASM_PGTABLE_3LEVEL_HWDEF_H | ||
18 | |||
19 | /* | ||
20 | * With LPAE and 4KB pages, there are 3 levels of page tables. Each level has | ||
21 | * 512 entries of 8 bytes each, occupying a 4K page. The first level table | ||
22 | * covers a range of 512GB, each entry representing 1GB. The user and kernel | ||
23 | * address spaces are limited to 512GB each. | ||
24 | */ | ||
25 | #define PTRS_PER_PTE 512 | ||
26 | #define PTRS_PER_PMD 512 | ||
27 | #define PTRS_PER_PGD 512 | ||
28 | |||
29 | /* | ||
30 | * PGDIR_SHIFT determines the size a top-level page table entry can map. | ||
31 | */ | ||
32 | #define PGDIR_SHIFT 30 | ||
33 | #define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) | ||
34 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
35 | |||
36 | /* | ||
37 | * PMD_SHIFT determines the size a middle-level page table entry can map. | ||
38 | */ | ||
39 | #define PMD_SHIFT 21 | ||
40 | #define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) | ||
41 | #define PMD_MASK (~(PMD_SIZE-1)) | ||
42 | |||
43 | /* | ||
44 | * section address mask and size definitions. | ||
45 | */ | ||
46 | #define SECTION_SHIFT 21 | ||
47 | #define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT) | ||
48 | #define SECTION_MASK (~(SECTION_SIZE-1)) | ||
49 | |||
50 | #endif | ||
diff --git a/arch/arm64/include/asm/pgtable-3level-types.h b/arch/arm64/include/asm/pgtable-3level-types.h new file mode 100644 index 000000000000..4489615f14a9 --- /dev/null +++ b/arch/arm64/include/asm/pgtable-3level-types.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_PGTABLE_3LEVEL_TYPES_H | ||
17 | #define __ASM_PGTABLE_3LEVEL_TYPES_H | ||
18 | |||
19 | typedef u64 pteval_t; | ||
20 | typedef u64 pmdval_t; | ||
21 | typedef u64 pgdval_t; | ||
22 | |||
23 | #undef STRICT_MM_TYPECHECKS | ||
24 | |||
25 | #ifdef STRICT_MM_TYPECHECKS | ||
26 | |||
27 | /* | ||
28 | * These are used to make use of C type-checking.. | ||
29 | */ | ||
30 | typedef struct { pteval_t pte; } pte_t; | ||
31 | typedef struct { pmdval_t pmd; } pmd_t; | ||
32 | typedef struct { pgdval_t pgd; } pgd_t; | ||
33 | typedef struct { pteval_t pgprot; } pgprot_t; | ||
34 | |||
35 | #define pte_val(x) ((x).pte) | ||
36 | #define pmd_val(x) ((x).pmd) | ||
37 | #define pgd_val(x) ((x).pgd) | ||
38 | #define pgprot_val(x) ((x).pgprot) | ||
39 | |||
40 | #define __pte(x) ((pte_t) { (x) } ) | ||
41 | #define __pmd(x) ((pmd_t) { (x) } ) | ||
42 | #define __pgd(x) ((pgd_t) { (x) } ) | ||
43 | #define __pgprot(x) ((pgprot_t) { (x) } ) | ||
44 | |||
45 | #else /* !STRICT_MM_TYPECHECKS */ | ||
46 | |||
47 | typedef pteval_t pte_t; | ||
48 | typedef pmdval_t pmd_t; | ||
49 | typedef pgdval_t pgd_t; | ||
50 | typedef pteval_t pgprot_t; | ||
51 | |||
52 | #define pte_val(x) (x) | ||
53 | #define pmd_val(x) (x) | ||
54 | #define pgd_val(x) (x) | ||
55 | #define pgprot_val(x) (x) | ||
56 | |||
57 | #define __pte(x) (x) | ||
58 | #define __pmd(x) (x) | ||
59 | #define __pgd(x) (x) | ||
60 | #define __pgprot(x) (x) | ||
61 | |||
62 | #endif /* STRICT_MM_TYPECHECKS */ | ||
63 | |||
64 | #include <asm-generic/pgtable-nopud.h> | ||
65 | |||
66 | #endif /* __ASM_PGTABLE_3LEVEL_TYPES_H */ | ||
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h new file mode 100644 index 000000000000..0f3b4581d925 --- /dev/null +++ b/arch/arm64/include/asm/pgtable-hwdef.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_PGTABLE_HWDEF_H | ||
17 | #define __ASM_PGTABLE_HWDEF_H | ||
18 | |||
19 | #ifdef CONFIG_ARM64_64K_PAGES | ||
20 | #include <asm/pgtable-2level-hwdef.h> | ||
21 | #else | ||
22 | #include <asm/pgtable-3level-hwdef.h> | ||
23 | #endif | ||
24 | |||
25 | /* | ||
26 | * Hardware page table definitions. | ||
27 | * | ||
28 | * Level 2 descriptor (PMD). | ||
29 | */ | ||
30 | #define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) | ||
31 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) | ||
32 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) | ||
33 | #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) | ||
34 | |||
35 | /* | ||
36 | * Section | ||
37 | */ | ||
38 | #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) | ||
39 | #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) | ||
40 | #define PMD_SECT_NG (_AT(pmdval_t, 1) << 11) | ||
41 | #define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) | ||
42 | |||
43 | /* | ||
44 | * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). | ||
45 | */ | ||
46 | #define PMD_ATTRINDX(t) (_AT(pmdval_t, (t)) << 2) | ||
47 | #define PMD_ATTRINDX_MASK (_AT(pmdval_t, 7) << 2) | ||
48 | |||
49 | /* | ||
50 | * Level 3 descriptor (PTE). | ||
51 | */ | ||
52 | #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) | ||
53 | #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) | ||
54 | #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) | ||
55 | #define PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ | ||
56 | #define PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ | ||
57 | #define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ | ||
58 | #define PTE_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ | ||
59 | #define PTE_NG (_AT(pteval_t, 1) << 11) /* nG */ | ||
60 | #define PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ | ||
61 | |||
62 | /* | ||
63 | * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). | ||
64 | */ | ||
65 | #define PTE_ATTRINDX(t) (_AT(pteval_t, (t)) << 2) | ||
66 | #define PTE_ATTRINDX_MASK (_AT(pteval_t, 7) << 2) | ||
67 | |||
68 | /* | ||
69 | * 40-bit physical address supported. | ||
70 | */ | ||
71 | #define PHYS_MASK_SHIFT (40) | ||
72 | #define PHYS_MASK ((UL(1) << PHYS_MASK_SHIFT) - 1) | ||
73 | |||
74 | /* | ||
75 | * TCR flags. | ||
76 | */ | ||
77 | #define TCR_TxSZ(x) (((UL(64) - (x)) << 16) | ((UL(64) - (x)) << 0)) | ||
78 | #define TCR_IRGN_NC ((UL(0) << 8) | (UL(0) << 24)) | ||
79 | #define TCR_IRGN_WBWA ((UL(1) << 8) | (UL(1) << 24)) | ||
80 | #define TCR_IRGN_WT ((UL(2) << 8) | (UL(2) << 24)) | ||
81 | #define TCR_IRGN_WBnWA ((UL(3) << 8) | (UL(3) << 24)) | ||
82 | #define TCR_IRGN_MASK ((UL(3) << 8) | (UL(3) << 24)) | ||
83 | #define TCR_ORGN_NC ((UL(0) << 10) | (UL(0) << 26)) | ||
84 | #define TCR_ORGN_WBWA ((UL(1) << 10) | (UL(1) << 26)) | ||
85 | #define TCR_ORGN_WT ((UL(2) << 10) | (UL(2) << 26)) | ||
86 | #define TCR_ORGN_WBnWA ((UL(3) << 10) | (UL(3) << 26)) | ||
87 | #define TCR_ORGN_MASK ((UL(3) << 10) | (UL(3) << 26)) | ||
88 | #define TCR_SHARED ((UL(3) << 12) | (UL(3) << 28)) | ||
89 | #define TCR_TG0_64K (UL(1) << 14) | ||
90 | #define TCR_TG1_64K (UL(1) << 30) | ||
91 | #define TCR_IPS_40BIT (UL(2) << 32) | ||
92 | #define TCR_ASID16 (UL(1) << 36) | ||
93 | |||
94 | #endif | ||
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h new file mode 100644 index 000000000000..8960239be722 --- /dev/null +++ b/arch/arm64/include/asm/pgtable.h | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_PGTABLE_H | ||
17 | #define __ASM_PGTABLE_H | ||
18 | |||
19 | #include <asm/proc-fns.h> | ||
20 | |||
21 | #include <asm/memory.h> | ||
22 | #include <asm/pgtable-hwdef.h> | ||
23 | |||
24 | /* | ||
25 | * Software defined PTE bits definition. | ||
26 | */ | ||
27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) /* pte_present() check */ | ||
28 | #define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */ | ||
29 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) | ||
30 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) | ||
31 | |||
32 | /* | ||
33 | * VMALLOC and SPARSEMEM_VMEMMAP ranges. | ||
34 | */ | ||
35 | #define VMALLOC_START UL(0xffffff8000000000) | ||
36 | #define VMALLOC_END (PAGE_OFFSET - UL(0x400000000) - SZ_64K) | ||
37 | |||
38 | #define vmemmap ((struct page *)(VMALLOC_END + SZ_64K)) | ||
39 | |||
40 | #define FIRST_USER_ADDRESS 0 | ||
41 | |||
42 | #ifndef __ASSEMBLY__ | ||
43 | extern void __pte_error(const char *file, int line, unsigned long val); | ||
44 | extern void __pmd_error(const char *file, int line, unsigned long val); | ||
45 | extern void __pgd_error(const char *file, int line, unsigned long val); | ||
46 | |||
47 | #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte)) | ||
48 | #ifndef CONFIG_ARM64_64K_PAGES | ||
49 | #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd)) | ||
50 | #endif | ||
51 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) | ||
52 | |||
53 | /* | ||
54 | * The pgprot_* and protection_map entries will be fixed up at runtime to | ||
55 | * include the cachable and bufferable bits based on memory policy, as well as | ||
56 | * any architecture dependent bits like global/ASID and SMP shared mapping | ||
57 | * bits. | ||
58 | */ | ||
59 | #define _PAGE_DEFAULT PTE_TYPE_PAGE | PTE_AF | ||
60 | |||
61 | extern pgprot_t pgprot_default; | ||
62 | |||
63 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) | ||
64 | |||
65 | #define PAGE_NONE _MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY) | ||
66 | #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN) | ||
67 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG) | ||
68 | #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) | ||
69 | #define PAGE_COPY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY) | ||
70 | #define PAGE_READONLY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) | ||
71 | #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY) | ||
72 | #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY) | ||
73 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_DIRTY) | ||
74 | |||
75 | #define __PAGE_NONE __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY) | ||
76 | #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN) | ||
77 | #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG) | ||
78 | #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) | ||
79 | #define __PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY) | ||
80 | #define __PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) | ||
81 | #define __PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY) | ||
82 | |||
83 | #endif /* __ASSEMBLY__ */ | ||
84 | |||
85 | #define __P000 __PAGE_NONE | ||
86 | #define __P001 __PAGE_READONLY | ||
87 | #define __P010 __PAGE_COPY | ||
88 | #define __P011 __PAGE_COPY | ||
89 | #define __P100 __PAGE_READONLY_EXEC | ||
90 | #define __P101 __PAGE_READONLY_EXEC | ||
91 | #define __P110 __PAGE_COPY_EXEC | ||
92 | #define __P111 __PAGE_COPY_EXEC | ||
93 | |||
94 | #define __S000 __PAGE_NONE | ||
95 | #define __S001 __PAGE_READONLY | ||
96 | #define __S010 __PAGE_SHARED | ||
97 | #define __S011 __PAGE_SHARED | ||
98 | #define __S100 __PAGE_READONLY_EXEC | ||
99 | #define __S101 __PAGE_READONLY_EXEC | ||
100 | #define __S110 __PAGE_SHARED_EXEC | ||
101 | #define __S111 __PAGE_SHARED_EXEC | ||
102 | |||
103 | #ifndef __ASSEMBLY__ | ||
104 | /* | ||
105 | * ZERO_PAGE is a global shared page that is always zero: used | ||
106 | * for zero-mapped memory areas etc.. | ||
107 | */ | ||
108 | extern struct page *empty_zero_page; | ||
109 | #define ZERO_PAGE(vaddr) (empty_zero_page) | ||
110 | |||
111 | #define pte_pfn(pte) ((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT) | ||
112 | |||
113 | #define pfn_pte(pfn,prot) (__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) | ||
114 | |||
115 | #define pte_none(pte) (!pte_val(pte)) | ||
116 | #define pte_clear(mm,addr,ptep) set_pte(ptep, __pte(0)) | ||
117 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) | ||
118 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) | ||
119 | |||
120 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) | ||
121 | #define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr)) | ||
122 | #define pte_unmap(pte) do { } while (0) | ||
123 | #define pte_unmap_nested(pte) do { } while (0) | ||
124 | |||
125 | /* | ||
126 | * The following only work if pte_present(). Undefined behaviour otherwise. | ||
127 | */ | ||
128 | #define pte_present(pte) (pte_val(pte) & PTE_VALID) | ||
129 | #define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY) | ||
130 | #define pte_young(pte) (pte_val(pte) & PTE_AF) | ||
131 | #define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) | ||
132 | #define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY)) | ||
133 | #define pte_exec(pte) (!(pte_val(pte) & PTE_XN)) | ||
134 | |||
135 | #define pte_present_exec_user(pte) \ | ||
136 | ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \ | ||
137 | (PTE_VALID | PTE_USER)) | ||
138 | |||
139 | #define PTE_BIT_FUNC(fn,op) \ | ||
140 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | ||
141 | |||
142 | PTE_BIT_FUNC(wrprotect, |= PTE_RDONLY); | ||
143 | PTE_BIT_FUNC(mkwrite, &= ~PTE_RDONLY); | ||
144 | PTE_BIT_FUNC(mkclean, &= ~PTE_DIRTY); | ||
145 | PTE_BIT_FUNC(mkdirty, |= PTE_DIRTY); | ||
146 | PTE_BIT_FUNC(mkold, &= ~PTE_AF); | ||
147 | PTE_BIT_FUNC(mkyoung, |= PTE_AF); | ||
148 | PTE_BIT_FUNC(mkspecial, |= PTE_SPECIAL); | ||
149 | |||
150 | static inline void set_pte(pte_t *ptep, pte_t pte) | ||
151 | { | ||
152 | *ptep = pte; | ||
153 | } | ||
154 | |||
155 | extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); | ||
156 | |||
157 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
158 | pte_t *ptep, pte_t pte) | ||
159 | { | ||
160 | if (pte_present_exec_user(pte)) | ||
161 | __sync_icache_dcache(pte, addr); | ||
162 | set_pte(ptep, pte); | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Huge pte definitions. | ||
167 | */ | ||
168 | #define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) | ||
169 | #define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) | ||
170 | |||
171 | #define __pgprot_modify(prot,mask,bits) \ | ||
172 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
173 | |||
174 | #define __HAVE_ARCH_PTE_SPECIAL | ||
175 | |||
176 | /* | ||
177 | * Mark the prot value as uncacheable and unbufferable. | ||
178 | */ | ||
179 | #define pgprot_noncached(prot) \ | ||
180 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE)) | ||
181 | #define pgprot_writecombine(prot) \ | ||
182 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE)) | ||
183 | #define pgprot_dmacoherent(prot) \ | ||
184 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) | ||
185 | #define __HAVE_PHYS_MEM_ACCESS_PROT | ||
186 | struct file; | ||
187 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
188 | unsigned long size, pgprot_t vma_prot); | ||
189 | |||
190 | #define pmd_none(pmd) (!pmd_val(pmd)) | ||
191 | #define pmd_present(pmd) (pmd_val(pmd)) | ||
192 | |||
193 | #define pmd_bad(pmd) (!(pmd_val(pmd) & 2)) | ||
194 | |||
195 | static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) | ||
196 | { | ||
197 | *pmdp = pmd; | ||
198 | dsb(); | ||
199 | } | ||
200 | |||
201 | static inline void pmd_clear(pmd_t *pmdp) | ||
202 | { | ||
203 | set_pmd(pmdp, __pmd(0)); | ||
204 | } | ||
205 | |||
206 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) | ||
207 | { | ||
208 | return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK); | ||
209 | } | ||
210 | |||
211 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | ||
212 | |||
213 | /* | ||
214 | * Conversion functions: convert a page and protection to a page entry, | ||
215 | * and a page entry and page directory to the page they refer to. | ||
216 | */ | ||
217 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot) | ||
218 | |||
219 | #ifndef CONFIG_ARM64_64K_PAGES | ||
220 | |||
221 | #define pud_none(pud) (!pud_val(pud)) | ||
222 | #define pud_bad(pud) (!(pud_val(pud) & 2)) | ||
223 | #define pud_present(pud) (pud_val(pud)) | ||
224 | |||
225 | static inline void set_pud(pud_t *pudp, pud_t pud) | ||
226 | { | ||
227 | *pudp = pud; | ||
228 | dsb(); | ||
229 | } | ||
230 | |||
231 | static inline void pud_clear(pud_t *pudp) | ||
232 | { | ||
233 | set_pud(pudp, __pud(0)); | ||
234 | } | ||
235 | |||
236 | static inline pmd_t *pud_page_vaddr(pud_t pud) | ||
237 | { | ||
238 | return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); | ||
239 | } | ||
240 | |||
241 | #endif /* CONFIG_ARM64_64K_PAGES */ | ||
242 | |||
243 | /* to find an entry in a page-table-directory */ | ||
244 | #define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) | ||
245 | |||
246 | #define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr)) | ||
247 | |||
248 | /* to find an entry in a kernel page-table-directory */ | ||
249 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) | ||
250 | |||
251 | /* Find an entry in the second-level page table.. */ | ||
252 | #ifndef CONFIG_ARM64_64K_PAGES | ||
253 | #define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) | ||
254 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | ||
255 | { | ||
256 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); | ||
257 | } | ||
258 | #endif | ||
259 | |||
260 | /* Find an entry in the third-level page table.. */ | ||
261 | #define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | ||
262 | |||
263 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | ||
264 | { | ||
265 | const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY; | ||
266 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); | ||
267 | return pte; | ||
268 | } | ||
269 | |||
270 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||
271 | extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | ||
272 | |||
273 | #define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) | ||
274 | #define IDMAP_DIR_SIZE (2 * PAGE_SIZE) | ||
275 | |||
276 | /* | ||
277 | * Encode and decode a swap entry: | ||
278 | * bits 0-1: present (must be zero) | ||
279 | * bit 2: PTE_FILE | ||
280 | * bits 3-8: swap type | ||
281 | * bits 9-63: swap offset | ||
282 | */ | ||
283 | #define __SWP_TYPE_SHIFT 3 | ||
284 | #define __SWP_TYPE_BITS 6 | ||
285 | #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) | ||
286 | #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) | ||
287 | |||
288 | #define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) | ||
289 | #define __swp_offset(x) ((x).val >> __SWP_OFFSET_SHIFT) | ||
290 | #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) }) | ||
291 | |||
292 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) | ||
293 | #define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) | ||
294 | |||
295 | /* | ||
296 | * Ensure that there are not more swap files than can be encoded in the kernel | ||
297 | * the PTEs. | ||
298 | */ | ||
299 | #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) | ||
300 | |||
301 | /* | ||
302 | * Encode and decode a file entry: | ||
303 | * bits 0-1: present (must be zero) | ||
304 | * bit 2: PTE_FILE | ||
305 | * bits 3-63: file offset / PAGE_SIZE | ||
306 | */ | ||
307 | #define pte_file(pte) (pte_val(pte) & PTE_FILE) | ||
308 | #define pte_to_pgoff(x) (pte_val(x) >> 3) | ||
309 | #define pgoff_to_pte(x) __pte(((x) << 3) | PTE_FILE) | ||
310 | |||
311 | #define PTE_FILE_MAX_BITS 61 | ||
312 | |||
313 | extern int kern_addr_valid(unsigned long addr); | ||
314 | |||
315 | #include <asm-generic/pgtable.h> | ||
316 | |||
317 | /* | ||
318 | * remap a physical page `pfn' of size `size' with page protection `prot' | ||
319 | * into virtual address `from' | ||
320 | */ | ||
321 | #define io_remap_pfn_range(vma,from,pfn,size,prot) \ | ||
322 | remap_pfn_range(vma, from, pfn, size, prot) | ||
323 | |||
324 | #define pgtable_cache_init() do { } while (0) | ||
325 | |||
326 | #endif /* !__ASSEMBLY__ */ | ||
327 | |||
328 | #endif /* __ASM_PGTABLE_H */ | ||
diff --git a/arch/arm64/include/asm/pmu.h b/arch/arm64/include/asm/pmu.h new file mode 100644 index 000000000000..e6f087806aaf --- /dev/null +++ b/arch/arm64/include/asm/pmu.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/pmu.h | ||
3 | * | ||
4 | * Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_PMU_H | ||
20 | #define __ASM_PMU_H | ||
21 | |||
22 | #ifdef CONFIG_HW_PERF_EVENTS | ||
23 | |||
24 | /* The events for a given PMU register set. */ | ||
25 | struct pmu_hw_events { | ||
26 | /* | ||
27 | * The events that are active on the PMU for the given index. | ||
28 | */ | ||
29 | struct perf_event **events; | ||
30 | |||
31 | /* | ||
32 | * A 1 bit for an index indicates that the counter is being used for | ||
33 | * an event. A 0 means that the counter can be used. | ||
34 | */ | ||
35 | unsigned long *used_mask; | ||
36 | |||
37 | /* | ||
38 | * Hardware lock to serialize accesses to PMU registers. Needed for the | ||
39 | * read/modify/write sequences. | ||
40 | */ | ||
41 | raw_spinlock_t pmu_lock; | ||
42 | }; | ||
43 | |||
44 | struct arm_pmu { | ||
45 | struct pmu pmu; | ||
46 | cpumask_t active_irqs; | ||
47 | const char *name; | ||
48 | irqreturn_t (*handle_irq)(int irq_num, void *dev); | ||
49 | void (*enable)(struct hw_perf_event *evt, int idx); | ||
50 | void (*disable)(struct hw_perf_event *evt, int idx); | ||
51 | int (*get_event_idx)(struct pmu_hw_events *hw_events, | ||
52 | struct hw_perf_event *hwc); | ||
53 | int (*set_event_filter)(struct hw_perf_event *evt, | ||
54 | struct perf_event_attr *attr); | ||
55 | u32 (*read_counter)(int idx); | ||
56 | void (*write_counter)(int idx, u32 val); | ||
57 | void (*start)(void); | ||
58 | void (*stop)(void); | ||
59 | void (*reset)(void *); | ||
60 | int (*map_event)(struct perf_event *event); | ||
61 | int num_events; | ||
62 | atomic_t active_events; | ||
63 | struct mutex reserve_mutex; | ||
64 | u64 max_period; | ||
65 | struct platform_device *plat_device; | ||
66 | struct pmu_hw_events *(*get_hw_events)(void); | ||
67 | }; | ||
68 | |||
69 | #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) | ||
70 | |||
71 | int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type); | ||
72 | |||
73 | u64 armpmu_event_update(struct perf_event *event, | ||
74 | struct hw_perf_event *hwc, | ||
75 | int idx); | ||
76 | |||
77 | int armpmu_event_set_period(struct perf_event *event, | ||
78 | struct hw_perf_event *hwc, | ||
79 | int idx); | ||
80 | |||
81 | #endif /* CONFIG_HW_PERF_EVENTS */ | ||
82 | #endif /* __ASM_PMU_H */ | ||
diff --git a/arch/arm64/include/asm/proc-fns.h b/arch/arm64/include/asm/proc-fns.h new file mode 100644 index 000000000000..7cdf466fd0c5 --- /dev/null +++ b/arch/arm64/include/asm/proc-fns.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/proc-fns.h | ||
3 | * | ||
4 | * Copyright (C) 1997-1999 Russell King | ||
5 | * Copyright (C) 2000 Deep Blue Solutions Ltd | ||
6 | * Copyright (C) 2012 ARM Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | #ifndef __ASM_PROCFNS_H | ||
21 | #define __ASM_PROCFNS_H | ||
22 | |||
23 | #ifdef __KERNEL__ | ||
24 | #ifndef __ASSEMBLY__ | ||
25 | |||
26 | #include <asm/page.h> | ||
27 | |||
28 | struct mm_struct; | ||
29 | |||
30 | extern void cpu_cache_off(void); | ||
31 | extern void cpu_do_idle(void); | ||
32 | extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); | ||
33 | extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); | ||
34 | |||
35 | #include <asm/memory.h> | ||
36 | |||
37 | #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) | ||
38 | |||
39 | #define cpu_get_pgd() \ | ||
40 | ({ \ | ||
41 | unsigned long pg; \ | ||
42 | asm("mrs %0, ttbr0_el1\n" \ | ||
43 | : "=r" (pg)); \ | ||
44 | pg &= ~0xffff000000003ffful; \ | ||
45 | (pgd_t *)phys_to_virt(pg); \ | ||
46 | }) | ||
47 | |||
48 | #endif /* __ASSEMBLY__ */ | ||
49 | #endif /* __KERNEL__ */ | ||
50 | #endif /* __ASM_PROCFNS_H */ | ||
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h new file mode 100644 index 000000000000..39a208a392f7 --- /dev/null +++ b/arch/arm64/include/asm/processor.h | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/processor.h | ||
3 | * | ||
4 | * Copyright (C) 1995-1999 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_PROCESSOR_H | ||
20 | #define __ASM_PROCESSOR_H | ||
21 | |||
22 | /* | ||
23 | * Default implementation of macro that returns current | ||
24 | * instruction pointer ("program counter"). | ||
25 | */ | ||
26 | #define current_text_addr() ({ __label__ _l; _l: &&_l;}) | ||
27 | |||
28 | #ifdef __KERNEL__ | ||
29 | |||
30 | #include <linux/string.h> | ||
31 | |||
32 | #include <asm/fpsimd.h> | ||
33 | #include <asm/hw_breakpoint.h> | ||
34 | #include <asm/ptrace.h> | ||
35 | #include <asm/types.h> | ||
36 | |||
37 | #ifdef __KERNEL__ | ||
38 | #define STACK_TOP_MAX TASK_SIZE_64 | ||
39 | #ifdef CONFIG_COMPAT | ||
40 | #define AARCH32_VECTORS_BASE 0xffff0000 | ||
41 | #define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ | ||
42 | AARCH32_VECTORS_BASE : STACK_TOP_MAX) | ||
43 | #else | ||
44 | #define STACK_TOP STACK_TOP_MAX | ||
45 | #endif /* CONFIG_COMPAT */ | ||
46 | #endif /* __KERNEL__ */ | ||
47 | |||
48 | struct debug_info { | ||
49 | /* Have we suspended stepping by a debugger? */ | ||
50 | int suspended_step; | ||
51 | /* Allow breakpoints and watchpoints to be disabled for this thread. */ | ||
52 | int bps_disabled; | ||
53 | int wps_disabled; | ||
54 | /* Hardware breakpoints pinned to this task. */ | ||
55 | struct perf_event *hbp_break[ARM_MAX_BRP]; | ||
56 | struct perf_event *hbp_watch[ARM_MAX_WRP]; | ||
57 | }; | ||
58 | |||
59 | struct cpu_context { | ||
60 | unsigned long x19; | ||
61 | unsigned long x20; | ||
62 | unsigned long x21; | ||
63 | unsigned long x22; | ||
64 | unsigned long x23; | ||
65 | unsigned long x24; | ||
66 | unsigned long x25; | ||
67 | unsigned long x26; | ||
68 | unsigned long x27; | ||
69 | unsigned long x28; | ||
70 | unsigned long fp; | ||
71 | unsigned long sp; | ||
72 | unsigned long pc; | ||
73 | }; | ||
74 | |||
75 | struct thread_struct { | ||
76 | struct cpu_context cpu_context; /* cpu context */ | ||
77 | unsigned long tp_value; | ||
78 | struct fpsimd_state fpsimd_state; | ||
79 | unsigned long fault_address; /* fault info */ | ||
80 | struct debug_info debug; /* debugging */ | ||
81 | }; | ||
82 | |||
83 | #define INIT_THREAD { } | ||
84 | |||
85 | static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) | ||
86 | { | ||
87 | memset(regs, 0, sizeof(*regs)); | ||
88 | regs->syscallno = ~0UL; | ||
89 | regs->pc = pc; | ||
90 | } | ||
91 | |||
92 | static inline void start_thread(struct pt_regs *regs, unsigned long pc, | ||
93 | unsigned long sp) | ||
94 | { | ||
95 | unsigned long *stack = (unsigned long *)sp; | ||
96 | |||
97 | start_thread_common(regs, pc); | ||
98 | regs->pstate = PSR_MODE_EL0t; | ||
99 | regs->sp = sp; | ||
100 | regs->regs[2] = stack[2]; /* x2 (envp) */ | ||
101 | regs->regs[1] = stack[1]; /* x1 (argv) */ | ||
102 | regs->regs[0] = stack[0]; /* x0 (argc) */ | ||
103 | } | ||
104 | |||
105 | #ifdef CONFIG_COMPAT | ||
106 | static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc, | ||
107 | unsigned long sp) | ||
108 | { | ||
109 | unsigned int *stack = (unsigned int *)sp; | ||
110 | |||
111 | start_thread_common(regs, pc); | ||
112 | regs->pstate = COMPAT_PSR_MODE_USR; | ||
113 | if (pc & 1) | ||
114 | regs->pstate |= COMPAT_PSR_T_BIT; | ||
115 | regs->compat_sp = sp; | ||
116 | regs->regs[2] = stack[2]; /* x2 (envp) */ | ||
117 | regs->regs[1] = stack[1]; /* x1 (argv) */ | ||
118 | regs->regs[0] = stack[0]; /* x0 (argc) */ | ||
119 | } | ||
120 | #endif | ||
121 | |||
122 | /* Forward declaration, a strange C thing */ | ||
123 | struct task_struct; | ||
124 | |||
125 | /* Free all resources held by a thread. */ | ||
126 | extern void release_thread(struct task_struct *); | ||
127 | |||
128 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
129 | #define prepare_to_copy(tsk) do { } while (0) | ||
130 | |||
131 | unsigned long get_wchan(struct task_struct *p); | ||
132 | |||
133 | #define cpu_relax() barrier() | ||
134 | |||
135 | /* Thread switching */ | ||
136 | extern struct task_struct *cpu_switch_to(struct task_struct *prev, | ||
137 | struct task_struct *next); | ||
138 | |||
139 | /* | ||
140 | * Create a new kernel thread | ||
141 | */ | ||
142 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
143 | |||
144 | #define task_pt_regs(p) \ | ||
145 | ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) | ||
146 | |||
147 | #define KSTK_EIP(tsk) task_pt_regs(tsk)->pc | ||
148 | #define KSTK_ESP(tsk) task_pt_regs(tsk)->sp | ||
149 | |||
150 | /* | ||
151 | * Prefetching support | ||
152 | */ | ||
153 | #define ARCH_HAS_PREFETCH | ||
154 | static inline void prefetch(const void *ptr) | ||
155 | { | ||
156 | asm volatile("prfm pldl1keep, %a0\n" : : "p" (ptr)); | ||
157 | } | ||
158 | |||
159 | #define ARCH_HAS_PREFETCHW | ||
160 | static inline void prefetchw(const void *ptr) | ||
161 | { | ||
162 | asm volatile("prfm pstl1keep, %a0\n" : : "p" (ptr)); | ||
163 | } | ||
164 | |||
165 | #define ARCH_HAS_SPINLOCK_PREFETCH | ||
166 | static inline void spin_lock_prefetch(const void *x) | ||
167 | { | ||
168 | prefetchw(x); | ||
169 | } | ||
170 | |||
171 | #define HAVE_ARCH_PICK_MMAP_LAYOUT | ||
172 | |||
173 | #endif | ||
174 | |||
175 | #endif /* __ASM_PROCESSOR_H */ | ||
diff --git a/arch/arm64/include/asm/prom.h b/arch/arm64/include/asm/prom.h new file mode 100644 index 000000000000..68b90e682957 --- /dev/null +++ b/arch/arm64/include/asm/prom.h | |||
@@ -0,0 +1 @@ | |||
/* Empty for now */ | |||
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h new file mode 100644 index 000000000000..0fa5d6c9ef76 --- /dev/null +++ b/arch/arm64/include/asm/ptrace.h | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/ptrace.h | ||
3 | * | ||
4 | * Copyright (C) 1996-2003 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_PTRACE_H | ||
20 | #define __ASM_PTRACE_H | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | |||
24 | #include <asm/hwcap.h> | ||
25 | |||
26 | /* AArch32-specific ptrace requests */ | ||
27 | #define COMPAT_PTRACE_GETREGS 12 | ||
28 | #define COMPAT_PTRACE_SETREGS 13 | ||
29 | #define COMPAT_PTRACE_GET_THREAD_AREA 22 | ||
30 | #define COMPAT_PTRACE_SET_SYSCALL 23 | ||
31 | #define COMPAT_PTRACE_GETVFPREGS 27 | ||
32 | #define COMPAT_PTRACE_SETVFPREGS 28 | ||
33 | #define COMPAT_PTRACE_GETHBPREGS 29 | ||
34 | #define COMPAT_PTRACE_SETHBPREGS 30 | ||
35 | |||
36 | /* | ||
37 | * PSR bits | ||
38 | */ | ||
39 | #define PSR_MODE_EL0t 0x00000000 | ||
40 | #define PSR_MODE_EL1t 0x00000004 | ||
41 | #define PSR_MODE_EL1h 0x00000005 | ||
42 | #define PSR_MODE_EL2t 0x00000008 | ||
43 | #define PSR_MODE_EL2h 0x00000009 | ||
44 | #define PSR_MODE_EL3t 0x0000000c | ||
45 | #define PSR_MODE_EL3h 0x0000000d | ||
46 | #define PSR_MODE_MASK 0x0000000f | ||
47 | |||
48 | /* AArch32 CPSR bits */ | ||
49 | #define PSR_MODE32_BIT 0x00000010 | ||
50 | #define COMPAT_PSR_MODE_USR 0x00000010 | ||
51 | #define COMPAT_PSR_T_BIT 0x00000020 | ||
52 | #define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ | ||
53 | |||
54 | /* AArch64 SPSR bits */ | ||
55 | #define PSR_F_BIT 0x00000040 | ||
56 | #define PSR_I_BIT 0x00000080 | ||
57 | #define PSR_A_BIT 0x00000100 | ||
58 | #define PSR_D_BIT 0x00000200 | ||
59 | #define PSR_Q_BIT 0x08000000 | ||
60 | #define PSR_V_BIT 0x10000000 | ||
61 | #define PSR_C_BIT 0x20000000 | ||
62 | #define PSR_Z_BIT 0x40000000 | ||
63 | #define PSR_N_BIT 0x80000000 | ||
64 | |||
65 | /* | ||
66 | * Groups of PSR bits | ||
67 | */ | ||
68 | #define PSR_f 0xff000000 /* Flags */ | ||
69 | #define PSR_s 0x00ff0000 /* Status */ | ||
70 | #define PSR_x 0x0000ff00 /* Extension */ | ||
71 | #define PSR_c 0x000000ff /* Control */ | ||
72 | |||
73 | /* | ||
74 | * These are 'magic' values for PTRACE_PEEKUSR that return info about where a | ||
75 | * process is located in memory. | ||
76 | */ | ||
77 | #define PT_TEXT_ADDR 0x10000 | ||
78 | #define PT_DATA_ADDR 0x10004 | ||
79 | #define PT_TEXT_END_ADDR 0x10008 | ||
80 | |||
81 | #ifndef __ASSEMBLY__ | ||
82 | |||
83 | /* | ||
84 | * User structures for general purpose, floating point and debug registers. | ||
85 | */ | ||
86 | struct user_pt_regs { | ||
87 | __u64 regs[31]; | ||
88 | __u64 sp; | ||
89 | __u64 pc; | ||
90 | __u64 pstate; | ||
91 | }; | ||
92 | |||
93 | struct user_fpsimd_state { | ||
94 | __uint128_t vregs[32]; | ||
95 | __u32 fpsr; | ||
96 | __u32 fpcr; | ||
97 | }; | ||
98 | |||
99 | struct user_hwdebug_state { | ||
100 | __u32 dbg_info; | ||
101 | struct { | ||
102 | __u64 addr; | ||
103 | __u32 ctrl; | ||
104 | } dbg_regs[16]; | ||
105 | }; | ||
106 | |||
107 | #ifdef __KERNEL__ | ||
108 | |||
109 | /* sizeof(struct user) for AArch32 */ | ||
110 | #define COMPAT_USER_SZ 296 | ||
111 | /* AArch32 uses x13 as the stack pointer... */ | ||
112 | #define compat_sp regs[13] | ||
113 | /* ... and x14 as the link register. */ | ||
114 | #define compat_lr regs[14] | ||
115 | |||
116 | /* | ||
117 | * This struct defines the way the registers are stored on the stack during an | ||
118 | * exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for | ||
119 | * stack alignment). struct user_pt_regs must form a prefix of struct pt_regs. | ||
120 | */ | ||
121 | struct pt_regs { | ||
122 | union { | ||
123 | struct user_pt_regs user_regs; | ||
124 | struct { | ||
125 | u64 regs[31]; | ||
126 | u64 sp; | ||
127 | u64 pc; | ||
128 | u64 pstate; | ||
129 | }; | ||
130 | }; | ||
131 | u64 orig_x0; | ||
132 | u64 syscallno; | ||
133 | }; | ||
134 | |||
135 | #define arch_has_single_step() (1) | ||
136 | |||
137 | #ifdef CONFIG_COMPAT | ||
138 | #define compat_thumb_mode(regs) \ | ||
139 | (((regs)->pstate & COMPAT_PSR_T_BIT)) | ||
140 | #else | ||
141 | #define compat_thumb_mode(regs) (0) | ||
142 | #endif | ||
143 | |||
144 | #define user_mode(regs) \ | ||
145 | (((regs)->pstate & PSR_MODE_MASK) == PSR_MODE_EL0t) | ||
146 | |||
147 | #define compat_user_mode(regs) \ | ||
148 | (((regs)->pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) == \ | ||
149 | (PSR_MODE32_BIT | PSR_MODE_EL0t)) | ||
150 | |||
151 | #define processor_mode(regs) \ | ||
152 | ((regs)->pstate & PSR_MODE_MASK) | ||
153 | |||
154 | #define interrupts_enabled(regs) \ | ||
155 | (!((regs)->pstate & PSR_I_BIT)) | ||
156 | |||
157 | #define fast_interrupts_enabled(regs) \ | ||
158 | (!((regs)->pstate & PSR_F_BIT)) | ||
159 | |||
160 | #define user_stack_pointer(regs) \ | ||
161 | ((regs)->sp) | ||
162 | |||
163 | /* | ||
164 | * Are the current registers suitable for user mode? (used to maintain | ||
165 | * security in signal handlers) | ||
166 | */ | ||
167 | static inline int valid_user_regs(struct user_pt_regs *regs) | ||
168 | { | ||
169 | if (user_mode(regs) && (regs->pstate & PSR_I_BIT) == 0) { | ||
170 | regs->pstate &= ~(PSR_F_BIT | PSR_A_BIT); | ||
171 | |||
172 | /* The T bit is reserved for AArch64 */ | ||
173 | if (!(regs->pstate & PSR_MODE32_BIT)) | ||
174 | regs->pstate &= ~COMPAT_PSR_T_BIT; | ||
175 | |||
176 | return 1; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Force PSR to something logical... | ||
181 | */ | ||
182 | regs->pstate &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | \ | ||
183 | COMPAT_PSR_T_BIT | PSR_MODE32_BIT; | ||
184 | |||
185 | if (!(regs->pstate & PSR_MODE32_BIT)) { | ||
186 | regs->pstate &= ~COMPAT_PSR_T_BIT; | ||
187 | regs->pstate |= PSR_MODE_EL0t; | ||
188 | } | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | #define instruction_pointer(regs) (regs)->pc | ||
194 | |||
195 | #ifdef CONFIG_SMP | ||
196 | extern unsigned long profile_pc(struct pt_regs *regs); | ||
197 | #else | ||
198 | #define profile_pc(regs) instruction_pointer(regs) | ||
199 | #endif | ||
200 | |||
201 | extern int aarch32_break_trap(struct pt_regs *regs); | ||
202 | |||
203 | #endif /* __KERNEL__ */ | ||
204 | |||
205 | #endif /* __ASSEMBLY__ */ | ||
206 | |||
207 | #endif | ||
diff --git a/arch/arm64/include/asm/setup.h b/arch/arm64/include/asm/setup.h new file mode 100644 index 000000000000..9cf2e46fbbdf --- /dev/null +++ b/arch/arm64/include/asm/setup.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/setup.h | ||
3 | * | ||
4 | * Copyright (C) 1997-1999 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_SETUP_H | ||
20 | #define __ASM_SETUP_H | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | |||
24 | #define COMMAND_LINE_SIZE 2048 | ||
25 | |||
26 | #endif | ||
diff --git a/arch/arm64/include/asm/shmparam.h b/arch/arm64/include/asm/shmparam.h new file mode 100644 index 000000000000..4df608a8459e --- /dev/null +++ b/arch/arm64/include/asm/shmparam.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SHMPARAM_H | ||
17 | #define __ASM_SHMPARAM_H | ||
18 | |||
19 | /* | ||
20 | * For IPC syscalls from compat tasks, we need to use the legacy 16k | ||
21 | * alignment value. Since we don't have aliasing D-caches, the rest of | ||
22 | * the time we can safely use PAGE_SIZE. | ||
23 | */ | ||
24 | #define COMPAT_SHMLBA 0x4000 | ||
25 | |||
26 | #include <asm-generic/shmparam.h> | ||
27 | |||
28 | #endif /* __ASM_SHMPARAM_H */ | ||
diff --git a/arch/arm64/include/asm/sigcontext.h b/arch/arm64/include/asm/sigcontext.h new file mode 100644 index 000000000000..573cec778819 --- /dev/null +++ b/arch/arm64/include/asm/sigcontext.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SIGCONTEXT_H | ||
17 | #define __ASM_SIGCONTEXT_H | ||
18 | |||
19 | #include <linux/types.h> | ||
20 | |||
21 | /* | ||
22 | * Signal context structure - contains all info to do with the state | ||
23 | * before the signal handler was invoked. | ||
24 | */ | ||
25 | struct sigcontext { | ||
26 | __u64 fault_address; | ||
27 | /* AArch64 registers */ | ||
28 | __u64 regs[31]; | ||
29 | __u64 sp; | ||
30 | __u64 pc; | ||
31 | __u64 pstate; | ||
32 | /* 4K reserved for FP/SIMD state and future expansion */ | ||
33 | __u8 __reserved[4096] __attribute__((__aligned__(16))); | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * Header to be used at the beginning of structures extending the user | ||
38 | * context. Such structures must be placed after the rt_sigframe on the stack | ||
39 | * and be 16-byte aligned. The last structure must be a dummy one with the | ||
40 | * magic and size set to 0. | ||
41 | */ | ||
42 | struct _aarch64_ctx { | ||
43 | __u32 magic; | ||
44 | __u32 size; | ||
45 | }; | ||
46 | |||
47 | #define FPSIMD_MAGIC 0x46508001 | ||
48 | |||
49 | struct fpsimd_context { | ||
50 | struct _aarch64_ctx head; | ||
51 | __u32 fpsr; | ||
52 | __u32 fpcr; | ||
53 | __uint128_t vregs[32]; | ||
54 | }; | ||
55 | |||
56 | #ifdef __KERNEL__ | ||
57 | /* | ||
58 | * Auxiliary context saved in the sigcontext.__reserved array. Not exported to | ||
59 | * user space as it will change with the addition of new context. User space | ||
60 | * should check the magic/size information. | ||
61 | */ | ||
62 | struct aux_context { | ||
63 | struct fpsimd_context fpsimd; | ||
64 | /* additional context to be added before "end" */ | ||
65 | struct _aarch64_ctx end; | ||
66 | }; | ||
67 | #endif | ||
68 | |||
69 | #endif | ||
diff --git a/arch/arm64/include/asm/siginfo.h b/arch/arm64/include/asm/siginfo.h new file mode 100644 index 000000000000..5a74a0853db0 --- /dev/null +++ b/arch/arm64/include/asm/siginfo.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SIGINFO_H | ||
17 | #define __ASM_SIGINFO_H | ||
18 | |||
19 | #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) | ||
20 | |||
21 | #include <asm-generic/siginfo.h> | ||
22 | |||
23 | #endif | ||
diff --git a/arch/arm64/include/asm/signal.h b/arch/arm64/include/asm/signal.h new file mode 100644 index 000000000000..8d1e7236431b --- /dev/null +++ b/arch/arm64/include/asm/signal.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SIGNAL_H | ||
17 | #define __ASM_SIGNAL_H | ||
18 | |||
19 | /* Required for AArch32 compatibility. */ | ||
20 | #define SA_RESTORER 0x04000000 | ||
21 | |||
22 | #include <asm-generic/signal.h> | ||
23 | |||
24 | #endif | ||
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h new file mode 100644 index 000000000000..7c275e3b640f --- /dev/null +++ b/arch/arm64/include/asm/signal32.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SIGNAL32_H | ||
17 | #define __ASM_SIGNAL32_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | #ifdef CONFIG_COMPAT | ||
21 | #include <linux/compat.h> | ||
22 | |||
23 | #define AARCH32_KERN_SIGRET_CODE_OFFSET 0x500 | ||
24 | |||
25 | extern const compat_ulong_t aarch32_sigret_code[6]; | ||
26 | |||
27 | int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, | ||
28 | struct pt_regs *regs); | ||
29 | int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | ||
30 | sigset_t *set, struct pt_regs *regs); | ||
31 | |||
32 | void compat_setup_restart_syscall(struct pt_regs *regs); | ||
33 | #else | ||
34 | |||
35 | static inline int compat_setup_frame(int usid, struct k_sigaction *ka, | ||
36 | sigset_t *set, struct pt_regs *regs) | ||
37 | { | ||
38 | return -ENOSYS; | ||
39 | } | ||
40 | |||
41 | static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka, | ||
42 | siginfo_t *info, sigset_t *set, | ||
43 | struct pt_regs *regs) | ||
44 | { | ||
45 | return -ENOSYS; | ||
46 | } | ||
47 | |||
48 | static inline void compat_setup_restart_syscall(struct pt_regs *regs) | ||
49 | { | ||
50 | } | ||
51 | #endif /* CONFIG_COMPAT */ | ||
52 | #endif /* __KERNEL__ */ | ||
53 | #endif /* __ASM_SIGNAL32_H */ | ||
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h new file mode 100644 index 000000000000..7e34295f78e3 --- /dev/null +++ b/arch/arm64/include/asm/smp.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SMP_H | ||
17 | #define __ASM_SMP_H | ||
18 | |||
19 | #include <linux/threads.h> | ||
20 | #include <linux/cpumask.h> | ||
21 | #include <linux/thread_info.h> | ||
22 | |||
23 | #ifndef CONFIG_SMP | ||
24 | # error "<asm/smp.h> included in non-SMP build" | ||
25 | #endif | ||
26 | |||
27 | #define raw_smp_processor_id() (current_thread_info()->cpu) | ||
28 | |||
29 | struct seq_file; | ||
30 | |||
31 | /* | ||
32 | * generate IPI list text | ||
33 | */ | ||
34 | extern void show_ipi_list(struct seq_file *p, int prec); | ||
35 | |||
36 | /* | ||
37 | * Called from C code, this handles an IPI. | ||
38 | */ | ||
39 | extern void handle_IPI(int ipinr, struct pt_regs *regs); | ||
40 | |||
41 | /* | ||
42 | * Setup the set of possible CPUs (via set_cpu_possible) | ||
43 | */ | ||
44 | extern void smp_init_cpus(void); | ||
45 | |||
46 | /* | ||
47 | * Provide a function to raise an IPI cross call on CPUs in callmap. | ||
48 | */ | ||
49 | extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int)); | ||
50 | |||
51 | /* | ||
52 | * Called from the secondary holding pen, this is the secondary CPU entry point. | ||
53 | */ | ||
54 | asmlinkage void secondary_start_kernel(void); | ||
55 | |||
56 | /* | ||
57 | * Initial data for bringing up a secondary CPU. | ||
58 | */ | ||
59 | struct secondary_data { | ||
60 | void *stack; | ||
61 | }; | ||
62 | extern struct secondary_data secondary_data; | ||
63 | extern void secondary_holding_pen(void); | ||
64 | extern volatile unsigned long secondary_holding_pen_release; | ||
65 | |||
66 | extern void arch_send_call_function_single_ipi(int cpu); | ||
67 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | ||
68 | |||
69 | #endif /* ifndef __ASM_SMP_H */ | ||
diff --git a/arch/arm64/include/asm/sparsemem.h b/arch/arm64/include/asm/sparsemem.h new file mode 100644 index 000000000000..1be62bcb9d47 --- /dev/null +++ b/arch/arm64/include/asm/sparsemem.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SPARSEMEM_H | ||
17 | #define __ASM_SPARSEMEM_H | ||
18 | |||
19 | #ifdef CONFIG_SPARSEMEM | ||
20 | #define MAX_PHYSMEM_BITS 40 | ||
21 | #define SECTION_SIZE_BITS 30 | ||
22 | #endif | ||
23 | |||
24 | #endif | ||
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h new file mode 100644 index 000000000000..41112fe2f8b1 --- /dev/null +++ b/arch/arm64/include/asm/spinlock.h | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SPINLOCK_H | ||
17 | #define __ASM_SPINLOCK_H | ||
18 | |||
19 | #include <asm/spinlock_types.h> | ||
20 | #include <asm/processor.h> | ||
21 | |||
22 | /* | ||
23 | * Spinlock implementation. | ||
24 | * | ||
25 | * The old value is read exclusively and the new one, if unlocked, is written | ||
26 | * exclusively. In case of failure, the loop is restarted. | ||
27 | * | ||
28 | * The memory barriers are implicit with the load-acquire and store-release | ||
29 | * instructions. | ||
30 | * | ||
31 | * Unlocked value: 0 | ||
32 | * Locked value: 1 | ||
33 | */ | ||
34 | |||
35 | #define arch_spin_is_locked(x) ((x)->lock != 0) | ||
36 | #define arch_spin_unlock_wait(lock) \ | ||
37 | do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0) | ||
38 | |||
39 | #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) | ||
40 | |||
41 | static inline void arch_spin_lock(arch_spinlock_t *lock) | ||
42 | { | ||
43 | unsigned int tmp; | ||
44 | |||
45 | asm volatile( | ||
46 | " sevl\n" | ||
47 | "1: wfe\n" | ||
48 | "2: ldaxr %w0, [%1]\n" | ||
49 | " cbnz %w0, 1b\n" | ||
50 | " stxr %w0, %w2, [%1]\n" | ||
51 | " cbnz %w0, 2b\n" | ||
52 | : "=&r" (tmp) | ||
53 | : "r" (&lock->lock), "r" (1) | ||
54 | : "memory"); | ||
55 | } | ||
56 | |||
57 | static inline int arch_spin_trylock(arch_spinlock_t *lock) | ||
58 | { | ||
59 | unsigned int tmp; | ||
60 | |||
61 | asm volatile( | ||
62 | " ldaxr %w0, [%1]\n" | ||
63 | " cbnz %w0, 1f\n" | ||
64 | " stxr %w0, %w2, [%1]\n" | ||
65 | "1:\n" | ||
66 | : "=&r" (tmp) | ||
67 | : "r" (&lock->lock), "r" (1) | ||
68 | : "memory"); | ||
69 | |||
70 | return !tmp; | ||
71 | } | ||
72 | |||
73 | static inline void arch_spin_unlock(arch_spinlock_t *lock) | ||
74 | { | ||
75 | asm volatile( | ||
76 | " stlr %w1, [%0]\n" | ||
77 | : : "r" (&lock->lock), "r" (0) : "memory"); | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Write lock implementation. | ||
82 | * | ||
83 | * Write locks set bit 31. Unlocking, is done by writing 0 since the lock is | ||
84 | * exclusively held. | ||
85 | * | ||
86 | * The memory barriers are implicit with the load-acquire and store-release | ||
87 | * instructions. | ||
88 | */ | ||
89 | |||
90 | static inline void arch_write_lock(arch_rwlock_t *rw) | ||
91 | { | ||
92 | unsigned int tmp; | ||
93 | |||
94 | asm volatile( | ||
95 | " sevl\n" | ||
96 | "1: wfe\n" | ||
97 | "2: ldaxr %w0, [%1]\n" | ||
98 | " cbnz %w0, 1b\n" | ||
99 | " stxr %w0, %w2, [%1]\n" | ||
100 | " cbnz %w0, 2b\n" | ||
101 | : "=&r" (tmp) | ||
102 | : "r" (&rw->lock), "r" (0x80000000) | ||
103 | : "memory"); | ||
104 | } | ||
105 | |||
106 | static inline int arch_write_trylock(arch_rwlock_t *rw) | ||
107 | { | ||
108 | unsigned int tmp; | ||
109 | |||
110 | asm volatile( | ||
111 | " ldaxr %w0, [%1]\n" | ||
112 | " cbnz %w0, 1f\n" | ||
113 | " stxr %w0, %w2, [%1]\n" | ||
114 | "1:\n" | ||
115 | : "=&r" (tmp) | ||
116 | : "r" (&rw->lock), "r" (0x80000000) | ||
117 | : "memory"); | ||
118 | |||
119 | return !tmp; | ||
120 | } | ||
121 | |||
122 | static inline void arch_write_unlock(arch_rwlock_t *rw) | ||
123 | { | ||
124 | asm volatile( | ||
125 | " stlr %w1, [%0]\n" | ||
126 | : : "r" (&rw->lock), "r" (0) : "memory"); | ||
127 | } | ||
128 | |||
129 | /* write_can_lock - would write_trylock() succeed? */ | ||
130 | #define arch_write_can_lock(x) ((x)->lock == 0) | ||
131 | |||
132 | /* | ||
133 | * Read lock implementation. | ||
134 | * | ||
135 | * It exclusively loads the lock value, increments it and stores the new value | ||
136 | * back if positive and the CPU still exclusively owns the location. If the | ||
137 | * value is negative, the lock is already held. | ||
138 | * | ||
139 | * During unlocking there may be multiple active read locks but no write lock. | ||
140 | * | ||
141 | * The memory barriers are implicit with the load-acquire and store-release | ||
142 | * instructions. | ||
143 | */ | ||
144 | static inline void arch_read_lock(arch_rwlock_t *rw) | ||
145 | { | ||
146 | unsigned int tmp, tmp2; | ||
147 | |||
148 | asm volatile( | ||
149 | " sevl\n" | ||
150 | "1: wfe\n" | ||
151 | "2: ldaxr %w0, [%2]\n" | ||
152 | " add %w0, %w0, #1\n" | ||
153 | " tbnz %w0, #31, 1b\n" | ||
154 | " stxr %w1, %w0, [%2]\n" | ||
155 | " cbnz %w1, 2b\n" | ||
156 | : "=&r" (tmp), "=&r" (tmp2) | ||
157 | : "r" (&rw->lock) | ||
158 | : "memory"); | ||
159 | } | ||
160 | |||
161 | static inline void arch_read_unlock(arch_rwlock_t *rw) | ||
162 | { | ||
163 | unsigned int tmp, tmp2; | ||
164 | |||
165 | asm volatile( | ||
166 | "1: ldxr %w0, [%2]\n" | ||
167 | " sub %w0, %w0, #1\n" | ||
168 | " stlxr %w1, %w0, [%2]\n" | ||
169 | " cbnz %w1, 1b\n" | ||
170 | : "=&r" (tmp), "=&r" (tmp2) | ||
171 | : "r" (&rw->lock) | ||
172 | : "memory"); | ||
173 | } | ||
174 | |||
175 | static inline int arch_read_trylock(arch_rwlock_t *rw) | ||
176 | { | ||
177 | unsigned int tmp, tmp2 = 1; | ||
178 | |||
179 | asm volatile( | ||
180 | " ldaxr %w0, [%2]\n" | ||
181 | " add %w0, %w0, #1\n" | ||
182 | " tbnz %w0, #31, 1f\n" | ||
183 | " stxr %w1, %w0, [%2]\n" | ||
184 | "1:\n" | ||
185 | : "=&r" (tmp), "+r" (tmp2) | ||
186 | : "r" (&rw->lock) | ||
187 | : "memory"); | ||
188 | |||
189 | return !tmp2; | ||
190 | } | ||
191 | |||
192 | /* read_can_lock - would read_trylock() succeed? */ | ||
193 | #define arch_read_can_lock(x) ((x)->lock < 0x80000000) | ||
194 | |||
195 | #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) | ||
196 | #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) | ||
197 | |||
198 | #define arch_spin_relax(lock) cpu_relax() | ||
199 | #define arch_read_relax(lock) cpu_relax() | ||
200 | #define arch_write_relax(lock) cpu_relax() | ||
201 | |||
202 | #endif /* __ASM_SPINLOCK_H */ | ||
diff --git a/arch/arm64/include/asm/spinlock_types.h b/arch/arm64/include/asm/spinlock_types.h new file mode 100644 index 000000000000..9a494346efed --- /dev/null +++ b/arch/arm64/include/asm/spinlock_types.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SPINLOCK_TYPES_H | ||
17 | #define __ASM_SPINLOCK_TYPES_H | ||
18 | |||
19 | #if !defined(__LINUX_SPINLOCK_TYPES_H) && !defined(__ASM_SPINLOCK_H) | ||
20 | # error "please don't include this file directly" | ||
21 | #endif | ||
22 | |||
23 | /* We only require natural alignment for exclusive accesses. */ | ||
24 | #define __lock_aligned | ||
25 | |||
26 | typedef struct { | ||
27 | volatile unsigned int lock; | ||
28 | } arch_spinlock_t; | ||
29 | |||
30 | #define __ARCH_SPIN_LOCK_UNLOCKED { 0 } | ||
31 | |||
32 | typedef struct { | ||
33 | volatile unsigned int lock; | ||
34 | } arch_rwlock_t; | ||
35 | |||
36 | #define __ARCH_RW_LOCK_UNLOCKED { 0 } | ||
37 | |||
38 | #endif | ||
diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h new file mode 100644 index 000000000000..7318f6d54aa9 --- /dev/null +++ b/arch/arm64/include/asm/stacktrace.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_STACKTRACE_H | ||
17 | #define __ASM_STACKTRACE_H | ||
18 | |||
19 | struct stackframe { | ||
20 | unsigned long fp; | ||
21 | unsigned long sp; | ||
22 | unsigned long pc; | ||
23 | }; | ||
24 | |||
25 | extern int unwind_frame(struct stackframe *frame); | ||
26 | extern void walk_stackframe(struct stackframe *frame, | ||
27 | int (*fn)(struct stackframe *, void *), void *data); | ||
28 | |||
29 | #endif /* __ASM_STACKTRACE_H */ | ||
diff --git a/arch/arm64/include/asm/stat.h b/arch/arm64/include/asm/stat.h new file mode 100644 index 000000000000..d87225cbead8 --- /dev/null +++ b/arch/arm64/include/asm/stat.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_STAT_H | ||
17 | #define __ASM_STAT_H | ||
18 | |||
19 | #include <asm-generic/stat.h> | ||
20 | |||
21 | #if defined(__KERNEL__) && defined(CONFIG_COMPAT) | ||
22 | |||
23 | #include <asm/compat.h> | ||
24 | |||
25 | /* | ||
26 | * struct stat64 is needed for compat tasks only. Its definition is different | ||
27 | * from the generic struct stat64. | ||
28 | */ | ||
29 | struct stat64 { | ||
30 | compat_u64 st_dev; | ||
31 | unsigned char __pad0[4]; | ||
32 | |||
33 | #define STAT64_HAS_BROKEN_ST_INO 1 | ||
34 | compat_ulong_t __st_ino; | ||
35 | compat_uint_t st_mode; | ||
36 | compat_uint_t st_nlink; | ||
37 | |||
38 | compat_ulong_t st_uid; | ||
39 | compat_ulong_t st_gid; | ||
40 | |||
41 | compat_u64 st_rdev; | ||
42 | unsigned char __pad3[4]; | ||
43 | |||
44 | compat_s64 st_size; | ||
45 | compat_ulong_t st_blksize; | ||
46 | compat_u64 st_blocks; /* Number of 512-byte blocks allocated. */ | ||
47 | |||
48 | compat_ulong_t st_atime; | ||
49 | compat_ulong_t st_atime_nsec; | ||
50 | |||
51 | compat_ulong_t st_mtime; | ||
52 | compat_ulong_t st_mtime_nsec; | ||
53 | |||
54 | compat_ulong_t st_ctime; | ||
55 | compat_ulong_t st_ctime_nsec; | ||
56 | |||
57 | compat_u64 st_ino; | ||
58 | }; | ||
59 | |||
60 | #endif | ||
61 | |||
62 | #endif | ||
diff --git a/arch/arm64/include/asm/statfs.h b/arch/arm64/include/asm/statfs.h new file mode 100644 index 000000000000..6f6219050978 --- /dev/null +++ b/arch/arm64/include/asm/statfs.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_STATFS_H | ||
17 | #define __ASM_STATFS_H | ||
18 | |||
19 | #define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4))) | ||
20 | |||
21 | #include <asm-generic/statfs.h> | ||
22 | |||
23 | #endif | ||
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h new file mode 100644 index 000000000000..89c047f9a971 --- /dev/null +++ b/arch/arm64/include/asm/syscall.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SYSCALL_H | ||
17 | #define __ASM_SYSCALL_H | ||
18 | |||
19 | #include <linux/err.h> | ||
20 | |||
21 | |||
22 | static inline int syscall_get_nr(struct task_struct *task, | ||
23 | struct pt_regs *regs) | ||
24 | { | ||
25 | return regs->syscallno; | ||
26 | } | ||
27 | |||
28 | static inline void syscall_rollback(struct task_struct *task, | ||
29 | struct pt_regs *regs) | ||
30 | { | ||
31 | regs->regs[0] = regs->orig_x0; | ||
32 | } | ||
33 | |||
34 | |||
35 | static inline long syscall_get_error(struct task_struct *task, | ||
36 | struct pt_regs *regs) | ||
37 | { | ||
38 | unsigned long error = regs->regs[0]; | ||
39 | return IS_ERR_VALUE(error) ? error : 0; | ||
40 | } | ||
41 | |||
42 | static inline long syscall_get_return_value(struct task_struct *task, | ||
43 | struct pt_regs *regs) | ||
44 | { | ||
45 | return regs->regs[0]; | ||
46 | } | ||
47 | |||
48 | static inline void syscall_set_return_value(struct task_struct *task, | ||
49 | struct pt_regs *regs, | ||
50 | int error, long val) | ||
51 | { | ||
52 | regs->regs[0] = (long) error ? error : val; | ||
53 | } | ||
54 | |||
55 | #define SYSCALL_MAX_ARGS 6 | ||
56 | |||
57 | static inline void syscall_get_arguments(struct task_struct *task, | ||
58 | struct pt_regs *regs, | ||
59 | unsigned int i, unsigned int n, | ||
60 | unsigned long *args) | ||
61 | { | ||
62 | if (i + n > SYSCALL_MAX_ARGS) { | ||
63 | unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i; | ||
64 | unsigned int n_bad = n + i - SYSCALL_MAX_ARGS; | ||
65 | pr_warning("%s called with max args %d, handling only %d\n", | ||
66 | __func__, i + n, SYSCALL_MAX_ARGS); | ||
67 | memset(args_bad, 0, n_bad * sizeof(args[0])); | ||
68 | } | ||
69 | |||
70 | if (i == 0) { | ||
71 | args[0] = regs->orig_x0; | ||
72 | args++; | ||
73 | i++; | ||
74 | n--; | ||
75 | } | ||
76 | |||
77 | memcpy(args, ®s->regs[i], n * sizeof(args[0])); | ||
78 | } | ||
79 | |||
80 | static inline void syscall_set_arguments(struct task_struct *task, | ||
81 | struct pt_regs *regs, | ||
82 | unsigned int i, unsigned int n, | ||
83 | const unsigned long *args) | ||
84 | { | ||
85 | if (i + n > SYSCALL_MAX_ARGS) { | ||
86 | pr_warning("%s called with max args %d, handling only %d\n", | ||
87 | __func__, i + n, SYSCALL_MAX_ARGS); | ||
88 | n = SYSCALL_MAX_ARGS - i; | ||
89 | } | ||
90 | |||
91 | if (i == 0) { | ||
92 | regs->orig_x0 = args[0]; | ||
93 | args++; | ||
94 | i++; | ||
95 | n--; | ||
96 | } | ||
97 | |||
98 | memcpy(®s->regs[i], args, n * sizeof(args[0])); | ||
99 | } | ||
100 | |||
101 | #endif /* __ASM_SYSCALL_H */ | ||
diff --git a/arch/arm64/include/asm/syscalls.h b/arch/arm64/include/asm/syscalls.h new file mode 100644 index 000000000000..09ff33572aab --- /dev/null +++ b/arch/arm64/include/asm/syscalls.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_SYSCALLS_H | ||
17 | #define __ASM_SYSCALLS_H | ||
18 | |||
19 | #include <linux/linkage.h> | ||
20 | #include <linux/compiler.h> | ||
21 | #include <linux/signal.h> | ||
22 | |||
23 | /* | ||
24 | * System call wrappers implemented in kernel/entry.S. | ||
25 | */ | ||
26 | asmlinkage long sys_execve_wrapper(const char __user *filename, | ||
27 | const char __user *const __user *argv, | ||
28 | const char __user *const __user *envp); | ||
29 | asmlinkage long sys_clone_wrapper(unsigned long clone_flags, | ||
30 | unsigned long newsp, | ||
31 | void __user *parent_tid, | ||
32 | unsigned long tls_val, | ||
33 | void __user *child_tid); | ||
34 | asmlinkage long sys_rt_sigreturn_wrapper(void); | ||
35 | asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss, | ||
36 | stack_t __user *uoss); | ||
37 | |||
38 | #include <asm-generic/syscalls.h> | ||
39 | |||
40 | #endif /* __ASM_SYSCALLS_H */ | ||
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h new file mode 100644 index 000000000000..95e407255347 --- /dev/null +++ b/arch/arm64/include/asm/system_misc.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/system_misc.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_SYSTEM_MISC_H | ||
19 | #define __ASM_SYSTEM_MISC_H | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | |||
23 | #include <linux/compiler.h> | ||
24 | #include <linux/linkage.h> | ||
25 | #include <linux/irqflags.h> | ||
26 | |||
27 | struct pt_regs; | ||
28 | |||
29 | void die(const char *msg, struct pt_regs *regs, int err); | ||
30 | |||
31 | struct siginfo; | ||
32 | void arm64_notify_die(const char *str, struct pt_regs *regs, | ||
33 | struct siginfo *info, int err); | ||
34 | |||
35 | void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, | ||
36 | struct pt_regs *), | ||
37 | int sig, int code, const char *name); | ||
38 | |||
39 | struct mm_struct; | ||
40 | extern void show_pte(struct mm_struct *mm, unsigned long addr); | ||
41 | extern void __show_regs(struct pt_regs *); | ||
42 | |||
43 | void soft_restart(unsigned long); | ||
44 | extern void (*pm_restart)(const char *cmd); | ||
45 | |||
46 | #define UDBG_UNDEFINED (1 << 0) | ||
47 | #define UDBG_SYSCALL (1 << 1) | ||
48 | #define UDBG_BADABORT (1 << 2) | ||
49 | #define UDBG_SEGV (1 << 3) | ||
50 | #define UDBG_BUS (1 << 4) | ||
51 | |||
52 | #endif /* __ASSEMBLY__ */ | ||
53 | |||
54 | #endif /* __ASM_SYSTEM_MISC_H */ | ||
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h new file mode 100644 index 000000000000..3659e460071d --- /dev/null +++ b/arch/arm64/include/asm/thread_info.h | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/thread_info.h | ||
3 | * | ||
4 | * Copyright (C) 2002 Russell King. | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_THREAD_INFO_H | ||
20 | #define __ASM_THREAD_INFO_H | ||
21 | |||
22 | #ifdef __KERNEL__ | ||
23 | |||
24 | #include <linux/compiler.h> | ||
25 | |||
26 | #ifndef CONFIG_ARM64_64K_PAGES | ||
27 | #define THREAD_SIZE_ORDER 1 | ||
28 | #endif | ||
29 | |||
30 | #define THREAD_SIZE 8192 | ||
31 | #define THREAD_START_SP (THREAD_SIZE - 16) | ||
32 | |||
33 | #ifndef __ASSEMBLY__ | ||
34 | |||
35 | struct task_struct; | ||
36 | struct exec_domain; | ||
37 | |||
38 | #include <asm/types.h> | ||
39 | |||
40 | typedef unsigned long mm_segment_t; | ||
41 | |||
42 | /* | ||
43 | * low level task data that entry.S needs immediate access to. | ||
44 | * __switch_to() assumes cpu_context follows immediately after cpu_domain. | ||
45 | */ | ||
46 | struct thread_info { | ||
47 | unsigned long flags; /* low level flags */ | ||
48 | mm_segment_t addr_limit; /* address limit */ | ||
49 | struct task_struct *task; /* main task structure */ | ||
50 | struct exec_domain *exec_domain; /* execution domain */ | ||
51 | struct restart_block restart_block; | ||
52 | int preempt_count; /* 0 => preemptable, <0 => bug */ | ||
53 | int cpu; /* cpu */ | ||
54 | }; | ||
55 | |||
56 | #define INIT_THREAD_INFO(tsk) \ | ||
57 | { \ | ||
58 | .task = &tsk, \ | ||
59 | .exec_domain = &default_exec_domain, \ | ||
60 | .flags = 0, \ | ||
61 | .preempt_count = INIT_PREEMPT_COUNT, \ | ||
62 | .addr_limit = KERNEL_DS, \ | ||
63 | .restart_block = { \ | ||
64 | .fn = do_no_restart_syscall, \ | ||
65 | }, \ | ||
66 | } | ||
67 | |||
68 | #define init_thread_info (init_thread_union.thread_info) | ||
69 | #define init_stack (init_thread_union.stack) | ||
70 | |||
71 | /* | ||
72 | * how to get the thread information struct from C | ||
73 | */ | ||
74 | static inline struct thread_info *current_thread_info(void) __attribute_const__; | ||
75 | |||
76 | static inline struct thread_info *current_thread_info(void) | ||
77 | { | ||
78 | register unsigned long sp asm ("sp"); | ||
79 | return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); | ||
80 | } | ||
81 | |||
82 | #define thread_saved_pc(tsk) \ | ||
83 | ((unsigned long)(tsk->thread.cpu_context.pc)) | ||
84 | #define thread_saved_sp(tsk) \ | ||
85 | ((unsigned long)(tsk->thread.cpu_context.sp)) | ||
86 | #define thread_saved_fp(tsk) \ | ||
87 | ((unsigned long)(tsk->thread.cpu_context.fp)) | ||
88 | |||
89 | #endif | ||
90 | |||
91 | /* | ||
92 | * We use bit 30 of the preempt_count to indicate that kernel | ||
93 | * preemption is occurring. See <asm/hardirq.h>. | ||
94 | */ | ||
95 | #define PREEMPT_ACTIVE 0x40000000 | ||
96 | |||
97 | /* | ||
98 | * thread information flags: | ||
99 | * TIF_SYSCALL_TRACE - syscall trace active | ||
100 | * TIF_SIGPENDING - signal pending | ||
101 | * TIF_NEED_RESCHED - rescheduling necessary | ||
102 | * TIF_NOTIFY_RESUME - callback before returning to user | ||
103 | * TIF_USEDFPU - FPU was used by this task this quantum (SMP) | ||
104 | * TIF_POLLING_NRFLAG - true if poll_idle() is polling TIF_NEED_RESCHED | ||
105 | */ | ||
106 | #define TIF_SIGPENDING 0 | ||
107 | #define TIF_NEED_RESCHED 1 | ||
108 | #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ | ||
109 | #define TIF_SYSCALL_TRACE 8 | ||
110 | #define TIF_POLLING_NRFLAG 16 | ||
111 | #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ | ||
112 | #define TIF_FREEZE 19 | ||
113 | #define TIF_RESTORE_SIGMASK 20 | ||
114 | #define TIF_SINGLESTEP 21 | ||
115 | #define TIF_32BIT 22 /* 32bit process */ | ||
116 | #define TIF_SWITCH_MM 23 /* deferred switch_mm */ | ||
117 | |||
118 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | ||
119 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | ||
120 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | ||
121 | #define _TIF_32BIT (1 << TIF_32BIT) | ||
122 | |||
123 | #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ | ||
124 | _TIF_NOTIFY_RESUME) | ||
125 | |||
126 | #endif /* __KERNEL__ */ | ||
127 | #endif /* __ASM_THREAD_INFO_H */ | ||
diff --git a/arch/arm64/include/asm/timex.h b/arch/arm64/include/asm/timex.h new file mode 100644 index 000000000000..b24a31a7e2c9 --- /dev/null +++ b/arch/arm64/include/asm/timex.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_TIMEX_H | ||
17 | #define __ASM_TIMEX_H | ||
18 | |||
19 | /* | ||
20 | * Use the current timer as a cycle counter since this is what we use for | ||
21 | * the delay loop. | ||
22 | */ | ||
23 | #define get_cycles() ({ cycles_t c; read_current_timer(&c); c; }) | ||
24 | |||
25 | #include <asm-generic/timex.h> | ||
26 | |||
27 | #define ARCH_HAS_READ_CURRENT_TIMER | ||
28 | |||
29 | #endif | ||
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h new file mode 100644 index 000000000000..654f0968030b --- /dev/null +++ b/arch/arm64/include/asm/tlb.h | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/tlb.h | ||
3 | * | ||
4 | * Copyright (C) 2002 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_TLB_H | ||
20 | #define __ASM_TLB_H | ||
21 | |||
22 | #include <linux/pagemap.h> | ||
23 | #include <linux/swap.h> | ||
24 | |||
25 | #include <asm/pgalloc.h> | ||
26 | #include <asm/tlbflush.h> | ||
27 | |||
28 | #define MMU_GATHER_BUNDLE 8 | ||
29 | |||
30 | /* | ||
31 | * TLB handling. This allows us to remove pages from the page | ||
32 | * tables, and efficiently handle the TLB issues. | ||
33 | */ | ||
34 | struct mmu_gather { | ||
35 | struct mm_struct *mm; | ||
36 | unsigned int fullmm; | ||
37 | struct vm_area_struct *vma; | ||
38 | unsigned long range_start; | ||
39 | unsigned long range_end; | ||
40 | unsigned int nr; | ||
41 | unsigned int max; | ||
42 | struct page **pages; | ||
43 | struct page *local[MMU_GATHER_BUNDLE]; | ||
44 | }; | ||
45 | |||
46 | /* | ||
47 | * This is unnecessarily complex. There's three ways the TLB shootdown | ||
48 | * code is used: | ||
49 | * 1. Unmapping a range of vmas. See zap_page_range(), unmap_region(). | ||
50 | * tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called. | ||
51 | * tlb->vma will be non-NULL. | ||
52 | * 2. Unmapping all vmas. See exit_mmap(). | ||
53 | * tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called. | ||
54 | * tlb->vma will be non-NULL. Additionally, page tables will be freed. | ||
55 | * 3. Unmapping argument pages. See shift_arg_pages(). | ||
56 | * tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called. | ||
57 | * tlb->vma will be NULL. | ||
58 | */ | ||
59 | static inline void tlb_flush(struct mmu_gather *tlb) | ||
60 | { | ||
61 | if (tlb->fullmm || !tlb->vma) | ||
62 | flush_tlb_mm(tlb->mm); | ||
63 | else if (tlb->range_end > 0) { | ||
64 | flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end); | ||
65 | tlb->range_start = TASK_SIZE; | ||
66 | tlb->range_end = 0; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr) | ||
71 | { | ||
72 | if (!tlb->fullmm) { | ||
73 | if (addr < tlb->range_start) | ||
74 | tlb->range_start = addr; | ||
75 | if (addr + PAGE_SIZE > tlb->range_end) | ||
76 | tlb->range_end = addr + PAGE_SIZE; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static inline void __tlb_alloc_page(struct mmu_gather *tlb) | ||
81 | { | ||
82 | unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); | ||
83 | |||
84 | if (addr) { | ||
85 | tlb->pages = (void *)addr; | ||
86 | tlb->max = PAGE_SIZE / sizeof(struct page *); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static inline void tlb_flush_mmu(struct mmu_gather *tlb) | ||
91 | { | ||
92 | tlb_flush(tlb); | ||
93 | free_pages_and_swap_cache(tlb->pages, tlb->nr); | ||
94 | tlb->nr = 0; | ||
95 | if (tlb->pages == tlb->local) | ||
96 | __tlb_alloc_page(tlb); | ||
97 | } | ||
98 | |||
99 | static inline void | ||
100 | tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm) | ||
101 | { | ||
102 | tlb->mm = mm; | ||
103 | tlb->fullmm = fullmm; | ||
104 | tlb->vma = NULL; | ||
105 | tlb->max = ARRAY_SIZE(tlb->local); | ||
106 | tlb->pages = tlb->local; | ||
107 | tlb->nr = 0; | ||
108 | __tlb_alloc_page(tlb); | ||
109 | } | ||
110 | |||
111 | static inline void | ||
112 | tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) | ||
113 | { | ||
114 | tlb_flush_mmu(tlb); | ||
115 | |||
116 | /* keep the page table cache within bounds */ | ||
117 | check_pgt_cache(); | ||
118 | |||
119 | if (tlb->pages != tlb->local) | ||
120 | free_pages((unsigned long)tlb->pages, 0); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Memorize the range for the TLB flush. | ||
125 | */ | ||
126 | static inline void | ||
127 | tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr) | ||
128 | { | ||
129 | tlb_add_flush(tlb, addr); | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * In the case of tlb vma handling, we can optimise these away in the | ||
134 | * case where we're doing a full MM flush. When we're doing a munmap, | ||
135 | * the vmas are adjusted to only cover the region to be torn down. | ||
136 | */ | ||
137 | static inline void | ||
138 | tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) | ||
139 | { | ||
140 | if (!tlb->fullmm) { | ||
141 | tlb->vma = vma; | ||
142 | tlb->range_start = TASK_SIZE; | ||
143 | tlb->range_end = 0; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static inline void | ||
148 | tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) | ||
149 | { | ||
150 | if (!tlb->fullmm) | ||
151 | tlb_flush(tlb); | ||
152 | } | ||
153 | |||
154 | static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) | ||
155 | { | ||
156 | tlb->pages[tlb->nr++] = page; | ||
157 | VM_BUG_ON(tlb->nr > tlb->max); | ||
158 | return tlb->max - tlb->nr; | ||
159 | } | ||
160 | |||
161 | static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) | ||
162 | { | ||
163 | if (!__tlb_remove_page(tlb, page)) | ||
164 | tlb_flush_mmu(tlb); | ||
165 | } | ||
166 | |||
167 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | ||
168 | unsigned long addr) | ||
169 | { | ||
170 | pgtable_page_dtor(pte); | ||
171 | tlb_add_flush(tlb, addr); | ||
172 | tlb_remove_page(tlb, pte); | ||
173 | } | ||
174 | |||
175 | #ifndef CONFIG_ARM64_64K_PAGES | ||
176 | static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, | ||
177 | unsigned long addr) | ||
178 | { | ||
179 | tlb_add_flush(tlb, addr); | ||
180 | tlb_remove_page(tlb, virt_to_page(pmdp)); | ||
181 | } | ||
182 | #endif | ||
183 | |||
184 | #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) | ||
185 | #define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr) | ||
186 | #define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) | ||
187 | |||
188 | #define tlb_migrate_finish(mm) do { } while (0) | ||
189 | |||
190 | #endif | ||
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h new file mode 100644 index 000000000000..122d6320f745 --- /dev/null +++ b/arch/arm64/include/asm/tlbflush.h | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/tlbflush.h | ||
3 | * | ||
4 | * Copyright (C) 1999-2003 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #ifndef __ASM_TLBFLUSH_H | ||
20 | #define __ASM_TLBFLUSH_H | ||
21 | |||
22 | #ifndef __ASSEMBLY__ | ||
23 | |||
24 | #include <linux/sched.h> | ||
25 | #include <asm/cputype.h> | ||
26 | |||
27 | extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *); | ||
28 | extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long); | ||
29 | |||
30 | extern struct cpu_tlb_fns cpu_tlb; | ||
31 | |||
32 | /* | ||
33 | * TLB Management | ||
34 | * ============== | ||
35 | * | ||
36 | * The arch/arm64/mm/tlb.S files implement these methods. | ||
37 | * | ||
38 | * The TLB specific code is expected to perform whatever tests it needs | ||
39 | * to determine if it should invalidate the TLB for each call. Start | ||
40 | * addresses are inclusive and end addresses are exclusive; it is safe to | ||
41 | * round these addresses down. | ||
42 | * | ||
43 | * flush_tlb_all() | ||
44 | * | ||
45 | * Invalidate the entire TLB. | ||
46 | * | ||
47 | * flush_tlb_mm(mm) | ||
48 | * | ||
49 | * Invalidate all TLB entries in a particular address space. | ||
50 | * - mm - mm_struct describing address space | ||
51 | * | ||
52 | * flush_tlb_range(mm,start,end) | ||
53 | * | ||
54 | * Invalidate a range of TLB entries in the specified address | ||
55 | * space. | ||
56 | * - mm - mm_struct describing address space | ||
57 | * - start - start address (may not be aligned) | ||
58 | * - end - end address (exclusive, may not be aligned) | ||
59 | * | ||
60 | * flush_tlb_page(vaddr,vma) | ||
61 | * | ||
62 | * Invalidate the specified page in the specified address range. | ||
63 | * - vaddr - virtual address (may not be aligned) | ||
64 | * - vma - vma_struct describing address range | ||
65 | * | ||
66 | * flush_kern_tlb_page(kaddr) | ||
67 | * | ||
68 | * Invalidate the TLB entry for the specified page. The address | ||
69 | * will be in the kernels virtual memory space. Current uses | ||
70 | * only require the D-TLB to be invalidated. | ||
71 | * - kaddr - Kernel virtual memory address | ||
72 | */ | ||
73 | static inline void flush_tlb_all(void) | ||
74 | { | ||
75 | dsb(); | ||
76 | asm("tlbi vmalle1is"); | ||
77 | dsb(); | ||
78 | isb(); | ||
79 | } | ||
80 | |||
81 | static inline void flush_tlb_mm(struct mm_struct *mm) | ||
82 | { | ||
83 | unsigned long asid = (unsigned long)ASID(mm) << 48; | ||
84 | |||
85 | dsb(); | ||
86 | asm("tlbi aside1is, %0" : : "r" (asid)); | ||
87 | dsb(); | ||
88 | } | ||
89 | |||
90 | static inline void flush_tlb_page(struct vm_area_struct *vma, | ||
91 | unsigned long uaddr) | ||
92 | { | ||
93 | unsigned long addr = uaddr >> 12 | | ||
94 | ((unsigned long)ASID(vma->vm_mm) << 48); | ||
95 | |||
96 | dsb(); | ||
97 | asm("tlbi vae1is, %0" : : "r" (addr)); | ||
98 | dsb(); | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Convert calls to our calling convention. | ||
103 | */ | ||
104 | #define flush_tlb_range(vma,start,end) __cpu_flush_user_tlb_range(start,end,vma) | ||
105 | #define flush_tlb_kernel_range(s,e) __cpu_flush_kern_tlb_range(s,e) | ||
106 | |||
107 | /* | ||
108 | * On AArch64, the cache coherency is handled via the set_pte_at() function. | ||
109 | */ | ||
110 | static inline void update_mmu_cache(struct vm_area_struct *vma, | ||
111 | unsigned long addr, pte_t *ptep) | ||
112 | { | ||
113 | /* | ||
114 | * set_pte() does not have a DSB, so make sure that the page table | ||
115 | * write is visible. | ||
116 | */ | ||
117 | dsb(); | ||
118 | } | ||
119 | |||
120 | #endif | ||
121 | |||
122 | #endif | ||
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h new file mode 100644 index 000000000000..10ca8ff93cc2 --- /dev/null +++ b/arch/arm64/include/asm/traps.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/traps.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_TRAP_H | ||
19 | #define __ASM_TRAP_H | ||
20 | |||
21 | static inline int in_exception_text(unsigned long ptr) | ||
22 | { | ||
23 | extern char __exception_text_start[]; | ||
24 | extern char __exception_text_end[]; | ||
25 | |||
26 | return ptr >= (unsigned long)&__exception_text_start && | ||
27 | ptr < (unsigned long)&__exception_text_end; | ||
28 | } | ||
29 | |||
30 | #endif | ||
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h new file mode 100644 index 000000000000..008f8481da65 --- /dev/null +++ b/arch/arm64/include/asm/uaccess.h | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/uaccess.h | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #ifndef __ASM_UACCESS_H | ||
19 | #define __ASM_UACCESS_H | ||
20 | |||
21 | /* | ||
22 | * User space memory access functions | ||
23 | */ | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/thread_info.h> | ||
26 | |||
27 | #include <asm/ptrace.h> | ||
28 | #include <asm/errno.h> | ||
29 | #include <asm/memory.h> | ||
30 | #include <asm/compiler.h> | ||
31 | |||
32 | #define VERIFY_READ 0 | ||
33 | #define VERIFY_WRITE 1 | ||
34 | |||
35 | /* | ||
36 | * The exception table consists of pairs of addresses: the first is the | ||
37 | * address of an instruction that is allowed to fault, and the second is | ||
38 | * the address at which the program should continue. No registers are | ||
39 | * modified, so it is entirely up to the continuation code to figure out | ||
40 | * what to do. | ||
41 | * | ||
42 | * All the routines below use bits of fixup code that are out of line | ||
43 | * with the main instruction path. This means when everything is well, | ||
44 | * we don't even have to jump over them. Further, they do not intrude | ||
45 | * on our cache or tlb entries. | ||
46 | */ | ||
47 | |||
48 | struct exception_table_entry | ||
49 | { | ||
50 | unsigned long insn, fixup; | ||
51 | }; | ||
52 | |||
53 | extern int fixup_exception(struct pt_regs *regs); | ||
54 | |||
55 | #define KERNEL_DS (-1UL) | ||
56 | #define get_ds() (KERNEL_DS) | ||
57 | |||
58 | #define USER_DS TASK_SIZE_64 | ||
59 | #define get_fs() (current_thread_info()->addr_limit) | ||
60 | |||
61 | static inline void set_fs(mm_segment_t fs) | ||
62 | { | ||
63 | current_thread_info()->addr_limit = fs; | ||
64 | } | ||
65 | |||
66 | #define segment_eq(a,b) ((a) == (b)) | ||
67 | |||
68 | /* | ||
69 | * Return 1 if addr < current->addr_limit, 0 otherwise. | ||
70 | */ | ||
71 | #define __addr_ok(addr) \ | ||
72 | ({ \ | ||
73 | unsigned long flag; \ | ||
74 | asm("cmp %1, %0; cset %0, lo" \ | ||
75 | : "=&r" (flag) \ | ||
76 | : "r" (addr), "0" (current_thread_info()->addr_limit) \ | ||
77 | : "cc"); \ | ||
78 | flag; \ | ||
79 | }) | ||
80 | |||
81 | /* | ||
82 | * Test whether a block of memory is a valid user space address. | ||
83 | * Returns 1 if the range is valid, 0 otherwise. | ||
84 | * | ||
85 | * This is equivalent to the following test: | ||
86 | * (u65)addr + (u65)size < (u65)current->addr_limit | ||
87 | * | ||
88 | * This needs 65-bit arithmetic. | ||
89 | */ | ||
90 | #define __range_ok(addr, size) \ | ||
91 | ({ \ | ||
92 | unsigned long flag, roksum; \ | ||
93 | __chk_user_ptr(addr); \ | ||
94 | asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, cc" \ | ||
95 | : "=&r" (flag), "=&r" (roksum) \ | ||
96 | : "1" (addr), "Ir" (size), \ | ||
97 | "r" (current_thread_info()->addr_limit) \ | ||
98 | : "cc"); \ | ||
99 | flag; \ | ||
100 | }) | ||
101 | |||
102 | #define access_ok(type, addr, size) __range_ok(addr, size) | ||
103 | |||
104 | /* | ||
105 | * The "__xxx" versions of the user access functions do not verify the address | ||
106 | * space - it must have been done previously with a separate "access_ok()" | ||
107 | * call. | ||
108 | * | ||
109 | * The "__xxx_error" versions set the third argument to -EFAULT if an error | ||
110 | * occurs, and leave it unchanged on success. | ||
111 | */ | ||
112 | #define __get_user_asm(instr, reg, x, addr, err) \ | ||
113 | asm volatile( \ | ||
114 | "1: " instr " " reg "1, [%2]\n" \ | ||
115 | "2:\n" \ | ||
116 | " .section .fixup, \"ax\"\n" \ | ||
117 | " .align 2\n" \ | ||
118 | "3: mov %w0, %3\n" \ | ||
119 | " mov %1, #0\n" \ | ||
120 | " b 2b\n" \ | ||
121 | " .previous\n" \ | ||
122 | " .section __ex_table,\"a\"\n" \ | ||
123 | " .align 3\n" \ | ||
124 | " .quad 1b, 3b\n" \ | ||
125 | " .previous" \ | ||
126 | : "+r" (err), "=&r" (x) \ | ||
127 | : "r" (addr), "i" (-EFAULT)) | ||
128 | |||
129 | #define __get_user_err(x, ptr, err) \ | ||
130 | do { \ | ||
131 | unsigned long __gu_val; \ | ||
132 | __chk_user_ptr(ptr); \ | ||
133 | switch (sizeof(*(ptr))) { \ | ||
134 | case 1: \ | ||
135 | __get_user_asm("ldrb", "%w", __gu_val, (ptr), (err)); \ | ||
136 | break; \ | ||
137 | case 2: \ | ||
138 | __get_user_asm("ldrh", "%w", __gu_val, (ptr), (err)); \ | ||
139 | break; \ | ||
140 | case 4: \ | ||
141 | __get_user_asm("ldr", "%w", __gu_val, (ptr), (err)); \ | ||
142 | break; \ | ||
143 | case 8: \ | ||
144 | __get_user_asm("ldr", "%", __gu_val, (ptr), (err)); \ | ||
145 | break; \ | ||
146 | default: \ | ||
147 | BUILD_BUG(); \ | ||
148 | } \ | ||
149 | (x) = (__typeof__(*(ptr)))__gu_val; \ | ||
150 | } while (0) | ||
151 | |||
152 | #define __get_user(x, ptr) \ | ||
153 | ({ \ | ||
154 | int __gu_err = 0; \ | ||
155 | __get_user_err((x), (ptr), __gu_err); \ | ||
156 | __gu_err; \ | ||
157 | }) | ||
158 | |||
159 | #define __get_user_error(x, ptr, err) \ | ||
160 | ({ \ | ||
161 | __get_user_err((x), (ptr), (err)); \ | ||
162 | (void)0; \ | ||
163 | }) | ||
164 | |||
165 | #define __get_user_unaligned __get_user | ||
166 | |||
167 | #define get_user(x, ptr) \ | ||
168 | ({ \ | ||
169 | might_sleep(); \ | ||
170 | access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) ? \ | ||
171 | __get_user((x), (ptr)) : \ | ||
172 | ((x) = 0, -EFAULT); \ | ||
173 | }) | ||
174 | |||
175 | #define __put_user_asm(instr, reg, x, addr, err) \ | ||
176 | asm volatile( \ | ||
177 | "1: " instr " " reg "1, [%2]\n" \ | ||
178 | "2:\n" \ | ||
179 | " .section .fixup,\"ax\"\n" \ | ||
180 | " .align 2\n" \ | ||
181 | "3: mov %w0, %3\n" \ | ||
182 | " b 2b\n" \ | ||
183 | " .previous\n" \ | ||
184 | " .section __ex_table,\"a\"\n" \ | ||
185 | " .align 3\n" \ | ||
186 | " .quad 1b, 3b\n" \ | ||
187 | " .previous" \ | ||
188 | : "+r" (err) \ | ||
189 | : "r" (x), "r" (addr), "i" (-EFAULT)) | ||
190 | |||
191 | #define __put_user_err(x, ptr, err) \ | ||
192 | do { \ | ||
193 | __typeof__(*(ptr)) __pu_val = (x); \ | ||
194 | __chk_user_ptr(ptr); \ | ||
195 | switch (sizeof(*(ptr))) { \ | ||
196 | case 1: \ | ||
197 | __put_user_asm("strb", "%w", __pu_val, (ptr), (err)); \ | ||
198 | break; \ | ||
199 | case 2: \ | ||
200 | __put_user_asm("strh", "%w", __pu_val, (ptr), (err)); \ | ||
201 | break; \ | ||
202 | case 4: \ | ||
203 | __put_user_asm("str", "%w", __pu_val, (ptr), (err)); \ | ||
204 | break; \ | ||
205 | case 8: \ | ||
206 | __put_user_asm("str", "%", __pu_val, (ptr), (err)); \ | ||
207 | break; \ | ||
208 | default: \ | ||
209 | BUILD_BUG(); \ | ||
210 | } \ | ||
211 | } while (0) | ||
212 | |||
213 | #define __put_user(x, ptr) \ | ||
214 | ({ \ | ||
215 | int __pu_err = 0; \ | ||
216 | __put_user_err((x), (ptr), __pu_err); \ | ||
217 | __pu_err; \ | ||
218 | }) | ||
219 | |||
220 | #define __put_user_error(x, ptr, err) \ | ||
221 | ({ \ | ||
222 | __put_user_err((x), (ptr), (err)); \ | ||
223 | (void)0; \ | ||
224 | }) | ||
225 | |||
226 | #define __put_user_unaligned __put_user | ||
227 | |||
228 | #define put_user(x, ptr) \ | ||
229 | ({ \ | ||
230 | might_sleep(); \ | ||
231 | access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) ? \ | ||
232 | __put_user((x), (ptr)) : \ | ||
233 | -EFAULT; \ | ||
234 | }) | ||
235 | |||
236 | extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n); | ||
237 | extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n); | ||
238 | extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n); | ||
239 | extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); | ||
240 | |||
241 | extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count); | ||
242 | extern unsigned long __must_check __strnlen_user(const char __user *s, long n); | ||
243 | |||
244 | static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) | ||
245 | { | ||
246 | if (access_ok(VERIFY_READ, from, n)) | ||
247 | n = __copy_from_user(to, from, n); | ||
248 | else /* security hole - plug it */ | ||
249 | memset(to, 0, n); | ||
250 | return n; | ||
251 | } | ||
252 | |||
253 | static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) | ||
254 | { | ||
255 | if (access_ok(VERIFY_WRITE, to, n)) | ||
256 | n = __copy_to_user(to, from, n); | ||
257 | return n; | ||
258 | } | ||
259 | |||
260 | static inline unsigned long __must_check copy_in_user(void __user *to, const void __user *from, unsigned long n) | ||
261 | { | ||
262 | if (access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n)) | ||
263 | n = __copy_in_user(to, from, n); | ||
264 | return n; | ||
265 | } | ||
266 | |||
267 | #define __copy_to_user_inatomic __copy_to_user | ||
268 | #define __copy_from_user_inatomic __copy_from_user | ||
269 | |||
270 | static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) | ||
271 | { | ||
272 | if (access_ok(VERIFY_WRITE, to, n)) | ||
273 | n = __clear_user(to, n); | ||
274 | return n; | ||
275 | } | ||
276 | |||
277 | static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count) | ||
278 | { | ||
279 | long res = -EFAULT; | ||
280 | if (access_ok(VERIFY_READ, src, 1)) | ||
281 | res = __strncpy_from_user(dst, src, count); | ||
282 | return res; | ||
283 | } | ||
284 | |||
285 | #define strlen_user(s) strnlen_user(s, ~0UL >> 1) | ||
286 | |||
287 | static inline long __must_check strnlen_user(const char __user *s, long n) | ||
288 | { | ||
289 | unsigned long res = 0; | ||
290 | |||
291 | if (__addr_ok(s)) | ||
292 | res = __strnlen_user(s, n); | ||
293 | |||
294 | return res; | ||
295 | } | ||
296 | |||
297 | #endif /* __ASM_UACCESS_H */ | ||
diff --git a/arch/arm64/include/asm/ucontext.h b/arch/arm64/include/asm/ucontext.h new file mode 100644 index 000000000000..bde960720892 --- /dev/null +++ b/arch/arm64/include/asm/ucontext.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_UCONTEXT_H | ||
17 | #define __ASM_UCONTEXT_H | ||
18 | |||
19 | struct ucontext { | ||
20 | unsigned long uc_flags; | ||
21 | struct ucontext *uc_link; | ||
22 | stack_t uc_stack; | ||
23 | sigset_t uc_sigmask; | ||
24 | /* glibc uses a 1024-bit sigset_t */ | ||
25 | __u8 __unused[(1024 - sizeof(sigset_t)) / 8]; | ||
26 | /* last for future expansion */ | ||
27 | struct sigcontext uc_mcontext; | ||
28 | }; | ||
29 | |||
30 | #endif /* __ASM_UCONTEXT_H */ | ||
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h new file mode 100644 index 000000000000..fe18a683274f --- /dev/null +++ b/arch/arm64/include/asm/unistd.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #if !defined(__ASM_UNISTD_H) || defined(__SYSCALL) | ||
17 | #define __ASM_UNISTD_H | ||
18 | |||
19 | #ifndef __SYSCALL_COMPAT | ||
20 | #include <asm-generic/unistd.h> | ||
21 | #endif | ||
22 | |||
23 | #if defined(__KERNEL__) && defined(CONFIG_COMPAT) | ||
24 | #include <asm/unistd32.h> | ||
25 | #endif | ||
26 | |||
27 | #endif /* __ASM_UNISTD_H */ | ||
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h new file mode 100644 index 000000000000..a50405f5ee42 --- /dev/null +++ b/arch/arm64/include/asm/unistd32.h | |||
@@ -0,0 +1,758 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/include/asm/unistd.h | ||
3 | * | ||
4 | * Copyright (C) 2001-2005 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | #if !defined(__ASM_UNISTD32_H) || defined(__SYSCALL) | ||
20 | #define __ASM_UNISTD32_H | ||
21 | |||
22 | #ifndef __SYSCALL | ||
23 | #define __SYSCALL(x, y) | ||
24 | #endif | ||
25 | |||
26 | /* | ||
27 | * This file contains the system call numbers. | ||
28 | */ | ||
29 | |||
30 | #ifdef __SYSCALL_COMPAT | ||
31 | |||
32 | #define __NR_restart_syscall 0 | ||
33 | __SYSCALL(__NR_restart_syscall, sys_restart_syscall) | ||
34 | #define __NR_exit 1 | ||
35 | __SYSCALL(__NR_exit, sys_exit) | ||
36 | #define __NR_fork 2 | ||
37 | __SYSCALL(__NR_fork, sys_fork) | ||
38 | #define __NR_read 3 | ||
39 | __SYSCALL(__NR_read, sys_read) | ||
40 | #define __NR_write 4 | ||
41 | __SYSCALL(__NR_write, sys_write) | ||
42 | #define __NR_open 5 | ||
43 | __SYSCALL(__NR_open, sys_open) | ||
44 | #define __NR_close 6 | ||
45 | __SYSCALL(__NR_close, sys_close) | ||
46 | __SYSCALL(7, sys_ni_syscall) /* 7 was sys_waitpid */ | ||
47 | #define __NR_creat 8 | ||
48 | __SYSCALL(__NR_creat, sys_creat) | ||
49 | #define __NR_link 9 | ||
50 | __SYSCALL(__NR_link, sys_link) | ||
51 | #define __NR_unlink 10 | ||
52 | __SYSCALL(__NR_unlink, sys_unlink) | ||
53 | #define __NR_execve 11 | ||
54 | __SYSCALL(__NR_execve, sys_execve) | ||
55 | #define __NR_chdir 12 | ||
56 | __SYSCALL(__NR_chdir, sys_chdir) | ||
57 | __SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */ | ||
58 | #define __NR_mknod 14 | ||
59 | __SYSCALL(__NR_mknod, sys_mknod) | ||
60 | #define __NR_chmod 15 | ||
61 | __SYSCALL(__NR_chmod, sys_chmod) | ||
62 | #define __NR_lchown 16 | ||
63 | __SYSCALL(__NR_lchown, sys_lchown16) | ||
64 | __SYSCALL(17, sys_ni_syscall) /* 17 was sys_break */ | ||
65 | __SYSCALL(18, sys_ni_syscall) /* 18 was sys_stat */ | ||
66 | #define __NR_lseek 19 | ||
67 | __SYSCALL(__NR_lseek, sys_lseek) | ||
68 | #define __NR_getpid 20 | ||
69 | __SYSCALL(__NR_getpid, sys_getpid) | ||
70 | #define __NR_mount 21 | ||
71 | __SYSCALL(__NR_mount, sys_mount) | ||
72 | __SYSCALL(22, sys_ni_syscall) /* 22 was sys_umount */ | ||
73 | #define __NR_setuid 23 | ||
74 | __SYSCALL(__NR_setuid, sys_setuid16) | ||
75 | #define __NR_getuid 24 | ||
76 | __SYSCALL(__NR_getuid, sys_getuid16) | ||
77 | __SYSCALL(25, sys_ni_syscall) /* 25 was sys_stime */ | ||
78 | #define __NR_ptrace 26 | ||
79 | __SYSCALL(__NR_ptrace, sys_ptrace) | ||
80 | __SYSCALL(27, sys_ni_syscall) /* 27 was sys_alarm */ | ||
81 | __SYSCALL(28, sys_ni_syscall) /* 28 was sys_fstat */ | ||
82 | #define __NR_pause 29 | ||
83 | __SYSCALL(__NR_pause, sys_pause) | ||
84 | __SYSCALL(30, sys_ni_syscall) /* 30 was sys_utime */ | ||
85 | __SYSCALL(31, sys_ni_syscall) /* 31 was sys_stty */ | ||
86 | __SYSCALL(32, sys_ni_syscall) /* 32 was sys_gtty */ | ||
87 | #define __NR_access 33 | ||
88 | __SYSCALL(__NR_access, sys_access) | ||
89 | #define __NR_nice 34 | ||
90 | __SYSCALL(__NR_nice, sys_nice) | ||
91 | __SYSCALL(35, sys_ni_syscall) /* 35 was sys_ftime */ | ||
92 | #define __NR_sync 36 | ||
93 | __SYSCALL(__NR_sync, sys_sync) | ||
94 | #define __NR_kill 37 | ||
95 | __SYSCALL(__NR_kill, sys_kill) | ||
96 | #define __NR_rename 38 | ||
97 | __SYSCALL(__NR_rename, sys_rename) | ||
98 | #define __NR_mkdir 39 | ||
99 | __SYSCALL(__NR_mkdir, sys_mkdir) | ||
100 | #define __NR_rmdir 40 | ||
101 | __SYSCALL(__NR_rmdir, sys_rmdir) | ||
102 | #define __NR_dup 41 | ||
103 | __SYSCALL(__NR_dup, sys_dup) | ||
104 | #define __NR_pipe 42 | ||
105 | __SYSCALL(__NR_pipe, sys_pipe) | ||
106 | #define __NR_times 43 | ||
107 | __SYSCALL(__NR_times, sys_times) | ||
108 | __SYSCALL(44, sys_ni_syscall) /* 44 was sys_prof */ | ||
109 | #define __NR_brk 45 | ||
110 | __SYSCALL(__NR_brk, sys_brk) | ||
111 | #define __NR_setgid 46 | ||
112 | __SYSCALL(__NR_setgid, sys_setgid16) | ||
113 | #define __NR_getgid 47 | ||
114 | __SYSCALL(__NR_getgid, sys_getgid16) | ||
115 | __SYSCALL(48, sys_ni_syscall) /* 48 was sys_signal */ | ||
116 | #define __NR_geteuid 49 | ||
117 | __SYSCALL(__NR_geteuid, sys_geteuid16) | ||
118 | #define __NR_getegid 50 | ||
119 | __SYSCALL(__NR_getegid, sys_getegid16) | ||
120 | #define __NR_acct 51 | ||
121 | __SYSCALL(__NR_acct, sys_acct) | ||
122 | #define __NR_umount2 52 | ||
123 | __SYSCALL(__NR_umount2, sys_umount) | ||
124 | __SYSCALL(53, sys_ni_syscall) /* 53 was sys_lock */ | ||
125 | #define __NR_ioctl 54 | ||
126 | __SYSCALL(__NR_ioctl, sys_ioctl) | ||
127 | #define __NR_fcntl 55 | ||
128 | __SYSCALL(__NR_fcntl, sys_fcntl) | ||
129 | __SYSCALL(56, sys_ni_syscall) /* 56 was sys_mpx */ | ||
130 | #define __NR_setpgid 57 | ||
131 | __SYSCALL(__NR_setpgid, sys_setpgid) | ||
132 | __SYSCALL(58, sys_ni_syscall) /* 58 was sys_ulimit */ | ||
133 | __SYSCALL(59, sys_ni_syscall) /* 59 was sys_olduname */ | ||
134 | #define __NR_umask 60 | ||
135 | __SYSCALL(__NR_umask, sys_umask) | ||
136 | #define __NR_chroot 61 | ||
137 | __SYSCALL(__NR_chroot, sys_chroot) | ||
138 | #define __NR_ustat 62 | ||
139 | __SYSCALL(__NR_ustat, sys_ustat) | ||
140 | #define __NR_dup2 63 | ||
141 | __SYSCALL(__NR_dup2, sys_dup2) | ||
142 | #define __NR_getppid 64 | ||
143 | __SYSCALL(__NR_getppid, sys_getppid) | ||
144 | #define __NR_getpgrp 65 | ||
145 | __SYSCALL(__NR_getpgrp, sys_getpgrp) | ||
146 | #define __NR_setsid 66 | ||
147 | __SYSCALL(__NR_setsid, sys_setsid) | ||
148 | #define __NR_sigaction 67 | ||
149 | __SYSCALL(__NR_sigaction, sys_sigaction) | ||
150 | __SYSCALL(68, sys_ni_syscall) /* 68 was sys_sgetmask */ | ||
151 | __SYSCALL(69, sys_ni_syscall) /* 69 was sys_ssetmask */ | ||
152 | #define __NR_setreuid 70 | ||
153 | __SYSCALL(__NR_setreuid, sys_setreuid16) | ||
154 | #define __NR_setregid 71 | ||
155 | __SYSCALL(__NR_setregid, sys_setregid16) | ||
156 | #define __NR_sigsuspend 72 | ||
157 | __SYSCALL(__NR_sigsuspend, sys_sigsuspend) | ||
158 | #define __NR_sigpending 73 | ||
159 | __SYSCALL(__NR_sigpending, sys_sigpending) | ||
160 | #define __NR_sethostname 74 | ||
161 | __SYSCALL(__NR_sethostname, sys_sethostname) | ||
162 | #define __NR_setrlimit 75 | ||
163 | __SYSCALL(__NR_setrlimit, sys_setrlimit) | ||
164 | __SYSCALL(76, sys_ni_syscall) /* 76 was sys_getrlimit */ | ||
165 | #define __NR_getrusage 77 | ||
166 | __SYSCALL(__NR_getrusage, sys_getrusage) | ||
167 | #define __NR_gettimeofday 78 | ||
168 | __SYSCALL(__NR_gettimeofday, sys_gettimeofday) | ||
169 | #define __NR_settimeofday 79 | ||
170 | __SYSCALL(__NR_settimeofday, sys_settimeofday) | ||
171 | #define __NR_getgroups 80 | ||
172 | __SYSCALL(__NR_getgroups, sys_getgroups16) | ||
173 | #define __NR_setgroups 81 | ||
174 | __SYSCALL(__NR_setgroups, sys_setgroups16) | ||
175 | __SYSCALL(82, sys_ni_syscall) /* 82 was sys_select */ | ||
176 | #define __NR_symlink 83 | ||
177 | __SYSCALL(__NR_symlink, sys_symlink) | ||
178 | __SYSCALL(84, sys_ni_syscall) /* 84 was sys_lstat */ | ||
179 | #define __NR_readlink 85 | ||
180 | __SYSCALL(__NR_readlink, sys_readlink) | ||
181 | #define __NR_uselib 86 | ||
182 | __SYSCALL(__NR_uselib, sys_uselib) | ||
183 | #define __NR_swapon 87 | ||
184 | __SYSCALL(__NR_swapon, sys_swapon) | ||
185 | #define __NR_reboot 88 | ||
186 | __SYSCALL(__NR_reboot, sys_reboot) | ||
187 | __SYSCALL(89, sys_ni_syscall) /* 89 was sys_readdir */ | ||
188 | __SYSCALL(90, sys_ni_syscall) /* 90 was sys_mmap */ | ||
189 | #define __NR_munmap 91 | ||
190 | __SYSCALL(__NR_munmap, sys_munmap) | ||
191 | #define __NR_truncate 92 | ||
192 | __SYSCALL(__NR_truncate, sys_truncate) | ||
193 | #define __NR_ftruncate 93 | ||
194 | __SYSCALL(__NR_ftruncate, sys_ftruncate) | ||
195 | #define __NR_fchmod 94 | ||
196 | __SYSCALL(__NR_fchmod, sys_fchmod) | ||
197 | #define __NR_fchown 95 | ||
198 | __SYSCALL(__NR_fchown, sys_fchown16) | ||
199 | #define __NR_getpriority 96 | ||
200 | __SYSCALL(__NR_getpriority, sys_getpriority) | ||
201 | #define __NR_setpriority 97 | ||
202 | __SYSCALL(__NR_setpriority, sys_setpriority) | ||
203 | __SYSCALL(98, sys_ni_syscall) /* 98 was sys_profil */ | ||
204 | #define __NR_statfs 99 | ||
205 | __SYSCALL(__NR_statfs, sys_statfs) | ||
206 | #define __NR_fstatfs 100 | ||
207 | __SYSCALL(__NR_fstatfs, sys_fstatfs) | ||
208 | __SYSCALL(101, sys_ni_syscall) /* 101 was sys_ioperm */ | ||
209 | __SYSCALL(102, sys_ni_syscall) /* 102 was sys_socketcall */ | ||
210 | #define __NR_syslog 103 | ||
211 | __SYSCALL(__NR_syslog, sys_syslog) | ||
212 | #define __NR_setitimer 104 | ||
213 | __SYSCALL(__NR_setitimer, sys_setitimer) | ||
214 | #define __NR_getitimer 105 | ||
215 | __SYSCALL(__NR_getitimer, sys_getitimer) | ||
216 | #define __NR_stat 106 | ||
217 | __SYSCALL(__NR_stat, sys_newstat) | ||
218 | #define __NR_lstat 107 | ||
219 | __SYSCALL(__NR_lstat, sys_newlstat) | ||
220 | #define __NR_fstat 108 | ||
221 | __SYSCALL(__NR_fstat, sys_newfstat) | ||
222 | __SYSCALL(109, sys_ni_syscall) /* 109 was sys_uname */ | ||
223 | __SYSCALL(110, sys_ni_syscall) /* 110 was sys_iopl */ | ||
224 | #define __NR_vhangup 111 | ||
225 | __SYSCALL(__NR_vhangup, sys_vhangup) | ||
226 | __SYSCALL(112, sys_ni_syscall) /* 112 was sys_idle */ | ||
227 | __SYSCALL(113, sys_ni_syscall) /* 113 was sys_syscall */ | ||
228 | #define __NR_wait4 114 | ||
229 | __SYSCALL(__NR_wait4, sys_wait4) | ||
230 | #define __NR_swapoff 115 | ||
231 | __SYSCALL(__NR_swapoff, sys_swapoff) | ||
232 | #define __NR_sysinfo 116 | ||
233 | __SYSCALL(__NR_sysinfo, sys_sysinfo) | ||
234 | __SYSCALL(117, sys_ni_syscall) /* 117 was sys_ipc */ | ||
235 | #define __NR_fsync 118 | ||
236 | __SYSCALL(__NR_fsync, sys_fsync) | ||
237 | #define __NR_sigreturn 119 | ||
238 | __SYSCALL(__NR_sigreturn, sys_sigreturn) | ||
239 | #define __NR_clone 120 | ||
240 | __SYSCALL(__NR_clone, sys_clone) | ||
241 | #define __NR_setdomainname 121 | ||
242 | __SYSCALL(__NR_setdomainname, sys_setdomainname) | ||
243 | #define __NR_uname 122 | ||
244 | __SYSCALL(__NR_uname, sys_newuname) | ||
245 | __SYSCALL(123, sys_ni_syscall) /* 123 was sys_modify_ldt */ | ||
246 | #define __NR_adjtimex 124 | ||
247 | __SYSCALL(__NR_adjtimex, sys_adjtimex) | ||
248 | #define __NR_mprotect 125 | ||
249 | __SYSCALL(__NR_mprotect, sys_mprotect) | ||
250 | #define __NR_sigprocmask 126 | ||
251 | __SYSCALL(__NR_sigprocmask, sys_sigprocmask) | ||
252 | __SYSCALL(127, sys_ni_syscall) /* 127 was sys_create_module */ | ||
253 | #define __NR_init_module 128 | ||
254 | __SYSCALL(__NR_init_module, sys_init_module) | ||
255 | #define __NR_delete_module 129 | ||
256 | __SYSCALL(__NR_delete_module, sys_delete_module) | ||
257 | __SYSCALL(130, sys_ni_syscall) /* 130 was sys_get_kernel_syms */ | ||
258 | #define __NR_quotactl 131 | ||
259 | __SYSCALL(__NR_quotactl, sys_quotactl) | ||
260 | #define __NR_getpgid 132 | ||
261 | __SYSCALL(__NR_getpgid, sys_getpgid) | ||
262 | #define __NR_fchdir 133 | ||
263 | __SYSCALL(__NR_fchdir, sys_fchdir) | ||
264 | #define __NR_bdflush 134 | ||
265 | __SYSCALL(__NR_bdflush, sys_bdflush) | ||
266 | #define __NR_sysfs 135 | ||
267 | __SYSCALL(__NR_sysfs, sys_sysfs) | ||
268 | #define __NR_personality 136 | ||
269 | __SYSCALL(__NR_personality, sys_personality) | ||
270 | __SYSCALL(137, sys_ni_syscall) /* 137 was sys_afs_syscall */ | ||
271 | #define __NR_setfsuid 138 | ||
272 | __SYSCALL(__NR_setfsuid, sys_setfsuid16) | ||
273 | #define __NR_setfsgid 139 | ||
274 | __SYSCALL(__NR_setfsgid, sys_setfsgid16) | ||
275 | #define __NR__llseek 140 | ||
276 | __SYSCALL(__NR__llseek, sys_llseek) | ||
277 | #define __NR_getdents 141 | ||
278 | __SYSCALL(__NR_getdents, sys_getdents) | ||
279 | #define __NR__newselect 142 | ||
280 | __SYSCALL(__NR__newselect, sys_select) | ||
281 | #define __NR_flock 143 | ||
282 | __SYSCALL(__NR_flock, sys_flock) | ||
283 | #define __NR_msync 144 | ||
284 | __SYSCALL(__NR_msync, sys_msync) | ||
285 | #define __NR_readv 145 | ||
286 | __SYSCALL(__NR_readv, sys_readv) | ||
287 | #define __NR_writev 146 | ||
288 | __SYSCALL(__NR_writev, sys_writev) | ||
289 | #define __NR_getsid 147 | ||
290 | __SYSCALL(__NR_getsid, sys_getsid) | ||
291 | #define __NR_fdatasync 148 | ||
292 | __SYSCALL(__NR_fdatasync, sys_fdatasync) | ||
293 | #define __NR__sysctl 149 | ||
294 | __SYSCALL(__NR__sysctl, sys_sysctl) | ||
295 | #define __NR_mlock 150 | ||
296 | __SYSCALL(__NR_mlock, sys_mlock) | ||
297 | #define __NR_munlock 151 | ||
298 | __SYSCALL(__NR_munlock, sys_munlock) | ||
299 | #define __NR_mlockall 152 | ||
300 | __SYSCALL(__NR_mlockall, sys_mlockall) | ||
301 | #define __NR_munlockall 153 | ||
302 | __SYSCALL(__NR_munlockall, sys_munlockall) | ||
303 | #define __NR_sched_setparam 154 | ||
304 | __SYSCALL(__NR_sched_setparam, sys_sched_setparam) | ||
305 | #define __NR_sched_getparam 155 | ||
306 | __SYSCALL(__NR_sched_getparam, sys_sched_getparam) | ||
307 | #define __NR_sched_setscheduler 156 | ||
308 | __SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler) | ||
309 | #define __NR_sched_getscheduler 157 | ||
310 | __SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler) | ||
311 | #define __NR_sched_yield 158 | ||
312 | __SYSCALL(__NR_sched_yield, sys_sched_yield) | ||
313 | #define __NR_sched_get_priority_max 159 | ||
314 | __SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max) | ||
315 | #define __NR_sched_get_priority_min 160 | ||
316 | __SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min) | ||
317 | #define __NR_sched_rr_get_interval 161 | ||
318 | __SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval) | ||
319 | #define __NR_nanosleep 162 | ||
320 | __SYSCALL(__NR_nanosleep, sys_nanosleep) | ||
321 | #define __NR_mremap 163 | ||
322 | __SYSCALL(__NR_mremap, sys_mremap) | ||
323 | #define __NR_setresuid 164 | ||
324 | __SYSCALL(__NR_setresuid, sys_setresuid16) | ||
325 | #define __NR_getresuid 165 | ||
326 | __SYSCALL(__NR_getresuid, sys_getresuid16) | ||
327 | __SYSCALL(166, sys_ni_syscall) /* 166 was sys_vm86 */ | ||
328 | __SYSCALL(167, sys_ni_syscall) /* 167 was sys_query_module */ | ||
329 | #define __NR_poll 168 | ||
330 | __SYSCALL(__NR_poll, sys_poll) | ||
331 | #define __NR_nfsservctl 169 | ||
332 | __SYSCALL(__NR_nfsservctl, sys_ni_syscall) | ||
333 | #define __NR_setresgid 170 | ||
334 | __SYSCALL(__NR_setresgid, sys_setresgid16) | ||
335 | #define __NR_getresgid 171 | ||
336 | __SYSCALL(__NR_getresgid, sys_getresgid16) | ||
337 | #define __NR_prctl 172 | ||
338 | __SYSCALL(__NR_prctl, sys_prctl) | ||
339 | #define __NR_rt_sigreturn 173 | ||
340 | __SYSCALL(__NR_rt_sigreturn, sys_rt_sigreturn) | ||
341 | #define __NR_rt_sigaction 174 | ||
342 | __SYSCALL(__NR_rt_sigaction, sys_rt_sigaction) | ||
343 | #define __NR_rt_sigprocmask 175 | ||
344 | __SYSCALL(__NR_rt_sigprocmask, sys_rt_sigprocmask) | ||
345 | #define __NR_rt_sigpending 176 | ||
346 | __SYSCALL(__NR_rt_sigpending, sys_rt_sigpending) | ||
347 | #define __NR_rt_sigtimedwait 177 | ||
348 | __SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait) | ||
349 | #define __NR_rt_sigqueueinfo 178 | ||
350 | __SYSCALL(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo) | ||
351 | #define __NR_rt_sigsuspend 179 | ||
352 | __SYSCALL(__NR_rt_sigsuspend, sys_rt_sigsuspend) | ||
353 | #define __NR_pread64 180 | ||
354 | __SYSCALL(__NR_pread64, sys_pread64) | ||
355 | #define __NR_pwrite64 181 | ||
356 | __SYSCALL(__NR_pwrite64, sys_pwrite64) | ||
357 | #define __NR_chown 182 | ||
358 | __SYSCALL(__NR_chown, sys_chown16) | ||
359 | #define __NR_getcwd 183 | ||
360 | __SYSCALL(__NR_getcwd, sys_getcwd) | ||
361 | #define __NR_capget 184 | ||
362 | __SYSCALL(__NR_capget, sys_capget) | ||
363 | #define __NR_capset 185 | ||
364 | __SYSCALL(__NR_capset, sys_capset) | ||
365 | #define __NR_sigaltstack 186 | ||
366 | __SYSCALL(__NR_sigaltstack, sys_sigaltstack) | ||
367 | #define __NR_sendfile 187 | ||
368 | __SYSCALL(__NR_sendfile, sys_sendfile) | ||
369 | __SYSCALL(188, sys_ni_syscall) /* 188 reserved */ | ||
370 | __SYSCALL(189, sys_ni_syscall) /* 189 reserved */ | ||
371 | #define __NR_vfork 190 | ||
372 | __SYSCALL(__NR_vfork, sys_vfork) | ||
373 | #define __NR_ugetrlimit 191 /* SuS compliant getrlimit */ | ||
374 | __SYSCALL(__NR_ugetrlimit, sys_getrlimit) | ||
375 | #define __NR_mmap2 192 | ||
376 | __SYSCALL(__NR_mmap2, sys_mmap2) | ||
377 | #define __NR_truncate64 193 | ||
378 | __SYSCALL(__NR_truncate64, sys_truncate64) | ||
379 | #define __NR_ftruncate64 194 | ||
380 | __SYSCALL(__NR_ftruncate64, sys_ftruncate64) | ||
381 | #define __NR_stat64 195 | ||
382 | __SYSCALL(__NR_stat64, sys_stat64) | ||
383 | #define __NR_lstat64 196 | ||
384 | __SYSCALL(__NR_lstat64, sys_lstat64) | ||
385 | #define __NR_fstat64 197 | ||
386 | __SYSCALL(__NR_fstat64, sys_fstat64) | ||
387 | #define __NR_lchown32 198 | ||
388 | __SYSCALL(__NR_lchown32, sys_lchown) | ||
389 | #define __NR_getuid32 199 | ||
390 | __SYSCALL(__NR_getuid32, sys_getuid) | ||
391 | #define __NR_getgid32 200 | ||
392 | __SYSCALL(__NR_getgid32, sys_getgid) | ||
393 | #define __NR_geteuid32 201 | ||
394 | __SYSCALL(__NR_geteuid32, sys_geteuid) | ||
395 | #define __NR_getegid32 202 | ||
396 | __SYSCALL(__NR_getegid32, sys_getegid) | ||
397 | #define __NR_setreuid32 203 | ||
398 | __SYSCALL(__NR_setreuid32, sys_setreuid) | ||
399 | #define __NR_setregid32 204 | ||
400 | __SYSCALL(__NR_setregid32, sys_setregid) | ||
401 | #define __NR_getgroups32 205 | ||
402 | __SYSCALL(__NR_getgroups32, sys_getgroups) | ||
403 | #define __NR_setgroups32 206 | ||
404 | __SYSCALL(__NR_setgroups32, sys_setgroups) | ||
405 | #define __NR_fchown32 207 | ||
406 | __SYSCALL(__NR_fchown32, sys_fchown) | ||
407 | #define __NR_setresuid32 208 | ||
408 | __SYSCALL(__NR_setresuid32, sys_setresuid) | ||
409 | #define __NR_getresuid32 209 | ||
410 | __SYSCALL(__NR_getresuid32, sys_getresuid) | ||
411 | #define __NR_setresgid32 210 | ||
412 | __SYSCALL(__NR_setresgid32, sys_setresgid) | ||
413 | #define __NR_getresgid32 211 | ||
414 | __SYSCALL(__NR_getresgid32, sys_getresgid) | ||
415 | #define __NR_chown32 212 | ||
416 | __SYSCALL(__NR_chown32, sys_chown) | ||
417 | #define __NR_setuid32 213 | ||
418 | __SYSCALL(__NR_setuid32, sys_setuid) | ||
419 | #define __NR_setgid32 214 | ||
420 | __SYSCALL(__NR_setgid32, sys_setgid) | ||
421 | #define __NR_setfsuid32 215 | ||
422 | __SYSCALL(__NR_setfsuid32, sys_setfsuid) | ||
423 | #define __NR_setfsgid32 216 | ||
424 | __SYSCALL(__NR_setfsgid32, sys_setfsgid) | ||
425 | #define __NR_getdents64 217 | ||
426 | __SYSCALL(__NR_getdents64, sys_getdents64) | ||
427 | #define __NR_pivot_root 218 | ||
428 | __SYSCALL(__NR_pivot_root, sys_pivot_root) | ||
429 | #define __NR_mincore 219 | ||
430 | __SYSCALL(__NR_mincore, sys_mincore) | ||
431 | #define __NR_madvise 220 | ||
432 | __SYSCALL(__NR_madvise, sys_madvise) | ||
433 | #define __NR_fcntl64 221 | ||
434 | __SYSCALL(__NR_fcntl64, sys_fcntl64) | ||
435 | __SYSCALL(222, sys_ni_syscall) /* 222 for tux */ | ||
436 | __SYSCALL(223, sys_ni_syscall) /* 223 is unused */ | ||
437 | #define __NR_gettid 224 | ||
438 | __SYSCALL(__NR_gettid, sys_gettid) | ||
439 | #define __NR_readahead 225 | ||
440 | __SYSCALL(__NR_readahead, sys_readahead) | ||
441 | #define __NR_setxattr 226 | ||
442 | __SYSCALL(__NR_setxattr, sys_setxattr) | ||
443 | #define __NR_lsetxattr 227 | ||
444 | __SYSCALL(__NR_lsetxattr, sys_lsetxattr) | ||
445 | #define __NR_fsetxattr 228 | ||
446 | __SYSCALL(__NR_fsetxattr, sys_fsetxattr) | ||
447 | #define __NR_getxattr 229 | ||
448 | __SYSCALL(__NR_getxattr, sys_getxattr) | ||
449 | #define __NR_lgetxattr 230 | ||
450 | __SYSCALL(__NR_lgetxattr, sys_lgetxattr) | ||
451 | #define __NR_fgetxattr 231 | ||
452 | __SYSCALL(__NR_fgetxattr, sys_fgetxattr) | ||
453 | #define __NR_listxattr 232 | ||
454 | __SYSCALL(__NR_listxattr, sys_listxattr) | ||
455 | #define __NR_llistxattr 233 | ||
456 | __SYSCALL(__NR_llistxattr, sys_llistxattr) | ||
457 | #define __NR_flistxattr 234 | ||
458 | __SYSCALL(__NR_flistxattr, sys_flistxattr) | ||
459 | #define __NR_removexattr 235 | ||
460 | __SYSCALL(__NR_removexattr, sys_removexattr) | ||
461 | #define __NR_lremovexattr 236 | ||
462 | __SYSCALL(__NR_lremovexattr, sys_lremovexattr) | ||
463 | #define __NR_fremovexattr 237 | ||
464 | __SYSCALL(__NR_fremovexattr, sys_fremovexattr) | ||
465 | #define __NR_tkill 238 | ||
466 | __SYSCALL(__NR_tkill, sys_tkill) | ||
467 | #define __NR_sendfile64 239 | ||
468 | __SYSCALL(__NR_sendfile64, sys_sendfile64) | ||
469 | #define __NR_futex 240 | ||
470 | __SYSCALL(__NR_futex, sys_futex) | ||
471 | #define __NR_sched_setaffinity 241 | ||
472 | __SYSCALL(__NR_sched_setaffinity, sys_sched_setaffinity) | ||
473 | #define __NR_sched_getaffinity 242 | ||
474 | __SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity) | ||
475 | #define __NR_io_setup 243 | ||
476 | __SYSCALL(__NR_io_setup, sys_io_setup) | ||
477 | #define __NR_io_destroy 244 | ||
478 | __SYSCALL(__NR_io_destroy, sys_io_destroy) | ||
479 | #define __NR_io_getevents 245 | ||
480 | __SYSCALL(__NR_io_getevents, sys_io_getevents) | ||
481 | #define __NR_io_submit 246 | ||
482 | __SYSCALL(__NR_io_submit, sys_io_submit) | ||
483 | #define __NR_io_cancel 247 | ||
484 | __SYSCALL(__NR_io_cancel, sys_io_cancel) | ||
485 | #define __NR_exit_group 248 | ||
486 | __SYSCALL(__NR_exit_group, sys_exit_group) | ||
487 | #define __NR_lookup_dcookie 249 | ||
488 | __SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie) | ||
489 | #define __NR_epoll_create 250 | ||
490 | __SYSCALL(__NR_epoll_create, sys_epoll_create) | ||
491 | #define __NR_epoll_ctl 251 | ||
492 | __SYSCALL(__NR_epoll_ctl, sys_epoll_ctl) | ||
493 | #define __NR_epoll_wait 252 | ||
494 | __SYSCALL(__NR_epoll_wait, sys_epoll_wait) | ||
495 | #define __NR_remap_file_pages 253 | ||
496 | __SYSCALL(__NR_remap_file_pages, sys_remap_file_pages) | ||
497 | __SYSCALL(254, sys_ni_syscall) /* 254 for set_thread_area */ | ||
498 | __SYSCALL(255, sys_ni_syscall) /* 255 for get_thread_area */ | ||
499 | #define __NR_set_tid_address 256 | ||
500 | __SYSCALL(__NR_set_tid_address, sys_set_tid_address) | ||
501 | #define __NR_timer_create 257 | ||
502 | __SYSCALL(__NR_timer_create, sys_timer_create) | ||
503 | #define __NR_timer_settime 258 | ||
504 | __SYSCALL(__NR_timer_settime, sys_timer_settime) | ||
505 | #define __NR_timer_gettime 259 | ||
506 | __SYSCALL(__NR_timer_gettime, sys_timer_gettime) | ||
507 | #define __NR_timer_getoverrun 260 | ||
508 | __SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun) | ||
509 | #define __NR_timer_delete 261 | ||
510 | __SYSCALL(__NR_timer_delete, sys_timer_delete) | ||
511 | #define __NR_clock_settime 262 | ||
512 | __SYSCALL(__NR_clock_settime, sys_clock_settime) | ||
513 | #define __NR_clock_gettime 263 | ||
514 | __SYSCALL(__NR_clock_gettime, sys_clock_gettime) | ||
515 | #define __NR_clock_getres 264 | ||
516 | __SYSCALL(__NR_clock_getres, sys_clock_getres) | ||
517 | #define __NR_clock_nanosleep 265 | ||
518 | __SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep) | ||
519 | #define __NR_statfs64 266 | ||
520 | __SYSCALL(__NR_statfs64, sys_statfs64) | ||
521 | #define __NR_fstatfs64 267 | ||
522 | __SYSCALL(__NR_fstatfs64, sys_fstatfs64) | ||
523 | #define __NR_tgkill 268 | ||
524 | __SYSCALL(__NR_tgkill, sys_tgkill) | ||
525 | #define __NR_utimes 269 | ||
526 | __SYSCALL(__NR_utimes, sys_utimes) | ||
527 | #define __NR_fadvise64 270 | ||
528 | __SYSCALL(__NR_fadvise64, sys_fadvise64_64) | ||
529 | #define __NR_pciconfig_iobase 271 | ||
530 | __SYSCALL(__NR_pciconfig_iobase, sys_pciconfig_iobase) | ||
531 | #define __NR_pciconfig_read 272 | ||
532 | __SYSCALL(__NR_pciconfig_read, sys_pciconfig_read) | ||
533 | #define __NR_pciconfig_write 273 | ||
534 | __SYSCALL(__NR_pciconfig_write, sys_pciconfig_write) | ||
535 | #define __NR_mq_open 274 | ||
536 | __SYSCALL(__NR_mq_open, sys_mq_open) | ||
537 | #define __NR_mq_unlink 275 | ||
538 | __SYSCALL(__NR_mq_unlink, sys_mq_unlink) | ||
539 | #define __NR_mq_timedsend 276 | ||
540 | __SYSCALL(__NR_mq_timedsend, sys_mq_timedsend) | ||
541 | #define __NR_mq_timedreceive 277 | ||
542 | __SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive) | ||
543 | #define __NR_mq_notify 278 | ||
544 | __SYSCALL(__NR_mq_notify, sys_mq_notify) | ||
545 | #define __NR_mq_getsetattr 279 | ||
546 | __SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr) | ||
547 | #define __NR_waitid 280 | ||
548 | __SYSCALL(__NR_waitid, sys_waitid) | ||
549 | #define __NR_socket 281 | ||
550 | __SYSCALL(__NR_socket, sys_socket) | ||
551 | #define __NR_bind 282 | ||
552 | __SYSCALL(__NR_bind, sys_bind) | ||
553 | #define __NR_connect 283 | ||
554 | __SYSCALL(__NR_connect, sys_connect) | ||
555 | #define __NR_listen 284 | ||
556 | __SYSCALL(__NR_listen, sys_listen) | ||
557 | #define __NR_accept 285 | ||
558 | __SYSCALL(__NR_accept, sys_accept) | ||
559 | #define __NR_getsockname 286 | ||
560 | __SYSCALL(__NR_getsockname, sys_getsockname) | ||
561 | #define __NR_getpeername 287 | ||
562 | __SYSCALL(__NR_getpeername, sys_getpeername) | ||
563 | #define __NR_socketpair 288 | ||
564 | __SYSCALL(__NR_socketpair, sys_socketpair) | ||
565 | #define __NR_send 289 | ||
566 | __SYSCALL(__NR_send, sys_send) | ||
567 | #define __NR_sendto 290 | ||
568 | __SYSCALL(__NR_sendto, sys_sendto) | ||
569 | #define __NR_recv 291 | ||
570 | __SYSCALL(__NR_recv, sys_recv) | ||
571 | #define __NR_recvfrom 292 | ||
572 | __SYSCALL(__NR_recvfrom, sys_recvfrom) | ||
573 | #define __NR_shutdown 293 | ||
574 | __SYSCALL(__NR_shutdown, sys_shutdown) | ||
575 | #define __NR_setsockopt 294 | ||
576 | __SYSCALL(__NR_setsockopt, sys_setsockopt) | ||
577 | #define __NR_getsockopt 295 | ||
578 | __SYSCALL(__NR_getsockopt, sys_getsockopt) | ||
579 | #define __NR_sendmsg 296 | ||
580 | __SYSCALL(__NR_sendmsg, sys_sendmsg) | ||
581 | #define __NR_recvmsg 297 | ||
582 | __SYSCALL(__NR_recvmsg, sys_recvmsg) | ||
583 | #define __NR_semop 298 | ||
584 | __SYSCALL(__NR_semop, sys_semop) | ||
585 | #define __NR_semget 299 | ||
586 | __SYSCALL(__NR_semget, sys_semget) | ||
587 | #define __NR_semctl 300 | ||
588 | __SYSCALL(__NR_semctl, sys_semctl) | ||
589 | #define __NR_msgsnd 301 | ||
590 | __SYSCALL(__NR_msgsnd, sys_msgsnd) | ||
591 | #define __NR_msgrcv 302 | ||
592 | __SYSCALL(__NR_msgrcv, sys_msgrcv) | ||
593 | #define __NR_msgget 303 | ||
594 | __SYSCALL(__NR_msgget, sys_msgget) | ||
595 | #define __NR_msgctl 304 | ||
596 | __SYSCALL(__NR_msgctl, sys_msgctl) | ||
597 | #define __NR_shmat 305 | ||
598 | __SYSCALL(__NR_shmat, sys_shmat) | ||
599 | #define __NR_shmdt 306 | ||
600 | __SYSCALL(__NR_shmdt, sys_shmdt) | ||
601 | #define __NR_shmget 307 | ||
602 | __SYSCALL(__NR_shmget, sys_shmget) | ||
603 | #define __NR_shmctl 308 | ||
604 | __SYSCALL(__NR_shmctl, sys_shmctl) | ||
605 | #define __NR_add_key 309 | ||
606 | __SYSCALL(__NR_add_key, sys_add_key) | ||
607 | #define __NR_request_key 310 | ||
608 | __SYSCALL(__NR_request_key, sys_request_key) | ||
609 | #define __NR_keyctl 311 | ||
610 | __SYSCALL(__NR_keyctl, sys_keyctl) | ||
611 | #define __NR_semtimedop 312 | ||
612 | __SYSCALL(__NR_semtimedop, sys_semtimedop) | ||
613 | #define __NR_vserver 313 | ||
614 | __SYSCALL(__NR_vserver, sys_ni_syscall) | ||
615 | #define __NR_ioprio_set 314 | ||
616 | __SYSCALL(__NR_ioprio_set, sys_ioprio_set) | ||
617 | #define __NR_ioprio_get 315 | ||
618 | __SYSCALL(__NR_ioprio_get, sys_ioprio_get) | ||
619 | #define __NR_inotify_init 316 | ||
620 | __SYSCALL(__NR_inotify_init, sys_inotify_init) | ||
621 | #define __NR_inotify_add_watch 317 | ||
622 | __SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch) | ||
623 | #define __NR_inotify_rm_watch 318 | ||
624 | __SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch) | ||
625 | #define __NR_mbind 319 | ||
626 | __SYSCALL(__NR_mbind, sys_mbind) | ||
627 | #define __NR_get_mempolicy 320 | ||
628 | __SYSCALL(__NR_get_mempolicy, sys_get_mempolicy) | ||
629 | #define __NR_set_mempolicy 321 | ||
630 | __SYSCALL(__NR_set_mempolicy, sys_set_mempolicy) | ||
631 | #define __NR_openat 322 | ||
632 | __SYSCALL(__NR_openat, sys_openat) | ||
633 | #define __NR_mkdirat 323 | ||
634 | __SYSCALL(__NR_mkdirat, sys_mkdirat) | ||
635 | #define __NR_mknodat 324 | ||
636 | __SYSCALL(__NR_mknodat, sys_mknodat) | ||
637 | #define __NR_fchownat 325 | ||
638 | __SYSCALL(__NR_fchownat, sys_fchownat) | ||
639 | #define __NR_futimesat 326 | ||
640 | __SYSCALL(__NR_futimesat, sys_futimesat) | ||
641 | #define __NR_fstatat64 327 | ||
642 | __SYSCALL(__NR_fstatat64, sys_fstatat64) | ||
643 | #define __NR_unlinkat 328 | ||
644 | __SYSCALL(__NR_unlinkat, sys_unlinkat) | ||
645 | #define __NR_renameat 329 | ||
646 | __SYSCALL(__NR_renameat, sys_renameat) | ||
647 | #define __NR_linkat 330 | ||
648 | __SYSCALL(__NR_linkat, sys_linkat) | ||
649 | #define __NR_symlinkat 331 | ||
650 | __SYSCALL(__NR_symlinkat, sys_symlinkat) | ||
651 | #define __NR_readlinkat 332 | ||
652 | __SYSCALL(__NR_readlinkat, sys_readlinkat) | ||
653 | #define __NR_fchmodat 333 | ||
654 | __SYSCALL(__NR_fchmodat, sys_fchmodat) | ||
655 | #define __NR_faccessat 334 | ||
656 | __SYSCALL(__NR_faccessat, sys_faccessat) | ||
657 | #define __NR_pselect6 335 | ||
658 | __SYSCALL(__NR_pselect6, sys_pselect6) | ||
659 | #define __NR_ppoll 336 | ||
660 | __SYSCALL(__NR_ppoll, sys_ppoll) | ||
661 | #define __NR_unshare 337 | ||
662 | __SYSCALL(__NR_unshare, sys_unshare) | ||
663 | #define __NR_set_robust_list 338 | ||
664 | __SYSCALL(__NR_set_robust_list, sys_set_robust_list) | ||
665 | #define __NR_get_robust_list 339 | ||
666 | __SYSCALL(__NR_get_robust_list, sys_get_robust_list) | ||
667 | #define __NR_splice 340 | ||
668 | __SYSCALL(__NR_splice, sys_splice) | ||
669 | #define __NR_sync_file_range2 341 | ||
670 | __SYSCALL(__NR_sync_file_range2, sys_sync_file_range2) | ||
671 | #define __NR_tee 342 | ||
672 | __SYSCALL(__NR_tee, sys_tee) | ||
673 | #define __NR_vmsplice 343 | ||
674 | __SYSCALL(__NR_vmsplice, sys_vmsplice) | ||
675 | #define __NR_move_pages 344 | ||
676 | __SYSCALL(__NR_move_pages, sys_move_pages) | ||
677 | #define __NR_getcpu 345 | ||
678 | __SYSCALL(__NR_getcpu, sys_getcpu) | ||
679 | #define __NR_epoll_pwait 346 | ||
680 | __SYSCALL(__NR_epoll_pwait, sys_epoll_pwait) | ||
681 | #define __NR_kexec_load 347 | ||
682 | __SYSCALL(__NR_kexec_load, sys_kexec_load) | ||
683 | #define __NR_utimensat 348 | ||
684 | __SYSCALL(__NR_utimensat, sys_utimensat) | ||
685 | #define __NR_signalfd 349 | ||
686 | __SYSCALL(__NR_signalfd, sys_signalfd) | ||
687 | #define __NR_timerfd_create 350 | ||
688 | __SYSCALL(__NR_timerfd_create, sys_timerfd_create) | ||
689 | #define __NR_eventfd 351 | ||
690 | __SYSCALL(__NR_eventfd, sys_eventfd) | ||
691 | #define __NR_fallocate 352 | ||
692 | __SYSCALL(__NR_fallocate, sys_fallocate) | ||
693 | #define __NR_timerfd_settime 353 | ||
694 | __SYSCALL(__NR_timerfd_settime, sys_timerfd_settime) | ||
695 | #define __NR_timerfd_gettime 354 | ||
696 | __SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime) | ||
697 | #define __NR_signalfd4 355 | ||
698 | __SYSCALL(__NR_signalfd4, sys_signalfd4) | ||
699 | #define __NR_eventfd2 356 | ||
700 | __SYSCALL(__NR_eventfd2, sys_eventfd2) | ||
701 | #define __NR_epoll_create1 357 | ||
702 | __SYSCALL(__NR_epoll_create1, sys_epoll_create1) | ||
703 | #define __NR_dup3 358 | ||
704 | __SYSCALL(__NR_dup3, sys_dup3) | ||
705 | #define __NR_pipe2 359 | ||
706 | __SYSCALL(__NR_pipe2, sys_pipe2) | ||
707 | #define __NR_inotify_init1 360 | ||
708 | __SYSCALL(__NR_inotify_init1, sys_inotify_init1) | ||
709 | #define __NR_preadv 361 | ||
710 | __SYSCALL(__NR_preadv, sys_preadv) | ||
711 | #define __NR_pwritev 362 | ||
712 | __SYSCALL(__NR_pwritev, sys_pwritev) | ||
713 | #define __NR_rt_tgsigqueueinfo 363 | ||
714 | __SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo) | ||
715 | #define __NR_perf_event_open 364 | ||
716 | __SYSCALL(__NR_perf_event_open, sys_perf_event_open) | ||
717 | #define __NR_recvmmsg 365 | ||
718 | __SYSCALL(__NR_recvmmsg, sys_recvmmsg) | ||
719 | #define __NR_accept4 366 | ||
720 | __SYSCALL(__NR_accept4, sys_accept4) | ||
721 | #define __NR_fanotify_init 367 | ||
722 | __SYSCALL(__NR_fanotify_init, sys_fanotify_init) | ||
723 | #define __NR_fanotify_mark 368 | ||
724 | __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark) | ||
725 | #define __NR_prlimit64 369 | ||
726 | __SYSCALL(__NR_prlimit64, sys_prlimit64) | ||
727 | #define __NR_name_to_handle_at 370 | ||
728 | __SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at) | ||
729 | #define __NR_open_by_handle_at 371 | ||
730 | __SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at) | ||
731 | #define __NR_clock_adjtime 372 | ||
732 | __SYSCALL(__NR_clock_adjtime, sys_clock_adjtime) | ||
733 | #define __NR_syncfs 373 | ||
734 | __SYSCALL(__NR_syncfs, sys_syncfs) | ||
735 | |||
736 | /* | ||
737 | * The following SVCs are ARM private. | ||
738 | */ | ||
739 | #define __ARM_NR_COMPAT_BASE 0x0f0000 | ||
740 | #define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2) | ||
741 | #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5) | ||
742 | |||
743 | #endif /* __SYSCALL_COMPAT */ | ||
744 | |||
745 | #define __NR_compat_syscalls 374 | ||
746 | |||
747 | #define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION | ||
748 | #define __ARCH_WANT_COMPAT_STAT64 | ||
749 | #define __ARCH_WANT_SYS_GETHOSTNAME | ||
750 | #define __ARCH_WANT_SYS_PAUSE | ||
751 | #define __ARCH_WANT_SYS_GETPGRP | ||
752 | #define __ARCH_WANT_SYS_LLSEEK | ||
753 | #define __ARCH_WANT_SYS_NICE | ||
754 | #define __ARCH_WANT_SYS_SIGPENDING | ||
755 | #define __ARCH_WANT_SYS_SIGPROCMASK | ||
756 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | ||
757 | |||
758 | #endif /* __ASM_UNISTD32_H */ | ||
diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h new file mode 100644 index 000000000000..839ce0031bd5 --- /dev/null +++ b/arch/arm64/include/asm/vdso.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Limited | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_VDSO_H | ||
17 | #define __ASM_VDSO_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | /* | ||
22 | * Default link address for the vDSO. | ||
23 | * Since we randomise the VDSO mapping, there's little point in trying | ||
24 | * to prelink this. | ||
25 | */ | ||
26 | #define VDSO_LBASE 0x0 | ||
27 | |||
28 | #ifndef __ASSEMBLY__ | ||
29 | |||
30 | #include <generated/vdso-offsets.h> | ||
31 | |||
32 | #define VDSO_SYMBOL(base, name) \ | ||
33 | ({ \ | ||
34 | (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ | ||
35 | }) | ||
36 | |||
37 | #endif /* !__ASSEMBLY__ */ | ||
38 | |||
39 | #endif /* __KERNEL__ */ | ||
40 | |||
41 | #endif /* __ASM_VDSO_H */ | ||
diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h new file mode 100644 index 000000000000..de66199673d7 --- /dev/null +++ b/arch/arm64/include/asm/vdso_datapage.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Limited | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_VDSO_DATAPAGE_H | ||
17 | #define __ASM_VDSO_DATAPAGE_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | |||
23 | struct vdso_data { | ||
24 | __u64 cs_cycle_last; /* Timebase at clocksource init */ | ||
25 | __u64 xtime_clock_sec; /* Kernel time */ | ||
26 | __u64 xtime_clock_nsec; | ||
27 | __u64 xtime_coarse_sec; /* Coarse time */ | ||
28 | __u64 xtime_coarse_nsec; | ||
29 | __u64 wtm_clock_sec; /* Wall to monotonic time */ | ||
30 | __u64 wtm_clock_nsec; | ||
31 | __u32 tb_seq_count; /* Timebase sequence counter */ | ||
32 | __u32 cs_mult; /* Clocksource multiplier */ | ||
33 | __u32 cs_shift; /* Clocksource shift */ | ||
34 | __u32 tz_minuteswest; /* Whacky timezone stuff */ | ||
35 | __u32 tz_dsttime; | ||
36 | __u32 use_syscall; | ||
37 | }; | ||
38 | |||
39 | #endif /* !__ASSEMBLY__ */ | ||
40 | |||
41 | #endif /* __KERNEL__ */ | ||
42 | |||
43 | #endif /* __ASM_VDSO_DATAPAGE_H */ | ||
diff --git a/arch/arm64/kernel/.gitignore b/arch/arm64/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/arm64/kernel/.gitignore | |||
@@ -0,0 +1 @@ | |||
vmlinux.lds | |||
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile new file mode 100644 index 000000000000..e2caff1b812a --- /dev/null +++ b/arch/arm64/kernel/Makefile | |||
@@ -0,0 +1,27 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) | ||
6 | AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) | ||
7 | |||
8 | # Object file lists. | ||
9 | arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ | ||
10 | entry-fpsimd.o process.o ptrace.o setup.o signal.o \ | ||
11 | sys.o stacktrace.o time.o traps.o io.o vdso.o | ||
12 | |||
13 | arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ | ||
14 | sys_compat.o | ||
15 | arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o | ||
16 | arm64-obj-$(CONFIG_SMP) += smp.o | ||
17 | arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o | ||
18 | arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o | ||
19 | |||
20 | obj-y += $(arm64-obj-y) vdso/ | ||
21 | obj-m += $(arm64-obj-m) | ||
22 | head-y := head.o | ||
23 | extra-y := $(head-y) vmlinux.lds | ||
24 | |||
25 | # vDSO - this must be built first to generate the symbol offsets | ||
26 | $(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h | ||
27 | $(obj)/vdso/vdso-offsets.h: $(obj)/vdso | ||
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c new file mode 100644 index 000000000000..cef3925eaf60 --- /dev/null +++ b/arch/arm64/kernel/arm64ksyms.c | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/armksyms.c | ||
3 | * | ||
4 | * Copyright (C) 2000 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/export.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/cryptohash.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/in6.h> | ||
26 | #include <linux/syscalls.h> | ||
27 | #include <linux/uaccess.h> | ||
28 | #include <linux/io.h> | ||
29 | |||
30 | #include <asm/checksum.h> | ||
31 | |||
32 | /* user mem (segment) */ | ||
33 | EXPORT_SYMBOL(__strnlen_user); | ||
34 | EXPORT_SYMBOL(__strncpy_from_user); | ||
35 | |||
36 | EXPORT_SYMBOL(copy_page); | ||
37 | |||
38 | EXPORT_SYMBOL(__copy_from_user); | ||
39 | EXPORT_SYMBOL(__copy_to_user); | ||
40 | EXPORT_SYMBOL(__clear_user); | ||
41 | |||
42 | /* bitops */ | ||
43 | EXPORT_SYMBOL(__atomic_hash); | ||
44 | |||
45 | /* physical memory */ | ||
46 | EXPORT_SYMBOL(memstart_addr); | ||
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c new file mode 100644 index 000000000000..a2a4d810bea3 --- /dev/null +++ b/arch/arm64/kernel/asm-offsets.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/asm-offsets.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2003 Russell King | ||
5 | * 2001-2002 Keith Owens | ||
6 | * Copyright (C) 2012 ARM Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/sched.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <asm/thread_info.h> | ||
25 | #include <asm/memory.h> | ||
26 | #include <asm/cputable.h> | ||
27 | #include <asm/vdso_datapage.h> | ||
28 | #include <linux/kbuild.h> | ||
29 | |||
30 | int main(void) | ||
31 | { | ||
32 | DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); | ||
33 | BLANK(); | ||
34 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | ||
35 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); | ||
36 | DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); | ||
37 | DEFINE(TI_TASK, offsetof(struct thread_info, task)); | ||
38 | DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); | ||
39 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); | ||
40 | BLANK(); | ||
41 | DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context)); | ||
42 | BLANK(); | ||
43 | DEFINE(S_X0, offsetof(struct pt_regs, regs[0])); | ||
44 | DEFINE(S_X1, offsetof(struct pt_regs, regs[1])); | ||
45 | DEFINE(S_X2, offsetof(struct pt_regs, regs[2])); | ||
46 | DEFINE(S_X3, offsetof(struct pt_regs, regs[3])); | ||
47 | DEFINE(S_X4, offsetof(struct pt_regs, regs[4])); | ||
48 | DEFINE(S_X5, offsetof(struct pt_regs, regs[5])); | ||
49 | DEFINE(S_X6, offsetof(struct pt_regs, regs[6])); | ||
50 | DEFINE(S_X7, offsetof(struct pt_regs, regs[7])); | ||
51 | DEFINE(S_LR, offsetof(struct pt_regs, regs[30])); | ||
52 | DEFINE(S_SP, offsetof(struct pt_regs, sp)); | ||
53 | #ifdef CONFIG_COMPAT | ||
54 | DEFINE(S_COMPAT_SP, offsetof(struct pt_regs, compat_sp)); | ||
55 | #endif | ||
56 | DEFINE(S_PSTATE, offsetof(struct pt_regs, pstate)); | ||
57 | DEFINE(S_PC, offsetof(struct pt_regs, pc)); | ||
58 | DEFINE(S_ORIG_X0, offsetof(struct pt_regs, orig_x0)); | ||
59 | DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno)); | ||
60 | DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); | ||
61 | BLANK(); | ||
62 | DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); | ||
63 | BLANK(); | ||
64 | DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); | ||
65 | DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags)); | ||
66 | BLANK(); | ||
67 | DEFINE(VM_EXEC, VM_EXEC); | ||
68 | BLANK(); | ||
69 | DEFINE(PAGE_SZ, PAGE_SIZE); | ||
70 | BLANK(); | ||
71 | DEFINE(CPU_INFO_SZ, sizeof(struct cpu_info)); | ||
72 | DEFINE(CPU_INFO_SETUP, offsetof(struct cpu_info, cpu_setup)); | ||
73 | BLANK(); | ||
74 | DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL); | ||
75 | DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); | ||
76 | DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); | ||
77 | BLANK(); | ||
78 | DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); | ||
79 | DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); | ||
80 | DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); | ||
81 | DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE); | ||
82 | DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE); | ||
83 | DEFINE(CLOCK_COARSE_RES, LOW_RES_NSEC); | ||
84 | DEFINE(NSEC_PER_SEC, NSEC_PER_SEC); | ||
85 | BLANK(); | ||
86 | DEFINE(VDSO_CS_CYCLE_LAST, offsetof(struct vdso_data, cs_cycle_last)); | ||
87 | DEFINE(VDSO_XTIME_CLK_SEC, offsetof(struct vdso_data, xtime_clock_sec)); | ||
88 | DEFINE(VDSO_XTIME_CLK_NSEC, offsetof(struct vdso_data, xtime_clock_nsec)); | ||
89 | DEFINE(VDSO_XTIME_CRS_SEC, offsetof(struct vdso_data, xtime_coarse_sec)); | ||
90 | DEFINE(VDSO_XTIME_CRS_NSEC, offsetof(struct vdso_data, xtime_coarse_nsec)); | ||
91 | DEFINE(VDSO_WTM_CLK_SEC, offsetof(struct vdso_data, wtm_clock_sec)); | ||
92 | DEFINE(VDSO_WTM_CLK_NSEC, offsetof(struct vdso_data, wtm_clock_nsec)); | ||
93 | DEFINE(VDSO_TB_SEQ_COUNT, offsetof(struct vdso_data, tb_seq_count)); | ||
94 | DEFINE(VDSO_CS_MULT, offsetof(struct vdso_data, cs_mult)); | ||
95 | DEFINE(VDSO_CS_SHIFT, offsetof(struct vdso_data, cs_shift)); | ||
96 | DEFINE(VDSO_TZ_MINWEST, offsetof(struct vdso_data, tz_minuteswest)); | ||
97 | DEFINE(VDSO_TZ_DSTTIME, offsetof(struct vdso_data, tz_dsttime)); | ||
98 | DEFINE(VDSO_USE_SYSCALL, offsetof(struct vdso_data, use_syscall)); | ||
99 | BLANK(); | ||
100 | DEFINE(TVAL_TV_SEC, offsetof(struct timeval, tv_sec)); | ||
101 | DEFINE(TVAL_TV_USEC, offsetof(struct timeval, tv_usec)); | ||
102 | DEFINE(TSPEC_TV_SEC, offsetof(struct timespec, tv_sec)); | ||
103 | DEFINE(TSPEC_TV_NSEC, offsetof(struct timespec, tv_nsec)); | ||
104 | BLANK(); | ||
105 | DEFINE(TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); | ||
106 | DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); | ||
107 | return 0; | ||
108 | } | ||
diff --git a/arch/arm64/kernel/cputable.c b/arch/arm64/kernel/cputable.c new file mode 100644 index 000000000000..63cfc4a43f4e --- /dev/null +++ b/arch/arm64/kernel/cputable.c | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * arch/arm64/kernel/cputable.c | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/init.h> | ||
20 | |||
21 | #include <asm/cputable.h> | ||
22 | |||
23 | extern unsigned long __cpu_setup(void); | ||
24 | |||
25 | struct cpu_info __initdata cpu_table[] = { | ||
26 | { | ||
27 | .cpu_id_val = 0x000f0000, | ||
28 | .cpu_id_mask = 0x000f0000, | ||
29 | .cpu_name = "AArch64 Processor", | ||
30 | .cpu_setup = __cpu_setup, | ||
31 | }, | ||
32 | { /* Empty */ }, | ||
33 | }; | ||
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c new file mode 100644 index 000000000000..0c3ba9f51376 --- /dev/null +++ b/arch/arm64/kernel/debug-monitors.c | |||
@@ -0,0 +1,288 @@ | |||
1 | /* | ||
2 | * ARMv8 single-step debug support and mdscr context switching. | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Limited | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Author: Will Deacon <will.deacon@arm.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/cpu.h> | ||
22 | #include <linux/debugfs.h> | ||
23 | #include <linux/hardirq.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/ptrace.h> | ||
26 | #include <linux/stat.h> | ||
27 | |||
28 | #include <asm/debug-monitors.h> | ||
29 | #include <asm/local.h> | ||
30 | #include <asm/cputype.h> | ||
31 | #include <asm/system_misc.h> | ||
32 | |||
33 | /* Low-level stepping controls. */ | ||
34 | #define DBG_MDSCR_SS (1 << 0) | ||
35 | #define DBG_SPSR_SS (1 << 21) | ||
36 | |||
37 | /* MDSCR_EL1 enabling bits */ | ||
38 | #define DBG_MDSCR_KDE (1 << 13) | ||
39 | #define DBG_MDSCR_MDE (1 << 15) | ||
40 | #define DBG_MDSCR_MASK ~(DBG_MDSCR_KDE | DBG_MDSCR_MDE) | ||
41 | |||
42 | /* Determine debug architecture. */ | ||
43 | u8 debug_monitors_arch(void) | ||
44 | { | ||
45 | return read_cpuid(ID_AA64DFR0_EL1) & 0xf; | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * MDSCR access routines. | ||
50 | */ | ||
51 | static void mdscr_write(u32 mdscr) | ||
52 | { | ||
53 | unsigned long flags; | ||
54 | local_dbg_save(flags); | ||
55 | asm volatile("msr mdscr_el1, %0" :: "r" (mdscr)); | ||
56 | local_dbg_restore(flags); | ||
57 | } | ||
58 | |||
59 | static u32 mdscr_read(void) | ||
60 | { | ||
61 | u32 mdscr; | ||
62 | asm volatile("mrs %0, mdscr_el1" : "=r" (mdscr)); | ||
63 | return mdscr; | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Allow root to disable self-hosted debug from userspace. | ||
68 | * This is useful if you want to connect an external JTAG debugger. | ||
69 | */ | ||
70 | static u32 debug_enabled = 1; | ||
71 | |||
72 | static int create_debug_debugfs_entry(void) | ||
73 | { | ||
74 | debugfs_create_bool("debug_enabled", 0644, NULL, &debug_enabled); | ||
75 | return 0; | ||
76 | } | ||
77 | fs_initcall(create_debug_debugfs_entry); | ||
78 | |||
79 | static int __init early_debug_disable(char *buf) | ||
80 | { | ||
81 | debug_enabled = 0; | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | early_param("nodebugmon", early_debug_disable); | ||
86 | |||
87 | /* | ||
88 | * Keep track of debug users on each core. | ||
89 | * The ref counts are per-cpu so we use a local_t type. | ||
90 | */ | ||
91 | static DEFINE_PER_CPU(local_t, mde_ref_count); | ||
92 | static DEFINE_PER_CPU(local_t, kde_ref_count); | ||
93 | |||
94 | void enable_debug_monitors(enum debug_el el) | ||
95 | { | ||
96 | u32 mdscr, enable = 0; | ||
97 | |||
98 | WARN_ON(preemptible()); | ||
99 | |||
100 | if (local_inc_return(&__get_cpu_var(mde_ref_count)) == 1) | ||
101 | enable = DBG_MDSCR_MDE; | ||
102 | |||
103 | if (el == DBG_ACTIVE_EL1 && | ||
104 | local_inc_return(&__get_cpu_var(kde_ref_count)) == 1) | ||
105 | enable |= DBG_MDSCR_KDE; | ||
106 | |||
107 | if (enable && debug_enabled) { | ||
108 | mdscr = mdscr_read(); | ||
109 | mdscr |= enable; | ||
110 | mdscr_write(mdscr); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | void disable_debug_monitors(enum debug_el el) | ||
115 | { | ||
116 | u32 mdscr, disable = 0; | ||
117 | |||
118 | WARN_ON(preemptible()); | ||
119 | |||
120 | if (local_dec_and_test(&__get_cpu_var(mde_ref_count))) | ||
121 | disable = ~DBG_MDSCR_MDE; | ||
122 | |||
123 | if (el == DBG_ACTIVE_EL1 && | ||
124 | local_dec_and_test(&__get_cpu_var(kde_ref_count))) | ||
125 | disable &= ~DBG_MDSCR_KDE; | ||
126 | |||
127 | if (disable) { | ||
128 | mdscr = mdscr_read(); | ||
129 | mdscr &= disable; | ||
130 | mdscr_write(mdscr); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * OS lock clearing. | ||
136 | */ | ||
137 | static void clear_os_lock(void *unused) | ||
138 | { | ||
139 | asm volatile("msr mdscr_el1, %0" : : "r" (0)); | ||
140 | isb(); | ||
141 | asm volatile("msr oslar_el1, %0" : : "r" (0)); | ||
142 | isb(); | ||
143 | } | ||
144 | |||
145 | static int __cpuinit os_lock_notify(struct notifier_block *self, | ||
146 | unsigned long action, void *data) | ||
147 | { | ||
148 | int cpu = (unsigned long)data; | ||
149 | if (action == CPU_ONLINE) | ||
150 | smp_call_function_single(cpu, clear_os_lock, NULL, 1); | ||
151 | return NOTIFY_OK; | ||
152 | } | ||
153 | |||
154 | static struct notifier_block __cpuinitdata os_lock_nb = { | ||
155 | .notifier_call = os_lock_notify, | ||
156 | }; | ||
157 | |||
158 | static int __cpuinit debug_monitors_init(void) | ||
159 | { | ||
160 | /* Clear the OS lock. */ | ||
161 | smp_call_function(clear_os_lock, NULL, 1); | ||
162 | clear_os_lock(NULL); | ||
163 | |||
164 | /* Register hotplug handler. */ | ||
165 | register_cpu_notifier(&os_lock_nb); | ||
166 | return 0; | ||
167 | } | ||
168 | postcore_initcall(debug_monitors_init); | ||
169 | |||
170 | /* | ||
171 | * Single step API and exception handling. | ||
172 | */ | ||
173 | static void set_regs_spsr_ss(struct pt_regs *regs) | ||
174 | { | ||
175 | unsigned long spsr; | ||
176 | |||
177 | spsr = regs->pstate; | ||
178 | spsr &= ~DBG_SPSR_SS; | ||
179 | spsr |= DBG_SPSR_SS; | ||
180 | regs->pstate = spsr; | ||
181 | } | ||
182 | |||
183 | static void clear_regs_spsr_ss(struct pt_regs *regs) | ||
184 | { | ||
185 | unsigned long spsr; | ||
186 | |||
187 | spsr = regs->pstate; | ||
188 | spsr &= ~DBG_SPSR_SS; | ||
189 | regs->pstate = spsr; | ||
190 | } | ||
191 | |||
192 | static int single_step_handler(unsigned long addr, unsigned int esr, | ||
193 | struct pt_regs *regs) | ||
194 | { | ||
195 | siginfo_t info; | ||
196 | |||
197 | /* | ||
198 | * If we are stepping a pending breakpoint, call the hw_breakpoint | ||
199 | * handler first. | ||
200 | */ | ||
201 | if (!reinstall_suspended_bps(regs)) | ||
202 | return 0; | ||
203 | |||
204 | if (user_mode(regs)) { | ||
205 | info.si_signo = SIGTRAP; | ||
206 | info.si_errno = 0; | ||
207 | info.si_code = TRAP_HWBKPT; | ||
208 | info.si_addr = (void __user *)instruction_pointer(regs); | ||
209 | force_sig_info(SIGTRAP, &info, current); | ||
210 | |||
211 | /* | ||
212 | * ptrace will disable single step unless explicitly | ||
213 | * asked to re-enable it. For other clients, it makes | ||
214 | * sense to leave it enabled (i.e. rewind the controls | ||
215 | * to the active-not-pending state). | ||
216 | */ | ||
217 | user_rewind_single_step(current); | ||
218 | } else { | ||
219 | /* TODO: route to KGDB */ | ||
220 | pr_warning("Unexpected kernel single-step exception at EL1\n"); | ||
221 | /* | ||
222 | * Re-enable stepping since we know that we will be | ||
223 | * returning to regs. | ||
224 | */ | ||
225 | set_regs_spsr_ss(regs); | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int __init single_step_init(void) | ||
232 | { | ||
233 | hook_debug_fault_code(DBG_ESR_EVT_HWSS, single_step_handler, SIGTRAP, | ||
234 | TRAP_HWBKPT, "single-step handler"); | ||
235 | return 0; | ||
236 | } | ||
237 | arch_initcall(single_step_init); | ||
238 | |||
239 | /* Re-enable single step for syscall restarting. */ | ||
240 | void user_rewind_single_step(struct task_struct *task) | ||
241 | { | ||
242 | /* | ||
243 | * If single step is active for this thread, then set SPSR.SS | ||
244 | * to 1 to avoid returning to the active-pending state. | ||
245 | */ | ||
246 | if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP)) | ||
247 | set_regs_spsr_ss(task_pt_regs(task)); | ||
248 | } | ||
249 | |||
250 | void user_fastforward_single_step(struct task_struct *task) | ||
251 | { | ||
252 | if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP)) | ||
253 | clear_regs_spsr_ss(task_pt_regs(task)); | ||
254 | } | ||
255 | |||
256 | /* Kernel API */ | ||
257 | void kernel_enable_single_step(struct pt_regs *regs) | ||
258 | { | ||
259 | WARN_ON(!irqs_disabled()); | ||
260 | set_regs_spsr_ss(regs); | ||
261 | mdscr_write(mdscr_read() | DBG_MDSCR_SS); | ||
262 | enable_debug_monitors(DBG_ACTIVE_EL1); | ||
263 | } | ||
264 | |||
265 | void kernel_disable_single_step(void) | ||
266 | { | ||
267 | WARN_ON(!irqs_disabled()); | ||
268 | mdscr_write(mdscr_read() & ~DBG_MDSCR_SS); | ||
269 | disable_debug_monitors(DBG_ACTIVE_EL1); | ||
270 | } | ||
271 | |||
272 | int kernel_active_single_step(void) | ||
273 | { | ||
274 | WARN_ON(!irqs_disabled()); | ||
275 | return mdscr_read() & DBG_MDSCR_SS; | ||
276 | } | ||
277 | |||
278 | /* ptrace API */ | ||
279 | void user_enable_single_step(struct task_struct *task) | ||
280 | { | ||
281 | set_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP); | ||
282 | set_regs_spsr_ss(task_pt_regs(task)); | ||
283 | } | ||
284 | |||
285 | void user_disable_single_step(struct task_struct *task) | ||
286 | { | ||
287 | clear_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP); | ||
288 | } | ||
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S new file mode 100644 index 000000000000..17988a6e7ea2 --- /dev/null +++ b/arch/arm64/kernel/entry-fpsimd.S | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * FP/SIMD state saving and restoring | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/linkage.h> | ||
21 | |||
22 | #include <asm/assembler.h> | ||
23 | |||
24 | /* | ||
25 | * Save the FP registers. | ||
26 | * | ||
27 | * x0 - pointer to struct fpsimd_state | ||
28 | */ | ||
29 | ENTRY(fpsimd_save_state) | ||
30 | stp q0, q1, [x0, #16 * 0] | ||
31 | stp q2, q3, [x0, #16 * 2] | ||
32 | stp q4, q5, [x0, #16 * 4] | ||
33 | stp q6, q7, [x0, #16 * 6] | ||
34 | stp q8, q9, [x0, #16 * 8] | ||
35 | stp q10, q11, [x0, #16 * 10] | ||
36 | stp q12, q13, [x0, #16 * 12] | ||
37 | stp q14, q15, [x0, #16 * 14] | ||
38 | stp q16, q17, [x0, #16 * 16] | ||
39 | stp q18, q19, [x0, #16 * 18] | ||
40 | stp q20, q21, [x0, #16 * 20] | ||
41 | stp q22, q23, [x0, #16 * 22] | ||
42 | stp q24, q25, [x0, #16 * 24] | ||
43 | stp q26, q27, [x0, #16 * 26] | ||
44 | stp q28, q29, [x0, #16 * 28] | ||
45 | stp q30, q31, [x0, #16 * 30]! | ||
46 | mrs x8, fpsr | ||
47 | str w8, [x0, #16 * 2] | ||
48 | mrs x8, fpcr | ||
49 | str w8, [x0, #16 * 2 + 4] | ||
50 | ret | ||
51 | ENDPROC(fpsimd_save_state) | ||
52 | |||
53 | /* | ||
54 | * Load the FP registers. | ||
55 | * | ||
56 | * x0 - pointer to struct fpsimd_state | ||
57 | */ | ||
58 | ENTRY(fpsimd_load_state) | ||
59 | ldp q0, q1, [x0, #16 * 0] | ||
60 | ldp q2, q3, [x0, #16 * 2] | ||
61 | ldp q4, q5, [x0, #16 * 4] | ||
62 | ldp q6, q7, [x0, #16 * 6] | ||
63 | ldp q8, q9, [x0, #16 * 8] | ||
64 | ldp q10, q11, [x0, #16 * 10] | ||
65 | ldp q12, q13, [x0, #16 * 12] | ||
66 | ldp q14, q15, [x0, #16 * 14] | ||
67 | ldp q16, q17, [x0, #16 * 16] | ||
68 | ldp q18, q19, [x0, #16 * 18] | ||
69 | ldp q20, q21, [x0, #16 * 20] | ||
70 | ldp q22, q23, [x0, #16 * 22] | ||
71 | ldp q24, q25, [x0, #16 * 24] | ||
72 | ldp q26, q27, [x0, #16 * 26] | ||
73 | ldp q28, q29, [x0, #16 * 28] | ||
74 | ldp q30, q31, [x0, #16 * 30]! | ||
75 | ldr w8, [x0, #16 * 2] | ||
76 | ldr w9, [x0, #16 * 2 + 4] | ||
77 | msr fpsr, x8 | ||
78 | msr fpcr, x9 | ||
79 | ret | ||
80 | ENDPROC(fpsimd_load_state) | ||
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S new file mode 100644 index 000000000000..38cf853a3667 --- /dev/null +++ b/arch/arm64/kernel/entry.S | |||
@@ -0,0 +1,695 @@ | |||
1 | /* | ||
2 | * Low-level exception handling code | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * Authors: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * Will Deacon <will.deacon@arm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/linkage.h> | ||
23 | |||
24 | #include <asm/assembler.h> | ||
25 | #include <asm/asm-offsets.h> | ||
26 | #include <asm/errno.h> | ||
27 | #include <asm/thread_info.h> | ||
28 | #include <asm/unistd.h> | ||
29 | |||
30 | /* | ||
31 | * Bad Abort numbers | ||
32 | *----------------- | ||
33 | */ | ||
34 | #define BAD_SYNC 0 | ||
35 | #define BAD_IRQ 1 | ||
36 | #define BAD_FIQ 2 | ||
37 | #define BAD_ERROR 3 | ||
38 | |||
39 | .macro kernel_entry, el, regsize = 64 | ||
40 | sub sp, sp, #S_FRAME_SIZE - S_LR // room for LR, SP, SPSR, ELR | ||
41 | .if \regsize == 32 | ||
42 | mov w0, w0 // zero upper 32 bits of x0 | ||
43 | .endif | ||
44 | push x28, x29 | ||
45 | push x26, x27 | ||
46 | push x24, x25 | ||
47 | push x22, x23 | ||
48 | push x20, x21 | ||
49 | push x18, x19 | ||
50 | push x16, x17 | ||
51 | push x14, x15 | ||
52 | push x12, x13 | ||
53 | push x10, x11 | ||
54 | push x8, x9 | ||
55 | push x6, x7 | ||
56 | push x4, x5 | ||
57 | push x2, x3 | ||
58 | push x0, x1 | ||
59 | .if \el == 0 | ||
60 | mrs x21, sp_el0 | ||
61 | .else | ||
62 | add x21, sp, #S_FRAME_SIZE | ||
63 | .endif | ||
64 | mrs x22, elr_el1 | ||
65 | mrs x23, spsr_el1 | ||
66 | stp lr, x21, [sp, #S_LR] | ||
67 | stp x22, x23, [sp, #S_PC] | ||
68 | |||
69 | /* | ||
70 | * Set syscallno to -1 by default (overridden later if real syscall). | ||
71 | */ | ||
72 | .if \el == 0 | ||
73 | mvn x21, xzr | ||
74 | str x21, [sp, #S_SYSCALLNO] | ||
75 | .endif | ||
76 | |||
77 | /* | ||
78 | * Registers that may be useful after this macro is invoked: | ||
79 | * | ||
80 | * x21 - aborted SP | ||
81 | * x22 - aborted PC | ||
82 | * x23 - aborted PSTATE | ||
83 | */ | ||
84 | .endm | ||
85 | |||
86 | .macro kernel_exit, el, ret = 0 | ||
87 | ldp x21, x22, [sp, #S_PC] // load ELR, SPSR | ||
88 | .if \el == 0 | ||
89 | ldr x23, [sp, #S_SP] // load return stack pointer | ||
90 | .endif | ||
91 | .if \ret | ||
92 | ldr x1, [sp, #S_X1] // preserve x0 (syscall return) | ||
93 | add sp, sp, S_X2 | ||
94 | .else | ||
95 | pop x0, x1 | ||
96 | .endif | ||
97 | pop x2, x3 // load the rest of the registers | ||
98 | pop x4, x5 | ||
99 | pop x6, x7 | ||
100 | pop x8, x9 | ||
101 | msr elr_el1, x21 // set up the return data | ||
102 | msr spsr_el1, x22 | ||
103 | .if \el == 0 | ||
104 | msr sp_el0, x23 | ||
105 | .endif | ||
106 | pop x10, x11 | ||
107 | pop x12, x13 | ||
108 | pop x14, x15 | ||
109 | pop x16, x17 | ||
110 | pop x18, x19 | ||
111 | pop x20, x21 | ||
112 | pop x22, x23 | ||
113 | pop x24, x25 | ||
114 | pop x26, x27 | ||
115 | pop x28, x29 | ||
116 | ldr lr, [sp], #S_FRAME_SIZE - S_LR // load LR and restore SP | ||
117 | eret // return to kernel | ||
118 | .endm | ||
119 | |||
120 | .macro get_thread_info, rd | ||
121 | mov \rd, sp | ||
122 | and \rd, \rd, #~((1 << 13) - 1) // top of 8K stack | ||
123 | .endm | ||
124 | |||
125 | /* | ||
126 | * These are the registers used in the syscall handler, and allow us to | ||
127 | * have in theory up to 7 arguments to a function - x0 to x6. | ||
128 | * | ||
129 | * x7 is reserved for the system call number in 32-bit mode. | ||
130 | */ | ||
131 | sc_nr .req x25 // number of system calls | ||
132 | scno .req x26 // syscall number | ||
133 | stbl .req x27 // syscall table pointer | ||
134 | tsk .req x28 // current thread_info | ||
135 | |||
136 | /* | ||
137 | * Interrupt handling. | ||
138 | */ | ||
139 | .macro irq_handler | ||
140 | ldr x1, handle_arch_irq | ||
141 | mov x0, sp | ||
142 | blr x1 | ||
143 | .endm | ||
144 | |||
145 | .text | ||
146 | |||
147 | /* | ||
148 | * Exception vectors. | ||
149 | */ | ||
150 | .macro ventry label | ||
151 | .align 7 | ||
152 | b \label | ||
153 | .endm | ||
154 | |||
155 | .align 11 | ||
156 | ENTRY(vectors) | ||
157 | ventry el1_sync_invalid // Synchronous EL1t | ||
158 | ventry el1_irq_invalid // IRQ EL1t | ||
159 | ventry el1_fiq_invalid // FIQ EL1t | ||
160 | ventry el1_error_invalid // Error EL1t | ||
161 | |||
162 | ventry el1_sync // Synchronous EL1h | ||
163 | ventry el1_irq // IRQ EL1h | ||
164 | ventry el1_fiq_invalid // FIQ EL1h | ||
165 | ventry el1_error_invalid // Error EL1h | ||
166 | |||
167 | ventry el0_sync // Synchronous 64-bit EL0 | ||
168 | ventry el0_irq // IRQ 64-bit EL0 | ||
169 | ventry el0_fiq_invalid // FIQ 64-bit EL0 | ||
170 | ventry el0_error_invalid // Error 64-bit EL0 | ||
171 | |||
172 | #ifdef CONFIG_COMPAT | ||
173 | ventry el0_sync_compat // Synchronous 32-bit EL0 | ||
174 | ventry el0_irq_compat // IRQ 32-bit EL0 | ||
175 | ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 | ||
176 | ventry el0_error_invalid_compat // Error 32-bit EL0 | ||
177 | #else | ||
178 | ventry el0_sync_invalid // Synchronous 32-bit EL0 | ||
179 | ventry el0_irq_invalid // IRQ 32-bit EL0 | ||
180 | ventry el0_fiq_invalid // FIQ 32-bit EL0 | ||
181 | ventry el0_error_invalid // Error 32-bit EL0 | ||
182 | #endif | ||
183 | END(vectors) | ||
184 | |||
185 | /* | ||
186 | * Invalid mode handlers | ||
187 | */ | ||
188 | .macro inv_entry, el, reason, regsize = 64 | ||
189 | kernel_entry el, \regsize | ||
190 | mov x0, sp | ||
191 | mov x1, #\reason | ||
192 | mrs x2, esr_el1 | ||
193 | b bad_mode | ||
194 | .endm | ||
195 | |||
196 | el0_sync_invalid: | ||
197 | inv_entry 0, BAD_SYNC | ||
198 | ENDPROC(el0_sync_invalid) | ||
199 | |||
200 | el0_irq_invalid: | ||
201 | inv_entry 0, BAD_IRQ | ||
202 | ENDPROC(el0_irq_invalid) | ||
203 | |||
204 | el0_fiq_invalid: | ||
205 | inv_entry 0, BAD_FIQ | ||
206 | ENDPROC(el0_fiq_invalid) | ||
207 | |||
208 | el0_error_invalid: | ||
209 | inv_entry 0, BAD_ERROR | ||
210 | ENDPROC(el0_error_invalid) | ||
211 | |||
212 | #ifdef CONFIG_COMPAT | ||
213 | el0_fiq_invalid_compat: | ||
214 | inv_entry 0, BAD_FIQ, 32 | ||
215 | ENDPROC(el0_fiq_invalid_compat) | ||
216 | |||
217 | el0_error_invalid_compat: | ||
218 | inv_entry 0, BAD_ERROR, 32 | ||
219 | ENDPROC(el0_error_invalid_compat) | ||
220 | #endif | ||
221 | |||
222 | el1_sync_invalid: | ||
223 | inv_entry 1, BAD_SYNC | ||
224 | ENDPROC(el1_sync_invalid) | ||
225 | |||
226 | el1_irq_invalid: | ||
227 | inv_entry 1, BAD_IRQ | ||
228 | ENDPROC(el1_irq_invalid) | ||
229 | |||
230 | el1_fiq_invalid: | ||
231 | inv_entry 1, BAD_FIQ | ||
232 | ENDPROC(el1_fiq_invalid) | ||
233 | |||
234 | el1_error_invalid: | ||
235 | inv_entry 1, BAD_ERROR | ||
236 | ENDPROC(el1_error_invalid) | ||
237 | |||
238 | /* | ||
239 | * EL1 mode handlers. | ||
240 | */ | ||
241 | .align 6 | ||
242 | el1_sync: | ||
243 | kernel_entry 1 | ||
244 | mrs x1, esr_el1 // read the syndrome register | ||
245 | lsr x24, x1, #26 // exception class | ||
246 | cmp x24, #0x25 // data abort in EL1 | ||
247 | b.eq el1_da | ||
248 | cmp x24, #0x18 // configurable trap | ||
249 | b.eq el1_undef | ||
250 | cmp x24, #0x26 // stack alignment exception | ||
251 | b.eq el1_sp_pc | ||
252 | cmp x24, #0x22 // pc alignment exception | ||
253 | b.eq el1_sp_pc | ||
254 | cmp x24, #0x00 // unknown exception in EL1 | ||
255 | b.eq el1_undef | ||
256 | cmp x24, #0x30 // debug exception in EL1 | ||
257 | b.ge el1_dbg | ||
258 | b el1_inv | ||
259 | el1_da: | ||
260 | /* | ||
261 | * Data abort handling | ||
262 | */ | ||
263 | mrs x0, far_el1 | ||
264 | enable_dbg_if_not_stepping x2 | ||
265 | // re-enable interrupts if they were enabled in the aborted context | ||
266 | tbnz x23, #7, 1f // PSR_I_BIT | ||
267 | enable_irq | ||
268 | 1: | ||
269 | mov x2, sp // struct pt_regs | ||
270 | bl do_mem_abort | ||
271 | |||
272 | // disable interrupts before pulling preserved data off the stack | ||
273 | disable_irq | ||
274 | kernel_exit 1 | ||
275 | el1_sp_pc: | ||
276 | /* | ||
277 | * Stack or PC alignment exception handling | ||
278 | */ | ||
279 | mrs x0, far_el1 | ||
280 | mov x1, x25 | ||
281 | mov x2, sp | ||
282 | b do_sp_pc_abort | ||
283 | el1_undef: | ||
284 | /* | ||
285 | * Undefined instruction | ||
286 | */ | ||
287 | mov x0, sp | ||
288 | b do_undefinstr | ||
289 | el1_dbg: | ||
290 | /* | ||
291 | * Debug exception handling | ||
292 | */ | ||
293 | tbz x24, #0, el1_inv // EL1 only | ||
294 | mrs x0, far_el1 | ||
295 | mov x2, sp // struct pt_regs | ||
296 | bl do_debug_exception | ||
297 | |||
298 | kernel_exit 1 | ||
299 | el1_inv: | ||
300 | // TODO: add support for undefined instructions in kernel mode | ||
301 | mov x0, sp | ||
302 | mov x1, #BAD_SYNC | ||
303 | mrs x2, esr_el1 | ||
304 | b bad_mode | ||
305 | ENDPROC(el1_sync) | ||
306 | |||
307 | .align 6 | ||
308 | el1_irq: | ||
309 | kernel_entry 1 | ||
310 | enable_dbg_if_not_stepping x0 | ||
311 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
312 | bl trace_hardirqs_off | ||
313 | #endif | ||
314 | #ifdef CONFIG_PREEMPT | ||
315 | get_thread_info tsk | ||
316 | ldr x24, [tsk, #TI_PREEMPT] // get preempt count | ||
317 | add x0, x24, #1 // increment it | ||
318 | str x0, [tsk, #TI_PREEMPT] | ||
319 | #endif | ||
320 | irq_handler | ||
321 | #ifdef CONFIG_PREEMPT | ||
322 | str x24, [tsk, #TI_PREEMPT] // restore preempt count | ||
323 | cbnz x24, 1f // preempt count != 0 | ||
324 | ldr x0, [tsk, #TI_FLAGS] // get flags | ||
325 | tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? | ||
326 | bl el1_preempt | ||
327 | 1: | ||
328 | #endif | ||
329 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
330 | bl trace_hardirqs_on | ||
331 | #endif | ||
332 | kernel_exit 1 | ||
333 | ENDPROC(el1_irq) | ||
334 | |||
335 | #ifdef CONFIG_PREEMPT | ||
336 | el1_preempt: | ||
337 | mov x24, lr | ||
338 | 1: enable_dbg | ||
339 | bl preempt_schedule_irq // irq en/disable is done inside | ||
340 | ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS | ||
341 | tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling? | ||
342 | ret x24 | ||
343 | #endif | ||
344 | |||
345 | /* | ||
346 | * EL0 mode handlers. | ||
347 | */ | ||
348 | .align 6 | ||
349 | el0_sync: | ||
350 | kernel_entry 0 | ||
351 | mrs x25, esr_el1 // read the syndrome register | ||
352 | lsr x24, x25, #26 // exception class | ||
353 | cmp x24, #0x15 // SVC in 64-bit state | ||
354 | b.eq el0_svc | ||
355 | adr lr, ret_from_exception | ||
356 | cmp x24, #0x24 // data abort in EL0 | ||
357 | b.eq el0_da | ||
358 | cmp x24, #0x20 // instruction abort in EL0 | ||
359 | b.eq el0_ia | ||
360 | cmp x24, #0x07 // FP/ASIMD access | ||
361 | b.eq el0_fpsimd_acc | ||
362 | cmp x24, #0x2c // FP/ASIMD exception | ||
363 | b.eq el0_fpsimd_exc | ||
364 | cmp x24, #0x18 // configurable trap | ||
365 | b.eq el0_undef | ||
366 | cmp x24, #0x26 // stack alignment exception | ||
367 | b.eq el0_sp_pc | ||
368 | cmp x24, #0x22 // pc alignment exception | ||
369 | b.eq el0_sp_pc | ||
370 | cmp x24, #0x00 // unknown exception in EL0 | ||
371 | b.eq el0_undef | ||
372 | cmp x24, #0x30 // debug exception in EL0 | ||
373 | b.ge el0_dbg | ||
374 | b el0_inv | ||
375 | |||
376 | #ifdef CONFIG_COMPAT | ||
377 | .align 6 | ||
378 | el0_sync_compat: | ||
379 | kernel_entry 0, 32 | ||
380 | mrs x25, esr_el1 // read the syndrome register | ||
381 | lsr x24, x25, #26 // exception class | ||
382 | cmp x24, #0x11 // SVC in 32-bit state | ||
383 | b.eq el0_svc_compat | ||
384 | adr lr, ret_from_exception | ||
385 | cmp x24, #0x24 // data abort in EL0 | ||
386 | b.eq el0_da | ||
387 | cmp x24, #0x20 // instruction abort in EL0 | ||
388 | b.eq el0_ia | ||
389 | cmp x24, #0x07 // FP/ASIMD access | ||
390 | b.eq el0_fpsimd_acc | ||
391 | cmp x24, #0x28 // FP/ASIMD exception | ||
392 | b.eq el0_fpsimd_exc | ||
393 | cmp x24, #0x00 // unknown exception in EL0 | ||
394 | b.eq el0_undef | ||
395 | cmp x24, #0x30 // debug exception in EL0 | ||
396 | b.ge el0_dbg | ||
397 | b el0_inv | ||
398 | el0_svc_compat: | ||
399 | /* | ||
400 | * AArch32 syscall handling | ||
401 | */ | ||
402 | adr stbl, compat_sys_call_table // load compat syscall table pointer | ||
403 | uxtw scno, w7 // syscall number in w7 (r7) | ||
404 | mov sc_nr, #__NR_compat_syscalls | ||
405 | b el0_svc_naked | ||
406 | |||
407 | .align 6 | ||
408 | el0_irq_compat: | ||
409 | kernel_entry 0, 32 | ||
410 | b el0_irq_naked | ||
411 | #endif | ||
412 | |||
413 | el0_da: | ||
414 | /* | ||
415 | * Data abort handling | ||
416 | */ | ||
417 | mrs x0, far_el1 | ||
418 | disable_step x1 | ||
419 | isb | ||
420 | enable_dbg | ||
421 | // enable interrupts before calling the main handler | ||
422 | enable_irq | ||
423 | mov x1, x25 | ||
424 | mov x2, sp | ||
425 | b do_mem_abort | ||
426 | el0_ia: | ||
427 | /* | ||
428 | * Instruction abort handling | ||
429 | */ | ||
430 | mrs x0, far_el1 | ||
431 | disable_step x1 | ||
432 | isb | ||
433 | enable_dbg | ||
434 | // enable interrupts before calling the main handler | ||
435 | enable_irq | ||
436 | orr x1, x25, #1 << 24 // use reserved ISS bit for instruction aborts | ||
437 | mov x2, sp | ||
438 | b do_mem_abort | ||
439 | el0_fpsimd_acc: | ||
440 | /* | ||
441 | * Floating Point or Advanced SIMD access | ||
442 | */ | ||
443 | mov x0, x25 | ||
444 | mov x1, sp | ||
445 | b do_fpsimd_acc | ||
446 | el0_fpsimd_exc: | ||
447 | /* | ||
448 | * Floating Point or Advanced SIMD exception | ||
449 | */ | ||
450 | mov x0, x25 | ||
451 | mov x1, sp | ||
452 | b do_fpsimd_exc | ||
453 | el0_sp_pc: | ||
454 | /* | ||
455 | * Stack or PC alignment exception handling | ||
456 | */ | ||
457 | mrs x0, far_el1 | ||
458 | disable_step x1 | ||
459 | isb | ||
460 | enable_dbg | ||
461 | // enable interrupts before calling the main handler | ||
462 | enable_irq | ||
463 | mov x1, x25 | ||
464 | mov x2, sp | ||
465 | b do_sp_pc_abort | ||
466 | el0_undef: | ||
467 | /* | ||
468 | * Undefined instruction | ||
469 | */ | ||
470 | mov x0, sp | ||
471 | b do_undefinstr | ||
472 | el0_dbg: | ||
473 | /* | ||
474 | * Debug exception handling | ||
475 | */ | ||
476 | tbnz x24, #0, el0_inv // EL0 only | ||
477 | mrs x0, far_el1 | ||
478 | disable_step x1 | ||
479 | mov x1, x25 | ||
480 | mov x2, sp | ||
481 | b do_debug_exception | ||
482 | el0_inv: | ||
483 | mov x0, sp | ||
484 | mov x1, #BAD_SYNC | ||
485 | mrs x2, esr_el1 | ||
486 | b bad_mode | ||
487 | ENDPROC(el0_sync) | ||
488 | |||
489 | .align 6 | ||
490 | el0_irq: | ||
491 | kernel_entry 0 | ||
492 | el0_irq_naked: | ||
493 | disable_step x1 | ||
494 | isb | ||
495 | enable_dbg | ||
496 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
497 | bl trace_hardirqs_off | ||
498 | #endif | ||
499 | get_thread_info tsk | ||
500 | #ifdef CONFIG_PREEMPT | ||
501 | ldr x24, [tsk, #TI_PREEMPT] // get preempt count | ||
502 | add x23, x24, #1 // increment it | ||
503 | str x23, [tsk, #TI_PREEMPT] | ||
504 | #endif | ||
505 | irq_handler | ||
506 | #ifdef CONFIG_PREEMPT | ||
507 | ldr x0, [tsk, #TI_PREEMPT] | ||
508 | str x24, [tsk, #TI_PREEMPT] | ||
509 | cmp x0, x23 | ||
510 | b.eq 1f | ||
511 | mov x1, #0 | ||
512 | str x1, [x1] // BUG | ||
513 | 1: | ||
514 | #endif | ||
515 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
516 | bl trace_hardirqs_on | ||
517 | #endif | ||
518 | b ret_to_user | ||
519 | ENDPROC(el0_irq) | ||
520 | |||
521 | /* | ||
522 | * This is the return code to user mode for abort handlers | ||
523 | */ | ||
524 | ret_from_exception: | ||
525 | get_thread_info tsk | ||
526 | b ret_to_user | ||
527 | ENDPROC(ret_from_exception) | ||
528 | |||
529 | /* | ||
530 | * Register switch for AArch64. The callee-saved registers need to be saved | ||
531 | * and restored. On entry: | ||
532 | * x0 = previous task_struct (must be preserved across the switch) | ||
533 | * x1 = next task_struct | ||
534 | * Previous and next are guaranteed not to be the same. | ||
535 | * | ||
536 | */ | ||
537 | ENTRY(cpu_switch_to) | ||
538 | add x8, x0, #THREAD_CPU_CONTEXT | ||
539 | mov x9, sp | ||
540 | stp x19, x20, [x8], #16 // store callee-saved registers | ||
541 | stp x21, x22, [x8], #16 | ||
542 | stp x23, x24, [x8], #16 | ||
543 | stp x25, x26, [x8], #16 | ||
544 | stp x27, x28, [x8], #16 | ||
545 | stp x29, x9, [x8], #16 | ||
546 | str lr, [x8] | ||
547 | add x8, x1, #THREAD_CPU_CONTEXT | ||
548 | ldp x19, x20, [x8], #16 // restore callee-saved registers | ||
549 | ldp x21, x22, [x8], #16 | ||
550 | ldp x23, x24, [x8], #16 | ||
551 | ldp x25, x26, [x8], #16 | ||
552 | ldp x27, x28, [x8], #16 | ||
553 | ldp x29, x9, [x8], #16 | ||
554 | ldr lr, [x8] | ||
555 | mov sp, x9 | ||
556 | ret | ||
557 | ENDPROC(cpu_switch_to) | ||
558 | |||
559 | /* | ||
560 | * This is the fast syscall return path. We do as little as possible here, | ||
561 | * and this includes saving x0 back into the kernel stack. | ||
562 | */ | ||
563 | ret_fast_syscall: | ||
564 | disable_irq // disable interrupts | ||
565 | ldr x1, [tsk, #TI_FLAGS] | ||
566 | and x2, x1, #_TIF_WORK_MASK | ||
567 | cbnz x2, fast_work_pending | ||
568 | tbz x1, #TIF_SINGLESTEP, fast_exit | ||
569 | disable_dbg | ||
570 | enable_step x2 | ||
571 | fast_exit: | ||
572 | kernel_exit 0, ret = 1 | ||
573 | |||
574 | /* | ||
575 | * Ok, we need to do extra processing, enter the slow path. | ||
576 | */ | ||
577 | fast_work_pending: | ||
578 | str x0, [sp, #S_X0] // returned x0 | ||
579 | work_pending: | ||
580 | tbnz x1, #TIF_NEED_RESCHED, work_resched | ||
581 | /* TIF_SIGPENDING or TIF_NOTIFY_RESUME case */ | ||
582 | ldr x2, [sp, #S_PSTATE] | ||
583 | mov x0, sp // 'regs' | ||
584 | tst x2, #PSR_MODE_MASK // user mode regs? | ||
585 | b.ne no_work_pending // returning to kernel | ||
586 | bl do_notify_resume | ||
587 | b ret_to_user | ||
588 | work_resched: | ||
589 | enable_dbg | ||
590 | bl schedule | ||
591 | |||
592 | /* | ||
593 | * "slow" syscall return path. | ||
594 | */ | ||
595 | ENTRY(ret_to_user) | ||
596 | disable_irq // disable interrupts | ||
597 | ldr x1, [tsk, #TI_FLAGS] | ||
598 | and x2, x1, #_TIF_WORK_MASK | ||
599 | cbnz x2, work_pending | ||
600 | tbz x1, #TIF_SINGLESTEP, no_work_pending | ||
601 | disable_dbg | ||
602 | enable_step x2 | ||
603 | no_work_pending: | ||
604 | kernel_exit 0, ret = 0 | ||
605 | ENDPROC(ret_to_user) | ||
606 | |||
607 | /* | ||
608 | * This is how we return from a fork. | ||
609 | */ | ||
610 | ENTRY(ret_from_fork) | ||
611 | bl schedule_tail | ||
612 | get_thread_info tsk | ||
613 | b ret_to_user | ||
614 | ENDPROC(ret_from_fork) | ||
615 | |||
616 | /* | ||
617 | * SVC handler. | ||
618 | */ | ||
619 | .align 6 | ||
620 | el0_svc: | ||
621 | adrp stbl, sys_call_table // load syscall table pointer | ||
622 | uxtw scno, w8 // syscall number in w8 | ||
623 | mov sc_nr, #__NR_syscalls | ||
624 | el0_svc_naked: // compat entry point | ||
625 | stp x0, scno, [sp, #S_ORIG_X0] // save the original x0 and syscall number | ||
626 | disable_step x16 | ||
627 | isb | ||
628 | enable_dbg | ||
629 | enable_irq | ||
630 | |||
631 | get_thread_info tsk | ||
632 | ldr x16, [tsk, #TI_FLAGS] // check for syscall tracing | ||
633 | tbnz x16, #TIF_SYSCALL_TRACE, __sys_trace // are we tracing syscalls? | ||
634 | adr lr, ret_fast_syscall // return address | ||
635 | cmp scno, sc_nr // check upper syscall limit | ||
636 | b.hs ni_sys | ||
637 | ldr x16, [stbl, scno, lsl #3] // address in the syscall table | ||
638 | br x16 // call sys_* routine | ||
639 | ni_sys: | ||
640 | mov x0, sp | ||
641 | b do_ni_syscall | ||
642 | ENDPROC(el0_svc) | ||
643 | |||
644 | /* | ||
645 | * This is the really slow path. We're going to be doing context | ||
646 | * switches, and waiting for our parent to respond. | ||
647 | */ | ||
648 | __sys_trace: | ||
649 | mov x1, sp | ||
650 | mov w0, #0 // trace entry | ||
651 | bl syscall_trace | ||
652 | adr lr, __sys_trace_return // return address | ||
653 | uxtw scno, w0 // syscall number (possibly new) | ||
654 | mov x1, sp // pointer to regs | ||
655 | cmp scno, sc_nr // check upper syscall limit | ||
656 | b.hs ni_sys | ||
657 | ldp x0, x1, [sp] // restore the syscall args | ||
658 | ldp x2, x3, [sp, #S_X2] | ||
659 | ldp x4, x5, [sp, #S_X4] | ||
660 | ldp x6, x7, [sp, #S_X6] | ||
661 | ldr x16, [stbl, scno, lsl #3] // address in the syscall table | ||
662 | br x16 // call sys_* routine | ||
663 | |||
664 | __sys_trace_return: | ||
665 | str x0, [sp] // save returned x0 | ||
666 | mov x1, sp | ||
667 | mov w0, #1 // trace exit | ||
668 | bl syscall_trace | ||
669 | b ret_to_user | ||
670 | |||
671 | /* | ||
672 | * Special system call wrappers. | ||
673 | */ | ||
674 | ENTRY(sys_execve_wrapper) | ||
675 | mov x3, sp | ||
676 | b sys_execve | ||
677 | ENDPROC(sys_execve_wrapper) | ||
678 | |||
679 | ENTRY(sys_clone_wrapper) | ||
680 | mov x5, sp | ||
681 | b sys_clone | ||
682 | ENDPROC(sys_clone_wrapper) | ||
683 | |||
684 | ENTRY(sys_rt_sigreturn_wrapper) | ||
685 | mov x0, sp | ||
686 | b sys_rt_sigreturn | ||
687 | ENDPROC(sys_rt_sigreturn_wrapper) | ||
688 | |||
689 | ENTRY(sys_sigaltstack_wrapper) | ||
690 | ldr x2, [sp, #S_SP] | ||
691 | b sys_sigaltstack | ||
692 | ENDPROC(sys_sigaltstack_wrapper) | ||
693 | |||
694 | ENTRY(handle_arch_irq) | ||
695 | .quad 0 | ||
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c new file mode 100644 index 000000000000..e8b8357aedb4 --- /dev/null +++ b/arch/arm64/kernel/fpsimd.c | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | * FP/SIMD context switching and fault handling | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/signal.h> | ||
24 | |||
25 | #include <asm/fpsimd.h> | ||
26 | #include <asm/cputype.h> | ||
27 | |||
28 | #define FPEXC_IOF (1 << 0) | ||
29 | #define FPEXC_DZF (1 << 1) | ||
30 | #define FPEXC_OFF (1 << 2) | ||
31 | #define FPEXC_UFF (1 << 3) | ||
32 | #define FPEXC_IXF (1 << 4) | ||
33 | #define FPEXC_IDF (1 << 7) | ||
34 | |||
35 | /* | ||
36 | * Trapped FP/ASIMD access. | ||
37 | */ | ||
38 | void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs) | ||
39 | { | ||
40 | /* TODO: implement lazy context saving/restoring */ | ||
41 | WARN_ON(1); | ||
42 | } | ||
43 | |||
44 | /* | ||
45 | * Raise a SIGFPE for the current process. | ||
46 | */ | ||
47 | void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs) | ||
48 | { | ||
49 | siginfo_t info; | ||
50 | unsigned int si_code = 0; | ||
51 | |||
52 | if (esr & FPEXC_IOF) | ||
53 | si_code = FPE_FLTINV; | ||
54 | else if (esr & FPEXC_DZF) | ||
55 | si_code = FPE_FLTDIV; | ||
56 | else if (esr & FPEXC_OFF) | ||
57 | si_code = FPE_FLTOVF; | ||
58 | else if (esr & FPEXC_UFF) | ||
59 | si_code = FPE_FLTUND; | ||
60 | else if (esr & FPEXC_IXF) | ||
61 | si_code = FPE_FLTRES; | ||
62 | |||
63 | memset(&info, 0, sizeof(info)); | ||
64 | info.si_signo = SIGFPE; | ||
65 | info.si_code = si_code; | ||
66 | info.si_addr = (void __user *)instruction_pointer(regs); | ||
67 | |||
68 | send_sig_info(SIGFPE, &info, current); | ||
69 | } | ||
70 | |||
71 | void fpsimd_thread_switch(struct task_struct *next) | ||
72 | { | ||
73 | /* check if not kernel threads */ | ||
74 | if (current->mm) | ||
75 | fpsimd_save_state(¤t->thread.fpsimd_state); | ||
76 | if (next->mm) | ||
77 | fpsimd_load_state(&next->thread.fpsimd_state); | ||
78 | } | ||
79 | |||
80 | void fpsimd_flush_thread(void) | ||
81 | { | ||
82 | memset(¤t->thread.fpsimd_state, 0, sizeof(struct fpsimd_state)); | ||
83 | fpsimd_load_state(¤t->thread.fpsimd_state); | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * FP/SIMD support code initialisation. | ||
88 | */ | ||
89 | static int __init fpsimd_init(void) | ||
90 | { | ||
91 | u64 pfr = read_cpuid(ID_AA64PFR0_EL1); | ||
92 | |||
93 | if (pfr & (0xf << 16)) { | ||
94 | pr_notice("Floating-point is not implemented\n"); | ||
95 | return 0; | ||
96 | } | ||
97 | elf_hwcap |= HWCAP_FP; | ||
98 | |||
99 | if (pfr & (0xf << 20)) | ||
100 | pr_notice("Advanced SIMD is not implemented\n"); | ||
101 | else | ||
102 | elf_hwcap |= HWCAP_ASIMD; | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | late_initcall(fpsimd_init); | ||
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S new file mode 100644 index 000000000000..a2f02b63eae9 --- /dev/null +++ b/arch/arm64/kernel/head.S | |||
@@ -0,0 +1,510 @@ | |||
1 | /* | ||
2 | * Low-level CPU initialisation | ||
3 | * Based on arch/arm/kernel/head.S | ||
4 | * | ||
5 | * Copyright (C) 1994-2002 Russell King | ||
6 | * Copyright (C) 2003-2012 ARM Ltd. | ||
7 | * Authors: Catalin Marinas <catalin.marinas@arm.com> | ||
8 | * Will Deacon <will.deacon@arm.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | */ | ||
22 | |||
23 | #include <linux/linkage.h> | ||
24 | #include <linux/init.h> | ||
25 | |||
26 | #include <asm/assembler.h> | ||
27 | #include <asm/ptrace.h> | ||
28 | #include <asm/asm-offsets.h> | ||
29 | #include <asm/memory.h> | ||
30 | #include <asm/thread_info.h> | ||
31 | #include <asm/pgtable-hwdef.h> | ||
32 | #include <asm/pgtable.h> | ||
33 | #include <asm/page.h> | ||
34 | |||
35 | /* | ||
36 | * swapper_pg_dir is the virtual address of the initial page table. We place | ||
37 | * the page tables 3 * PAGE_SIZE below KERNEL_RAM_VADDR. The idmap_pg_dir has | ||
38 | * 2 pages and is placed below swapper_pg_dir. | ||
39 | */ | ||
40 | #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) | ||
41 | |||
42 | #if (KERNEL_RAM_VADDR & 0xfffff) != 0x80000 | ||
43 | #error KERNEL_RAM_VADDR must start at 0xXXX80000 | ||
44 | #endif | ||
45 | |||
46 | #define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) | ||
47 | #define IDMAP_DIR_SIZE (2 * PAGE_SIZE) | ||
48 | |||
49 | .globl swapper_pg_dir | ||
50 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - SWAPPER_DIR_SIZE | ||
51 | |||
52 | .globl idmap_pg_dir | ||
53 | .equ idmap_pg_dir, swapper_pg_dir - IDMAP_DIR_SIZE | ||
54 | |||
55 | .macro pgtbl, ttb0, ttb1, phys | ||
56 | add \ttb1, \phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE | ||
57 | sub \ttb0, \ttb1, #IDMAP_DIR_SIZE | ||
58 | .endm | ||
59 | |||
60 | #ifdef CONFIG_ARM64_64K_PAGES | ||
61 | #define BLOCK_SHIFT PAGE_SHIFT | ||
62 | #define BLOCK_SIZE PAGE_SIZE | ||
63 | #else | ||
64 | #define BLOCK_SHIFT SECTION_SHIFT | ||
65 | #define BLOCK_SIZE SECTION_SIZE | ||
66 | #endif | ||
67 | |||
68 | #define KERNEL_START KERNEL_RAM_VADDR | ||
69 | #define KERNEL_END _end | ||
70 | |||
71 | /* | ||
72 | * Initial memory map attributes. | ||
73 | */ | ||
74 | #ifndef CONFIG_SMP | ||
75 | #define PTE_FLAGS PTE_TYPE_PAGE | PTE_AF | ||
76 | #define PMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF | ||
77 | #else | ||
78 | #define PTE_FLAGS PTE_TYPE_PAGE | PTE_AF | PTE_SHARED | ||
79 | #define PMD_FLAGS PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S | ||
80 | #endif | ||
81 | |||
82 | #ifdef CONFIG_ARM64_64K_PAGES | ||
83 | #define MM_MMUFLAGS PTE_ATTRINDX(MT_NORMAL) | PTE_FLAGS | ||
84 | #define IO_MMUFLAGS PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_XN | PTE_FLAGS | ||
85 | #else | ||
86 | #define MM_MMUFLAGS PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS | ||
87 | #define IO_MMUFLAGS PMD_ATTRINDX(MT_DEVICE_nGnRE) | PMD_SECT_XN | PMD_FLAGS | ||
88 | #endif | ||
89 | |||
90 | /* | ||
91 | * Kernel startup entry point. | ||
92 | * --------------------------- | ||
93 | * | ||
94 | * The requirements are: | ||
95 | * MMU = off, D-cache = off, I-cache = on or off, | ||
96 | * x0 = physical address to the FDT blob. | ||
97 | * | ||
98 | * This code is mostly position independent so you call this at | ||
99 | * __pa(PAGE_OFFSET + TEXT_OFFSET). | ||
100 | * | ||
101 | * Note that the callee-saved registers are used for storing variables | ||
102 | * that are useful before the MMU is enabled. The allocations are described | ||
103 | * in the entry routines. | ||
104 | */ | ||
105 | __HEAD | ||
106 | |||
107 | /* | ||
108 | * DO NOT MODIFY. Image header expected by Linux boot-loaders. | ||
109 | */ | ||
110 | b stext // branch to kernel start, magic | ||
111 | .long 0 // reserved | ||
112 | .quad TEXT_OFFSET // Image load offset from start of RAM | ||
113 | .quad 0 // reserved | ||
114 | .quad 0 // reserved | ||
115 | |||
116 | ENTRY(stext) | ||
117 | mov x21, x0 // x21=FDT | ||
118 | bl el2_setup // Drop to EL1 | ||
119 | mrs x22, midr_el1 // x22=cpuid | ||
120 | mov x0, x22 | ||
121 | bl lookup_processor_type | ||
122 | mov x23, x0 // x23=current cpu_table | ||
123 | cbz x23, __error_p // invalid processor (x23=0)? | ||
124 | bl __calc_phys_offset // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET | ||
125 | bl __vet_fdt | ||
126 | bl __create_page_tables // x25=TTBR0, x26=TTBR1 | ||
127 | /* | ||
128 | * The following calls CPU specific code in a position independent | ||
129 | * manner. See arch/arm64/mm/proc.S for details. x23 = base of | ||
130 | * cpu_info structure selected by lookup_processor_type above. | ||
131 | * On return, the CPU will be ready for the MMU to be turned on and | ||
132 | * the TCR will have been set. | ||
133 | */ | ||
134 | ldr x27, __switch_data // address to jump to after | ||
135 | // MMU has been enabled | ||
136 | adr lr, __enable_mmu // return (PIC) address | ||
137 | ldr x12, [x23, #CPU_INFO_SETUP] | ||
138 | add x12, x12, x28 // __virt_to_phys | ||
139 | br x12 // initialise processor | ||
140 | ENDPROC(stext) | ||
141 | |||
142 | /* | ||
143 | * If we're fortunate enough to boot at EL2, ensure that the world is | ||
144 | * sane before dropping to EL1. | ||
145 | */ | ||
146 | ENTRY(el2_setup) | ||
147 | mrs x0, CurrentEL | ||
148 | cmp x0, #PSR_MODE_EL2t | ||
149 | ccmp x0, #PSR_MODE_EL2h, #0x4, ne | ||
150 | b.eq 1f | ||
151 | ret | ||
152 | |||
153 | /* Hyp configuration. */ | ||
154 | 1: mov x0, #(1 << 31) // 64-bit EL1 | ||
155 | msr hcr_el2, x0 | ||
156 | |||
157 | /* Generic timers. */ | ||
158 | mrs x0, cnthctl_el2 | ||
159 | orr x0, x0, #3 // Enable EL1 physical timers | ||
160 | msr cnthctl_el2, x0 | ||
161 | |||
162 | /* Populate ID registers. */ | ||
163 | mrs x0, midr_el1 | ||
164 | mrs x1, mpidr_el1 | ||
165 | msr vpidr_el2, x0 | ||
166 | msr vmpidr_el2, x1 | ||
167 | |||
168 | /* sctlr_el1 */ | ||
169 | mov x0, #0x0800 // Set/clear RES{1,0} bits | ||
170 | movk x0, #0x30d0, lsl #16 | ||
171 | msr sctlr_el1, x0 | ||
172 | |||
173 | /* Coprocessor traps. */ | ||
174 | mov x0, #0x33ff | ||
175 | msr cptr_el2, x0 // Disable copro. traps to EL2 | ||
176 | |||
177 | #ifdef CONFIG_COMPAT | ||
178 | msr hstr_el2, xzr // Disable CP15 traps to EL2 | ||
179 | #endif | ||
180 | |||
181 | /* spsr */ | ||
182 | mov x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ | ||
183 | PSR_MODE_EL1h) | ||
184 | msr spsr_el2, x0 | ||
185 | msr elr_el2, lr | ||
186 | eret | ||
187 | ENDPROC(el2_setup) | ||
188 | |||
189 | .align 3 | ||
190 | 2: .quad . | ||
191 | .quad PAGE_OFFSET | ||
192 | |||
193 | #ifdef CONFIG_SMP | ||
194 | .pushsection .smp.pen.text, "ax" | ||
195 | .align 3 | ||
196 | 1: .quad . | ||
197 | .quad secondary_holding_pen_release | ||
198 | |||
199 | /* | ||
200 | * This provides a "holding pen" for platforms to hold all secondary | ||
201 | * cores are held until we're ready for them to initialise. | ||
202 | */ | ||
203 | ENTRY(secondary_holding_pen) | ||
204 | bl el2_setup // Drop to EL1 | ||
205 | mrs x0, mpidr_el1 | ||
206 | and x0, x0, #15 // CPU number | ||
207 | adr x1, 1b | ||
208 | ldp x2, x3, [x1] | ||
209 | sub x1, x1, x2 | ||
210 | add x3, x3, x1 | ||
211 | pen: ldr x4, [x3] | ||
212 | cmp x4, x0 | ||
213 | b.eq secondary_startup | ||
214 | wfe | ||
215 | b pen | ||
216 | ENDPROC(secondary_holding_pen) | ||
217 | .popsection | ||
218 | |||
219 | ENTRY(secondary_startup) | ||
220 | /* | ||
221 | * Common entry point for secondary CPUs. | ||
222 | */ | ||
223 | mrs x22, midr_el1 // x22=cpuid | ||
224 | mov x0, x22 | ||
225 | bl lookup_processor_type | ||
226 | mov x23, x0 // x23=current cpu_table | ||
227 | cbz x23, __error_p // invalid processor (x23=0)? | ||
228 | |||
229 | bl __calc_phys_offset // x24=phys offset | ||
230 | pgtbl x25, x26, x24 // x25=TTBR0, x26=TTBR1 | ||
231 | ldr x12, [x23, #CPU_INFO_SETUP] | ||
232 | add x12, x12, x28 // __virt_to_phys | ||
233 | blr x12 // initialise processor | ||
234 | |||
235 | ldr x21, =secondary_data | ||
236 | ldr x27, =__secondary_switched // address to jump to after enabling the MMU | ||
237 | b __enable_mmu | ||
238 | ENDPROC(secondary_startup) | ||
239 | |||
240 | ENTRY(__secondary_switched) | ||
241 | ldr x0, [x21] // get secondary_data.stack | ||
242 | mov sp, x0 | ||
243 | mov x29, #0 | ||
244 | b secondary_start_kernel | ||
245 | ENDPROC(__secondary_switched) | ||
246 | #endif /* CONFIG_SMP */ | ||
247 | |||
248 | /* | ||
249 | * Setup common bits before finally enabling the MMU. Essentially this is just | ||
250 | * loading the page table pointer and vector base registers. | ||
251 | * | ||
252 | * On entry to this code, x0 must contain the SCTLR_EL1 value for turning on | ||
253 | * the MMU. | ||
254 | */ | ||
255 | __enable_mmu: | ||
256 | ldr x5, =vectors | ||
257 | msr vbar_el1, x5 | ||
258 | msr ttbr0_el1, x25 // load TTBR0 | ||
259 | msr ttbr1_el1, x26 // load TTBR1 | ||
260 | isb | ||
261 | b __turn_mmu_on | ||
262 | ENDPROC(__enable_mmu) | ||
263 | |||
264 | /* | ||
265 | * Enable the MMU. This completely changes the structure of the visible memory | ||
266 | * space. You will not be able to trace execution through this. | ||
267 | * | ||
268 | * x0 = system control register | ||
269 | * x27 = *virtual* address to jump to upon completion | ||
270 | * | ||
271 | * other registers depend on the function called upon completion | ||
272 | */ | ||
273 | .align 6 | ||
274 | __turn_mmu_on: | ||
275 | msr sctlr_el1, x0 | ||
276 | isb | ||
277 | br x27 | ||
278 | ENDPROC(__turn_mmu_on) | ||
279 | |||
280 | /* | ||
281 | * Calculate the start of physical memory. | ||
282 | */ | ||
283 | __calc_phys_offset: | ||
284 | adr x0, 1f | ||
285 | ldp x1, x2, [x0] | ||
286 | sub x28, x0, x1 // x28 = PHYS_OFFSET - PAGE_OFFSET | ||
287 | add x24, x2, x28 // x24 = PHYS_OFFSET | ||
288 | ret | ||
289 | ENDPROC(__calc_phys_offset) | ||
290 | |||
291 | .align 3 | ||
292 | 1: .quad . | ||
293 | .quad PAGE_OFFSET | ||
294 | |||
295 | /* | ||
296 | * Macro to populate the PGD for the corresponding block entry in the next | ||
297 | * level (tbl) for the given virtual address. | ||
298 | * | ||
299 | * Preserves: pgd, tbl, virt | ||
300 | * Corrupts: tmp1, tmp2 | ||
301 | */ | ||
302 | .macro create_pgd_entry, pgd, tbl, virt, tmp1, tmp2 | ||
303 | lsr \tmp1, \virt, #PGDIR_SHIFT | ||
304 | and \tmp1, \tmp1, #PTRS_PER_PGD - 1 // PGD index | ||
305 | orr \tmp2, \tbl, #3 // PGD entry table type | ||
306 | str \tmp2, [\pgd, \tmp1, lsl #3] | ||
307 | .endm | ||
308 | |||
309 | /* | ||
310 | * Macro to populate block entries in the page table for the start..end | ||
311 | * virtual range (inclusive). | ||
312 | * | ||
313 | * Preserves: tbl, flags | ||
314 | * Corrupts: phys, start, end, pstate | ||
315 | */ | ||
316 | .macro create_block_map, tbl, flags, phys, start, end, idmap=0 | ||
317 | lsr \phys, \phys, #BLOCK_SHIFT | ||
318 | .if \idmap | ||
319 | and \start, \phys, #PTRS_PER_PTE - 1 // table index | ||
320 | .else | ||
321 | lsr \start, \start, #BLOCK_SHIFT | ||
322 | and \start, \start, #PTRS_PER_PTE - 1 // table index | ||
323 | .endif | ||
324 | orr \phys, \flags, \phys, lsl #BLOCK_SHIFT // table entry | ||
325 | .ifnc \start,\end | ||
326 | lsr \end, \end, #BLOCK_SHIFT | ||
327 | and \end, \end, #PTRS_PER_PTE - 1 // table end index | ||
328 | .endif | ||
329 | 9999: str \phys, [\tbl, \start, lsl #3] // store the entry | ||
330 | .ifnc \start,\end | ||
331 | add \start, \start, #1 // next entry | ||
332 | add \phys, \phys, #BLOCK_SIZE // next block | ||
333 | cmp \start, \end | ||
334 | b.ls 9999b | ||
335 | .endif | ||
336 | .endm | ||
337 | |||
338 | /* | ||
339 | * Setup the initial page tables. We only setup the barest amount which is | ||
340 | * required to get the kernel running. The following sections are required: | ||
341 | * - identity mapping to enable the MMU (low address, TTBR0) | ||
342 | * - first few MB of the kernel linear mapping to jump to once the MMU has | ||
343 | * been enabled, including the FDT blob (TTBR1) | ||
344 | */ | ||
345 | __create_page_tables: | ||
346 | pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses | ||
347 | |||
348 | /* | ||
349 | * Clear the idmap and swapper page tables. | ||
350 | */ | ||
351 | mov x0, x25 | ||
352 | add x6, x26, #SWAPPER_DIR_SIZE | ||
353 | 1: stp xzr, xzr, [x0], #16 | ||
354 | stp xzr, xzr, [x0], #16 | ||
355 | stp xzr, xzr, [x0], #16 | ||
356 | stp xzr, xzr, [x0], #16 | ||
357 | cmp x0, x6 | ||
358 | b.lo 1b | ||
359 | |||
360 | ldr x7, =MM_MMUFLAGS | ||
361 | |||
362 | /* | ||
363 | * Create the identity mapping. | ||
364 | */ | ||
365 | add x0, x25, #PAGE_SIZE // section table address | ||
366 | adr x3, __turn_mmu_on // virtual/physical address | ||
367 | create_pgd_entry x25, x0, x3, x5, x6 | ||
368 | create_block_map x0, x7, x3, x5, x5, idmap=1 | ||
369 | |||
370 | /* | ||
371 | * Map the kernel image (starting with PHYS_OFFSET). | ||
372 | */ | ||
373 | add x0, x26, #PAGE_SIZE // section table address | ||
374 | mov x5, #PAGE_OFFSET | ||
375 | create_pgd_entry x26, x0, x5, x3, x6 | ||
376 | ldr x6, =KERNEL_END - 1 | ||
377 | mov x3, x24 // phys offset | ||
378 | create_block_map x0, x7, x3, x5, x6 | ||
379 | |||
380 | /* | ||
381 | * Map the FDT blob (maximum 2MB; must be within 512MB of | ||
382 | * PHYS_OFFSET). | ||
383 | */ | ||
384 | mov x3, x21 // FDT phys address | ||
385 | and x3, x3, #~((1 << 21) - 1) // 2MB aligned | ||
386 | mov x6, #PAGE_OFFSET | ||
387 | sub x5, x3, x24 // subtract PHYS_OFFSET | ||
388 | tst x5, #~((1 << 29) - 1) // within 512MB? | ||
389 | csel x21, xzr, x21, ne // zero the FDT pointer | ||
390 | b.ne 1f | ||
391 | add x5, x5, x6 // __va(FDT blob) | ||
392 | add x6, x5, #1 << 21 // 2MB for the FDT blob | ||
393 | sub x6, x6, #1 // inclusive range | ||
394 | create_block_map x0, x7, x3, x5, x6 | ||
395 | 1: | ||
396 | ret | ||
397 | ENDPROC(__create_page_tables) | ||
398 | .ltorg | ||
399 | |||
400 | .align 3 | ||
401 | .type __switch_data, %object | ||
402 | __switch_data: | ||
403 | .quad __mmap_switched | ||
404 | .quad __data_loc // x4 | ||
405 | .quad _data // x5 | ||
406 | .quad __bss_start // x6 | ||
407 | .quad _end // x7 | ||
408 | .quad processor_id // x4 | ||
409 | .quad __fdt_pointer // x5 | ||
410 | .quad memstart_addr // x6 | ||
411 | .quad init_thread_union + THREAD_START_SP // sp | ||
412 | |||
413 | /* | ||
414 | * The following fragment of code is executed with the MMU on in MMU mode, and | ||
415 | * uses absolute addresses; this is not position independent. | ||
416 | */ | ||
417 | __mmap_switched: | ||
418 | adr x3, __switch_data + 8 | ||
419 | |||
420 | ldp x4, x5, [x3], #16 | ||
421 | ldp x6, x7, [x3], #16 | ||
422 | cmp x4, x5 // Copy data segment if needed | ||
423 | 1: ccmp x5, x6, #4, ne | ||
424 | b.eq 2f | ||
425 | ldr x16, [x4], #8 | ||
426 | str x16, [x5], #8 | ||
427 | b 1b | ||
428 | 2: | ||
429 | 1: cmp x6, x7 | ||
430 | b.hs 2f | ||
431 | str xzr, [x6], #8 // Clear BSS | ||
432 | b 1b | ||
433 | 2: | ||
434 | ldp x4, x5, [x3], #16 | ||
435 | ldr x6, [x3], #8 | ||
436 | ldr x16, [x3] | ||
437 | mov sp, x16 | ||
438 | str x22, [x4] // Save processor ID | ||
439 | str x21, [x5] // Save FDT pointer | ||
440 | str x24, [x6] // Save PHYS_OFFSET | ||
441 | mov x29, #0 | ||
442 | b start_kernel | ||
443 | ENDPROC(__mmap_switched) | ||
444 | |||
445 | /* | ||
446 | * Exception handling. Something went wrong and we can't proceed. We ought to | ||
447 | * tell the user, but since we don't have any guarantee that we're even | ||
448 | * running on the right architecture, we do virtually nothing. | ||
449 | */ | ||
450 | __error_p: | ||
451 | ENDPROC(__error_p) | ||
452 | |||
453 | __error: | ||
454 | 1: nop | ||
455 | b 1b | ||
456 | ENDPROC(__error) | ||
457 | |||
458 | /* | ||
459 | * This function gets the processor ID in w0 and searches the cpu_table[] for | ||
460 | * a match. It returns a pointer to the struct cpu_info it found. The | ||
461 | * cpu_table[] must end with an empty (all zeros) structure. | ||
462 | * | ||
463 | * This routine can be called via C code and it needs to work with the MMU | ||
464 | * both disabled and enabled (the offset is calculated automatically). | ||
465 | */ | ||
466 | ENTRY(lookup_processor_type) | ||
467 | adr x1, __lookup_processor_type_data | ||
468 | ldp x2, x3, [x1] | ||
469 | sub x1, x1, x2 // get offset between VA and PA | ||
470 | add x3, x3, x1 // convert VA to PA | ||
471 | 1: | ||
472 | ldp w5, w6, [x3] // load cpu_id_val and cpu_id_mask | ||
473 | cbz w5, 2f // end of list? | ||
474 | and w6, w6, w0 | ||
475 | cmp w5, w6 | ||
476 | b.eq 3f | ||
477 | add x3, x3, #CPU_INFO_SZ | ||
478 | b 1b | ||
479 | 2: | ||
480 | mov x3, #0 // unknown processor | ||
481 | 3: | ||
482 | mov x0, x3 | ||
483 | ret | ||
484 | ENDPROC(lookup_processor_type) | ||
485 | |||
486 | .align 3 | ||
487 | .type __lookup_processor_type_data, %object | ||
488 | __lookup_processor_type_data: | ||
489 | .quad . | ||
490 | .quad cpu_table | ||
491 | .size __lookup_processor_type_data, . - __lookup_processor_type_data | ||
492 | |||
493 | /* | ||
494 | * Determine validity of the x21 FDT pointer. | ||
495 | * The dtb must be 8-byte aligned and live in the first 512M of memory. | ||
496 | */ | ||
497 | __vet_fdt: | ||
498 | tst x21, #0x7 | ||
499 | b.ne 1f | ||
500 | cmp x21, x24 | ||
501 | b.lt 1f | ||
502 | mov x0, #(1 << 29) | ||
503 | add x0, x0, x24 | ||
504 | cmp x21, x0 | ||
505 | b.ge 1f | ||
506 | ret | ||
507 | 1: | ||
508 | mov x21, #0 | ||
509 | ret | ||
510 | ENDPROC(__vet_fdt) | ||
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c new file mode 100644 index 000000000000..5ab825c59db9 --- /dev/null +++ b/arch/arm64/kernel/hw_breakpoint.c | |||
@@ -0,0 +1,880 @@ | |||
1 | /* | ||
2 | * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility, | ||
3 | * using the CPU's debug registers. | ||
4 | * | ||
5 | * Copyright (C) 2012 ARM Limited | ||
6 | * Author: Will Deacon <will.deacon@arm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #define pr_fmt(fmt) "hw-breakpoint: " fmt | ||
22 | |||
23 | #include <linux/errno.h> | ||
24 | #include <linux/hw_breakpoint.h> | ||
25 | #include <linux/perf_event.h> | ||
26 | #include <linux/ptrace.h> | ||
27 | #include <linux/smp.h> | ||
28 | |||
29 | #include <asm/compat.h> | ||
30 | #include <asm/current.h> | ||
31 | #include <asm/debug-monitors.h> | ||
32 | #include <asm/hw_breakpoint.h> | ||
33 | #include <asm/kdebug.h> | ||
34 | #include <asm/traps.h> | ||
35 | #include <asm/cputype.h> | ||
36 | #include <asm/system_misc.h> | ||
37 | |||
38 | /* Breakpoint currently in use for each BRP. */ | ||
39 | static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); | ||
40 | |||
41 | /* Watchpoint currently in use for each WRP. */ | ||
42 | static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]); | ||
43 | |||
44 | /* Currently stepping a per-CPU kernel breakpoint. */ | ||
45 | static DEFINE_PER_CPU(int, stepping_kernel_bp); | ||
46 | |||
47 | /* Number of BRP/WRP registers on this CPU. */ | ||
48 | static int core_num_brps; | ||
49 | static int core_num_wrps; | ||
50 | |||
51 | /* Determine number of BRP registers available. */ | ||
52 | static int get_num_brps(void) | ||
53 | { | ||
54 | return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1; | ||
55 | } | ||
56 | |||
57 | /* Determine number of WRP registers available. */ | ||
58 | static int get_num_wrps(void) | ||
59 | { | ||
60 | return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1; | ||
61 | } | ||
62 | |||
63 | int hw_breakpoint_slots(int type) | ||
64 | { | ||
65 | /* | ||
66 | * We can be called early, so don't rely on | ||
67 | * our static variables being initialised. | ||
68 | */ | ||
69 | switch (type) { | ||
70 | case TYPE_INST: | ||
71 | return get_num_brps(); | ||
72 | case TYPE_DATA: | ||
73 | return get_num_wrps(); | ||
74 | default: | ||
75 | pr_warning("unknown slot type: %d\n", type); | ||
76 | return 0; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | #define READ_WB_REG_CASE(OFF, N, REG, VAL) \ | ||
81 | case (OFF + N): \ | ||
82 | AARCH64_DBG_READ(N, REG, VAL); \ | ||
83 | break | ||
84 | |||
85 | #define WRITE_WB_REG_CASE(OFF, N, REG, VAL) \ | ||
86 | case (OFF + N): \ | ||
87 | AARCH64_DBG_WRITE(N, REG, VAL); \ | ||
88 | break | ||
89 | |||
90 | #define GEN_READ_WB_REG_CASES(OFF, REG, VAL) \ | ||
91 | READ_WB_REG_CASE(OFF, 0, REG, VAL); \ | ||
92 | READ_WB_REG_CASE(OFF, 1, REG, VAL); \ | ||
93 | READ_WB_REG_CASE(OFF, 2, REG, VAL); \ | ||
94 | READ_WB_REG_CASE(OFF, 3, REG, VAL); \ | ||
95 | READ_WB_REG_CASE(OFF, 4, REG, VAL); \ | ||
96 | READ_WB_REG_CASE(OFF, 5, REG, VAL); \ | ||
97 | READ_WB_REG_CASE(OFF, 6, REG, VAL); \ | ||
98 | READ_WB_REG_CASE(OFF, 7, REG, VAL); \ | ||
99 | READ_WB_REG_CASE(OFF, 8, REG, VAL); \ | ||
100 | READ_WB_REG_CASE(OFF, 9, REG, VAL); \ | ||
101 | READ_WB_REG_CASE(OFF, 10, REG, VAL); \ | ||
102 | READ_WB_REG_CASE(OFF, 11, REG, VAL); \ | ||
103 | READ_WB_REG_CASE(OFF, 12, REG, VAL); \ | ||
104 | READ_WB_REG_CASE(OFF, 13, REG, VAL); \ | ||
105 | READ_WB_REG_CASE(OFF, 14, REG, VAL); \ | ||
106 | READ_WB_REG_CASE(OFF, 15, REG, VAL) | ||
107 | |||
108 | #define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL) \ | ||
109 | WRITE_WB_REG_CASE(OFF, 0, REG, VAL); \ | ||
110 | WRITE_WB_REG_CASE(OFF, 1, REG, VAL); \ | ||
111 | WRITE_WB_REG_CASE(OFF, 2, REG, VAL); \ | ||
112 | WRITE_WB_REG_CASE(OFF, 3, REG, VAL); \ | ||
113 | WRITE_WB_REG_CASE(OFF, 4, REG, VAL); \ | ||
114 | WRITE_WB_REG_CASE(OFF, 5, REG, VAL); \ | ||
115 | WRITE_WB_REG_CASE(OFF, 6, REG, VAL); \ | ||
116 | WRITE_WB_REG_CASE(OFF, 7, REG, VAL); \ | ||
117 | WRITE_WB_REG_CASE(OFF, 8, REG, VAL); \ | ||
118 | WRITE_WB_REG_CASE(OFF, 9, REG, VAL); \ | ||
119 | WRITE_WB_REG_CASE(OFF, 10, REG, VAL); \ | ||
120 | WRITE_WB_REG_CASE(OFF, 11, REG, VAL); \ | ||
121 | WRITE_WB_REG_CASE(OFF, 12, REG, VAL); \ | ||
122 | WRITE_WB_REG_CASE(OFF, 13, REG, VAL); \ | ||
123 | WRITE_WB_REG_CASE(OFF, 14, REG, VAL); \ | ||
124 | WRITE_WB_REG_CASE(OFF, 15, REG, VAL) | ||
125 | |||
126 | static u64 read_wb_reg(int reg, int n) | ||
127 | { | ||
128 | u64 val = 0; | ||
129 | |||
130 | switch (reg + n) { | ||
131 | GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); | ||
132 | GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); | ||
133 | GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); | ||
134 | GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); | ||
135 | default: | ||
136 | pr_warning("attempt to read from unknown breakpoint register %d\n", n); | ||
137 | } | ||
138 | |||
139 | return val; | ||
140 | } | ||
141 | |||
142 | static void write_wb_reg(int reg, int n, u64 val) | ||
143 | { | ||
144 | switch (reg + n) { | ||
145 | GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val); | ||
146 | GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val); | ||
147 | GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val); | ||
148 | GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val); | ||
149 | default: | ||
150 | pr_warning("attempt to write to unknown breakpoint register %d\n", n); | ||
151 | } | ||
152 | isb(); | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Convert a breakpoint privilege level to the corresponding exception | ||
157 | * level. | ||
158 | */ | ||
159 | static enum debug_el debug_exception_level(int privilege) | ||
160 | { | ||
161 | switch (privilege) { | ||
162 | case AARCH64_BREAKPOINT_EL0: | ||
163 | return DBG_ACTIVE_EL0; | ||
164 | case AARCH64_BREAKPOINT_EL1: | ||
165 | return DBG_ACTIVE_EL1; | ||
166 | default: | ||
167 | pr_warning("invalid breakpoint privilege level %d\n", privilege); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Install a perf counter breakpoint. | ||
174 | */ | ||
175 | int arch_install_hw_breakpoint(struct perf_event *bp) | ||
176 | { | ||
177 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
178 | struct perf_event **slot, **slots; | ||
179 | struct debug_info *debug_info = ¤t->thread.debug; | ||
180 | int i, max_slots, ctrl_reg, val_reg, reg_enable; | ||
181 | u32 ctrl; | ||
182 | |||
183 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { | ||
184 | /* Breakpoint */ | ||
185 | ctrl_reg = AARCH64_DBG_REG_BCR; | ||
186 | val_reg = AARCH64_DBG_REG_BVR; | ||
187 | slots = __get_cpu_var(bp_on_reg); | ||
188 | max_slots = core_num_brps; | ||
189 | reg_enable = !debug_info->bps_disabled; | ||
190 | } else { | ||
191 | /* Watchpoint */ | ||
192 | ctrl_reg = AARCH64_DBG_REG_WCR; | ||
193 | val_reg = AARCH64_DBG_REG_WVR; | ||
194 | slots = __get_cpu_var(wp_on_reg); | ||
195 | max_slots = core_num_wrps; | ||
196 | reg_enable = !debug_info->wps_disabled; | ||
197 | } | ||
198 | |||
199 | for (i = 0; i < max_slots; ++i) { | ||
200 | slot = &slots[i]; | ||
201 | |||
202 | if (!*slot) { | ||
203 | *slot = bp; | ||
204 | break; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) | ||
209 | return -ENOSPC; | ||
210 | |||
211 | /* Ensure debug monitors are enabled at the correct exception level. */ | ||
212 | enable_debug_monitors(debug_exception_level(info->ctrl.privilege)); | ||
213 | |||
214 | /* Setup the address register. */ | ||
215 | write_wb_reg(val_reg, i, info->address); | ||
216 | |||
217 | /* Setup the control register. */ | ||
218 | ctrl = encode_ctrl_reg(info->ctrl); | ||
219 | write_wb_reg(ctrl_reg, i, reg_enable ? ctrl | 0x1 : ctrl & ~0x1); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | void arch_uninstall_hw_breakpoint(struct perf_event *bp) | ||
225 | { | ||
226 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
227 | struct perf_event **slot, **slots; | ||
228 | int i, max_slots, base; | ||
229 | |||
230 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { | ||
231 | /* Breakpoint */ | ||
232 | base = AARCH64_DBG_REG_BCR; | ||
233 | slots = __get_cpu_var(bp_on_reg); | ||
234 | max_slots = core_num_brps; | ||
235 | } else { | ||
236 | /* Watchpoint */ | ||
237 | base = AARCH64_DBG_REG_WCR; | ||
238 | slots = __get_cpu_var(wp_on_reg); | ||
239 | max_slots = core_num_wrps; | ||
240 | } | ||
241 | |||
242 | /* Remove the breakpoint. */ | ||
243 | for (i = 0; i < max_slots; ++i) { | ||
244 | slot = &slots[i]; | ||
245 | |||
246 | if (*slot == bp) { | ||
247 | *slot = NULL; | ||
248 | break; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) | ||
253 | return; | ||
254 | |||
255 | /* Reset the control register. */ | ||
256 | write_wb_reg(base, i, 0); | ||
257 | |||
258 | /* Release the debug monitors for the correct exception level. */ | ||
259 | disable_debug_monitors(debug_exception_level(info->ctrl.privilege)); | ||
260 | } | ||
261 | |||
262 | static int get_hbp_len(u8 hbp_len) | ||
263 | { | ||
264 | unsigned int len_in_bytes = 0; | ||
265 | |||
266 | switch (hbp_len) { | ||
267 | case ARM_BREAKPOINT_LEN_1: | ||
268 | len_in_bytes = 1; | ||
269 | break; | ||
270 | case ARM_BREAKPOINT_LEN_2: | ||
271 | len_in_bytes = 2; | ||
272 | break; | ||
273 | case ARM_BREAKPOINT_LEN_4: | ||
274 | len_in_bytes = 4; | ||
275 | break; | ||
276 | case ARM_BREAKPOINT_LEN_8: | ||
277 | len_in_bytes = 8; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | return len_in_bytes; | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * Check whether bp virtual address is in kernel space. | ||
286 | */ | ||
287 | int arch_check_bp_in_kernelspace(struct perf_event *bp) | ||
288 | { | ||
289 | unsigned int len; | ||
290 | unsigned long va; | ||
291 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
292 | |||
293 | va = info->address; | ||
294 | len = get_hbp_len(info->ctrl.len); | ||
295 | |||
296 | return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl. | ||
301 | * Hopefully this will disappear when ptrace can bypass the conversion | ||
302 | * to generic breakpoint descriptions. | ||
303 | */ | ||
304 | int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, | ||
305 | int *gen_len, int *gen_type) | ||
306 | { | ||
307 | /* Type */ | ||
308 | switch (ctrl.type) { | ||
309 | case ARM_BREAKPOINT_EXECUTE: | ||
310 | *gen_type = HW_BREAKPOINT_X; | ||
311 | break; | ||
312 | case ARM_BREAKPOINT_LOAD: | ||
313 | *gen_type = HW_BREAKPOINT_R; | ||
314 | break; | ||
315 | case ARM_BREAKPOINT_STORE: | ||
316 | *gen_type = HW_BREAKPOINT_W; | ||
317 | break; | ||
318 | case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE: | ||
319 | *gen_type = HW_BREAKPOINT_RW; | ||
320 | break; | ||
321 | default: | ||
322 | return -EINVAL; | ||
323 | } | ||
324 | |||
325 | /* Len */ | ||
326 | switch (ctrl.len) { | ||
327 | case ARM_BREAKPOINT_LEN_1: | ||
328 | *gen_len = HW_BREAKPOINT_LEN_1; | ||
329 | break; | ||
330 | case ARM_BREAKPOINT_LEN_2: | ||
331 | *gen_len = HW_BREAKPOINT_LEN_2; | ||
332 | break; | ||
333 | case ARM_BREAKPOINT_LEN_4: | ||
334 | *gen_len = HW_BREAKPOINT_LEN_4; | ||
335 | break; | ||
336 | case ARM_BREAKPOINT_LEN_8: | ||
337 | *gen_len = HW_BREAKPOINT_LEN_8; | ||
338 | break; | ||
339 | default: | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | /* | ||
347 | * Construct an arch_hw_breakpoint from a perf_event. | ||
348 | */ | ||
349 | static int arch_build_bp_info(struct perf_event *bp) | ||
350 | { | ||
351 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
352 | |||
353 | /* Type */ | ||
354 | switch (bp->attr.bp_type) { | ||
355 | case HW_BREAKPOINT_X: | ||
356 | info->ctrl.type = ARM_BREAKPOINT_EXECUTE; | ||
357 | break; | ||
358 | case HW_BREAKPOINT_R: | ||
359 | info->ctrl.type = ARM_BREAKPOINT_LOAD; | ||
360 | break; | ||
361 | case HW_BREAKPOINT_W: | ||
362 | info->ctrl.type = ARM_BREAKPOINT_STORE; | ||
363 | break; | ||
364 | case HW_BREAKPOINT_RW: | ||
365 | info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; | ||
366 | break; | ||
367 | default: | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | |||
371 | /* Len */ | ||
372 | switch (bp->attr.bp_len) { | ||
373 | case HW_BREAKPOINT_LEN_1: | ||
374 | info->ctrl.len = ARM_BREAKPOINT_LEN_1; | ||
375 | break; | ||
376 | case HW_BREAKPOINT_LEN_2: | ||
377 | info->ctrl.len = ARM_BREAKPOINT_LEN_2; | ||
378 | break; | ||
379 | case HW_BREAKPOINT_LEN_4: | ||
380 | info->ctrl.len = ARM_BREAKPOINT_LEN_4; | ||
381 | break; | ||
382 | case HW_BREAKPOINT_LEN_8: | ||
383 | info->ctrl.len = ARM_BREAKPOINT_LEN_8; | ||
384 | break; | ||
385 | default: | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | |||
389 | /* | ||
390 | * On AArch64, we only permit breakpoints of length 4, whereas | ||
391 | * AArch32 also requires breakpoints of length 2 for Thumb. | ||
392 | * Watchpoints can be of length 1, 2, 4 or 8 bytes. | ||
393 | */ | ||
394 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { | ||
395 | if (is_compat_task()) { | ||
396 | if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 && | ||
397 | info->ctrl.len != ARM_BREAKPOINT_LEN_4) | ||
398 | return -EINVAL; | ||
399 | } else if (info->ctrl.len != ARM_BREAKPOINT_LEN_4) { | ||
400 | /* | ||
401 | * FIXME: Some tools (I'm looking at you perf) assume | ||
402 | * that breakpoints should be sizeof(long). This | ||
403 | * is nonsense. For now, we fix up the parameter | ||
404 | * but we should probably return -EINVAL instead. | ||
405 | */ | ||
406 | info->ctrl.len = ARM_BREAKPOINT_LEN_4; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | /* Address */ | ||
411 | info->address = bp->attr.bp_addr; | ||
412 | |||
413 | /* | ||
414 | * Privilege | ||
415 | * Note that we disallow combined EL0/EL1 breakpoints because | ||
416 | * that would complicate the stepping code. | ||
417 | */ | ||
418 | if (arch_check_bp_in_kernelspace(bp)) | ||
419 | info->ctrl.privilege = AARCH64_BREAKPOINT_EL1; | ||
420 | else | ||
421 | info->ctrl.privilege = AARCH64_BREAKPOINT_EL0; | ||
422 | |||
423 | /* Enabled? */ | ||
424 | info->ctrl.enabled = !bp->attr.disabled; | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * Validate the arch-specific HW Breakpoint register settings. | ||
431 | */ | ||
432 | int arch_validate_hwbkpt_settings(struct perf_event *bp) | ||
433 | { | ||
434 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
435 | int ret; | ||
436 | u64 alignment_mask, offset; | ||
437 | |||
438 | /* Build the arch_hw_breakpoint. */ | ||
439 | ret = arch_build_bp_info(bp); | ||
440 | if (ret) | ||
441 | return ret; | ||
442 | |||
443 | /* | ||
444 | * Check address alignment. | ||
445 | * We don't do any clever alignment correction for watchpoints | ||
446 | * because using 64-bit unaligned addresses is deprecated for | ||
447 | * AArch64. | ||
448 | * | ||
449 | * AArch32 tasks expect some simple alignment fixups, so emulate | ||
450 | * that here. | ||
451 | */ | ||
452 | if (is_compat_task()) { | ||
453 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) | ||
454 | alignment_mask = 0x7; | ||
455 | else | ||
456 | alignment_mask = 0x3; | ||
457 | offset = info->address & alignment_mask; | ||
458 | switch (offset) { | ||
459 | case 0: | ||
460 | /* Aligned */ | ||
461 | break; | ||
462 | case 1: | ||
463 | /* Allow single byte watchpoint. */ | ||
464 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) | ||
465 | break; | ||
466 | case 2: | ||
467 | /* Allow halfword watchpoints and breakpoints. */ | ||
468 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) | ||
469 | break; | ||
470 | default: | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | |||
474 | info->address &= ~alignment_mask; | ||
475 | info->ctrl.len <<= offset; | ||
476 | } else { | ||
477 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) | ||
478 | alignment_mask = 0x3; | ||
479 | else | ||
480 | alignment_mask = 0x7; | ||
481 | if (info->address & alignment_mask) | ||
482 | return -EINVAL; | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * Disallow per-task kernel breakpoints since these would | ||
487 | * complicate the stepping code. | ||
488 | */ | ||
489 | if (info->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.bp_target) | ||
490 | return -EINVAL; | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | /* | ||
496 | * Enable/disable all of the breakpoints active at the specified | ||
497 | * exception level at the register level. | ||
498 | * This is used when single-stepping after a breakpoint exception. | ||
499 | */ | ||
500 | static void toggle_bp_registers(int reg, enum debug_el el, int enable) | ||
501 | { | ||
502 | int i, max_slots, privilege; | ||
503 | u32 ctrl; | ||
504 | struct perf_event **slots; | ||
505 | |||
506 | switch (reg) { | ||
507 | case AARCH64_DBG_REG_BCR: | ||
508 | slots = __get_cpu_var(bp_on_reg); | ||
509 | max_slots = core_num_brps; | ||
510 | break; | ||
511 | case AARCH64_DBG_REG_WCR: | ||
512 | slots = __get_cpu_var(wp_on_reg); | ||
513 | max_slots = core_num_wrps; | ||
514 | break; | ||
515 | default: | ||
516 | return; | ||
517 | } | ||
518 | |||
519 | for (i = 0; i < max_slots; ++i) { | ||
520 | if (!slots[i]) | ||
521 | continue; | ||
522 | |||
523 | privilege = counter_arch_bp(slots[i])->ctrl.privilege; | ||
524 | if (debug_exception_level(privilege) != el) | ||
525 | continue; | ||
526 | |||
527 | ctrl = read_wb_reg(reg, i); | ||
528 | if (enable) | ||
529 | ctrl |= 0x1; | ||
530 | else | ||
531 | ctrl &= ~0x1; | ||
532 | write_wb_reg(reg, i, ctrl); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Debug exception handlers. | ||
538 | */ | ||
539 | static int breakpoint_handler(unsigned long unused, unsigned int esr, | ||
540 | struct pt_regs *regs) | ||
541 | { | ||
542 | int i, step = 0, *kernel_step; | ||
543 | u32 ctrl_reg; | ||
544 | u64 addr, val; | ||
545 | struct perf_event *bp, **slots; | ||
546 | struct debug_info *debug_info; | ||
547 | struct arch_hw_breakpoint_ctrl ctrl; | ||
548 | |||
549 | slots = (struct perf_event **)__get_cpu_var(bp_on_reg); | ||
550 | addr = instruction_pointer(regs); | ||
551 | debug_info = ¤t->thread.debug; | ||
552 | |||
553 | for (i = 0; i < core_num_brps; ++i) { | ||
554 | rcu_read_lock(); | ||
555 | |||
556 | bp = slots[i]; | ||
557 | |||
558 | if (bp == NULL) | ||
559 | goto unlock; | ||
560 | |||
561 | /* Check if the breakpoint value matches. */ | ||
562 | val = read_wb_reg(AARCH64_DBG_REG_BVR, i); | ||
563 | if (val != (addr & ~0x3)) | ||
564 | goto unlock; | ||
565 | |||
566 | /* Possible match, check the byte address select to confirm. */ | ||
567 | ctrl_reg = read_wb_reg(AARCH64_DBG_REG_BCR, i); | ||
568 | decode_ctrl_reg(ctrl_reg, &ctrl); | ||
569 | if (!((1 << (addr & 0x3)) & ctrl.len)) | ||
570 | goto unlock; | ||
571 | |||
572 | counter_arch_bp(bp)->trigger = addr; | ||
573 | perf_bp_event(bp, regs); | ||
574 | |||
575 | /* Do we need to handle the stepping? */ | ||
576 | if (!bp->overflow_handler) | ||
577 | step = 1; | ||
578 | unlock: | ||
579 | rcu_read_unlock(); | ||
580 | } | ||
581 | |||
582 | if (!step) | ||
583 | return 0; | ||
584 | |||
585 | if (user_mode(regs)) { | ||
586 | debug_info->bps_disabled = 1; | ||
587 | toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 0); | ||
588 | |||
589 | /* If we're already stepping a watchpoint, just return. */ | ||
590 | if (debug_info->wps_disabled) | ||
591 | return 0; | ||
592 | |||
593 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
594 | debug_info->suspended_step = 1; | ||
595 | else | ||
596 | user_enable_single_step(current); | ||
597 | } else { | ||
598 | toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 0); | ||
599 | kernel_step = &__get_cpu_var(stepping_kernel_bp); | ||
600 | |||
601 | if (*kernel_step != ARM_KERNEL_STEP_NONE) | ||
602 | return 0; | ||
603 | |||
604 | if (kernel_active_single_step()) { | ||
605 | *kernel_step = ARM_KERNEL_STEP_SUSPEND; | ||
606 | } else { | ||
607 | *kernel_step = ARM_KERNEL_STEP_ACTIVE; | ||
608 | kernel_enable_single_step(regs); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int watchpoint_handler(unsigned long addr, unsigned int esr, | ||
616 | struct pt_regs *regs) | ||
617 | { | ||
618 | int i, step = 0, *kernel_step, access; | ||
619 | u32 ctrl_reg; | ||
620 | u64 val, alignment_mask; | ||
621 | struct perf_event *wp, **slots; | ||
622 | struct debug_info *debug_info; | ||
623 | struct arch_hw_breakpoint *info; | ||
624 | struct arch_hw_breakpoint_ctrl ctrl; | ||
625 | |||
626 | slots = (struct perf_event **)__get_cpu_var(wp_on_reg); | ||
627 | debug_info = ¤t->thread.debug; | ||
628 | |||
629 | for (i = 0; i < core_num_wrps; ++i) { | ||
630 | rcu_read_lock(); | ||
631 | |||
632 | wp = slots[i]; | ||
633 | |||
634 | if (wp == NULL) | ||
635 | goto unlock; | ||
636 | |||
637 | info = counter_arch_bp(wp); | ||
638 | /* AArch32 watchpoints are either 4 or 8 bytes aligned. */ | ||
639 | if (is_compat_task()) { | ||
640 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) | ||
641 | alignment_mask = 0x7; | ||
642 | else | ||
643 | alignment_mask = 0x3; | ||
644 | } else { | ||
645 | alignment_mask = 0x7; | ||
646 | } | ||
647 | |||
648 | /* Check if the watchpoint value matches. */ | ||
649 | val = read_wb_reg(AARCH64_DBG_REG_WVR, i); | ||
650 | if (val != (addr & ~alignment_mask)) | ||
651 | goto unlock; | ||
652 | |||
653 | /* Possible match, check the byte address select to confirm. */ | ||
654 | ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i); | ||
655 | decode_ctrl_reg(ctrl_reg, &ctrl); | ||
656 | if (!((1 << (addr & alignment_mask)) & ctrl.len)) | ||
657 | goto unlock; | ||
658 | |||
659 | /* | ||
660 | * Check that the access type matches. | ||
661 | * 0 => load, otherwise => store | ||
662 | */ | ||
663 | access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W : | ||
664 | HW_BREAKPOINT_R; | ||
665 | if (!(access & hw_breakpoint_type(wp))) | ||
666 | goto unlock; | ||
667 | |||
668 | info->trigger = addr; | ||
669 | perf_bp_event(wp, regs); | ||
670 | |||
671 | /* Do we need to handle the stepping? */ | ||
672 | if (!wp->overflow_handler) | ||
673 | step = 1; | ||
674 | |||
675 | unlock: | ||
676 | rcu_read_unlock(); | ||
677 | } | ||
678 | |||
679 | if (!step) | ||
680 | return 0; | ||
681 | |||
682 | /* | ||
683 | * We always disable EL0 watchpoints because the kernel can | ||
684 | * cause these to fire via an unprivileged access. | ||
685 | */ | ||
686 | toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 0); | ||
687 | |||
688 | if (user_mode(regs)) { | ||
689 | debug_info->wps_disabled = 1; | ||
690 | |||
691 | /* If we're already stepping a breakpoint, just return. */ | ||
692 | if (debug_info->bps_disabled) | ||
693 | return 0; | ||
694 | |||
695 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
696 | debug_info->suspended_step = 1; | ||
697 | else | ||
698 | user_enable_single_step(current); | ||
699 | } else { | ||
700 | toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 0); | ||
701 | kernel_step = &__get_cpu_var(stepping_kernel_bp); | ||
702 | |||
703 | if (*kernel_step != ARM_KERNEL_STEP_NONE) | ||
704 | return 0; | ||
705 | |||
706 | if (kernel_active_single_step()) { | ||
707 | *kernel_step = ARM_KERNEL_STEP_SUSPEND; | ||
708 | } else { | ||
709 | *kernel_step = ARM_KERNEL_STEP_ACTIVE; | ||
710 | kernel_enable_single_step(regs); | ||
711 | } | ||
712 | } | ||
713 | |||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | /* | ||
718 | * Handle single-step exception. | ||
719 | */ | ||
720 | int reinstall_suspended_bps(struct pt_regs *regs) | ||
721 | { | ||
722 | struct debug_info *debug_info = ¤t->thread.debug; | ||
723 | int handled_exception = 0, *kernel_step; | ||
724 | |||
725 | kernel_step = &__get_cpu_var(stepping_kernel_bp); | ||
726 | |||
727 | /* | ||
728 | * Called from single-step exception handler. | ||
729 | * Return 0 if execution can resume, 1 if a SIGTRAP should be | ||
730 | * reported. | ||
731 | */ | ||
732 | if (user_mode(regs)) { | ||
733 | if (debug_info->bps_disabled) { | ||
734 | debug_info->bps_disabled = 0; | ||
735 | toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 1); | ||
736 | handled_exception = 1; | ||
737 | } | ||
738 | |||
739 | if (debug_info->wps_disabled) { | ||
740 | debug_info->wps_disabled = 0; | ||
741 | toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1); | ||
742 | handled_exception = 1; | ||
743 | } | ||
744 | |||
745 | if (handled_exception) { | ||
746 | if (debug_info->suspended_step) { | ||
747 | debug_info->suspended_step = 0; | ||
748 | /* Allow exception handling to fall-through. */ | ||
749 | handled_exception = 0; | ||
750 | } else { | ||
751 | user_disable_single_step(current); | ||
752 | } | ||
753 | } | ||
754 | } else if (*kernel_step != ARM_KERNEL_STEP_NONE) { | ||
755 | toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 1); | ||
756 | toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 1); | ||
757 | |||
758 | if (!debug_info->wps_disabled) | ||
759 | toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1); | ||
760 | |||
761 | if (*kernel_step != ARM_KERNEL_STEP_SUSPEND) { | ||
762 | kernel_disable_single_step(); | ||
763 | handled_exception = 1; | ||
764 | } else { | ||
765 | handled_exception = 0; | ||
766 | } | ||
767 | |||
768 | *kernel_step = ARM_KERNEL_STEP_NONE; | ||
769 | } | ||
770 | |||
771 | return !handled_exception; | ||
772 | } | ||
773 | |||
774 | /* | ||
775 | * Context-switcher for restoring suspended breakpoints. | ||
776 | */ | ||
777 | void hw_breakpoint_thread_switch(struct task_struct *next) | ||
778 | { | ||
779 | /* | ||
780 | * current next | ||
781 | * disabled: 0 0 => The usual case, NOTIFY_DONE | ||
782 | * 0 1 => Disable the registers | ||
783 | * 1 0 => Enable the registers | ||
784 | * 1 1 => NOTIFY_DONE. per-task bps will | ||
785 | * get taken care of by perf. | ||
786 | */ | ||
787 | |||
788 | struct debug_info *current_debug_info, *next_debug_info; | ||
789 | |||
790 | current_debug_info = ¤t->thread.debug; | ||
791 | next_debug_info = &next->thread.debug; | ||
792 | |||
793 | /* Update breakpoints. */ | ||
794 | if (current_debug_info->bps_disabled != next_debug_info->bps_disabled) | ||
795 | toggle_bp_registers(AARCH64_DBG_REG_BCR, | ||
796 | DBG_ACTIVE_EL0, | ||
797 | !next_debug_info->bps_disabled); | ||
798 | |||
799 | /* Update watchpoints. */ | ||
800 | if (current_debug_info->wps_disabled != next_debug_info->wps_disabled) | ||
801 | toggle_bp_registers(AARCH64_DBG_REG_WCR, | ||
802 | DBG_ACTIVE_EL0, | ||
803 | !next_debug_info->wps_disabled); | ||
804 | } | ||
805 | |||
806 | /* | ||
807 | * CPU initialisation. | ||
808 | */ | ||
809 | static void reset_ctrl_regs(void *unused) | ||
810 | { | ||
811 | int i; | ||
812 | |||
813 | for (i = 0; i < core_num_brps; ++i) { | ||
814 | write_wb_reg(AARCH64_DBG_REG_BCR, i, 0UL); | ||
815 | write_wb_reg(AARCH64_DBG_REG_BVR, i, 0UL); | ||
816 | } | ||
817 | |||
818 | for (i = 0; i < core_num_wrps; ++i) { | ||
819 | write_wb_reg(AARCH64_DBG_REG_WCR, i, 0UL); | ||
820 | write_wb_reg(AARCH64_DBG_REG_WVR, i, 0UL); | ||
821 | } | ||
822 | } | ||
823 | |||
824 | static int __cpuinit hw_breakpoint_reset_notify(struct notifier_block *self, | ||
825 | unsigned long action, | ||
826 | void *hcpu) | ||
827 | { | ||
828 | int cpu = (long)hcpu; | ||
829 | if (action == CPU_ONLINE) | ||
830 | smp_call_function_single(cpu, reset_ctrl_regs, NULL, 1); | ||
831 | return NOTIFY_OK; | ||
832 | } | ||
833 | |||
834 | static struct notifier_block __cpuinitdata hw_breakpoint_reset_nb = { | ||
835 | .notifier_call = hw_breakpoint_reset_notify, | ||
836 | }; | ||
837 | |||
838 | /* | ||
839 | * One-time initialisation. | ||
840 | */ | ||
841 | static int __init arch_hw_breakpoint_init(void) | ||
842 | { | ||
843 | core_num_brps = get_num_brps(); | ||
844 | core_num_wrps = get_num_wrps(); | ||
845 | |||
846 | pr_info("found %d breakpoint and %d watchpoint registers.\n", | ||
847 | core_num_brps, core_num_wrps); | ||
848 | |||
849 | /* | ||
850 | * Reset the breakpoint resources. We assume that a halting | ||
851 | * debugger will leave the world in a nice state for us. | ||
852 | */ | ||
853 | smp_call_function(reset_ctrl_regs, NULL, 1); | ||
854 | reset_ctrl_regs(NULL); | ||
855 | |||
856 | /* Register debug fault handlers. */ | ||
857 | hook_debug_fault_code(DBG_ESR_EVT_HWBP, breakpoint_handler, SIGTRAP, | ||
858 | TRAP_HWBKPT, "hw-breakpoint handler"); | ||
859 | hook_debug_fault_code(DBG_ESR_EVT_HWWP, watchpoint_handler, SIGTRAP, | ||
860 | TRAP_HWBKPT, "hw-watchpoint handler"); | ||
861 | |||
862 | /* Register hotplug notifier. */ | ||
863 | register_cpu_notifier(&hw_breakpoint_reset_nb); | ||
864 | |||
865 | return 0; | ||
866 | } | ||
867 | arch_initcall(arch_hw_breakpoint_init); | ||
868 | |||
869 | void hw_breakpoint_pmu_read(struct perf_event *bp) | ||
870 | { | ||
871 | } | ||
872 | |||
873 | /* | ||
874 | * Dummy function to register with die_notifier. | ||
875 | */ | ||
876 | int hw_breakpoint_exceptions_notify(struct notifier_block *unused, | ||
877 | unsigned long val, void *data) | ||
878 | { | ||
879 | return NOTIFY_DONE; | ||
880 | } | ||
diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c new file mode 100644 index 000000000000..7d37ead4d199 --- /dev/null +++ b/arch/arm64/kernel/io.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/io.c | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/export.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | /* | ||
24 | * Copy data from IO memory space to "real" memory space. | ||
25 | */ | ||
26 | void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) | ||
27 | { | ||
28 | unsigned char *t = to; | ||
29 | while (count) { | ||
30 | count--; | ||
31 | *t = readb(from); | ||
32 | t++; | ||
33 | from++; | ||
34 | } | ||
35 | } | ||
36 | EXPORT_SYMBOL(__memcpy_fromio); | ||
37 | |||
38 | /* | ||
39 | * Copy data from "real" memory space to IO memory space. | ||
40 | */ | ||
41 | void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count) | ||
42 | { | ||
43 | const unsigned char *f = from; | ||
44 | while (count) { | ||
45 | count--; | ||
46 | writeb(*f, to); | ||
47 | f++; | ||
48 | to++; | ||
49 | } | ||
50 | } | ||
51 | EXPORT_SYMBOL(__memcpy_toio); | ||
52 | |||
53 | /* | ||
54 | * "memset" on IO memory space. | ||
55 | */ | ||
56 | void __memset_io(volatile void __iomem *dst, int c, size_t count) | ||
57 | { | ||
58 | while (count) { | ||
59 | count--; | ||
60 | writeb(c, dst); | ||
61 | dst++; | ||
62 | } | ||
63 | } | ||
64 | EXPORT_SYMBOL(__memset_io); | ||
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c new file mode 100644 index 000000000000..0373c6609eaf --- /dev/null +++ b/arch/arm64/kernel/irq.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/irq.c | ||
3 | * | ||
4 | * Copyright (C) 1992 Linus Torvalds | ||
5 | * Modifications for ARM processor Copyright (C) 1995-2000 Russell King. | ||
6 | * Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation. | ||
7 | * Dynamic Tick Timer written by Tony Lindgren <tony@atomide.com> and | ||
8 | * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>. | ||
9 | * Copyright (C) 2012 ARM Ltd. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel_stat.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/smp.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/of_irq.h> | ||
29 | #include <linux/seq_file.h> | ||
30 | #include <linux/ratelimit.h> | ||
31 | |||
32 | unsigned long irq_err_count; | ||
33 | |||
34 | int arch_show_interrupts(struct seq_file *p, int prec) | ||
35 | { | ||
36 | #ifdef CONFIG_SMP | ||
37 | show_ipi_list(p, prec); | ||
38 | #endif | ||
39 | seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * handle_IRQ handles all hardware IRQ's. Decoded IRQs should | ||
45 | * not come via this function. Instead, they should provide their | ||
46 | * own 'handler'. Used by platform code implementing C-based 1st | ||
47 | * level decoding. | ||
48 | */ | ||
49 | void handle_IRQ(unsigned int irq, struct pt_regs *regs) | ||
50 | { | ||
51 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
52 | |||
53 | irq_enter(); | ||
54 | |||
55 | /* | ||
56 | * Some hardware gives randomly wrong interrupts. Rather | ||
57 | * than crashing, do something sensible. | ||
58 | */ | ||
59 | if (unlikely(irq >= nr_irqs)) { | ||
60 | pr_warn_ratelimited("Bad IRQ%u\n", irq); | ||
61 | ack_bad_irq(irq); | ||
62 | } else { | ||
63 | generic_handle_irq(irq); | ||
64 | } | ||
65 | |||
66 | irq_exit(); | ||
67 | set_irq_regs(old_regs); | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Interrupt controllers supported by the kernel. | ||
72 | */ | ||
73 | static const struct of_device_id intctrl_of_match[] __initconst = { | ||
74 | /* IRQ controllers { .compatible, .data } info to go here */ | ||
75 | {} | ||
76 | }; | ||
77 | |||
78 | void __init init_IRQ(void) | ||
79 | { | ||
80 | of_irq_init(intctrl_of_match); | ||
81 | |||
82 | if (!handle_arch_irq) | ||
83 | panic("No interrupt controller found."); | ||
84 | } | ||
diff --git a/arch/arm64/kernel/kuser32.S b/arch/arm64/kernel/kuser32.S new file mode 100644 index 000000000000..8b69ecb1d8bc --- /dev/null +++ b/arch/arm64/kernel/kuser32.S | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * Low-level user helpers placed in the vectors page for AArch32. | ||
3 | * Based on the kuser helpers in arch/arm/kernel/entry-armv.S. | ||
4 | * | ||
5 | * Copyright (C) 2005-2011 Nicolas Pitre <nico@fluxnic.net> | ||
6 | * Copyright (C) 2012 ARM Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | * | ||
20 | * | ||
21 | * AArch32 user helpers. | ||
22 | * | ||
23 | * Each segment is 32-byte aligned and will be moved to the top of the high | ||
24 | * vector page. New segments (if ever needed) must be added in front of | ||
25 | * existing ones. This mechanism should be used only for things that are | ||
26 | * really small and justified, and not be abused freely. | ||
27 | * | ||
28 | * See Documentation/arm/kernel_user_helpers.txt for formal definitions. | ||
29 | */ | ||
30 | .align 5 | ||
31 | .globl __kuser_helper_start | ||
32 | __kuser_helper_start: | ||
33 | |||
34 | __kuser_cmpxchg64: // 0xffff0f60 | ||
35 | .inst 0xe92d00f0 // push {r4, r5, r6, r7} | ||
36 | .inst 0xe1c040d0 // ldrd r4, r5, [r0] | ||
37 | .inst 0xe1c160d0 // ldrd r6, r7, [r1] | ||
38 | .inst 0xf57ff05f // dmb sy | ||
39 | .inst 0xe1b20f9f // 1: ldrexd r0, r1, [r2] | ||
40 | .inst 0xe0303004 // eors r3, r0, r4 | ||
41 | .inst 0x00313005 // eoreqs r3, r1, r5 | ||
42 | .inst 0x01a23f96 // strexdeq r3, r6, [r2] | ||
43 | .inst 0x03330001 // teqeq r3, #1 | ||
44 | .inst 0x0afffff9 // beq 1b | ||
45 | .inst 0xf57ff05f // dmb sy | ||
46 | .inst 0xe2730000 // rsbs r0, r3, #0 | ||
47 | .inst 0xe8bd00f0 // pop {r4, r5, r6, r7} | ||
48 | .inst 0xe12fff1e // bx lr | ||
49 | |||
50 | .align 5 | ||
51 | __kuser_memory_barrier: // 0xffff0fa0 | ||
52 | .inst 0xf57ff05f // dmb sy | ||
53 | .inst 0xe12fff1e // bx lr | ||
54 | |||
55 | .align 5 | ||
56 | __kuser_cmpxchg: // 0xffff0fc0 | ||
57 | .inst 0xf57ff05f // dmb sy | ||
58 | .inst 0xe1923f9f // 1: ldrex r3, [r2] | ||
59 | .inst 0xe0533000 // subs r3, r3, r0 | ||
60 | .inst 0x01823f91 // strexeq r3, r1, [r2] | ||
61 | .inst 0x03330001 // teqeq r3, #1 | ||
62 | .inst 0x0afffffa // beq 1b | ||
63 | .inst 0xe2730000 // rsbs r0, r3, #0 | ||
64 | .inst 0xeaffffef // b <__kuser_memory_barrier> | ||
65 | |||
66 | .align 5 | ||
67 | __kuser_get_tls: // 0xffff0fe0 | ||
68 | .inst 0xee1d0f70 // mrc p15, 0, r0, c13, c0, 3 | ||
69 | .inst 0xe12fff1e // bx lr | ||
70 | .rep 5 | ||
71 | .word 0 | ||
72 | .endr | ||
73 | |||
74 | __kuser_helper_version: // 0xffff0ffc | ||
75 | .word ((__kuser_helper_end - __kuser_helper_start) >> 5) | ||
76 | .globl __kuser_helper_end | ||
77 | __kuser_helper_end: | ||
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c new file mode 100644 index 000000000000..ca0e3d55da99 --- /dev/null +++ b/arch/arm64/kernel/module.c | |||
@@ -0,0 +1,456 @@ | |||
1 | /* | ||
2 | * AArch64 loadable module support. | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Limited | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Author: Will Deacon <will.deacon@arm.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/bitops.h> | ||
22 | #include <linux/elf.h> | ||
23 | #include <linux/gfp.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <linux/moduleloader.h> | ||
27 | #include <linux/vmalloc.h> | ||
28 | |||
29 | void *module_alloc(unsigned long size) | ||
30 | { | ||
31 | return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, | ||
32 | GFP_KERNEL, PAGE_KERNEL_EXEC, -1, | ||
33 | __builtin_return_address(0)); | ||
34 | } | ||
35 | |||
36 | enum aarch64_reloc_op { | ||
37 | RELOC_OP_NONE, | ||
38 | RELOC_OP_ABS, | ||
39 | RELOC_OP_PREL, | ||
40 | RELOC_OP_PAGE, | ||
41 | }; | ||
42 | |||
43 | static u64 do_reloc(enum aarch64_reloc_op reloc_op, void *place, u64 val) | ||
44 | { | ||
45 | switch (reloc_op) { | ||
46 | case RELOC_OP_ABS: | ||
47 | return val; | ||
48 | case RELOC_OP_PREL: | ||
49 | return val - (u64)place; | ||
50 | case RELOC_OP_PAGE: | ||
51 | return (val & ~0xfff) - ((u64)place & ~0xfff); | ||
52 | case RELOC_OP_NONE: | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | pr_err("do_reloc: unknown relocation operation %d\n", reloc_op); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len) | ||
61 | { | ||
62 | u64 imm_mask = (1 << len) - 1; | ||
63 | s64 sval = do_reloc(op, place, val); | ||
64 | |||
65 | switch (len) { | ||
66 | case 16: | ||
67 | *(s16 *)place = sval; | ||
68 | break; | ||
69 | case 32: | ||
70 | *(s32 *)place = sval; | ||
71 | break; | ||
72 | case 64: | ||
73 | *(s64 *)place = sval; | ||
74 | break; | ||
75 | default: | ||
76 | pr_err("Invalid length (%d) for data relocation\n", len); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Extract the upper value bits (including the sign bit) and | ||
82 | * shift them to bit 0. | ||
83 | */ | ||
84 | sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1); | ||
85 | |||
86 | /* | ||
87 | * Overflow has occurred if the value is not representable in | ||
88 | * len bits (i.e the bottom len bits are not sign-extended and | ||
89 | * the top bits are not all zero). | ||
90 | */ | ||
91 | if ((u64)(sval + 1) > 2) | ||
92 | return -ERANGE; | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | enum aarch64_imm_type { | ||
98 | INSN_IMM_MOVNZ, | ||
99 | INSN_IMM_MOVK, | ||
100 | INSN_IMM_ADR, | ||
101 | INSN_IMM_26, | ||
102 | INSN_IMM_19, | ||
103 | INSN_IMM_16, | ||
104 | INSN_IMM_14, | ||
105 | INSN_IMM_12, | ||
106 | INSN_IMM_9, | ||
107 | }; | ||
108 | |||
109 | static u32 encode_insn_immediate(enum aarch64_imm_type type, u32 insn, u64 imm) | ||
110 | { | ||
111 | u32 immlo, immhi, lomask, himask, mask; | ||
112 | int shift; | ||
113 | |||
114 | switch (type) { | ||
115 | case INSN_IMM_MOVNZ: | ||
116 | /* | ||
117 | * For signed MOVW relocations, we have to manipulate the | ||
118 | * instruction encoding depending on whether or not the | ||
119 | * immediate is less than zero. | ||
120 | */ | ||
121 | insn &= ~(3 << 29); | ||
122 | if ((s64)imm >= 0) { | ||
123 | /* >=0: Set the instruction to MOVZ (opcode 10b). */ | ||
124 | insn |= 2 << 29; | ||
125 | } else { | ||
126 | /* | ||
127 | * <0: Set the instruction to MOVN (opcode 00b). | ||
128 | * Since we've masked the opcode already, we | ||
129 | * don't need to do anything other than | ||
130 | * inverting the new immediate field. | ||
131 | */ | ||
132 | imm = ~imm; | ||
133 | } | ||
134 | case INSN_IMM_MOVK: | ||
135 | mask = BIT(16) - 1; | ||
136 | shift = 5; | ||
137 | break; | ||
138 | case INSN_IMM_ADR: | ||
139 | lomask = 0x3; | ||
140 | himask = 0x7ffff; | ||
141 | immlo = imm & lomask; | ||
142 | imm >>= 2; | ||
143 | immhi = imm & himask; | ||
144 | imm = (immlo << 24) | (immhi); | ||
145 | mask = (lomask << 24) | (himask); | ||
146 | shift = 5; | ||
147 | break; | ||
148 | case INSN_IMM_26: | ||
149 | mask = BIT(26) - 1; | ||
150 | shift = 0; | ||
151 | break; | ||
152 | case INSN_IMM_19: | ||
153 | mask = BIT(19) - 1; | ||
154 | shift = 5; | ||
155 | break; | ||
156 | case INSN_IMM_16: | ||
157 | mask = BIT(16) - 1; | ||
158 | shift = 5; | ||
159 | break; | ||
160 | case INSN_IMM_14: | ||
161 | mask = BIT(14) - 1; | ||
162 | shift = 5; | ||
163 | break; | ||
164 | case INSN_IMM_12: | ||
165 | mask = BIT(12) - 1; | ||
166 | shift = 10; | ||
167 | break; | ||
168 | case INSN_IMM_9: | ||
169 | mask = BIT(9) - 1; | ||
170 | shift = 12; | ||
171 | break; | ||
172 | default: | ||
173 | pr_err("encode_insn_immediate: unknown immediate encoding %d\n", | ||
174 | type); | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | /* Update the immediate field. */ | ||
179 | insn &= ~(mask << shift); | ||
180 | insn |= (imm & mask) << shift; | ||
181 | |||
182 | return insn; | ||
183 | } | ||
184 | |||
185 | static int reloc_insn_movw(enum aarch64_reloc_op op, void *place, u64 val, | ||
186 | int lsb, enum aarch64_imm_type imm_type) | ||
187 | { | ||
188 | u64 imm, limit = 0; | ||
189 | s64 sval; | ||
190 | u32 insn = *(u32 *)place; | ||
191 | |||
192 | sval = do_reloc(op, place, val); | ||
193 | sval >>= lsb; | ||
194 | imm = sval & 0xffff; | ||
195 | |||
196 | /* Update the instruction with the new encoding. */ | ||
197 | *(u32 *)place = encode_insn_immediate(imm_type, insn, imm); | ||
198 | |||
199 | /* Shift out the immediate field. */ | ||
200 | sval >>= 16; | ||
201 | |||
202 | /* | ||
203 | * For unsigned immediates, the overflow check is straightforward. | ||
204 | * For signed immediates, the sign bit is actually the bit past the | ||
205 | * most significant bit of the field. | ||
206 | * The INSN_IMM_16 immediate type is unsigned. | ||
207 | */ | ||
208 | if (imm_type != INSN_IMM_16) { | ||
209 | sval++; | ||
210 | limit++; | ||
211 | } | ||
212 | |||
213 | /* Check the upper bits depending on the sign of the immediate. */ | ||
214 | if ((u64)sval > limit) | ||
215 | return -ERANGE; | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int reloc_insn_imm(enum aarch64_reloc_op op, void *place, u64 val, | ||
221 | int lsb, int len, enum aarch64_imm_type imm_type) | ||
222 | { | ||
223 | u64 imm, imm_mask; | ||
224 | s64 sval; | ||
225 | u32 insn = *(u32 *)place; | ||
226 | |||
227 | /* Calculate the relocation value. */ | ||
228 | sval = do_reloc(op, place, val); | ||
229 | sval >>= lsb; | ||
230 | |||
231 | /* Extract the value bits and shift them to bit 0. */ | ||
232 | imm_mask = (BIT(lsb + len) - 1) >> lsb; | ||
233 | imm = sval & imm_mask; | ||
234 | |||
235 | /* Update the instruction's immediate field. */ | ||
236 | *(u32 *)place = encode_insn_immediate(imm_type, insn, imm); | ||
237 | |||
238 | /* | ||
239 | * Extract the upper value bits (including the sign bit) and | ||
240 | * shift them to bit 0. | ||
241 | */ | ||
242 | sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1); | ||
243 | |||
244 | /* | ||
245 | * Overflow has occurred if the upper bits are not all equal to | ||
246 | * the sign bit of the value. | ||
247 | */ | ||
248 | if ((u64)(sval + 1) >= 2) | ||
249 | return -ERANGE; | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | int apply_relocate_add(Elf64_Shdr *sechdrs, | ||
255 | const char *strtab, | ||
256 | unsigned int symindex, | ||
257 | unsigned int relsec, | ||
258 | struct module *me) | ||
259 | { | ||
260 | unsigned int i; | ||
261 | int ovf; | ||
262 | bool overflow_check; | ||
263 | Elf64_Sym *sym; | ||
264 | void *loc; | ||
265 | u64 val; | ||
266 | Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; | ||
267 | |||
268 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
269 | /* loc corresponds to P in the AArch64 ELF document. */ | ||
270 | loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
271 | + rel[i].r_offset; | ||
272 | |||
273 | /* sym is the ELF symbol we're referring to. */ | ||
274 | sym = (Elf64_Sym *)sechdrs[symindex].sh_addr | ||
275 | + ELF64_R_SYM(rel[i].r_info); | ||
276 | |||
277 | /* val corresponds to (S + A) in the AArch64 ELF document. */ | ||
278 | val = sym->st_value + rel[i].r_addend; | ||
279 | |||
280 | /* Check for overflow by default. */ | ||
281 | overflow_check = true; | ||
282 | |||
283 | /* Perform the static relocation. */ | ||
284 | switch (ELF64_R_TYPE(rel[i].r_info)) { | ||
285 | /* Null relocations. */ | ||
286 | case R_ARM_NONE: | ||
287 | case R_AARCH64_NONE: | ||
288 | ovf = 0; | ||
289 | break; | ||
290 | |||
291 | /* Data relocations. */ | ||
292 | case R_AARCH64_ABS64: | ||
293 | overflow_check = false; | ||
294 | ovf = reloc_data(RELOC_OP_ABS, loc, val, 64); | ||
295 | break; | ||
296 | case R_AARCH64_ABS32: | ||
297 | ovf = reloc_data(RELOC_OP_ABS, loc, val, 32); | ||
298 | break; | ||
299 | case R_AARCH64_ABS16: | ||
300 | ovf = reloc_data(RELOC_OP_ABS, loc, val, 16); | ||
301 | break; | ||
302 | case R_AARCH64_PREL64: | ||
303 | overflow_check = false; | ||
304 | ovf = reloc_data(RELOC_OP_PREL, loc, val, 64); | ||
305 | break; | ||
306 | case R_AARCH64_PREL32: | ||
307 | ovf = reloc_data(RELOC_OP_PREL, loc, val, 32); | ||
308 | break; | ||
309 | case R_AARCH64_PREL16: | ||
310 | ovf = reloc_data(RELOC_OP_PREL, loc, val, 16); | ||
311 | break; | ||
312 | |||
313 | /* MOVW instruction relocations. */ | ||
314 | case R_AARCH64_MOVW_UABS_G0_NC: | ||
315 | overflow_check = false; | ||
316 | case R_AARCH64_MOVW_UABS_G0: | ||
317 | ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0, | ||
318 | INSN_IMM_16); | ||
319 | break; | ||
320 | case R_AARCH64_MOVW_UABS_G1_NC: | ||
321 | overflow_check = false; | ||
322 | case R_AARCH64_MOVW_UABS_G1: | ||
323 | ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16, | ||
324 | INSN_IMM_16); | ||
325 | break; | ||
326 | case R_AARCH64_MOVW_UABS_G2_NC: | ||
327 | overflow_check = false; | ||
328 | case R_AARCH64_MOVW_UABS_G2: | ||
329 | ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32, | ||
330 | INSN_IMM_16); | ||
331 | break; | ||
332 | case R_AARCH64_MOVW_UABS_G3: | ||
333 | /* We're using the top bits so we can't overflow. */ | ||
334 | overflow_check = false; | ||
335 | ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 48, | ||
336 | INSN_IMM_16); | ||
337 | break; | ||
338 | case R_AARCH64_MOVW_SABS_G0: | ||
339 | ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0, | ||
340 | INSN_IMM_MOVNZ); | ||
341 | break; | ||
342 | case R_AARCH64_MOVW_SABS_G1: | ||
343 | ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16, | ||
344 | INSN_IMM_MOVNZ); | ||
345 | break; | ||
346 | case R_AARCH64_MOVW_SABS_G2: | ||
347 | ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32, | ||
348 | INSN_IMM_MOVNZ); | ||
349 | break; | ||
350 | case R_AARCH64_MOVW_PREL_G0_NC: | ||
351 | overflow_check = false; | ||
352 | ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0, | ||
353 | INSN_IMM_MOVK); | ||
354 | break; | ||
355 | case R_AARCH64_MOVW_PREL_G0: | ||
356 | ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0, | ||
357 | INSN_IMM_MOVNZ); | ||
358 | break; | ||
359 | case R_AARCH64_MOVW_PREL_G1_NC: | ||
360 | overflow_check = false; | ||
361 | ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16, | ||
362 | INSN_IMM_MOVK); | ||
363 | break; | ||
364 | case R_AARCH64_MOVW_PREL_G1: | ||
365 | ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16, | ||
366 | INSN_IMM_MOVNZ); | ||
367 | break; | ||
368 | case R_AARCH64_MOVW_PREL_G2_NC: | ||
369 | overflow_check = false; | ||
370 | ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32, | ||
371 | INSN_IMM_MOVK); | ||
372 | break; | ||
373 | case R_AARCH64_MOVW_PREL_G2: | ||
374 | ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32, | ||
375 | INSN_IMM_MOVNZ); | ||
376 | break; | ||
377 | case R_AARCH64_MOVW_PREL_G3: | ||
378 | /* We're using the top bits so we can't overflow. */ | ||
379 | overflow_check = false; | ||
380 | ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 48, | ||
381 | INSN_IMM_MOVNZ); | ||
382 | break; | ||
383 | |||
384 | /* Immediate instruction relocations. */ | ||
385 | case R_AARCH64_LD_PREL_LO19: | ||
386 | ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19, | ||
387 | INSN_IMM_19); | ||
388 | break; | ||
389 | case R_AARCH64_ADR_PREL_LO21: | ||
390 | ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 0, 21, | ||
391 | INSN_IMM_ADR); | ||
392 | break; | ||
393 | case R_AARCH64_ADR_PREL_PG_HI21_NC: | ||
394 | overflow_check = false; | ||
395 | case R_AARCH64_ADR_PREL_PG_HI21: | ||
396 | ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21, | ||
397 | INSN_IMM_ADR); | ||
398 | break; | ||
399 | case R_AARCH64_ADD_ABS_LO12_NC: | ||
400 | case R_AARCH64_LDST8_ABS_LO12_NC: | ||
401 | overflow_check = false; | ||
402 | ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 0, 12, | ||
403 | INSN_IMM_12); | ||
404 | break; | ||
405 | case R_AARCH64_LDST16_ABS_LO12_NC: | ||
406 | overflow_check = false; | ||
407 | ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 1, 11, | ||
408 | INSN_IMM_12); | ||
409 | break; | ||
410 | case R_AARCH64_LDST32_ABS_LO12_NC: | ||
411 | overflow_check = false; | ||
412 | ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 2, 10, | ||
413 | INSN_IMM_12); | ||
414 | break; | ||
415 | case R_AARCH64_LDST64_ABS_LO12_NC: | ||
416 | overflow_check = false; | ||
417 | ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 3, 9, | ||
418 | INSN_IMM_12); | ||
419 | break; | ||
420 | case R_AARCH64_LDST128_ABS_LO12_NC: | ||
421 | overflow_check = false; | ||
422 | ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 4, 8, | ||
423 | INSN_IMM_12); | ||
424 | break; | ||
425 | case R_AARCH64_TSTBR14: | ||
426 | ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 14, | ||
427 | INSN_IMM_14); | ||
428 | break; | ||
429 | case R_AARCH64_CONDBR19: | ||
430 | ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19, | ||
431 | INSN_IMM_19); | ||
432 | break; | ||
433 | case R_AARCH64_JUMP26: | ||
434 | case R_AARCH64_CALL26: | ||
435 | ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 26, | ||
436 | INSN_IMM_26); | ||
437 | break; | ||
438 | |||
439 | default: | ||
440 | pr_err("module %s: unsupported RELA relocation: %llu\n", | ||
441 | me->name, ELF64_R_TYPE(rel[i].r_info)); | ||
442 | return -ENOEXEC; | ||
443 | } | ||
444 | |||
445 | if (overflow_check && ovf == -ERANGE) | ||
446 | goto overflow; | ||
447 | |||
448 | } | ||
449 | |||
450 | return 0; | ||
451 | |||
452 | overflow: | ||
453 | pr_err("module %s: overflow in relocation type %d val %Lx\n", | ||
454 | me->name, (int)ELF64_R_TYPE(rel[i].r_info), val); | ||
455 | return -ENOEXEC; | ||
456 | } | ||
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c new file mode 100644 index 000000000000..ecbf2d81ec5c --- /dev/null +++ b/arch/arm64/kernel/perf_event.c | |||
@@ -0,0 +1,1368 @@ | |||
1 | /* | ||
2 | * PMU support | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Limited | ||
5 | * Author: Will Deacon <will.deacon@arm.com> | ||
6 | * | ||
7 | * This code is based heavily on the ARMv7 perf event code. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | #define pr_fmt(fmt) "hw perfevents: " fmt | ||
22 | |||
23 | #include <linux/bitmap.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/export.h> | ||
27 | #include <linux/perf_event.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/spinlock.h> | ||
30 | #include <linux/uaccess.h> | ||
31 | |||
32 | #include <asm/cputype.h> | ||
33 | #include <asm/irq.h> | ||
34 | #include <asm/irq_regs.h> | ||
35 | #include <asm/pmu.h> | ||
36 | #include <asm/stacktrace.h> | ||
37 | |||
38 | /* | ||
39 | * ARMv8 supports a maximum of 32 events. | ||
40 | * The cycle counter is included in this total. | ||
41 | */ | ||
42 | #define ARMPMU_MAX_HWEVENTS 32 | ||
43 | |||
44 | static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); | ||
45 | static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); | ||
46 | static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); | ||
47 | |||
48 | #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) | ||
49 | |||
50 | /* Set at runtime when we know what CPU type we are. */ | ||
51 | static struct arm_pmu *cpu_pmu; | ||
52 | |||
53 | int | ||
54 | armpmu_get_max_events(void) | ||
55 | { | ||
56 | int max_events = 0; | ||
57 | |||
58 | if (cpu_pmu != NULL) | ||
59 | max_events = cpu_pmu->num_events; | ||
60 | |||
61 | return max_events; | ||
62 | } | ||
63 | EXPORT_SYMBOL_GPL(armpmu_get_max_events); | ||
64 | |||
65 | int perf_num_counters(void) | ||
66 | { | ||
67 | return armpmu_get_max_events(); | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(perf_num_counters); | ||
70 | |||
71 | #define HW_OP_UNSUPPORTED 0xFFFF | ||
72 | |||
73 | #define C(_x) \ | ||
74 | PERF_COUNT_HW_CACHE_##_x | ||
75 | |||
76 | #define CACHE_OP_UNSUPPORTED 0xFFFF | ||
77 | |||
78 | static int | ||
79 | armpmu_map_cache_event(const unsigned (*cache_map) | ||
80 | [PERF_COUNT_HW_CACHE_MAX] | ||
81 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
82 | [PERF_COUNT_HW_CACHE_RESULT_MAX], | ||
83 | u64 config) | ||
84 | { | ||
85 | unsigned int cache_type, cache_op, cache_result, ret; | ||
86 | |||
87 | cache_type = (config >> 0) & 0xff; | ||
88 | if (cache_type >= PERF_COUNT_HW_CACHE_MAX) | ||
89 | return -EINVAL; | ||
90 | |||
91 | cache_op = (config >> 8) & 0xff; | ||
92 | if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX) | ||
93 | return -EINVAL; | ||
94 | |||
95 | cache_result = (config >> 16) & 0xff; | ||
96 | if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) | ||
97 | return -EINVAL; | ||
98 | |||
99 | ret = (int)(*cache_map)[cache_type][cache_op][cache_result]; | ||
100 | |||
101 | if (ret == CACHE_OP_UNSUPPORTED) | ||
102 | return -ENOENT; | ||
103 | |||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static int | ||
108 | armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) | ||
109 | { | ||
110 | int mapping = (*event_map)[config]; | ||
111 | return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; | ||
112 | } | ||
113 | |||
114 | static int | ||
115 | armpmu_map_raw_event(u32 raw_event_mask, u64 config) | ||
116 | { | ||
117 | return (int)(config & raw_event_mask); | ||
118 | } | ||
119 | |||
120 | static int map_cpu_event(struct perf_event *event, | ||
121 | const unsigned (*event_map)[PERF_COUNT_HW_MAX], | ||
122 | const unsigned (*cache_map) | ||
123 | [PERF_COUNT_HW_CACHE_MAX] | ||
124 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
125 | [PERF_COUNT_HW_CACHE_RESULT_MAX], | ||
126 | u32 raw_event_mask) | ||
127 | { | ||
128 | u64 config = event->attr.config; | ||
129 | |||
130 | switch (event->attr.type) { | ||
131 | case PERF_TYPE_HARDWARE: | ||
132 | return armpmu_map_event(event_map, config); | ||
133 | case PERF_TYPE_HW_CACHE: | ||
134 | return armpmu_map_cache_event(cache_map, config); | ||
135 | case PERF_TYPE_RAW: | ||
136 | return armpmu_map_raw_event(raw_event_mask, config); | ||
137 | } | ||
138 | |||
139 | return -ENOENT; | ||
140 | } | ||
141 | |||
142 | int | ||
143 | armpmu_event_set_period(struct perf_event *event, | ||
144 | struct hw_perf_event *hwc, | ||
145 | int idx) | ||
146 | { | ||
147 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
148 | s64 left = local64_read(&hwc->period_left); | ||
149 | s64 period = hwc->sample_period; | ||
150 | int ret = 0; | ||
151 | |||
152 | if (unlikely(left <= -period)) { | ||
153 | left = period; | ||
154 | local64_set(&hwc->period_left, left); | ||
155 | hwc->last_period = period; | ||
156 | ret = 1; | ||
157 | } | ||
158 | |||
159 | if (unlikely(left <= 0)) { | ||
160 | left += period; | ||
161 | local64_set(&hwc->period_left, left); | ||
162 | hwc->last_period = period; | ||
163 | ret = 1; | ||
164 | } | ||
165 | |||
166 | if (left > (s64)armpmu->max_period) | ||
167 | left = armpmu->max_period; | ||
168 | |||
169 | local64_set(&hwc->prev_count, (u64)-left); | ||
170 | |||
171 | armpmu->write_counter(idx, (u64)(-left) & 0xffffffff); | ||
172 | |||
173 | perf_event_update_userpage(event); | ||
174 | |||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | u64 | ||
179 | armpmu_event_update(struct perf_event *event, | ||
180 | struct hw_perf_event *hwc, | ||
181 | int idx) | ||
182 | { | ||
183 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
184 | u64 delta, prev_raw_count, new_raw_count; | ||
185 | |||
186 | again: | ||
187 | prev_raw_count = local64_read(&hwc->prev_count); | ||
188 | new_raw_count = armpmu->read_counter(idx); | ||
189 | |||
190 | if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, | ||
191 | new_raw_count) != prev_raw_count) | ||
192 | goto again; | ||
193 | |||
194 | delta = (new_raw_count - prev_raw_count) & armpmu->max_period; | ||
195 | |||
196 | local64_add(delta, &event->count); | ||
197 | local64_sub(delta, &hwc->period_left); | ||
198 | |||
199 | return new_raw_count; | ||
200 | } | ||
201 | |||
202 | static void | ||
203 | armpmu_read(struct perf_event *event) | ||
204 | { | ||
205 | struct hw_perf_event *hwc = &event->hw; | ||
206 | |||
207 | /* Don't read disabled counters! */ | ||
208 | if (hwc->idx < 0) | ||
209 | return; | ||
210 | |||
211 | armpmu_event_update(event, hwc, hwc->idx); | ||
212 | } | ||
213 | |||
214 | static void | ||
215 | armpmu_stop(struct perf_event *event, int flags) | ||
216 | { | ||
217 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
218 | struct hw_perf_event *hwc = &event->hw; | ||
219 | |||
220 | /* | ||
221 | * ARM pmu always has to update the counter, so ignore | ||
222 | * PERF_EF_UPDATE, see comments in armpmu_start(). | ||
223 | */ | ||
224 | if (!(hwc->state & PERF_HES_STOPPED)) { | ||
225 | armpmu->disable(hwc, hwc->idx); | ||
226 | barrier(); /* why? */ | ||
227 | armpmu_event_update(event, hwc, hwc->idx); | ||
228 | hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | static void | ||
233 | armpmu_start(struct perf_event *event, int flags) | ||
234 | { | ||
235 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
236 | struct hw_perf_event *hwc = &event->hw; | ||
237 | |||
238 | /* | ||
239 | * ARM pmu always has to reprogram the period, so ignore | ||
240 | * PERF_EF_RELOAD, see the comment below. | ||
241 | */ | ||
242 | if (flags & PERF_EF_RELOAD) | ||
243 | WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); | ||
244 | |||
245 | hwc->state = 0; | ||
246 | /* | ||
247 | * Set the period again. Some counters can't be stopped, so when we | ||
248 | * were stopped we simply disabled the IRQ source and the counter | ||
249 | * may have been left counting. If we don't do this step then we may | ||
250 | * get an interrupt too soon or *way* too late if the overflow has | ||
251 | * happened since disabling. | ||
252 | */ | ||
253 | armpmu_event_set_period(event, hwc, hwc->idx); | ||
254 | armpmu->enable(hwc, hwc->idx); | ||
255 | } | ||
256 | |||
257 | static void | ||
258 | armpmu_del(struct perf_event *event, int flags) | ||
259 | { | ||
260 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
261 | struct pmu_hw_events *hw_events = armpmu->get_hw_events(); | ||
262 | struct hw_perf_event *hwc = &event->hw; | ||
263 | int idx = hwc->idx; | ||
264 | |||
265 | WARN_ON(idx < 0); | ||
266 | |||
267 | armpmu_stop(event, PERF_EF_UPDATE); | ||
268 | hw_events->events[idx] = NULL; | ||
269 | clear_bit(idx, hw_events->used_mask); | ||
270 | |||
271 | perf_event_update_userpage(event); | ||
272 | } | ||
273 | |||
274 | static int | ||
275 | armpmu_add(struct perf_event *event, int flags) | ||
276 | { | ||
277 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
278 | struct pmu_hw_events *hw_events = armpmu->get_hw_events(); | ||
279 | struct hw_perf_event *hwc = &event->hw; | ||
280 | int idx; | ||
281 | int err = 0; | ||
282 | |||
283 | perf_pmu_disable(event->pmu); | ||
284 | |||
285 | /* If we don't have a space for the counter then finish early. */ | ||
286 | idx = armpmu->get_event_idx(hw_events, hwc); | ||
287 | if (idx < 0) { | ||
288 | err = idx; | ||
289 | goto out; | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * If there is an event in the counter we are going to use then make | ||
294 | * sure it is disabled. | ||
295 | */ | ||
296 | event->hw.idx = idx; | ||
297 | armpmu->disable(hwc, idx); | ||
298 | hw_events->events[idx] = event; | ||
299 | |||
300 | hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; | ||
301 | if (flags & PERF_EF_START) | ||
302 | armpmu_start(event, PERF_EF_RELOAD); | ||
303 | |||
304 | /* Propagate our changes to the userspace mapping. */ | ||
305 | perf_event_update_userpage(event); | ||
306 | |||
307 | out: | ||
308 | perf_pmu_enable(event->pmu); | ||
309 | return err; | ||
310 | } | ||
311 | |||
312 | static int | ||
313 | validate_event(struct pmu_hw_events *hw_events, | ||
314 | struct perf_event *event) | ||
315 | { | ||
316 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
317 | struct hw_perf_event fake_event = event->hw; | ||
318 | struct pmu *leader_pmu = event->group_leader->pmu; | ||
319 | |||
320 | if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF) | ||
321 | return 1; | ||
322 | |||
323 | return armpmu->get_event_idx(hw_events, &fake_event) >= 0; | ||
324 | } | ||
325 | |||
326 | static int | ||
327 | validate_group(struct perf_event *event) | ||
328 | { | ||
329 | struct perf_event *sibling, *leader = event->group_leader; | ||
330 | struct pmu_hw_events fake_pmu; | ||
331 | DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS); | ||
332 | |||
333 | /* | ||
334 | * Initialise the fake PMU. We only need to populate the | ||
335 | * used_mask for the purposes of validation. | ||
336 | */ | ||
337 | memset(fake_used_mask, 0, sizeof(fake_used_mask)); | ||
338 | fake_pmu.used_mask = fake_used_mask; | ||
339 | |||
340 | if (!validate_event(&fake_pmu, leader)) | ||
341 | return -EINVAL; | ||
342 | |||
343 | list_for_each_entry(sibling, &leader->sibling_list, group_entry) { | ||
344 | if (!validate_event(&fake_pmu, sibling)) | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | |||
348 | if (!validate_event(&fake_pmu, event)) | ||
349 | return -EINVAL; | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static void | ||
355 | armpmu_release_hardware(struct arm_pmu *armpmu) | ||
356 | { | ||
357 | int i, irq, irqs; | ||
358 | struct platform_device *pmu_device = armpmu->plat_device; | ||
359 | |||
360 | irqs = min(pmu_device->num_resources, num_possible_cpus()); | ||
361 | |||
362 | for (i = 0; i < irqs; ++i) { | ||
363 | if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) | ||
364 | continue; | ||
365 | irq = platform_get_irq(pmu_device, i); | ||
366 | if (irq >= 0) | ||
367 | free_irq(irq, armpmu); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | static int | ||
372 | armpmu_reserve_hardware(struct arm_pmu *armpmu) | ||
373 | { | ||
374 | int i, err, irq, irqs; | ||
375 | struct platform_device *pmu_device = armpmu->plat_device; | ||
376 | |||
377 | if (!pmu_device) { | ||
378 | pr_err("no PMU device registered\n"); | ||
379 | return -ENODEV; | ||
380 | } | ||
381 | |||
382 | irqs = min(pmu_device->num_resources, num_possible_cpus()); | ||
383 | if (irqs < 1) { | ||
384 | pr_err("no irqs for PMUs defined\n"); | ||
385 | return -ENODEV; | ||
386 | } | ||
387 | |||
388 | for (i = 0; i < irqs; ++i) { | ||
389 | err = 0; | ||
390 | irq = platform_get_irq(pmu_device, i); | ||
391 | if (irq < 0) | ||
392 | continue; | ||
393 | |||
394 | /* | ||
395 | * If we have a single PMU interrupt that we can't shift, | ||
396 | * assume that we're running on a uniprocessor machine and | ||
397 | * continue. Otherwise, continue without this interrupt. | ||
398 | */ | ||
399 | if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) { | ||
400 | pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", | ||
401 | irq, i); | ||
402 | continue; | ||
403 | } | ||
404 | |||
405 | err = request_irq(irq, armpmu->handle_irq, | ||
406 | IRQF_NOBALANCING, | ||
407 | "arm-pmu", armpmu); | ||
408 | if (err) { | ||
409 | pr_err("unable to request IRQ%d for ARM PMU counters\n", | ||
410 | irq); | ||
411 | armpmu_release_hardware(armpmu); | ||
412 | return err; | ||
413 | } | ||
414 | |||
415 | cpumask_set_cpu(i, &armpmu->active_irqs); | ||
416 | } | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static void | ||
422 | hw_perf_event_destroy(struct perf_event *event) | ||
423 | { | ||
424 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
425 | atomic_t *active_events = &armpmu->active_events; | ||
426 | struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex; | ||
427 | |||
428 | if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) { | ||
429 | armpmu_release_hardware(armpmu); | ||
430 | mutex_unlock(pmu_reserve_mutex); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | static int | ||
435 | event_requires_mode_exclusion(struct perf_event_attr *attr) | ||
436 | { | ||
437 | return attr->exclude_idle || attr->exclude_user || | ||
438 | attr->exclude_kernel || attr->exclude_hv; | ||
439 | } | ||
440 | |||
441 | static int | ||
442 | __hw_perf_event_init(struct perf_event *event) | ||
443 | { | ||
444 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
445 | struct hw_perf_event *hwc = &event->hw; | ||
446 | int mapping, err; | ||
447 | |||
448 | mapping = armpmu->map_event(event); | ||
449 | |||
450 | if (mapping < 0) { | ||
451 | pr_debug("event %x:%llx not supported\n", event->attr.type, | ||
452 | event->attr.config); | ||
453 | return mapping; | ||
454 | } | ||
455 | |||
456 | /* | ||
457 | * We don't assign an index until we actually place the event onto | ||
458 | * hardware. Use -1 to signify that we haven't decided where to put it | ||
459 | * yet. For SMP systems, each core has it's own PMU so we can't do any | ||
460 | * clever allocation or constraints checking at this point. | ||
461 | */ | ||
462 | hwc->idx = -1; | ||
463 | hwc->config_base = 0; | ||
464 | hwc->config = 0; | ||
465 | hwc->event_base = 0; | ||
466 | |||
467 | /* | ||
468 | * Check whether we need to exclude the counter from certain modes. | ||
469 | */ | ||
470 | if ((!armpmu->set_event_filter || | ||
471 | armpmu->set_event_filter(hwc, &event->attr)) && | ||
472 | event_requires_mode_exclusion(&event->attr)) { | ||
473 | pr_debug("ARM performance counters do not support mode exclusion\n"); | ||
474 | return -EPERM; | ||
475 | } | ||
476 | |||
477 | /* | ||
478 | * Store the event encoding into the config_base field. | ||
479 | */ | ||
480 | hwc->config_base |= (unsigned long)mapping; | ||
481 | |||
482 | if (!hwc->sample_period) { | ||
483 | /* | ||
484 | * For non-sampling runs, limit the sample_period to half | ||
485 | * of the counter width. That way, the new counter value | ||
486 | * is far less likely to overtake the previous one unless | ||
487 | * you have some serious IRQ latency issues. | ||
488 | */ | ||
489 | hwc->sample_period = armpmu->max_period >> 1; | ||
490 | hwc->last_period = hwc->sample_period; | ||
491 | local64_set(&hwc->period_left, hwc->sample_period); | ||
492 | } | ||
493 | |||
494 | err = 0; | ||
495 | if (event->group_leader != event) { | ||
496 | err = validate_group(event); | ||
497 | if (err) | ||
498 | return -EINVAL; | ||
499 | } | ||
500 | |||
501 | return err; | ||
502 | } | ||
503 | |||
504 | static int armpmu_event_init(struct perf_event *event) | ||
505 | { | ||
506 | struct arm_pmu *armpmu = to_arm_pmu(event->pmu); | ||
507 | int err = 0; | ||
508 | atomic_t *active_events = &armpmu->active_events; | ||
509 | |||
510 | if (armpmu->map_event(event) == -ENOENT) | ||
511 | return -ENOENT; | ||
512 | |||
513 | event->destroy = hw_perf_event_destroy; | ||
514 | |||
515 | if (!atomic_inc_not_zero(active_events)) { | ||
516 | mutex_lock(&armpmu->reserve_mutex); | ||
517 | if (atomic_read(active_events) == 0) | ||
518 | err = armpmu_reserve_hardware(armpmu); | ||
519 | |||
520 | if (!err) | ||
521 | atomic_inc(active_events); | ||
522 | mutex_unlock(&armpmu->reserve_mutex); | ||
523 | } | ||
524 | |||
525 | if (err) | ||
526 | return err; | ||
527 | |||
528 | err = __hw_perf_event_init(event); | ||
529 | if (err) | ||
530 | hw_perf_event_destroy(event); | ||
531 | |||
532 | return err; | ||
533 | } | ||
534 | |||
535 | static void armpmu_enable(struct pmu *pmu) | ||
536 | { | ||
537 | struct arm_pmu *armpmu = to_arm_pmu(pmu); | ||
538 | struct pmu_hw_events *hw_events = armpmu->get_hw_events(); | ||
539 | int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events); | ||
540 | |||
541 | if (enabled) | ||
542 | armpmu->start(); | ||
543 | } | ||
544 | |||
545 | static void armpmu_disable(struct pmu *pmu) | ||
546 | { | ||
547 | struct arm_pmu *armpmu = to_arm_pmu(pmu); | ||
548 | armpmu->stop(); | ||
549 | } | ||
550 | |||
551 | static void __init armpmu_init(struct arm_pmu *armpmu) | ||
552 | { | ||
553 | atomic_set(&armpmu->active_events, 0); | ||
554 | mutex_init(&armpmu->reserve_mutex); | ||
555 | |||
556 | armpmu->pmu = (struct pmu) { | ||
557 | .pmu_enable = armpmu_enable, | ||
558 | .pmu_disable = armpmu_disable, | ||
559 | .event_init = armpmu_event_init, | ||
560 | .add = armpmu_add, | ||
561 | .del = armpmu_del, | ||
562 | .start = armpmu_start, | ||
563 | .stop = armpmu_stop, | ||
564 | .read = armpmu_read, | ||
565 | }; | ||
566 | } | ||
567 | |||
568 | int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type) | ||
569 | { | ||
570 | armpmu_init(armpmu); | ||
571 | return perf_pmu_register(&armpmu->pmu, name, type); | ||
572 | } | ||
573 | |||
574 | /* | ||
575 | * ARMv8 PMUv3 Performance Events handling code. | ||
576 | * Common event types. | ||
577 | */ | ||
578 | enum armv8_pmuv3_perf_types { | ||
579 | /* Required events. */ | ||
580 | ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR = 0x00, | ||
581 | ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL = 0x03, | ||
582 | ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS = 0x04, | ||
583 | ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED = 0x10, | ||
584 | ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES = 0x11, | ||
585 | ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED = 0x12, | ||
586 | |||
587 | /* At least one of the following is required. */ | ||
588 | ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED = 0x08, | ||
589 | ARMV8_PMUV3_PERFCTR_OP_SPEC = 0x1B, | ||
590 | |||
591 | /* Common architectural events. */ | ||
592 | ARMV8_PMUV3_PERFCTR_MEM_READ = 0x06, | ||
593 | ARMV8_PMUV3_PERFCTR_MEM_WRITE = 0x07, | ||
594 | ARMV8_PMUV3_PERFCTR_EXC_TAKEN = 0x09, | ||
595 | ARMV8_PMUV3_PERFCTR_EXC_EXECUTED = 0x0A, | ||
596 | ARMV8_PMUV3_PERFCTR_CID_WRITE = 0x0B, | ||
597 | ARMV8_PMUV3_PERFCTR_PC_WRITE = 0x0C, | ||
598 | ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH = 0x0D, | ||
599 | ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN = 0x0E, | ||
600 | ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS = 0x0F, | ||
601 | ARMV8_PMUV3_PERFCTR_TTBR_WRITE = 0x1C, | ||
602 | |||
603 | /* Common microarchitectural events. */ | ||
604 | ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL = 0x01, | ||
605 | ARMV8_PMUV3_PERFCTR_ITLB_REFILL = 0x02, | ||
606 | ARMV8_PMUV3_PERFCTR_DTLB_REFILL = 0x05, | ||
607 | ARMV8_PMUV3_PERFCTR_MEM_ACCESS = 0x13, | ||
608 | ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS = 0x14, | ||
609 | ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB = 0x15, | ||
610 | ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS = 0x16, | ||
611 | ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL = 0x17, | ||
612 | ARMV8_PMUV3_PERFCTR_L2_CACHE_WB = 0x18, | ||
613 | ARMV8_PMUV3_PERFCTR_BUS_ACCESS = 0x19, | ||
614 | ARMV8_PMUV3_PERFCTR_MEM_ERROR = 0x1A, | ||
615 | ARMV8_PMUV3_PERFCTR_BUS_CYCLES = 0x1D, | ||
616 | |||
617 | /* | ||
618 | * This isn't an architected event. | ||
619 | * We detect this event number and use the cycle counter instead. | ||
620 | */ | ||
621 | ARMV8_PMUV3_PERFCTR_CPU_CYCLES = 0xFF, | ||
622 | }; | ||
623 | |||
624 | /* PMUv3 HW events mapping. */ | ||
625 | static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { | ||
626 | [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, | ||
627 | [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, | ||
628 | [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, | ||
629 | [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, | ||
630 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = HW_OP_UNSUPPORTED, | ||
631 | [PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, | ||
632 | [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, | ||
633 | [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, | ||
634 | [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, | ||
635 | }; | ||
636 | |||
637 | static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] | ||
638 | [PERF_COUNT_HW_CACHE_OP_MAX] | ||
639 | [PERF_COUNT_HW_CACHE_RESULT_MAX] = { | ||
640 | [C(L1D)] = { | ||
641 | [C(OP_READ)] = { | ||
642 | [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, | ||
643 | [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, | ||
644 | }, | ||
645 | [C(OP_WRITE)] = { | ||
646 | [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, | ||
647 | [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, | ||
648 | }, | ||
649 | [C(OP_PREFETCH)] = { | ||
650 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
651 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
652 | }, | ||
653 | }, | ||
654 | [C(L1I)] = { | ||
655 | [C(OP_READ)] = { | ||
656 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
657 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
658 | }, | ||
659 | [C(OP_WRITE)] = { | ||
660 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
661 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
662 | }, | ||
663 | [C(OP_PREFETCH)] = { | ||
664 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
665 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
666 | }, | ||
667 | }, | ||
668 | [C(LL)] = { | ||
669 | [C(OP_READ)] = { | ||
670 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
671 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
672 | }, | ||
673 | [C(OP_WRITE)] = { | ||
674 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
675 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
676 | }, | ||
677 | [C(OP_PREFETCH)] = { | ||
678 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
679 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
680 | }, | ||
681 | }, | ||
682 | [C(DTLB)] = { | ||
683 | [C(OP_READ)] = { | ||
684 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
685 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
686 | }, | ||
687 | [C(OP_WRITE)] = { | ||
688 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
689 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
690 | }, | ||
691 | [C(OP_PREFETCH)] = { | ||
692 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
693 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
694 | }, | ||
695 | }, | ||
696 | [C(ITLB)] = { | ||
697 | [C(OP_READ)] = { | ||
698 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
699 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
700 | }, | ||
701 | [C(OP_WRITE)] = { | ||
702 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
703 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
704 | }, | ||
705 | [C(OP_PREFETCH)] = { | ||
706 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
707 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
708 | }, | ||
709 | }, | ||
710 | [C(BPU)] = { | ||
711 | [C(OP_READ)] = { | ||
712 | [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, | ||
713 | [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, | ||
714 | }, | ||
715 | [C(OP_WRITE)] = { | ||
716 | [C(RESULT_ACCESS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED, | ||
717 | [C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED, | ||
718 | }, | ||
719 | [C(OP_PREFETCH)] = { | ||
720 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
721 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
722 | }, | ||
723 | }, | ||
724 | [C(NODE)] = { | ||
725 | [C(OP_READ)] = { | ||
726 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
727 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
728 | }, | ||
729 | [C(OP_WRITE)] = { | ||
730 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
731 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
732 | }, | ||
733 | [C(OP_PREFETCH)] = { | ||
734 | [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, | ||
735 | [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, | ||
736 | }, | ||
737 | }, | ||
738 | }; | ||
739 | |||
740 | /* | ||
741 | * Perf Events' indices | ||
742 | */ | ||
743 | #define ARMV8_IDX_CYCLE_COUNTER 0 | ||
744 | #define ARMV8_IDX_COUNTER0 1 | ||
745 | #define ARMV8_IDX_COUNTER_LAST (ARMV8_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1) | ||
746 | |||
747 | #define ARMV8_MAX_COUNTERS 32 | ||
748 | #define ARMV8_COUNTER_MASK (ARMV8_MAX_COUNTERS - 1) | ||
749 | |||
750 | /* | ||
751 | * ARMv8 low level PMU access | ||
752 | */ | ||
753 | |||
754 | /* | ||
755 | * Perf Event to low level counters mapping | ||
756 | */ | ||
757 | #define ARMV8_IDX_TO_COUNTER(x) \ | ||
758 | (((x) - ARMV8_IDX_COUNTER0) & ARMV8_COUNTER_MASK) | ||
759 | |||
760 | /* | ||
761 | * Per-CPU PMCR: config reg | ||
762 | */ | ||
763 | #define ARMV8_PMCR_E (1 << 0) /* Enable all counters */ | ||
764 | #define ARMV8_PMCR_P (1 << 1) /* Reset all counters */ | ||
765 | #define ARMV8_PMCR_C (1 << 2) /* Cycle counter reset */ | ||
766 | #define ARMV8_PMCR_D (1 << 3) /* CCNT counts every 64th cpu cycle */ | ||
767 | #define ARMV8_PMCR_X (1 << 4) /* Export to ETM */ | ||
768 | #define ARMV8_PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ | ||
769 | #define ARMV8_PMCR_N_SHIFT 11 /* Number of counters supported */ | ||
770 | #define ARMV8_PMCR_N_MASK 0x1f | ||
771 | #define ARMV8_PMCR_MASK 0x3f /* Mask for writable bits */ | ||
772 | |||
773 | /* | ||
774 | * PMOVSR: counters overflow flag status reg | ||
775 | */ | ||
776 | #define ARMV8_OVSR_MASK 0xffffffff /* Mask for writable bits */ | ||
777 | #define ARMV8_OVERFLOWED_MASK ARMV8_OVSR_MASK | ||
778 | |||
779 | /* | ||
780 | * PMXEVTYPER: Event selection reg | ||
781 | */ | ||
782 | #define ARMV8_EVTYPE_MASK 0xc00000ff /* Mask for writable bits */ | ||
783 | #define ARMV8_EVTYPE_EVENT 0xff /* Mask for EVENT bits */ | ||
784 | |||
785 | /* | ||
786 | * Event filters for PMUv3 | ||
787 | */ | ||
788 | #define ARMV8_EXCLUDE_EL1 (1 << 31) | ||
789 | #define ARMV8_EXCLUDE_EL0 (1 << 30) | ||
790 | #define ARMV8_INCLUDE_EL2 (1 << 27) | ||
791 | |||
792 | static inline u32 armv8pmu_pmcr_read(void) | ||
793 | { | ||
794 | u32 val; | ||
795 | asm volatile("mrs %0, pmcr_el0" : "=r" (val)); | ||
796 | return val; | ||
797 | } | ||
798 | |||
799 | static inline void armv8pmu_pmcr_write(u32 val) | ||
800 | { | ||
801 | val &= ARMV8_PMCR_MASK; | ||
802 | isb(); | ||
803 | asm volatile("msr pmcr_el0, %0" :: "r" (val)); | ||
804 | } | ||
805 | |||
806 | static inline int armv8pmu_has_overflowed(u32 pmovsr) | ||
807 | { | ||
808 | return pmovsr & ARMV8_OVERFLOWED_MASK; | ||
809 | } | ||
810 | |||
811 | static inline int armv8pmu_counter_valid(int idx) | ||
812 | { | ||
813 | return idx >= ARMV8_IDX_CYCLE_COUNTER && idx <= ARMV8_IDX_COUNTER_LAST; | ||
814 | } | ||
815 | |||
816 | static inline int armv8pmu_counter_has_overflowed(u32 pmnc, int idx) | ||
817 | { | ||
818 | int ret = 0; | ||
819 | u32 counter; | ||
820 | |||
821 | if (!armv8pmu_counter_valid(idx)) { | ||
822 | pr_err("CPU%u checking wrong counter %d overflow status\n", | ||
823 | smp_processor_id(), idx); | ||
824 | } else { | ||
825 | counter = ARMV8_IDX_TO_COUNTER(idx); | ||
826 | ret = pmnc & BIT(counter); | ||
827 | } | ||
828 | |||
829 | return ret; | ||
830 | } | ||
831 | |||
832 | static inline int armv8pmu_select_counter(int idx) | ||
833 | { | ||
834 | u32 counter; | ||
835 | |||
836 | if (!armv8pmu_counter_valid(idx)) { | ||
837 | pr_err("CPU%u selecting wrong PMNC counter %d\n", | ||
838 | smp_processor_id(), idx); | ||
839 | return -EINVAL; | ||
840 | } | ||
841 | |||
842 | counter = ARMV8_IDX_TO_COUNTER(idx); | ||
843 | asm volatile("msr pmselr_el0, %0" :: "r" (counter)); | ||
844 | isb(); | ||
845 | |||
846 | return idx; | ||
847 | } | ||
848 | |||
849 | static inline u32 armv8pmu_read_counter(int idx) | ||
850 | { | ||
851 | u32 value = 0; | ||
852 | |||
853 | if (!armv8pmu_counter_valid(idx)) | ||
854 | pr_err("CPU%u reading wrong counter %d\n", | ||
855 | smp_processor_id(), idx); | ||
856 | else if (idx == ARMV8_IDX_CYCLE_COUNTER) | ||
857 | asm volatile("mrs %0, pmccntr_el0" : "=r" (value)); | ||
858 | else if (armv8pmu_select_counter(idx) == idx) | ||
859 | asm volatile("mrs %0, pmxevcntr_el0" : "=r" (value)); | ||
860 | |||
861 | return value; | ||
862 | } | ||
863 | |||
864 | static inline void armv8pmu_write_counter(int idx, u32 value) | ||
865 | { | ||
866 | if (!armv8pmu_counter_valid(idx)) | ||
867 | pr_err("CPU%u writing wrong counter %d\n", | ||
868 | smp_processor_id(), idx); | ||
869 | else if (idx == ARMV8_IDX_CYCLE_COUNTER) | ||
870 | asm volatile("msr pmccntr_el0, %0" :: "r" (value)); | ||
871 | else if (armv8pmu_select_counter(idx) == idx) | ||
872 | asm volatile("msr pmxevcntr_el0, %0" :: "r" (value)); | ||
873 | } | ||
874 | |||
875 | static inline void armv8pmu_write_evtype(int idx, u32 val) | ||
876 | { | ||
877 | if (armv8pmu_select_counter(idx) == idx) { | ||
878 | val &= ARMV8_EVTYPE_MASK; | ||
879 | asm volatile("msr pmxevtyper_el0, %0" :: "r" (val)); | ||
880 | } | ||
881 | } | ||
882 | |||
883 | static inline int armv8pmu_enable_counter(int idx) | ||
884 | { | ||
885 | u32 counter; | ||
886 | |||
887 | if (!armv8pmu_counter_valid(idx)) { | ||
888 | pr_err("CPU%u enabling wrong PMNC counter %d\n", | ||
889 | smp_processor_id(), idx); | ||
890 | return -EINVAL; | ||
891 | } | ||
892 | |||
893 | counter = ARMV8_IDX_TO_COUNTER(idx); | ||
894 | asm volatile("msr pmcntenset_el0, %0" :: "r" (BIT(counter))); | ||
895 | return idx; | ||
896 | } | ||
897 | |||
898 | static inline int armv8pmu_disable_counter(int idx) | ||
899 | { | ||
900 | u32 counter; | ||
901 | |||
902 | if (!armv8pmu_counter_valid(idx)) { | ||
903 | pr_err("CPU%u disabling wrong PMNC counter %d\n", | ||
904 | smp_processor_id(), idx); | ||
905 | return -EINVAL; | ||
906 | } | ||
907 | |||
908 | counter = ARMV8_IDX_TO_COUNTER(idx); | ||
909 | asm volatile("msr pmcntenclr_el0, %0" :: "r" (BIT(counter))); | ||
910 | return idx; | ||
911 | } | ||
912 | |||
913 | static inline int armv8pmu_enable_intens(int idx) | ||
914 | { | ||
915 | u32 counter; | ||
916 | |||
917 | if (!armv8pmu_counter_valid(idx)) { | ||
918 | pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n", | ||
919 | smp_processor_id(), idx); | ||
920 | return -EINVAL; | ||
921 | } | ||
922 | |||
923 | counter = ARMV8_IDX_TO_COUNTER(idx); | ||
924 | asm volatile("msr pmintenset_el1, %0" :: "r" (BIT(counter))); | ||
925 | return idx; | ||
926 | } | ||
927 | |||
928 | static inline int armv8pmu_disable_intens(int idx) | ||
929 | { | ||
930 | u32 counter; | ||
931 | |||
932 | if (!armv8pmu_counter_valid(idx)) { | ||
933 | pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n", | ||
934 | smp_processor_id(), idx); | ||
935 | return -EINVAL; | ||
936 | } | ||
937 | |||
938 | counter = ARMV8_IDX_TO_COUNTER(idx); | ||
939 | asm volatile("msr pmintenclr_el1, %0" :: "r" (BIT(counter))); | ||
940 | isb(); | ||
941 | /* Clear the overflow flag in case an interrupt is pending. */ | ||
942 | asm volatile("msr pmovsclr_el0, %0" :: "r" (BIT(counter))); | ||
943 | isb(); | ||
944 | return idx; | ||
945 | } | ||
946 | |||
947 | static inline u32 armv8pmu_getreset_flags(void) | ||
948 | { | ||
949 | u32 value; | ||
950 | |||
951 | /* Read */ | ||
952 | asm volatile("mrs %0, pmovsclr_el0" : "=r" (value)); | ||
953 | |||
954 | /* Write to clear flags */ | ||
955 | value &= ARMV8_OVSR_MASK; | ||
956 | asm volatile("msr pmovsclr_el0, %0" :: "r" (value)); | ||
957 | |||
958 | return value; | ||
959 | } | ||
960 | |||
961 | static void armv8pmu_enable_event(struct hw_perf_event *hwc, int idx) | ||
962 | { | ||
963 | unsigned long flags; | ||
964 | struct pmu_hw_events *events = cpu_pmu->get_hw_events(); | ||
965 | |||
966 | /* | ||
967 | * Enable counter and interrupt, and set the counter to count | ||
968 | * the event that we're interested in. | ||
969 | */ | ||
970 | raw_spin_lock_irqsave(&events->pmu_lock, flags); | ||
971 | |||
972 | /* | ||
973 | * Disable counter | ||
974 | */ | ||
975 | armv8pmu_disable_counter(idx); | ||
976 | |||
977 | /* | ||
978 | * Set event (if destined for PMNx counters). | ||
979 | */ | ||
980 | armv8pmu_write_evtype(idx, hwc->config_base); | ||
981 | |||
982 | /* | ||
983 | * Enable interrupt for this counter | ||
984 | */ | ||
985 | armv8pmu_enable_intens(idx); | ||
986 | |||
987 | /* | ||
988 | * Enable counter | ||
989 | */ | ||
990 | armv8pmu_enable_counter(idx); | ||
991 | |||
992 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); | ||
993 | } | ||
994 | |||
995 | static void armv8pmu_disable_event(struct hw_perf_event *hwc, int idx) | ||
996 | { | ||
997 | unsigned long flags; | ||
998 | struct pmu_hw_events *events = cpu_pmu->get_hw_events(); | ||
999 | |||
1000 | /* | ||
1001 | * Disable counter and interrupt | ||
1002 | */ | ||
1003 | raw_spin_lock_irqsave(&events->pmu_lock, flags); | ||
1004 | |||
1005 | /* | ||
1006 | * Disable counter | ||
1007 | */ | ||
1008 | armv8pmu_disable_counter(idx); | ||
1009 | |||
1010 | /* | ||
1011 | * Disable interrupt for this counter | ||
1012 | */ | ||
1013 | armv8pmu_disable_intens(idx); | ||
1014 | |||
1015 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); | ||
1016 | } | ||
1017 | |||
1018 | static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) | ||
1019 | { | ||
1020 | u32 pmovsr; | ||
1021 | struct perf_sample_data data; | ||
1022 | struct pmu_hw_events *cpuc; | ||
1023 | struct pt_regs *regs; | ||
1024 | int idx; | ||
1025 | |||
1026 | /* | ||
1027 | * Get and reset the IRQ flags | ||
1028 | */ | ||
1029 | pmovsr = armv8pmu_getreset_flags(); | ||
1030 | |||
1031 | /* | ||
1032 | * Did an overflow occur? | ||
1033 | */ | ||
1034 | if (!armv8pmu_has_overflowed(pmovsr)) | ||
1035 | return IRQ_NONE; | ||
1036 | |||
1037 | /* | ||
1038 | * Handle the counter(s) overflow(s) | ||
1039 | */ | ||
1040 | regs = get_irq_regs(); | ||
1041 | |||
1042 | cpuc = &__get_cpu_var(cpu_hw_events); | ||
1043 | for (idx = 0; idx < cpu_pmu->num_events; ++idx) { | ||
1044 | struct perf_event *event = cpuc->events[idx]; | ||
1045 | struct hw_perf_event *hwc; | ||
1046 | |||
1047 | /* Ignore if we don't have an event. */ | ||
1048 | if (!event) | ||
1049 | continue; | ||
1050 | |||
1051 | /* | ||
1052 | * We have a single interrupt for all counters. Check that | ||
1053 | * each counter has overflowed before we process it. | ||
1054 | */ | ||
1055 | if (!armv8pmu_counter_has_overflowed(pmovsr, idx)) | ||
1056 | continue; | ||
1057 | |||
1058 | hwc = &event->hw; | ||
1059 | armpmu_event_update(event, hwc, idx); | ||
1060 | perf_sample_data_init(&data, 0, hwc->last_period); | ||
1061 | if (!armpmu_event_set_period(event, hwc, idx)) | ||
1062 | continue; | ||
1063 | |||
1064 | if (perf_event_overflow(event, &data, regs)) | ||
1065 | cpu_pmu->disable(hwc, idx); | ||
1066 | } | ||
1067 | |||
1068 | /* | ||
1069 | * Handle the pending perf events. | ||
1070 | * | ||
1071 | * Note: this call *must* be run with interrupts disabled. For | ||
1072 | * platforms that can have the PMU interrupts raised as an NMI, this | ||
1073 | * will not work. | ||
1074 | */ | ||
1075 | irq_work_run(); | ||
1076 | |||
1077 | return IRQ_HANDLED; | ||
1078 | } | ||
1079 | |||
1080 | static void armv8pmu_start(void) | ||
1081 | { | ||
1082 | unsigned long flags; | ||
1083 | struct pmu_hw_events *events = cpu_pmu->get_hw_events(); | ||
1084 | |||
1085 | raw_spin_lock_irqsave(&events->pmu_lock, flags); | ||
1086 | /* Enable all counters */ | ||
1087 | armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E); | ||
1088 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); | ||
1089 | } | ||
1090 | |||
1091 | static void armv8pmu_stop(void) | ||
1092 | { | ||
1093 | unsigned long flags; | ||
1094 | struct pmu_hw_events *events = cpu_pmu->get_hw_events(); | ||
1095 | |||
1096 | raw_spin_lock_irqsave(&events->pmu_lock, flags); | ||
1097 | /* Disable all counters */ | ||
1098 | armv8pmu_pmcr_write(armv8pmu_pmcr_read() & ~ARMV8_PMCR_E); | ||
1099 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); | ||
1100 | } | ||
1101 | |||
1102 | static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, | ||
1103 | struct hw_perf_event *event) | ||
1104 | { | ||
1105 | int idx; | ||
1106 | unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT; | ||
1107 | |||
1108 | /* Always place a cycle counter into the cycle counter. */ | ||
1109 | if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) { | ||
1110 | if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) | ||
1111 | return -EAGAIN; | ||
1112 | |||
1113 | return ARMV8_IDX_CYCLE_COUNTER; | ||
1114 | } | ||
1115 | |||
1116 | /* | ||
1117 | * For anything other than a cycle counter, try and use | ||
1118 | * the events counters | ||
1119 | */ | ||
1120 | for (idx = ARMV8_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) { | ||
1121 | if (!test_and_set_bit(idx, cpuc->used_mask)) | ||
1122 | return idx; | ||
1123 | } | ||
1124 | |||
1125 | /* The counters are all in use. */ | ||
1126 | return -EAGAIN; | ||
1127 | } | ||
1128 | |||
1129 | /* | ||
1130 | * Add an event filter to a given event. This will only work for PMUv2 PMUs. | ||
1131 | */ | ||
1132 | static int armv8pmu_set_event_filter(struct hw_perf_event *event, | ||
1133 | struct perf_event_attr *attr) | ||
1134 | { | ||
1135 | unsigned long config_base = 0; | ||
1136 | |||
1137 | if (attr->exclude_idle) | ||
1138 | return -EPERM; | ||
1139 | if (attr->exclude_user) | ||
1140 | config_base |= ARMV8_EXCLUDE_EL0; | ||
1141 | if (attr->exclude_kernel) | ||
1142 | config_base |= ARMV8_EXCLUDE_EL1; | ||
1143 | if (!attr->exclude_hv) | ||
1144 | config_base |= ARMV8_INCLUDE_EL2; | ||
1145 | |||
1146 | /* | ||
1147 | * Install the filter into config_base as this is used to | ||
1148 | * construct the event type. | ||
1149 | */ | ||
1150 | event->config_base = config_base; | ||
1151 | |||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | static void armv8pmu_reset(void *info) | ||
1156 | { | ||
1157 | u32 idx, nb_cnt = cpu_pmu->num_events; | ||
1158 | |||
1159 | /* The counter and interrupt enable registers are unknown at reset. */ | ||
1160 | for (idx = ARMV8_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) | ||
1161 | armv8pmu_disable_event(NULL, idx); | ||
1162 | |||
1163 | /* Initialize & Reset PMNC: C and P bits. */ | ||
1164 | armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C); | ||
1165 | |||
1166 | /* Disable access from userspace. */ | ||
1167 | asm volatile("msr pmuserenr_el0, %0" :: "r" (0)); | ||
1168 | } | ||
1169 | |||
1170 | static int armv8_pmuv3_map_event(struct perf_event *event) | ||
1171 | { | ||
1172 | return map_cpu_event(event, &armv8_pmuv3_perf_map, | ||
1173 | &armv8_pmuv3_perf_cache_map, 0xFF); | ||
1174 | } | ||
1175 | |||
1176 | static struct arm_pmu armv8pmu = { | ||
1177 | .handle_irq = armv8pmu_handle_irq, | ||
1178 | .enable = armv8pmu_enable_event, | ||
1179 | .disable = armv8pmu_disable_event, | ||
1180 | .read_counter = armv8pmu_read_counter, | ||
1181 | .write_counter = armv8pmu_write_counter, | ||
1182 | .get_event_idx = armv8pmu_get_event_idx, | ||
1183 | .start = armv8pmu_start, | ||
1184 | .stop = armv8pmu_stop, | ||
1185 | .reset = armv8pmu_reset, | ||
1186 | .max_period = (1LLU << 32) - 1, | ||
1187 | }; | ||
1188 | |||
1189 | static u32 __init armv8pmu_read_num_pmnc_events(void) | ||
1190 | { | ||
1191 | u32 nb_cnt; | ||
1192 | |||
1193 | /* Read the nb of CNTx counters supported from PMNC */ | ||
1194 | nb_cnt = (armv8pmu_pmcr_read() >> ARMV8_PMCR_N_SHIFT) & ARMV8_PMCR_N_MASK; | ||
1195 | |||
1196 | /* Add the CPU cycles counter and return */ | ||
1197 | return nb_cnt + 1; | ||
1198 | } | ||
1199 | |||
1200 | static struct arm_pmu *__init armv8_pmuv3_pmu_init(void) | ||
1201 | { | ||
1202 | armv8pmu.name = "arm/armv8-pmuv3"; | ||
1203 | armv8pmu.map_event = armv8_pmuv3_map_event; | ||
1204 | armv8pmu.num_events = armv8pmu_read_num_pmnc_events(); | ||
1205 | armv8pmu.set_event_filter = armv8pmu_set_event_filter; | ||
1206 | return &armv8pmu; | ||
1207 | } | ||
1208 | |||
1209 | /* | ||
1210 | * Ensure the PMU has sane values out of reset. | ||
1211 | * This requires SMP to be available, so exists as a separate initcall. | ||
1212 | */ | ||
1213 | static int __init | ||
1214 | cpu_pmu_reset(void) | ||
1215 | { | ||
1216 | if (cpu_pmu && cpu_pmu->reset) | ||
1217 | return on_each_cpu(cpu_pmu->reset, NULL, 1); | ||
1218 | return 0; | ||
1219 | } | ||
1220 | arch_initcall(cpu_pmu_reset); | ||
1221 | |||
1222 | /* | ||
1223 | * PMU platform driver and devicetree bindings. | ||
1224 | */ | ||
1225 | static struct of_device_id armpmu_of_device_ids[] = { | ||
1226 | {.compatible = "arm,armv8-pmuv3"}, | ||
1227 | {}, | ||
1228 | }; | ||
1229 | |||
1230 | static int __devinit armpmu_device_probe(struct platform_device *pdev) | ||
1231 | { | ||
1232 | if (!cpu_pmu) | ||
1233 | return -ENODEV; | ||
1234 | |||
1235 | cpu_pmu->plat_device = pdev; | ||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | static struct platform_driver armpmu_driver = { | ||
1240 | .driver = { | ||
1241 | .name = "arm-pmu", | ||
1242 | .of_match_table = armpmu_of_device_ids, | ||
1243 | }, | ||
1244 | .probe = armpmu_device_probe, | ||
1245 | }; | ||
1246 | |||
1247 | static int __init register_pmu_driver(void) | ||
1248 | { | ||
1249 | return platform_driver_register(&armpmu_driver); | ||
1250 | } | ||
1251 | device_initcall(register_pmu_driver); | ||
1252 | |||
1253 | static struct pmu_hw_events *armpmu_get_cpu_events(void) | ||
1254 | { | ||
1255 | return &__get_cpu_var(cpu_hw_events); | ||
1256 | } | ||
1257 | |||
1258 | static void __init cpu_pmu_init(struct arm_pmu *armpmu) | ||
1259 | { | ||
1260 | int cpu; | ||
1261 | for_each_possible_cpu(cpu) { | ||
1262 | struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu); | ||
1263 | events->events = per_cpu(hw_events, cpu); | ||
1264 | events->used_mask = per_cpu(used_mask, cpu); | ||
1265 | raw_spin_lock_init(&events->pmu_lock); | ||
1266 | } | ||
1267 | armpmu->get_hw_events = armpmu_get_cpu_events; | ||
1268 | } | ||
1269 | |||
1270 | static int __init init_hw_perf_events(void) | ||
1271 | { | ||
1272 | u64 dfr = read_cpuid(ID_AA64DFR0_EL1); | ||
1273 | |||
1274 | switch ((dfr >> 8) & 0xf) { | ||
1275 | case 0x1: /* PMUv3 */ | ||
1276 | cpu_pmu = armv8_pmuv3_pmu_init(); | ||
1277 | break; | ||
1278 | } | ||
1279 | |||
1280 | if (cpu_pmu) { | ||
1281 | pr_info("enabled with %s PMU driver, %d counters available\n", | ||
1282 | cpu_pmu->name, cpu_pmu->num_events); | ||
1283 | cpu_pmu_init(cpu_pmu); | ||
1284 | armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); | ||
1285 | } else { | ||
1286 | pr_info("no hardware support available\n"); | ||
1287 | } | ||
1288 | |||
1289 | return 0; | ||
1290 | } | ||
1291 | early_initcall(init_hw_perf_events); | ||
1292 | |||
1293 | /* | ||
1294 | * Callchain handling code. | ||
1295 | */ | ||
1296 | struct frame_tail { | ||
1297 | struct frame_tail __user *fp; | ||
1298 | unsigned long lr; | ||
1299 | } __attribute__((packed)); | ||
1300 | |||
1301 | /* | ||
1302 | * Get the return address for a single stackframe and return a pointer to the | ||
1303 | * next frame tail. | ||
1304 | */ | ||
1305 | static struct frame_tail __user * | ||
1306 | user_backtrace(struct frame_tail __user *tail, | ||
1307 | struct perf_callchain_entry *entry) | ||
1308 | { | ||
1309 | struct frame_tail buftail; | ||
1310 | unsigned long err; | ||
1311 | |||
1312 | /* Also check accessibility of one struct frame_tail beyond */ | ||
1313 | if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) | ||
1314 | return NULL; | ||
1315 | |||
1316 | pagefault_disable(); | ||
1317 | err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); | ||
1318 | pagefault_enable(); | ||
1319 | |||
1320 | if (err) | ||
1321 | return NULL; | ||
1322 | |||
1323 | perf_callchain_store(entry, buftail.lr); | ||
1324 | |||
1325 | /* | ||
1326 | * Frame pointers should strictly progress back up the stack | ||
1327 | * (towards higher addresses). | ||
1328 | */ | ||
1329 | if (tail >= buftail.fp) | ||
1330 | return NULL; | ||
1331 | |||
1332 | return buftail.fp; | ||
1333 | } | ||
1334 | |||
1335 | void perf_callchain_user(struct perf_callchain_entry *entry, | ||
1336 | struct pt_regs *regs) | ||
1337 | { | ||
1338 | struct frame_tail __user *tail; | ||
1339 | |||
1340 | tail = (struct frame_tail __user *)regs->regs[29]; | ||
1341 | |||
1342 | while (entry->nr < PERF_MAX_STACK_DEPTH && | ||
1343 | tail && !((unsigned long)tail & 0xf)) | ||
1344 | tail = user_backtrace(tail, entry); | ||
1345 | } | ||
1346 | |||
1347 | /* | ||
1348 | * Gets called by walk_stackframe() for every stackframe. This will be called | ||
1349 | * whist unwinding the stackframe and is like a subroutine return so we use | ||
1350 | * the PC. | ||
1351 | */ | ||
1352 | static int callchain_trace(struct stackframe *frame, void *data) | ||
1353 | { | ||
1354 | struct perf_callchain_entry *entry = data; | ||
1355 | perf_callchain_store(entry, frame->pc); | ||
1356 | return 0; | ||
1357 | } | ||
1358 | |||
1359 | void perf_callchain_kernel(struct perf_callchain_entry *entry, | ||
1360 | struct pt_regs *regs) | ||
1361 | { | ||
1362 | struct stackframe frame; | ||
1363 | |||
1364 | frame.fp = regs->regs[29]; | ||
1365 | frame.sp = regs->sp; | ||
1366 | frame.pc = regs->pc; | ||
1367 | walk_stackframe(&frame, callchain_trace, entry); | ||
1368 | } | ||
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c new file mode 100644 index 000000000000..f22965ea1cfc --- /dev/null +++ b/arch/arm64/kernel/process.c | |||
@@ -0,0 +1,408 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/process.c | ||
3 | * | ||
4 | * Original Copyright (C) 1995 Linus Torvalds | ||
5 | * Copyright (C) 1996-2000 Russell King - Converted to ARM. | ||
6 | * Copyright (C) 2012 ARM Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <stdarg.h> | ||
22 | |||
23 | #include <linux/export.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/stddef.h> | ||
28 | #include <linux/unistd.h> | ||
29 | #include <linux/user.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/reboot.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/kallsyms.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/cpu.h> | ||
36 | #include <linux/elfcore.h> | ||
37 | #include <linux/pm.h> | ||
38 | #include <linux/tick.h> | ||
39 | #include <linux/utsname.h> | ||
40 | #include <linux/uaccess.h> | ||
41 | #include <linux/random.h> | ||
42 | #include <linux/hw_breakpoint.h> | ||
43 | #include <linux/personality.h> | ||
44 | #include <linux/notifier.h> | ||
45 | |||
46 | #include <asm/compat.h> | ||
47 | #include <asm/cacheflush.h> | ||
48 | #include <asm/processor.h> | ||
49 | #include <asm/stacktrace.h> | ||
50 | #include <asm/fpsimd.h> | ||
51 | |||
52 | static void setup_restart(void) | ||
53 | { | ||
54 | /* | ||
55 | * Tell the mm system that we are going to reboot - | ||
56 | * we may need it to insert some 1:1 mappings so that | ||
57 | * soft boot works. | ||
58 | */ | ||
59 | setup_mm_for_reboot(); | ||
60 | |||
61 | /* Clean and invalidate caches */ | ||
62 | flush_cache_all(); | ||
63 | |||
64 | /* Turn D-cache off */ | ||
65 | cpu_cache_off(); | ||
66 | |||
67 | /* Push out any further dirty data, and ensure cache is empty */ | ||
68 | flush_cache_all(); | ||
69 | } | ||
70 | |||
71 | void soft_restart(unsigned long addr) | ||
72 | { | ||
73 | setup_restart(); | ||
74 | cpu_reset(addr); | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * Function pointers to optional machine specific functions | ||
79 | */ | ||
80 | void (*pm_power_off)(void); | ||
81 | EXPORT_SYMBOL_GPL(pm_power_off); | ||
82 | |||
83 | void (*pm_restart)(const char *cmd); | ||
84 | EXPORT_SYMBOL_GPL(pm_restart); | ||
85 | |||
86 | |||
87 | /* | ||
88 | * This is our default idle handler. | ||
89 | */ | ||
90 | static void default_idle(void) | ||
91 | { | ||
92 | /* | ||
93 | * This should do all the clock switching and wait for interrupt | ||
94 | * tricks | ||
95 | */ | ||
96 | cpu_do_idle(); | ||
97 | local_irq_enable(); | ||
98 | } | ||
99 | |||
100 | void (*pm_idle)(void) = default_idle; | ||
101 | EXPORT_SYMBOL_GPL(pm_idle); | ||
102 | |||
103 | /* | ||
104 | * The idle thread, has rather strange semantics for calling pm_idle, | ||
105 | * but this is what x86 does and we need to do the same, so that | ||
106 | * things like cpuidle get called in the same way. The only difference | ||
107 | * is that we always respect 'hlt_counter' to prevent low power idle. | ||
108 | */ | ||
109 | void cpu_idle(void) | ||
110 | { | ||
111 | local_fiq_enable(); | ||
112 | |||
113 | /* endless idle loop with no priority at all */ | ||
114 | while (1) { | ||
115 | tick_nohz_idle_enter(); | ||
116 | rcu_idle_enter(); | ||
117 | while (!need_resched()) { | ||
118 | /* | ||
119 | * We need to disable interrupts here to ensure | ||
120 | * we don't miss a wakeup call. | ||
121 | */ | ||
122 | local_irq_disable(); | ||
123 | if (!need_resched()) { | ||
124 | stop_critical_timings(); | ||
125 | pm_idle(); | ||
126 | start_critical_timings(); | ||
127 | /* | ||
128 | * pm_idle functions should always return | ||
129 | * with IRQs enabled. | ||
130 | */ | ||
131 | WARN_ON(irqs_disabled()); | ||
132 | } else { | ||
133 | local_irq_enable(); | ||
134 | } | ||
135 | } | ||
136 | rcu_idle_exit(); | ||
137 | tick_nohz_idle_exit(); | ||
138 | schedule_preempt_disabled(); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | void machine_shutdown(void) | ||
143 | { | ||
144 | #ifdef CONFIG_SMP | ||
145 | smp_send_stop(); | ||
146 | #endif | ||
147 | } | ||
148 | |||
149 | void machine_halt(void) | ||
150 | { | ||
151 | machine_shutdown(); | ||
152 | while (1); | ||
153 | } | ||
154 | |||
155 | void machine_power_off(void) | ||
156 | { | ||
157 | machine_shutdown(); | ||
158 | if (pm_power_off) | ||
159 | pm_power_off(); | ||
160 | } | ||
161 | |||
162 | void machine_restart(char *cmd) | ||
163 | { | ||
164 | machine_shutdown(); | ||
165 | |||
166 | /* Disable interrupts first */ | ||
167 | local_irq_disable(); | ||
168 | local_fiq_disable(); | ||
169 | |||
170 | /* Now call the architecture specific reboot code. */ | ||
171 | if (pm_restart) | ||
172 | pm_restart(cmd); | ||
173 | |||
174 | /* | ||
175 | * Whoops - the architecture was unable to reboot. | ||
176 | */ | ||
177 | printk("Reboot failed -- System halted\n"); | ||
178 | while (1); | ||
179 | } | ||
180 | |||
181 | void __show_regs(struct pt_regs *regs) | ||
182 | { | ||
183 | int i; | ||
184 | |||
185 | printk("CPU: %d %s (%s %.*s)\n", | ||
186 | raw_smp_processor_id(), print_tainted(), | ||
187 | init_utsname()->release, | ||
188 | (int)strcspn(init_utsname()->version, " "), | ||
189 | init_utsname()->version); | ||
190 | print_symbol("PC is at %s\n", instruction_pointer(regs)); | ||
191 | print_symbol("LR is at %s\n", regs->regs[30]); | ||
192 | printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", | ||
193 | regs->pc, regs->regs[30], regs->pstate); | ||
194 | printk("sp : %016llx\n", regs->sp); | ||
195 | for (i = 29; i >= 0; i--) { | ||
196 | printk("x%-2d: %016llx ", i, regs->regs[i]); | ||
197 | if (i % 2 == 0) | ||
198 | printk("\n"); | ||
199 | } | ||
200 | printk("\n"); | ||
201 | } | ||
202 | |||
203 | void show_regs(struct pt_regs * regs) | ||
204 | { | ||
205 | printk("\n"); | ||
206 | printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); | ||
207 | __show_regs(regs); | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * Free current thread data structures etc.. | ||
212 | */ | ||
213 | void exit_thread(void) | ||
214 | { | ||
215 | } | ||
216 | |||
217 | void flush_thread(void) | ||
218 | { | ||
219 | fpsimd_flush_thread(); | ||
220 | flush_ptrace_hw_breakpoint(current); | ||
221 | } | ||
222 | |||
223 | void release_thread(struct task_struct *dead_task) | ||
224 | { | ||
225 | } | ||
226 | |||
227 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | ||
228 | { | ||
229 | fpsimd_save_state(¤t->thread.fpsimd_state); | ||
230 | *dst = *src; | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | asmlinkage void ret_from_fork(void) asm("ret_from_fork"); | ||
235 | |||
236 | int copy_thread(unsigned long clone_flags, unsigned long stack_start, | ||
237 | unsigned long stk_sz, struct task_struct *p, | ||
238 | struct pt_regs *regs) | ||
239 | { | ||
240 | struct pt_regs *childregs = task_pt_regs(p); | ||
241 | unsigned long tls = p->thread.tp_value; | ||
242 | |||
243 | *childregs = *regs; | ||
244 | childregs->regs[0] = 0; | ||
245 | |||
246 | if (is_compat_thread(task_thread_info(p))) | ||
247 | childregs->compat_sp = stack_start; | ||
248 | else { | ||
249 | /* | ||
250 | * Read the current TLS pointer from tpidr_el0 as it may be | ||
251 | * out-of-sync with the saved value. | ||
252 | */ | ||
253 | asm("mrs %0, tpidr_el0" : "=r" (tls)); | ||
254 | childregs->sp = stack_start; | ||
255 | } | ||
256 | |||
257 | memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); | ||
258 | p->thread.cpu_context.sp = (unsigned long)childregs; | ||
259 | p->thread.cpu_context.pc = (unsigned long)ret_from_fork; | ||
260 | |||
261 | /* If a TLS pointer was passed to clone, use that for the new thread. */ | ||
262 | if (clone_flags & CLONE_SETTLS) | ||
263 | tls = regs->regs[3]; | ||
264 | p->thread.tp_value = tls; | ||
265 | |||
266 | ptrace_hw_copy_thread(p); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static void tls_thread_switch(struct task_struct *next) | ||
272 | { | ||
273 | unsigned long tpidr, tpidrro; | ||
274 | |||
275 | if (!is_compat_task()) { | ||
276 | asm("mrs %0, tpidr_el0" : "=r" (tpidr)); | ||
277 | current->thread.tp_value = tpidr; | ||
278 | } | ||
279 | |||
280 | if (is_compat_thread(task_thread_info(next))) { | ||
281 | tpidr = 0; | ||
282 | tpidrro = next->thread.tp_value; | ||
283 | } else { | ||
284 | tpidr = next->thread.tp_value; | ||
285 | tpidrro = 0; | ||
286 | } | ||
287 | |||
288 | asm( | ||
289 | " msr tpidr_el0, %0\n" | ||
290 | " msr tpidrro_el0, %1" | ||
291 | : : "r" (tpidr), "r" (tpidrro)); | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * Thread switching. | ||
296 | */ | ||
297 | struct task_struct *__switch_to(struct task_struct *prev, | ||
298 | struct task_struct *next) | ||
299 | { | ||
300 | struct task_struct *last; | ||
301 | |||
302 | fpsimd_thread_switch(next); | ||
303 | tls_thread_switch(next); | ||
304 | hw_breakpoint_thread_switch(next); | ||
305 | |||
306 | /* the actual thread switch */ | ||
307 | last = cpu_switch_to(prev, next); | ||
308 | |||
309 | return last; | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * Fill in the task's elfregs structure for a core dump. | ||
314 | */ | ||
315 | int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs) | ||
316 | { | ||
317 | elf_core_copy_regs(elfregs, task_pt_regs(t)); | ||
318 | return 1; | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * fill in the fpe structure for a core dump... | ||
323 | */ | ||
324 | int dump_fpu (struct pt_regs *regs, struct user_fp *fp) | ||
325 | { | ||
326 | return 0; | ||
327 | } | ||
328 | EXPORT_SYMBOL(dump_fpu); | ||
329 | |||
330 | /* | ||
331 | * Shuffle the argument into the correct register before calling the | ||
332 | * thread function. x1 is the thread argument, x2 is the pointer to | ||
333 | * the thread function, and x3 points to the exit function. | ||
334 | */ | ||
335 | extern void kernel_thread_helper(void); | ||
336 | asm( ".section .text\n" | ||
337 | " .align\n" | ||
338 | " .type kernel_thread_helper, #function\n" | ||
339 | "kernel_thread_helper:\n" | ||
340 | " mov x0, x1\n" | ||
341 | " mov x30, x3\n" | ||
342 | " br x2\n" | ||
343 | " .size kernel_thread_helper, . - kernel_thread_helper\n" | ||
344 | " .previous"); | ||
345 | |||
346 | #define kernel_thread_exit do_exit | ||
347 | |||
348 | /* | ||
349 | * Create a kernel thread. | ||
350 | */ | ||
351 | pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
352 | { | ||
353 | struct pt_regs regs; | ||
354 | |||
355 | memset(®s, 0, sizeof(regs)); | ||
356 | |||
357 | regs.regs[1] = (unsigned long)arg; | ||
358 | regs.regs[2] = (unsigned long)fn; | ||
359 | regs.regs[3] = (unsigned long)kernel_thread_exit; | ||
360 | regs.pc = (unsigned long)kernel_thread_helper; | ||
361 | regs.pstate = PSR_MODE_EL1h; | ||
362 | |||
363 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
364 | } | ||
365 | EXPORT_SYMBOL(kernel_thread); | ||
366 | |||
367 | unsigned long get_wchan(struct task_struct *p) | ||
368 | { | ||
369 | struct stackframe frame; | ||
370 | int count = 0; | ||
371 | if (!p || p == current || p->state == TASK_RUNNING) | ||
372 | return 0; | ||
373 | |||
374 | frame.fp = thread_saved_fp(p); | ||
375 | frame.sp = thread_saved_sp(p); | ||
376 | frame.pc = thread_saved_pc(p); | ||
377 | do { | ||
378 | int ret = unwind_frame(&frame); | ||
379 | if (ret < 0) | ||
380 | return 0; | ||
381 | if (!in_sched_functions(frame.pc)) | ||
382 | return frame.pc; | ||
383 | } while (count ++ < 16); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | unsigned long arch_align_stack(unsigned long sp) | ||
388 | { | ||
389 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | ||
390 | sp -= get_random_int() & ~PAGE_MASK; | ||
391 | return sp & ~0xf; | ||
392 | } | ||
393 | |||
394 | static unsigned long randomize_base(unsigned long base) | ||
395 | { | ||
396 | unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1; | ||
397 | return randomize_range(base, range_end, 0) ? : base; | ||
398 | } | ||
399 | |||
400 | unsigned long arch_randomize_brk(struct mm_struct *mm) | ||
401 | { | ||
402 | return randomize_base(mm->brk); | ||
403 | } | ||
404 | |||
405 | unsigned long randomize_et_dyn(unsigned long base) | ||
406 | { | ||
407 | return randomize_base(base); | ||
408 | } | ||
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c new file mode 100644 index 000000000000..ac3550ecc7b5 --- /dev/null +++ b/arch/arm64/kernel/ptrace.c | |||
@@ -0,0 +1,1126 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/ptrace.c | ||
3 | * | ||
4 | * By Ross Biro 1/23/92 | ||
5 | * edited by Linus Torvalds | ||
6 | * ARM modifications Copyright (C) 2000 Russell King | ||
7 | * Copyright (C) 2012 ARM Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/smp.h> | ||
26 | #include <linux/ptrace.h> | ||
27 | #include <linux/user.h> | ||
28 | #include <linux/security.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/signal.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | #include <linux/perf_event.h> | ||
33 | #include <linux/hw_breakpoint.h> | ||
34 | #include <linux/regset.h> | ||
35 | #include <linux/tracehook.h> | ||
36 | #include <linux/elf.h> | ||
37 | |||
38 | #include <asm/compat.h> | ||
39 | #include <asm/debug-monitors.h> | ||
40 | #include <asm/pgtable.h> | ||
41 | #include <asm/traps.h> | ||
42 | #include <asm/system_misc.h> | ||
43 | |||
44 | /* | ||
45 | * TODO: does not yet catch signals sent when the child dies. | ||
46 | * in exit.c or in signal.c. | ||
47 | */ | ||
48 | |||
49 | /* | ||
50 | * Called by kernel/ptrace.c when detaching.. | ||
51 | */ | ||
52 | void ptrace_disable(struct task_struct *child) | ||
53 | { | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Handle hitting a breakpoint. | ||
58 | */ | ||
59 | static int ptrace_break(struct pt_regs *regs) | ||
60 | { | ||
61 | siginfo_t info = { | ||
62 | .si_signo = SIGTRAP, | ||
63 | .si_errno = 0, | ||
64 | .si_code = TRAP_BRKPT, | ||
65 | .si_addr = (void __user *)instruction_pointer(regs), | ||
66 | }; | ||
67 | |||
68 | force_sig_info(SIGTRAP, &info, current); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int arm64_break_trap(unsigned long addr, unsigned int esr, | ||
73 | struct pt_regs *regs) | ||
74 | { | ||
75 | return ptrace_break(regs); | ||
76 | } | ||
77 | |||
78 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
79 | /* | ||
80 | * Handle hitting a HW-breakpoint. | ||
81 | */ | ||
82 | static void ptrace_hbptriggered(struct perf_event *bp, | ||
83 | struct perf_sample_data *data, | ||
84 | struct pt_regs *regs) | ||
85 | { | ||
86 | struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); | ||
87 | siginfo_t info = { | ||
88 | .si_signo = SIGTRAP, | ||
89 | .si_errno = 0, | ||
90 | .si_code = TRAP_HWBKPT, | ||
91 | .si_addr = (void __user *)(bkpt->trigger), | ||
92 | }; | ||
93 | |||
94 | #ifdef CONFIG_COMPAT | ||
95 | int i; | ||
96 | |||
97 | if (!is_compat_task()) | ||
98 | goto send_sig; | ||
99 | |||
100 | for (i = 0; i < ARM_MAX_BRP; ++i) { | ||
101 | if (current->thread.debug.hbp_break[i] == bp) { | ||
102 | info.si_errno = (i << 1) + 1; | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) { | ||
107 | if (current->thread.debug.hbp_watch[i] == bp) { | ||
108 | info.si_errno = -((i << 1) + 1); | ||
109 | break; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | send_sig: | ||
114 | #endif | ||
115 | force_sig_info(SIGTRAP, &info, current); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Unregister breakpoints from this task and reset the pointers in | ||
120 | * the thread_struct. | ||
121 | */ | ||
122 | void flush_ptrace_hw_breakpoint(struct task_struct *tsk) | ||
123 | { | ||
124 | int i; | ||
125 | struct thread_struct *t = &tsk->thread; | ||
126 | |||
127 | for (i = 0; i < ARM_MAX_BRP; i++) { | ||
128 | if (t->debug.hbp_break[i]) { | ||
129 | unregister_hw_breakpoint(t->debug.hbp_break[i]); | ||
130 | t->debug.hbp_break[i] = NULL; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | for (i = 0; i < ARM_MAX_WRP; i++) { | ||
135 | if (t->debug.hbp_watch[i]) { | ||
136 | unregister_hw_breakpoint(t->debug.hbp_watch[i]); | ||
137 | t->debug.hbp_watch[i] = NULL; | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
142 | void ptrace_hw_copy_thread(struct task_struct *tsk) | ||
143 | { | ||
144 | memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); | ||
145 | } | ||
146 | |||
147 | static struct perf_event *ptrace_hbp_get_event(unsigned int note_type, | ||
148 | struct task_struct *tsk, | ||
149 | unsigned long idx) | ||
150 | { | ||
151 | struct perf_event *bp = ERR_PTR(-EINVAL); | ||
152 | |||
153 | switch (note_type) { | ||
154 | case NT_ARM_HW_BREAK: | ||
155 | if (idx < ARM_MAX_BRP) | ||
156 | bp = tsk->thread.debug.hbp_break[idx]; | ||
157 | break; | ||
158 | case NT_ARM_HW_WATCH: | ||
159 | if (idx < ARM_MAX_WRP) | ||
160 | bp = tsk->thread.debug.hbp_watch[idx]; | ||
161 | break; | ||
162 | } | ||
163 | |||
164 | return bp; | ||
165 | } | ||
166 | |||
167 | static int ptrace_hbp_set_event(unsigned int note_type, | ||
168 | struct task_struct *tsk, | ||
169 | unsigned long idx, | ||
170 | struct perf_event *bp) | ||
171 | { | ||
172 | int err = -EINVAL; | ||
173 | |||
174 | switch (note_type) { | ||
175 | case NT_ARM_HW_BREAK: | ||
176 | if (idx < ARM_MAX_BRP) { | ||
177 | tsk->thread.debug.hbp_break[idx] = bp; | ||
178 | err = 0; | ||
179 | } | ||
180 | break; | ||
181 | case NT_ARM_HW_WATCH: | ||
182 | if (idx < ARM_MAX_WRP) { | ||
183 | tsk->thread.debug.hbp_watch[idx] = bp; | ||
184 | err = 0; | ||
185 | } | ||
186 | break; | ||
187 | } | ||
188 | |||
189 | return err; | ||
190 | } | ||
191 | |||
192 | static struct perf_event *ptrace_hbp_create(unsigned int note_type, | ||
193 | struct task_struct *tsk, | ||
194 | unsigned long idx) | ||
195 | { | ||
196 | struct perf_event *bp; | ||
197 | struct perf_event_attr attr; | ||
198 | int err, type; | ||
199 | |||
200 | switch (note_type) { | ||
201 | case NT_ARM_HW_BREAK: | ||
202 | type = HW_BREAKPOINT_X; | ||
203 | break; | ||
204 | case NT_ARM_HW_WATCH: | ||
205 | type = HW_BREAKPOINT_RW; | ||
206 | break; | ||
207 | default: | ||
208 | return ERR_PTR(-EINVAL); | ||
209 | } | ||
210 | |||
211 | ptrace_breakpoint_init(&attr); | ||
212 | |||
213 | /* | ||
214 | * Initialise fields to sane defaults | ||
215 | * (i.e. values that will pass validation). | ||
216 | */ | ||
217 | attr.bp_addr = 0; | ||
218 | attr.bp_len = HW_BREAKPOINT_LEN_4; | ||
219 | attr.bp_type = type; | ||
220 | attr.disabled = 1; | ||
221 | |||
222 | bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, tsk); | ||
223 | if (IS_ERR(bp)) | ||
224 | return bp; | ||
225 | |||
226 | err = ptrace_hbp_set_event(note_type, tsk, idx, bp); | ||
227 | if (err) | ||
228 | return ERR_PTR(err); | ||
229 | |||
230 | return bp; | ||
231 | } | ||
232 | |||
233 | static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, | ||
234 | struct arch_hw_breakpoint_ctrl ctrl, | ||
235 | struct perf_event_attr *attr) | ||
236 | { | ||
237 | int err, len, type; | ||
238 | |||
239 | err = arch_bp_generic_fields(ctrl, &len, &type); | ||
240 | if (err) | ||
241 | return err; | ||
242 | |||
243 | switch (note_type) { | ||
244 | case NT_ARM_HW_BREAK: | ||
245 | if ((type & HW_BREAKPOINT_X) != type) | ||
246 | return -EINVAL; | ||
247 | break; | ||
248 | case NT_ARM_HW_WATCH: | ||
249 | if ((type & HW_BREAKPOINT_RW) != type) | ||
250 | return -EINVAL; | ||
251 | break; | ||
252 | default: | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | attr->bp_len = len; | ||
257 | attr->bp_type = type; | ||
258 | attr->disabled = !ctrl.enabled; | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info) | ||
264 | { | ||
265 | u8 num; | ||
266 | u32 reg = 0; | ||
267 | |||
268 | switch (note_type) { | ||
269 | case NT_ARM_HW_BREAK: | ||
270 | num = hw_breakpoint_slots(TYPE_INST); | ||
271 | break; | ||
272 | case NT_ARM_HW_WATCH: | ||
273 | num = hw_breakpoint_slots(TYPE_DATA); | ||
274 | break; | ||
275 | default: | ||
276 | return -EINVAL; | ||
277 | } | ||
278 | |||
279 | reg |= debug_monitors_arch(); | ||
280 | reg <<= 8; | ||
281 | reg |= num; | ||
282 | |||
283 | *info = reg; | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static int ptrace_hbp_get_ctrl(unsigned int note_type, | ||
288 | struct task_struct *tsk, | ||
289 | unsigned long idx, | ||
290 | u32 *ctrl) | ||
291 | { | ||
292 | struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); | ||
293 | |||
294 | if (IS_ERR(bp)) | ||
295 | return PTR_ERR(bp); | ||
296 | |||
297 | *ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0; | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int ptrace_hbp_get_addr(unsigned int note_type, | ||
302 | struct task_struct *tsk, | ||
303 | unsigned long idx, | ||
304 | u64 *addr) | ||
305 | { | ||
306 | struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); | ||
307 | |||
308 | if (IS_ERR(bp)) | ||
309 | return PTR_ERR(bp); | ||
310 | |||
311 | *addr = bp ? bp->attr.bp_addr : 0; | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type, | ||
316 | struct task_struct *tsk, | ||
317 | unsigned long idx) | ||
318 | { | ||
319 | struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); | ||
320 | |||
321 | if (!bp) | ||
322 | bp = ptrace_hbp_create(note_type, tsk, idx); | ||
323 | |||
324 | return bp; | ||
325 | } | ||
326 | |||
327 | static int ptrace_hbp_set_ctrl(unsigned int note_type, | ||
328 | struct task_struct *tsk, | ||
329 | unsigned long idx, | ||
330 | u32 uctrl) | ||
331 | { | ||
332 | int err; | ||
333 | struct perf_event *bp; | ||
334 | struct perf_event_attr attr; | ||
335 | struct arch_hw_breakpoint_ctrl ctrl; | ||
336 | |||
337 | bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); | ||
338 | if (IS_ERR(bp)) { | ||
339 | err = PTR_ERR(bp); | ||
340 | return err; | ||
341 | } | ||
342 | |||
343 | attr = bp->attr; | ||
344 | decode_ctrl_reg(uctrl, &ctrl); | ||
345 | err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr); | ||
346 | if (err) | ||
347 | return err; | ||
348 | |||
349 | return modify_user_hw_breakpoint(bp, &attr); | ||
350 | } | ||
351 | |||
352 | static int ptrace_hbp_set_addr(unsigned int note_type, | ||
353 | struct task_struct *tsk, | ||
354 | unsigned long idx, | ||
355 | u64 addr) | ||
356 | { | ||
357 | int err; | ||
358 | struct perf_event *bp; | ||
359 | struct perf_event_attr attr; | ||
360 | |||
361 | bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); | ||
362 | if (IS_ERR(bp)) { | ||
363 | err = PTR_ERR(bp); | ||
364 | return err; | ||
365 | } | ||
366 | |||
367 | attr = bp->attr; | ||
368 | attr.bp_addr = addr; | ||
369 | err = modify_user_hw_breakpoint(bp, &attr); | ||
370 | return err; | ||
371 | } | ||
372 | |||
373 | #define PTRACE_HBP_ADDR_SZ sizeof(u64) | ||
374 | #define PTRACE_HBP_CTRL_SZ sizeof(u32) | ||
375 | #define PTRACE_HBP_REG_OFF sizeof(u32) | ||
376 | |||
377 | static int hw_break_get(struct task_struct *target, | ||
378 | const struct user_regset *regset, | ||
379 | unsigned int pos, unsigned int count, | ||
380 | void *kbuf, void __user *ubuf) | ||
381 | { | ||
382 | unsigned int note_type = regset->core_note_type; | ||
383 | int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit; | ||
384 | u32 info, ctrl; | ||
385 | u64 addr; | ||
386 | |||
387 | /* Resource info */ | ||
388 | ret = ptrace_hbp_get_resource_info(note_type, &info); | ||
389 | if (ret) | ||
390 | return ret; | ||
391 | |||
392 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 4); | ||
393 | if (ret) | ||
394 | return ret; | ||
395 | |||
396 | /* (address, ctrl) registers */ | ||
397 | limit = regset->n * regset->size; | ||
398 | while (count && offset < limit) { | ||
399 | ret = ptrace_hbp_get_addr(note_type, target, idx, &addr); | ||
400 | if (ret) | ||
401 | return ret; | ||
402 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr, | ||
403 | offset, offset + PTRACE_HBP_ADDR_SZ); | ||
404 | if (ret) | ||
405 | return ret; | ||
406 | offset += PTRACE_HBP_ADDR_SZ; | ||
407 | |||
408 | ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl); | ||
409 | if (ret) | ||
410 | return ret; | ||
411 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl, | ||
412 | offset, offset + PTRACE_HBP_CTRL_SZ); | ||
413 | if (ret) | ||
414 | return ret; | ||
415 | offset += PTRACE_HBP_CTRL_SZ; | ||
416 | idx++; | ||
417 | } | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int hw_break_set(struct task_struct *target, | ||
423 | const struct user_regset *regset, | ||
424 | unsigned int pos, unsigned int count, | ||
425 | const void *kbuf, const void __user *ubuf) | ||
426 | { | ||
427 | unsigned int note_type = regset->core_note_type; | ||
428 | int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit; | ||
429 | u32 ctrl; | ||
430 | u64 addr; | ||
431 | |||
432 | /* Resource info */ | ||
433 | ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4); | ||
434 | if (ret) | ||
435 | return ret; | ||
436 | |||
437 | /* (address, ctrl) registers */ | ||
438 | limit = regset->n * regset->size; | ||
439 | while (count && offset < limit) { | ||
440 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr, | ||
441 | offset, offset + PTRACE_HBP_ADDR_SZ); | ||
442 | if (ret) | ||
443 | return ret; | ||
444 | ret = ptrace_hbp_set_addr(note_type, target, idx, addr); | ||
445 | if (ret) | ||
446 | return ret; | ||
447 | offset += PTRACE_HBP_ADDR_SZ; | ||
448 | |||
449 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, | ||
450 | offset, offset + PTRACE_HBP_CTRL_SZ); | ||
451 | if (ret) | ||
452 | return ret; | ||
453 | ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl); | ||
454 | if (ret) | ||
455 | return ret; | ||
456 | offset += PTRACE_HBP_CTRL_SZ; | ||
457 | idx++; | ||
458 | } | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
463 | |||
464 | static int gpr_get(struct task_struct *target, | ||
465 | const struct user_regset *regset, | ||
466 | unsigned int pos, unsigned int count, | ||
467 | void *kbuf, void __user *ubuf) | ||
468 | { | ||
469 | struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs; | ||
470 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); | ||
471 | } | ||
472 | |||
473 | static int gpr_set(struct task_struct *target, const struct user_regset *regset, | ||
474 | unsigned int pos, unsigned int count, | ||
475 | const void *kbuf, const void __user *ubuf) | ||
476 | { | ||
477 | int ret; | ||
478 | struct user_pt_regs newregs; | ||
479 | |||
480 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1); | ||
481 | if (ret) | ||
482 | return ret; | ||
483 | |||
484 | if (!valid_user_regs(&newregs)) | ||
485 | return -EINVAL; | ||
486 | |||
487 | task_pt_regs(target)->user_regs = newregs; | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * TODO: update fp accessors for lazy context switching (sync/flush hwstate) | ||
493 | */ | ||
494 | static int fpr_get(struct task_struct *target, const struct user_regset *regset, | ||
495 | unsigned int pos, unsigned int count, | ||
496 | void *kbuf, void __user *ubuf) | ||
497 | { | ||
498 | struct user_fpsimd_state *uregs; | ||
499 | uregs = &target->thread.fpsimd_state.user_fpsimd; | ||
500 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); | ||
501 | } | ||
502 | |||
503 | static int fpr_set(struct task_struct *target, const struct user_regset *regset, | ||
504 | unsigned int pos, unsigned int count, | ||
505 | const void *kbuf, const void __user *ubuf) | ||
506 | { | ||
507 | int ret; | ||
508 | struct user_fpsimd_state newstate; | ||
509 | |||
510 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1); | ||
511 | if (ret) | ||
512 | return ret; | ||
513 | |||
514 | target->thread.fpsimd_state.user_fpsimd = newstate; | ||
515 | return ret; | ||
516 | } | ||
517 | |||
518 | static int tls_get(struct task_struct *target, const struct user_regset *regset, | ||
519 | unsigned int pos, unsigned int count, | ||
520 | void *kbuf, void __user *ubuf) | ||
521 | { | ||
522 | unsigned long *tls = &target->thread.tp_value; | ||
523 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1); | ||
524 | } | ||
525 | |||
526 | static int tls_set(struct task_struct *target, const struct user_regset *regset, | ||
527 | unsigned int pos, unsigned int count, | ||
528 | const void *kbuf, const void __user *ubuf) | ||
529 | { | ||
530 | int ret; | ||
531 | unsigned long tls; | ||
532 | |||
533 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); | ||
534 | if (ret) | ||
535 | return ret; | ||
536 | |||
537 | target->thread.tp_value = tls; | ||
538 | return ret; | ||
539 | } | ||
540 | |||
541 | enum aarch64_regset { | ||
542 | REGSET_GPR, | ||
543 | REGSET_FPR, | ||
544 | REGSET_TLS, | ||
545 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
546 | REGSET_HW_BREAK, | ||
547 | REGSET_HW_WATCH, | ||
548 | #endif | ||
549 | }; | ||
550 | |||
551 | static const struct user_regset aarch64_regsets[] = { | ||
552 | [REGSET_GPR] = { | ||
553 | .core_note_type = NT_PRSTATUS, | ||
554 | .n = sizeof(struct user_pt_regs) / sizeof(u64), | ||
555 | .size = sizeof(u64), | ||
556 | .align = sizeof(u64), | ||
557 | .get = gpr_get, | ||
558 | .set = gpr_set | ||
559 | }, | ||
560 | [REGSET_FPR] = { | ||
561 | .core_note_type = NT_PRFPREG, | ||
562 | .n = sizeof(struct user_fpsimd_state) / sizeof(u32), | ||
563 | /* | ||
564 | * We pretend we have 32-bit registers because the fpsr and | ||
565 | * fpcr are 32-bits wide. | ||
566 | */ | ||
567 | .size = sizeof(u32), | ||
568 | .align = sizeof(u32), | ||
569 | .get = fpr_get, | ||
570 | .set = fpr_set | ||
571 | }, | ||
572 | [REGSET_TLS] = { | ||
573 | .core_note_type = NT_ARM_TLS, | ||
574 | .n = 1, | ||
575 | .size = sizeof(void *), | ||
576 | .align = sizeof(void *), | ||
577 | .get = tls_get, | ||
578 | .set = tls_set, | ||
579 | }, | ||
580 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
581 | [REGSET_HW_BREAK] = { | ||
582 | .core_note_type = NT_ARM_HW_BREAK, | ||
583 | .n = sizeof(struct user_hwdebug_state) / sizeof(u32), | ||
584 | .size = sizeof(u32), | ||
585 | .align = sizeof(u32), | ||
586 | .get = hw_break_get, | ||
587 | .set = hw_break_set, | ||
588 | }, | ||
589 | [REGSET_HW_WATCH] = { | ||
590 | .core_note_type = NT_ARM_HW_WATCH, | ||
591 | .n = sizeof(struct user_hwdebug_state) / sizeof(u32), | ||
592 | .size = sizeof(u32), | ||
593 | .align = sizeof(u32), | ||
594 | .get = hw_break_get, | ||
595 | .set = hw_break_set, | ||
596 | }, | ||
597 | #endif | ||
598 | }; | ||
599 | |||
600 | static const struct user_regset_view user_aarch64_view = { | ||
601 | .name = "aarch64", .e_machine = EM_AARCH64, | ||
602 | .regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets) | ||
603 | }; | ||
604 | |||
605 | #ifdef CONFIG_COMPAT | ||
606 | #include <linux/compat.h> | ||
607 | |||
608 | enum compat_regset { | ||
609 | REGSET_COMPAT_GPR, | ||
610 | REGSET_COMPAT_VFP, | ||
611 | }; | ||
612 | |||
613 | static int compat_gpr_get(struct task_struct *target, | ||
614 | const struct user_regset *regset, | ||
615 | unsigned int pos, unsigned int count, | ||
616 | void *kbuf, void __user *ubuf) | ||
617 | { | ||
618 | int ret = 0; | ||
619 | unsigned int i, start, num_regs; | ||
620 | |||
621 | /* Calculate the number of AArch32 registers contained in count */ | ||
622 | num_regs = count / regset->size; | ||
623 | |||
624 | /* Convert pos into an register number */ | ||
625 | start = pos / regset->size; | ||
626 | |||
627 | if (start + num_regs > regset->n) | ||
628 | return -EIO; | ||
629 | |||
630 | for (i = 0; i < num_regs; ++i) { | ||
631 | unsigned int idx = start + i; | ||
632 | void *reg; | ||
633 | |||
634 | switch (idx) { | ||
635 | case 15: | ||
636 | reg = (void *)&task_pt_regs(target)->pc; | ||
637 | break; | ||
638 | case 16: | ||
639 | reg = (void *)&task_pt_regs(target)->pstate; | ||
640 | break; | ||
641 | case 17: | ||
642 | reg = (void *)&task_pt_regs(target)->orig_x0; | ||
643 | break; | ||
644 | default: | ||
645 | reg = (void *)&task_pt_regs(target)->regs[idx]; | ||
646 | } | ||
647 | |||
648 | ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t)); | ||
649 | |||
650 | if (ret) | ||
651 | break; | ||
652 | else | ||
653 | ubuf += sizeof(compat_ulong_t); | ||
654 | } | ||
655 | |||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | static int compat_gpr_set(struct task_struct *target, | ||
660 | const struct user_regset *regset, | ||
661 | unsigned int pos, unsigned int count, | ||
662 | const void *kbuf, const void __user *ubuf) | ||
663 | { | ||
664 | struct pt_regs newregs; | ||
665 | int ret = 0; | ||
666 | unsigned int i, start, num_regs; | ||
667 | |||
668 | /* Calculate the number of AArch32 registers contained in count */ | ||
669 | num_regs = count / regset->size; | ||
670 | |||
671 | /* Convert pos into an register number */ | ||
672 | start = pos / regset->size; | ||
673 | |||
674 | if (start + num_regs > regset->n) | ||
675 | return -EIO; | ||
676 | |||
677 | newregs = *task_pt_regs(target); | ||
678 | |||
679 | for (i = 0; i < num_regs; ++i) { | ||
680 | unsigned int idx = start + i; | ||
681 | void *reg; | ||
682 | |||
683 | switch (idx) { | ||
684 | case 15: | ||
685 | reg = (void *)&newregs.pc; | ||
686 | break; | ||
687 | case 16: | ||
688 | reg = (void *)&newregs.pstate; | ||
689 | break; | ||
690 | case 17: | ||
691 | reg = (void *)&newregs.orig_x0; | ||
692 | break; | ||
693 | default: | ||
694 | reg = (void *)&newregs.regs[idx]; | ||
695 | } | ||
696 | |||
697 | ret = copy_from_user(reg, ubuf, sizeof(compat_ulong_t)); | ||
698 | |||
699 | if (ret) | ||
700 | goto out; | ||
701 | else | ||
702 | ubuf += sizeof(compat_ulong_t); | ||
703 | } | ||
704 | |||
705 | if (valid_user_regs(&newregs.user_regs)) | ||
706 | *task_pt_regs(target) = newregs; | ||
707 | else | ||
708 | ret = -EINVAL; | ||
709 | |||
710 | out: | ||
711 | return ret; | ||
712 | } | ||
713 | |||
714 | static int compat_vfp_get(struct task_struct *target, | ||
715 | const struct user_regset *regset, | ||
716 | unsigned int pos, unsigned int count, | ||
717 | void *kbuf, void __user *ubuf) | ||
718 | { | ||
719 | struct user_fpsimd_state *uregs; | ||
720 | compat_ulong_t fpscr; | ||
721 | int ret; | ||
722 | |||
723 | uregs = &target->thread.fpsimd_state.user_fpsimd; | ||
724 | |||
725 | /* | ||
726 | * The VFP registers are packed into the fpsimd_state, so they all sit | ||
727 | * nicely together for us. We just need to create the fpscr separately. | ||
728 | */ | ||
729 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, | ||
730 | VFP_STATE_SIZE - sizeof(compat_ulong_t)); | ||
731 | |||
732 | if (count && !ret) { | ||
733 | fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) | | ||
734 | (uregs->fpcr & VFP_FPSCR_CTRL_MASK); | ||
735 | ret = put_user(fpscr, (compat_ulong_t *)ubuf); | ||
736 | } | ||
737 | |||
738 | return ret; | ||
739 | } | ||
740 | |||
741 | static int compat_vfp_set(struct task_struct *target, | ||
742 | const struct user_regset *regset, | ||
743 | unsigned int pos, unsigned int count, | ||
744 | const void *kbuf, const void __user *ubuf) | ||
745 | { | ||
746 | struct user_fpsimd_state *uregs; | ||
747 | compat_ulong_t fpscr; | ||
748 | int ret; | ||
749 | |||
750 | if (pos + count > VFP_STATE_SIZE) | ||
751 | return -EIO; | ||
752 | |||
753 | uregs = &target->thread.fpsimd_state.user_fpsimd; | ||
754 | |||
755 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, | ||
756 | VFP_STATE_SIZE - sizeof(compat_ulong_t)); | ||
757 | |||
758 | if (count && !ret) { | ||
759 | ret = get_user(fpscr, (compat_ulong_t *)ubuf); | ||
760 | uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK; | ||
761 | uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK; | ||
762 | } | ||
763 | |||
764 | return ret; | ||
765 | } | ||
766 | |||
767 | static const struct user_regset aarch32_regsets[] = { | ||
768 | [REGSET_COMPAT_GPR] = { | ||
769 | .core_note_type = NT_PRSTATUS, | ||
770 | .n = COMPAT_ELF_NGREG, | ||
771 | .size = sizeof(compat_elf_greg_t), | ||
772 | .align = sizeof(compat_elf_greg_t), | ||
773 | .get = compat_gpr_get, | ||
774 | .set = compat_gpr_set | ||
775 | }, | ||
776 | [REGSET_COMPAT_VFP] = { | ||
777 | .core_note_type = NT_ARM_VFP, | ||
778 | .n = VFP_STATE_SIZE / sizeof(compat_ulong_t), | ||
779 | .size = sizeof(compat_ulong_t), | ||
780 | .align = sizeof(compat_ulong_t), | ||
781 | .get = compat_vfp_get, | ||
782 | .set = compat_vfp_set | ||
783 | }, | ||
784 | }; | ||
785 | |||
786 | static const struct user_regset_view user_aarch32_view = { | ||
787 | .name = "aarch32", .e_machine = EM_ARM, | ||
788 | .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets) | ||
789 | }; | ||
790 | |||
791 | int aarch32_break_trap(struct pt_regs *regs) | ||
792 | { | ||
793 | unsigned int instr; | ||
794 | bool bp = false; | ||
795 | void __user *pc = (void __user *)instruction_pointer(regs); | ||
796 | |||
797 | if (compat_thumb_mode(regs)) { | ||
798 | /* get 16-bit Thumb instruction */ | ||
799 | get_user(instr, (u16 __user *)pc); | ||
800 | if (instr == AARCH32_BREAK_THUMB2_LO) { | ||
801 | /* get second half of 32-bit Thumb-2 instruction */ | ||
802 | get_user(instr, (u16 __user *)(pc + 2)); | ||
803 | bp = instr == AARCH32_BREAK_THUMB2_HI; | ||
804 | } else { | ||
805 | bp = instr == AARCH32_BREAK_THUMB; | ||
806 | } | ||
807 | } else { | ||
808 | /* 32-bit ARM instruction */ | ||
809 | get_user(instr, (u32 __user *)pc); | ||
810 | bp = (instr & ~0xf0000000) == AARCH32_BREAK_ARM; | ||
811 | } | ||
812 | |||
813 | if (bp) | ||
814 | return ptrace_break(regs); | ||
815 | return 1; | ||
816 | } | ||
817 | |||
818 | static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off, | ||
819 | compat_ulong_t __user *ret) | ||
820 | { | ||
821 | compat_ulong_t tmp; | ||
822 | |||
823 | if (off & 3) | ||
824 | return -EIO; | ||
825 | |||
826 | if (off == PT_TEXT_ADDR) | ||
827 | tmp = tsk->mm->start_code; | ||
828 | else if (off == PT_DATA_ADDR) | ||
829 | tmp = tsk->mm->start_data; | ||
830 | else if (off == PT_TEXT_END_ADDR) | ||
831 | tmp = tsk->mm->end_code; | ||
832 | else if (off < sizeof(compat_elf_gregset_t)) | ||
833 | return copy_regset_to_user(tsk, &user_aarch32_view, | ||
834 | REGSET_COMPAT_GPR, off, | ||
835 | sizeof(compat_ulong_t), ret); | ||
836 | else if (off >= COMPAT_USER_SZ) | ||
837 | return -EIO; | ||
838 | else | ||
839 | tmp = 0; | ||
840 | |||
841 | return put_user(tmp, ret); | ||
842 | } | ||
843 | |||
844 | static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off, | ||
845 | compat_ulong_t val) | ||
846 | { | ||
847 | int ret; | ||
848 | |||
849 | if (off & 3 || off >= COMPAT_USER_SZ) | ||
850 | return -EIO; | ||
851 | |||
852 | if (off >= sizeof(compat_elf_gregset_t)) | ||
853 | return 0; | ||
854 | |||
855 | ret = copy_regset_from_user(tsk, &user_aarch32_view, | ||
856 | REGSET_COMPAT_GPR, off, | ||
857 | sizeof(compat_ulong_t), | ||
858 | &val); | ||
859 | return ret; | ||
860 | } | ||
861 | |||
862 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
863 | |||
864 | /* | ||
865 | * Convert a virtual register number into an index for a thread_info | ||
866 | * breakpoint array. Breakpoints are identified using positive numbers | ||
867 | * whilst watchpoints are negative. The registers are laid out as pairs | ||
868 | * of (address, control), each pair mapping to a unique hw_breakpoint struct. | ||
869 | * Register 0 is reserved for describing resource information. | ||
870 | */ | ||
871 | static int compat_ptrace_hbp_num_to_idx(compat_long_t num) | ||
872 | { | ||
873 | return (abs(num) - 1) >> 1; | ||
874 | } | ||
875 | |||
876 | static int compat_ptrace_hbp_get_resource_info(u32 *kdata) | ||
877 | { | ||
878 | u8 num_brps, num_wrps, debug_arch, wp_len; | ||
879 | u32 reg = 0; | ||
880 | |||
881 | num_brps = hw_breakpoint_slots(TYPE_INST); | ||
882 | num_wrps = hw_breakpoint_slots(TYPE_DATA); | ||
883 | |||
884 | debug_arch = debug_monitors_arch(); | ||
885 | wp_len = 8; | ||
886 | reg |= debug_arch; | ||
887 | reg <<= 8; | ||
888 | reg |= wp_len; | ||
889 | reg <<= 8; | ||
890 | reg |= num_wrps; | ||
891 | reg <<= 8; | ||
892 | reg |= num_brps; | ||
893 | |||
894 | *kdata = reg; | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | static int compat_ptrace_hbp_get(unsigned int note_type, | ||
899 | struct task_struct *tsk, | ||
900 | compat_long_t num, | ||
901 | u32 *kdata) | ||
902 | { | ||
903 | u64 addr = 0; | ||
904 | u32 ctrl = 0; | ||
905 | |||
906 | int err, idx = compat_ptrace_hbp_num_to_idx(num);; | ||
907 | |||
908 | if (num & 1) { | ||
909 | err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr); | ||
910 | *kdata = (u32)addr; | ||
911 | } else { | ||
912 | err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl); | ||
913 | *kdata = ctrl; | ||
914 | } | ||
915 | |||
916 | return err; | ||
917 | } | ||
918 | |||
919 | static int compat_ptrace_hbp_set(unsigned int note_type, | ||
920 | struct task_struct *tsk, | ||
921 | compat_long_t num, | ||
922 | u32 *kdata) | ||
923 | { | ||
924 | u64 addr; | ||
925 | u32 ctrl; | ||
926 | |||
927 | int err, idx = compat_ptrace_hbp_num_to_idx(num); | ||
928 | |||
929 | if (num & 1) { | ||
930 | addr = *kdata; | ||
931 | err = ptrace_hbp_set_addr(note_type, tsk, idx, addr); | ||
932 | } else { | ||
933 | ctrl = *kdata; | ||
934 | err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl); | ||
935 | } | ||
936 | |||
937 | return err; | ||
938 | } | ||
939 | |||
940 | static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, | ||
941 | compat_ulong_t __user *data) | ||
942 | { | ||
943 | int ret; | ||
944 | u32 kdata; | ||
945 | mm_segment_t old_fs = get_fs(); | ||
946 | |||
947 | set_fs(KERNEL_DS); | ||
948 | /* Watchpoint */ | ||
949 | if (num < 0) { | ||
950 | ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); | ||
951 | /* Resource info */ | ||
952 | } else if (num == 0) { | ||
953 | ret = compat_ptrace_hbp_get_resource_info(&kdata); | ||
954 | /* Breakpoint */ | ||
955 | } else { | ||
956 | ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); | ||
957 | } | ||
958 | set_fs(old_fs); | ||
959 | |||
960 | if (!ret) | ||
961 | ret = put_user(kdata, data); | ||
962 | |||
963 | return ret; | ||
964 | } | ||
965 | |||
966 | static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, | ||
967 | compat_ulong_t __user *data) | ||
968 | { | ||
969 | int ret; | ||
970 | u32 kdata = 0; | ||
971 | mm_segment_t old_fs = get_fs(); | ||
972 | |||
973 | if (num == 0) | ||
974 | return 0; | ||
975 | |||
976 | ret = get_user(kdata, data); | ||
977 | if (ret) | ||
978 | return ret; | ||
979 | |||
980 | set_fs(KERNEL_DS); | ||
981 | if (num < 0) | ||
982 | ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); | ||
983 | else | ||
984 | ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); | ||
985 | set_fs(old_fs); | ||
986 | |||
987 | return ret; | ||
988 | } | ||
989 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
990 | |||
991 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | ||
992 | compat_ulong_t caddr, compat_ulong_t cdata) | ||
993 | { | ||
994 | unsigned long addr = caddr; | ||
995 | unsigned long data = cdata; | ||
996 | void __user *datap = compat_ptr(data); | ||
997 | int ret; | ||
998 | |||
999 | switch (request) { | ||
1000 | case PTRACE_PEEKUSR: | ||
1001 | ret = compat_ptrace_read_user(child, addr, datap); | ||
1002 | break; | ||
1003 | |||
1004 | case PTRACE_POKEUSR: | ||
1005 | ret = compat_ptrace_write_user(child, addr, data); | ||
1006 | break; | ||
1007 | |||
1008 | case COMPAT_PTRACE_GETREGS: | ||
1009 | ret = copy_regset_to_user(child, | ||
1010 | &user_aarch32_view, | ||
1011 | REGSET_COMPAT_GPR, | ||
1012 | 0, sizeof(compat_elf_gregset_t), | ||
1013 | datap); | ||
1014 | break; | ||
1015 | |||
1016 | case COMPAT_PTRACE_SETREGS: | ||
1017 | ret = copy_regset_from_user(child, | ||
1018 | &user_aarch32_view, | ||
1019 | REGSET_COMPAT_GPR, | ||
1020 | 0, sizeof(compat_elf_gregset_t), | ||
1021 | datap); | ||
1022 | break; | ||
1023 | |||
1024 | case COMPAT_PTRACE_GET_THREAD_AREA: | ||
1025 | ret = put_user((compat_ulong_t)child->thread.tp_value, | ||
1026 | (compat_ulong_t __user *)datap); | ||
1027 | break; | ||
1028 | |||
1029 | case COMPAT_PTRACE_SET_SYSCALL: | ||
1030 | task_pt_regs(child)->syscallno = data; | ||
1031 | ret = 0; | ||
1032 | break; | ||
1033 | |||
1034 | case COMPAT_PTRACE_GETVFPREGS: | ||
1035 | ret = copy_regset_to_user(child, | ||
1036 | &user_aarch32_view, | ||
1037 | REGSET_COMPAT_VFP, | ||
1038 | 0, VFP_STATE_SIZE, | ||
1039 | datap); | ||
1040 | break; | ||
1041 | |||
1042 | case COMPAT_PTRACE_SETVFPREGS: | ||
1043 | ret = copy_regset_from_user(child, | ||
1044 | &user_aarch32_view, | ||
1045 | REGSET_COMPAT_VFP, | ||
1046 | 0, VFP_STATE_SIZE, | ||
1047 | datap); | ||
1048 | break; | ||
1049 | |||
1050 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
1051 | case COMPAT_PTRACE_GETHBPREGS: | ||
1052 | ret = compat_ptrace_gethbpregs(child, addr, datap); | ||
1053 | break; | ||
1054 | |||
1055 | case COMPAT_PTRACE_SETHBPREGS: | ||
1056 | ret = compat_ptrace_sethbpregs(child, addr, datap); | ||
1057 | break; | ||
1058 | #endif | ||
1059 | |||
1060 | default: | ||
1061 | ret = compat_ptrace_request(child, request, addr, | ||
1062 | data); | ||
1063 | break; | ||
1064 | } | ||
1065 | |||
1066 | return ret; | ||
1067 | } | ||
1068 | #endif /* CONFIG_COMPAT */ | ||
1069 | |||
1070 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | ||
1071 | { | ||
1072 | #ifdef CONFIG_COMPAT | ||
1073 | if (is_compat_thread(task_thread_info(task))) | ||
1074 | return &user_aarch32_view; | ||
1075 | #endif | ||
1076 | return &user_aarch64_view; | ||
1077 | } | ||
1078 | |||
1079 | long arch_ptrace(struct task_struct *child, long request, | ||
1080 | unsigned long addr, unsigned long data) | ||
1081 | { | ||
1082 | return ptrace_request(child, request, addr, data); | ||
1083 | } | ||
1084 | |||
1085 | |||
1086 | static int __init ptrace_break_init(void) | ||
1087 | { | ||
1088 | hook_debug_fault_code(DBG_ESR_EVT_BRK, arm64_break_trap, SIGTRAP, | ||
1089 | TRAP_BRKPT, "ptrace BRK handler"); | ||
1090 | return 0; | ||
1091 | } | ||
1092 | core_initcall(ptrace_break_init); | ||
1093 | |||
1094 | |||
1095 | asmlinkage int syscall_trace(int dir, struct pt_regs *regs) | ||
1096 | { | ||
1097 | unsigned long saved_reg; | ||
1098 | |||
1099 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
1100 | return regs->syscallno; | ||
1101 | |||
1102 | if (is_compat_task()) { | ||
1103 | /* AArch32 uses ip (r12) for scratch */ | ||
1104 | saved_reg = regs->regs[12]; | ||
1105 | regs->regs[12] = dir; | ||
1106 | } else { | ||
1107 | /* | ||
1108 | * Save X7. X7 is used to denote syscall entry/exit: | ||
1109 | * X7 = 0 -> entry, = 1 -> exit | ||
1110 | */ | ||
1111 | saved_reg = regs->regs[7]; | ||
1112 | regs->regs[7] = dir; | ||
1113 | } | ||
1114 | |||
1115 | if (dir) | ||
1116 | tracehook_report_syscall_exit(regs, 0); | ||
1117 | else if (tracehook_report_syscall_entry(regs)) | ||
1118 | regs->syscallno = ~0UL; | ||
1119 | |||
1120 | if (is_compat_task()) | ||
1121 | regs->regs[12] = saved_reg; | ||
1122 | else | ||
1123 | regs->regs[7] = saved_reg; | ||
1124 | |||
1125 | return regs->syscallno; | ||
1126 | } | ||
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c new file mode 100644 index 000000000000..48ffb9fb3fe3 --- /dev/null +++ b/arch/arm64/kernel/setup.c | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/setup.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2001 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/export.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/stddef.h> | ||
23 | #include <linux/ioport.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/utsname.h> | ||
26 | #include <linux/initrd.h> | ||
27 | #include <linux/console.h> | ||
28 | #include <linux/bootmem.h> | ||
29 | #include <linux/seq_file.h> | ||
30 | #include <linux/screen_info.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/kexec.h> | ||
33 | #include <linux/crash_dump.h> | ||
34 | #include <linux/root_dev.h> | ||
35 | #include <linux/cpu.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/smp.h> | ||
38 | #include <linux/fs.h> | ||
39 | #include <linux/proc_fs.h> | ||
40 | #include <linux/memblock.h> | ||
41 | #include <linux/of_fdt.h> | ||
42 | |||
43 | #include <asm/cputype.h> | ||
44 | #include <asm/elf.h> | ||
45 | #include <asm/cputable.h> | ||
46 | #include <asm/sections.h> | ||
47 | #include <asm/setup.h> | ||
48 | #include <asm/cacheflush.h> | ||
49 | #include <asm/tlbflush.h> | ||
50 | #include <asm/traps.h> | ||
51 | #include <asm/memblock.h> | ||
52 | |||
53 | unsigned int processor_id; | ||
54 | EXPORT_SYMBOL(processor_id); | ||
55 | |||
56 | unsigned int elf_hwcap __read_mostly; | ||
57 | EXPORT_SYMBOL_GPL(elf_hwcap); | ||
58 | |||
59 | static const char *cpu_name; | ||
60 | static const char *machine_name; | ||
61 | phys_addr_t __fdt_pointer __initdata; | ||
62 | |||
63 | /* | ||
64 | * Standard memory resources | ||
65 | */ | ||
66 | static struct resource mem_res[] = { | ||
67 | { | ||
68 | .name = "Kernel code", | ||
69 | .start = 0, | ||
70 | .end = 0, | ||
71 | .flags = IORESOURCE_MEM | ||
72 | }, | ||
73 | { | ||
74 | .name = "Kernel data", | ||
75 | .start = 0, | ||
76 | .end = 0, | ||
77 | .flags = IORESOURCE_MEM | ||
78 | } | ||
79 | }; | ||
80 | |||
81 | #define kernel_code mem_res[0] | ||
82 | #define kernel_data mem_res[1] | ||
83 | |||
84 | void __init early_print(const char *str, ...) | ||
85 | { | ||
86 | char buf[256]; | ||
87 | va_list ap; | ||
88 | |||
89 | va_start(ap, str); | ||
90 | vsnprintf(buf, sizeof(buf), str, ap); | ||
91 | va_end(ap); | ||
92 | |||
93 | printk("%s", buf); | ||
94 | } | ||
95 | |||
96 | static void __init setup_processor(void) | ||
97 | { | ||
98 | struct cpu_info *cpu_info; | ||
99 | |||
100 | /* | ||
101 | * locate processor in the list of supported processor | ||
102 | * types. The linker builds this table for us from the | ||
103 | * entries in arch/arm/mm/proc.S | ||
104 | */ | ||
105 | cpu_info = lookup_processor_type(read_cpuid_id()); | ||
106 | if (!cpu_info) { | ||
107 | printk("CPU configuration botched (ID %08x), unable to continue.\n", | ||
108 | read_cpuid_id()); | ||
109 | while (1); | ||
110 | } | ||
111 | |||
112 | cpu_name = cpu_info->cpu_name; | ||
113 | |||
114 | printk("CPU: %s [%08x] revision %d\n", | ||
115 | cpu_name, read_cpuid_id(), read_cpuid_id() & 15); | ||
116 | |||
117 | sprintf(init_utsname()->machine, "aarch64"); | ||
118 | elf_hwcap = 0; | ||
119 | } | ||
120 | |||
121 | static void __init setup_machine_fdt(phys_addr_t dt_phys) | ||
122 | { | ||
123 | struct boot_param_header *devtree; | ||
124 | unsigned long dt_root; | ||
125 | |||
126 | /* Check we have a non-NULL DT pointer */ | ||
127 | if (!dt_phys) { | ||
128 | early_print("\n" | ||
129 | "Error: NULL or invalid device tree blob\n" | ||
130 | "The dtb must be 8-byte aligned and passed in the first 512MB of memory\n" | ||
131 | "\nPlease check your bootloader.\n"); | ||
132 | |||
133 | while (true) | ||
134 | cpu_relax(); | ||
135 | |||
136 | } | ||
137 | |||
138 | devtree = phys_to_virt(dt_phys); | ||
139 | |||
140 | /* Check device tree validity */ | ||
141 | if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) { | ||
142 | early_print("\n" | ||
143 | "Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n" | ||
144 | "Expected 0x%x, found 0x%x\n" | ||
145 | "\nPlease check your bootloader.\n", | ||
146 | dt_phys, devtree, OF_DT_HEADER, | ||
147 | be32_to_cpu(devtree->magic)); | ||
148 | |||
149 | while (true) | ||
150 | cpu_relax(); | ||
151 | } | ||
152 | |||
153 | initial_boot_params = devtree; | ||
154 | dt_root = of_get_flat_dt_root(); | ||
155 | |||
156 | machine_name = of_get_flat_dt_prop(dt_root, "model", NULL); | ||
157 | if (!machine_name) | ||
158 | machine_name = of_get_flat_dt_prop(dt_root, "compatible", NULL); | ||
159 | if (!machine_name) | ||
160 | machine_name = "<unknown>"; | ||
161 | pr_info("Machine: %s\n", machine_name); | ||
162 | |||
163 | /* Retrieve various information from the /chosen node */ | ||
164 | of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); | ||
165 | /* Initialize {size,address}-cells info */ | ||
166 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
167 | /* Setup memory, calling early_init_dt_add_memory_arch */ | ||
168 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||
169 | } | ||
170 | |||
171 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | ||
172 | { | ||
173 | size &= PAGE_MASK; | ||
174 | memblock_add(base, size); | ||
175 | } | ||
176 | |||
177 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | ||
178 | { | ||
179 | return __va(memblock_alloc(size, align)); | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Limit the memory size that was specified via FDT. | ||
184 | */ | ||
185 | static int __init early_mem(char *p) | ||
186 | { | ||
187 | phys_addr_t limit; | ||
188 | |||
189 | if (!p) | ||
190 | return 1; | ||
191 | |||
192 | limit = memparse(p, &p) & PAGE_MASK; | ||
193 | pr_notice("Memory limited to %lldMB\n", limit >> 20); | ||
194 | |||
195 | memblock_enforce_memory_limit(limit); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | early_param("mem", early_mem); | ||
200 | |||
201 | static void __init request_standard_resources(void) | ||
202 | { | ||
203 | struct memblock_region *region; | ||
204 | struct resource *res; | ||
205 | |||
206 | kernel_code.start = virt_to_phys(_text); | ||
207 | kernel_code.end = virt_to_phys(_etext - 1); | ||
208 | kernel_data.start = virt_to_phys(_sdata); | ||
209 | kernel_data.end = virt_to_phys(_end - 1); | ||
210 | |||
211 | for_each_memblock(memory, region) { | ||
212 | res = alloc_bootmem_low(sizeof(*res)); | ||
213 | res->name = "System RAM"; | ||
214 | res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); | ||
215 | res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; | ||
216 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
217 | |||
218 | request_resource(&iomem_resource, res); | ||
219 | |||
220 | if (kernel_code.start >= res->start && | ||
221 | kernel_code.end <= res->end) | ||
222 | request_resource(res, &kernel_code); | ||
223 | if (kernel_data.start >= res->start && | ||
224 | kernel_data.end <= res->end) | ||
225 | request_resource(res, &kernel_data); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | void __init setup_arch(char **cmdline_p) | ||
230 | { | ||
231 | setup_processor(); | ||
232 | |||
233 | setup_machine_fdt(__fdt_pointer); | ||
234 | |||
235 | init_mm.start_code = (unsigned long) _text; | ||
236 | init_mm.end_code = (unsigned long) _etext; | ||
237 | init_mm.end_data = (unsigned long) _edata; | ||
238 | init_mm.brk = (unsigned long) _end; | ||
239 | |||
240 | *cmdline_p = boot_command_line; | ||
241 | |||
242 | parse_early_param(); | ||
243 | |||
244 | arm64_memblock_init(); | ||
245 | |||
246 | paging_init(); | ||
247 | request_standard_resources(); | ||
248 | |||
249 | unflatten_device_tree(); | ||
250 | |||
251 | #ifdef CONFIG_SMP | ||
252 | smp_init_cpus(); | ||
253 | #endif | ||
254 | |||
255 | #ifdef CONFIG_VT | ||
256 | #if defined(CONFIG_VGA_CONSOLE) | ||
257 | conswitchp = &vga_con; | ||
258 | #elif defined(CONFIG_DUMMY_CONSOLE) | ||
259 | conswitchp = &dummy_con; | ||
260 | #endif | ||
261 | #endif | ||
262 | } | ||
263 | |||
264 | static DEFINE_PER_CPU(struct cpu, cpu_data); | ||
265 | |||
266 | static int __init topology_init(void) | ||
267 | { | ||
268 | int i; | ||
269 | |||
270 | for_each_possible_cpu(i) { | ||
271 | struct cpu *cpu = &per_cpu(cpu_data, i); | ||
272 | cpu->hotpluggable = 1; | ||
273 | register_cpu(cpu, i); | ||
274 | } | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | subsys_initcall(topology_init); | ||
279 | |||
280 | static const char *hwcap_str[] = { | ||
281 | "fp", | ||
282 | "asimd", | ||
283 | NULL | ||
284 | }; | ||
285 | |||
286 | static int c_show(struct seq_file *m, void *v) | ||
287 | { | ||
288 | int i; | ||
289 | |||
290 | seq_printf(m, "Processor\t: %s rev %d (%s)\n", | ||
291 | cpu_name, read_cpuid_id() & 15, ELF_PLATFORM); | ||
292 | |||
293 | for_each_online_cpu(i) { | ||
294 | /* | ||
295 | * glibc reads /proc/cpuinfo to determine the number of | ||
296 | * online processors, looking for lines beginning with | ||
297 | * "processor". Give glibc what it expects. | ||
298 | */ | ||
299 | #ifdef CONFIG_SMP | ||
300 | seq_printf(m, "processor\t: %d\n", i); | ||
301 | #endif | ||
302 | seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n", | ||
303 | loops_per_jiffy / (500000UL/HZ), | ||
304 | loops_per_jiffy / (5000UL/HZ) % 100); | ||
305 | } | ||
306 | |||
307 | /* dump out the processor features */ | ||
308 | seq_puts(m, "Features\t: "); | ||
309 | |||
310 | for (i = 0; hwcap_str[i]; i++) | ||
311 | if (elf_hwcap & (1 << i)) | ||
312 | seq_printf(m, "%s ", hwcap_str[i]); | ||
313 | |||
314 | seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); | ||
315 | seq_printf(m, "CPU architecture: AArch64\n"); | ||
316 | seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15); | ||
317 | seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff); | ||
318 | seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); | ||
319 | |||
320 | seq_puts(m, "\n"); | ||
321 | |||
322 | seq_printf(m, "Hardware\t: %s\n", machine_name); | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
328 | { | ||
329 | return *pos < 1 ? (void *)1 : NULL; | ||
330 | } | ||
331 | |||
332 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
333 | { | ||
334 | ++*pos; | ||
335 | return NULL; | ||
336 | } | ||
337 | |||
338 | static void c_stop(struct seq_file *m, void *v) | ||
339 | { | ||
340 | } | ||
341 | |||
342 | const struct seq_operations cpuinfo_op = { | ||
343 | .start = c_start, | ||
344 | .next = c_next, | ||
345 | .stop = c_stop, | ||
346 | .show = c_show | ||
347 | }; | ||
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c new file mode 100644 index 000000000000..8807ba2cf262 --- /dev/null +++ b/arch/arm64/kernel/signal.c | |||
@@ -0,0 +1,437 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/signal.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2009 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/errno.h> | ||
21 | #include <linux/signal.h> | ||
22 | #include <linux/personality.h> | ||
23 | #include <linux/freezer.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | #include <linux/tracehook.h> | ||
26 | #include <linux/ratelimit.h> | ||
27 | |||
28 | #include <asm/compat.h> | ||
29 | #include <asm/debug-monitors.h> | ||
30 | #include <asm/elf.h> | ||
31 | #include <asm/cacheflush.h> | ||
32 | #include <asm/ucontext.h> | ||
33 | #include <asm/unistd.h> | ||
34 | #include <asm/fpsimd.h> | ||
35 | #include <asm/signal32.h> | ||
36 | #include <asm/vdso.h> | ||
37 | |||
38 | /* | ||
39 | * Do a signal return; undo the signal stack. These are aligned to 128-bit. | ||
40 | */ | ||
41 | struct rt_sigframe { | ||
42 | struct siginfo info; | ||
43 | struct ucontext uc; | ||
44 | }; | ||
45 | |||
46 | static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) | ||
47 | { | ||
48 | struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state; | ||
49 | int err; | ||
50 | |||
51 | /* dump the hardware registers to the fpsimd_state structure */ | ||
52 | fpsimd_save_state(fpsimd); | ||
53 | |||
54 | /* copy the FP and status/control registers */ | ||
55 | err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs)); | ||
56 | __put_user_error(fpsimd->fpsr, &ctx->fpsr, err); | ||
57 | __put_user_error(fpsimd->fpcr, &ctx->fpcr, err); | ||
58 | |||
59 | /* copy the magic/size information */ | ||
60 | __put_user_error(FPSIMD_MAGIC, &ctx->head.magic, err); | ||
61 | __put_user_error(sizeof(struct fpsimd_context), &ctx->head.size, err); | ||
62 | |||
63 | return err ? -EFAULT : 0; | ||
64 | } | ||
65 | |||
66 | static int restore_fpsimd_context(struct fpsimd_context __user *ctx) | ||
67 | { | ||
68 | struct fpsimd_state fpsimd; | ||
69 | __u32 magic, size; | ||
70 | int err = 0; | ||
71 | |||
72 | /* check the magic/size information */ | ||
73 | __get_user_error(magic, &ctx->head.magic, err); | ||
74 | __get_user_error(size, &ctx->head.size, err); | ||
75 | if (err) | ||
76 | return -EFAULT; | ||
77 | if (magic != FPSIMD_MAGIC || size != sizeof(struct fpsimd_context)) | ||
78 | return -EINVAL; | ||
79 | |||
80 | /* copy the FP and status/control registers */ | ||
81 | err = __copy_from_user(fpsimd.vregs, ctx->vregs, | ||
82 | sizeof(fpsimd.vregs)); | ||
83 | __get_user_error(fpsimd.fpsr, &ctx->fpsr, err); | ||
84 | __get_user_error(fpsimd.fpcr, &ctx->fpcr, err); | ||
85 | |||
86 | /* load the hardware registers from the fpsimd_state structure */ | ||
87 | if (!err) { | ||
88 | preempt_disable(); | ||
89 | fpsimd_load_state(&fpsimd); | ||
90 | preempt_enable(); | ||
91 | } | ||
92 | |||
93 | return err ? -EFAULT : 0; | ||
94 | } | ||
95 | |||
96 | static int restore_sigframe(struct pt_regs *regs, | ||
97 | struct rt_sigframe __user *sf) | ||
98 | { | ||
99 | sigset_t set; | ||
100 | int i, err; | ||
101 | struct aux_context __user *aux = | ||
102 | (struct aux_context __user *)sf->uc.uc_mcontext.__reserved; | ||
103 | |||
104 | err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); | ||
105 | if (err == 0) | ||
106 | set_current_blocked(&set); | ||
107 | |||
108 | for (i = 0; i < 31; i++) | ||
109 | __get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i], | ||
110 | err); | ||
111 | __get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err); | ||
112 | __get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err); | ||
113 | __get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err); | ||
114 | |||
115 | /* | ||
116 | * Avoid sys_rt_sigreturn() restarting. | ||
117 | */ | ||
118 | regs->syscallno = ~0UL; | ||
119 | |||
120 | err |= !valid_user_regs(®s->user_regs); | ||
121 | |||
122 | if (err == 0) | ||
123 | err |= restore_fpsimd_context(&aux->fpsimd); | ||
124 | |||
125 | return err; | ||
126 | } | ||
127 | |||
128 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | ||
129 | { | ||
130 | struct rt_sigframe __user *frame; | ||
131 | |||
132 | /* Always make any pending restarted system calls return -EINTR */ | ||
133 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
134 | |||
135 | /* | ||
136 | * Since we stacked the signal on a 128-bit boundary, then 'sp' should | ||
137 | * be word aligned here. | ||
138 | */ | ||
139 | if (regs->sp & 15) | ||
140 | goto badframe; | ||
141 | |||
142 | frame = (struct rt_sigframe __user *)regs->sp; | ||
143 | |||
144 | if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) | ||
145 | goto badframe; | ||
146 | |||
147 | if (restore_sigframe(regs, frame)) | ||
148 | goto badframe; | ||
149 | |||
150 | if (do_sigaltstack(&frame->uc.uc_stack, | ||
151 | NULL, regs->sp) == -EFAULT) | ||
152 | goto badframe; | ||
153 | |||
154 | return regs->regs[0]; | ||
155 | |||
156 | badframe: | ||
157 | if (show_unhandled_signals) | ||
158 | pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n", | ||
159 | current->comm, task_pid_nr(current), __func__, | ||
160 | regs->pc, regs->sp); | ||
161 | force_sig(SIGSEGV, current); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | ||
166 | unsigned long sp) | ||
167 | { | ||
168 | return do_sigaltstack(uss, uoss, sp); | ||
169 | } | ||
170 | |||
171 | static int setup_sigframe(struct rt_sigframe __user *sf, | ||
172 | struct pt_regs *regs, sigset_t *set) | ||
173 | { | ||
174 | int i, err = 0; | ||
175 | struct aux_context __user *aux = | ||
176 | (struct aux_context __user *)sf->uc.uc_mcontext.__reserved; | ||
177 | |||
178 | for (i = 0; i < 31; i++) | ||
179 | __put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i], | ||
180 | err); | ||
181 | __put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err); | ||
182 | __put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err); | ||
183 | __put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err); | ||
184 | |||
185 | __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err); | ||
186 | |||
187 | err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); | ||
188 | |||
189 | if (err == 0) | ||
190 | err |= preserve_fpsimd_context(&aux->fpsimd); | ||
191 | |||
192 | /* set the "end" magic */ | ||
193 | __put_user_error(0, &aux->end.magic, err); | ||
194 | __put_user_error(0, &aux->end.size, err); | ||
195 | |||
196 | return err; | ||
197 | } | ||
198 | |||
199 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||
200 | int framesize) | ||
201 | { | ||
202 | unsigned long sp, sp_top; | ||
203 | void __user *frame; | ||
204 | |||
205 | sp = sp_top = regs->sp; | ||
206 | |||
207 | /* | ||
208 | * This is the X/Open sanctioned signal stack switching. | ||
209 | */ | ||
210 | if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) | ||
211 | sp = sp_top = current->sas_ss_sp + current->sas_ss_size; | ||
212 | |||
213 | /* room for stack frame (FP, LR) */ | ||
214 | sp -= 16; | ||
215 | |||
216 | sp = (sp - framesize) & ~15; | ||
217 | frame = (void __user *)sp; | ||
218 | |||
219 | /* | ||
220 | * Check that we can actually write to the signal frame. | ||
221 | */ | ||
222 | if (!access_ok(VERIFY_WRITE, frame, sp_top - sp)) | ||
223 | frame = NULL; | ||
224 | |||
225 | return frame; | ||
226 | } | ||
227 | |||
228 | static int setup_return(struct pt_regs *regs, struct k_sigaction *ka, | ||
229 | void __user *frame, int usig) | ||
230 | { | ||
231 | int err = 0; | ||
232 | __sigrestore_t sigtramp; | ||
233 | unsigned long __user *sp = (unsigned long __user *)regs->sp; | ||
234 | |||
235 | /* set up the stack frame */ | ||
236 | __put_user_error(regs->regs[29], sp - 2, err); | ||
237 | __put_user_error(regs->regs[30], sp - 1, err); | ||
238 | |||
239 | regs->regs[0] = usig; | ||
240 | regs->regs[29] = regs->sp - 16; | ||
241 | regs->sp = (unsigned long)frame; | ||
242 | regs->pc = (unsigned long)ka->sa.sa_handler; | ||
243 | |||
244 | if (ka->sa.sa_flags & SA_RESTORER) | ||
245 | sigtramp = ka->sa.sa_restorer; | ||
246 | else | ||
247 | sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); | ||
248 | |||
249 | regs->regs[30] = (unsigned long)sigtramp; | ||
250 | |||
251 | return err; | ||
252 | } | ||
253 | |||
254 | static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | ||
255 | sigset_t *set, struct pt_regs *regs) | ||
256 | { | ||
257 | struct rt_sigframe __user *frame; | ||
258 | stack_t stack; | ||
259 | int err = 0; | ||
260 | |||
261 | frame = get_sigframe(ka, regs, sizeof(*frame)); | ||
262 | if (!frame) | ||
263 | return 1; | ||
264 | |||
265 | __put_user_error(0, &frame->uc.uc_flags, err); | ||
266 | __put_user_error(NULL, &frame->uc.uc_link, err); | ||
267 | |||
268 | memset(&stack, 0, sizeof(stack)); | ||
269 | stack.ss_sp = (void __user *)current->sas_ss_sp; | ||
270 | stack.ss_flags = sas_ss_flags(regs->sp); | ||
271 | stack.ss_size = current->sas_ss_size; | ||
272 | err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack)); | ||
273 | |||
274 | err |= setup_sigframe(frame, regs, set); | ||
275 | if (err == 0) | ||
276 | err = setup_return(regs, ka, frame, usig); | ||
277 | |||
278 | if (err == 0 && ka->sa.sa_flags & SA_SIGINFO) { | ||
279 | err |= copy_siginfo_to_user(&frame->info, info); | ||
280 | regs->regs[1] = (unsigned long)&frame->info; | ||
281 | regs->regs[2] = (unsigned long)&frame->uc; | ||
282 | } | ||
283 | |||
284 | return err; | ||
285 | } | ||
286 | |||
287 | static void setup_restart_syscall(struct pt_regs *regs) | ||
288 | { | ||
289 | if (is_compat_task()) | ||
290 | compat_setup_restart_syscall(regs); | ||
291 | else | ||
292 | regs->regs[8] = __NR_restart_syscall; | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * OK, we're invoking a handler | ||
297 | */ | ||
298 | static void handle_signal(unsigned long sig, struct k_sigaction *ka, | ||
299 | siginfo_t *info, struct pt_regs *regs) | ||
300 | { | ||
301 | struct thread_info *thread = current_thread_info(); | ||
302 | struct task_struct *tsk = current; | ||
303 | sigset_t *oldset = sigmask_to_save(); | ||
304 | int usig = sig; | ||
305 | int ret; | ||
306 | |||
307 | /* | ||
308 | * translate the signal | ||
309 | */ | ||
310 | if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) | ||
311 | usig = thread->exec_domain->signal_invmap[usig]; | ||
312 | |||
313 | /* | ||
314 | * Set up the stack frame | ||
315 | */ | ||
316 | if (is_compat_task()) { | ||
317 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
318 | ret = compat_setup_rt_frame(usig, ka, info, oldset, | ||
319 | regs); | ||
320 | else | ||
321 | ret = compat_setup_frame(usig, ka, oldset, regs); | ||
322 | } else { | ||
323 | ret = setup_rt_frame(usig, ka, info, oldset, regs); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * Check that the resulting registers are actually sane. | ||
328 | */ | ||
329 | ret |= !valid_user_regs(®s->user_regs); | ||
330 | |||
331 | if (ret != 0) { | ||
332 | force_sigsegv(sig, tsk); | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | * Fast forward the stepping logic so we step into the signal | ||
338 | * handler. | ||
339 | */ | ||
340 | user_fastforward_single_step(tsk); | ||
341 | |||
342 | signal_delivered(sig, info, ka, regs, 0); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
347 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
348 | * mistake. | ||
349 | * | ||
350 | * Note that we go through the signals twice: once to check the signals that | ||
351 | * the kernel can handle, and then we build all the user-level signal handling | ||
352 | * stack-frames in one go after that. | ||
353 | */ | ||
354 | static void do_signal(struct pt_regs *regs) | ||
355 | { | ||
356 | unsigned long continue_addr = 0, restart_addr = 0; | ||
357 | struct k_sigaction ka; | ||
358 | siginfo_t info; | ||
359 | int signr, retval = 0; | ||
360 | int syscall = (int)regs->syscallno; | ||
361 | |||
362 | /* | ||
363 | * If we were from a system call, check for system call restarting... | ||
364 | */ | ||
365 | if (syscall >= 0) { | ||
366 | continue_addr = regs->pc; | ||
367 | restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4); | ||
368 | retval = regs->regs[0]; | ||
369 | |||
370 | /* | ||
371 | * Avoid additional syscall restarting via ret_to_user. | ||
372 | */ | ||
373 | regs->syscallno = ~0UL; | ||
374 | |||
375 | /* | ||
376 | * Prepare for system call restart. We do this here so that a | ||
377 | * debugger will see the already changed PC. | ||
378 | */ | ||
379 | switch (retval) { | ||
380 | case -ERESTARTNOHAND: | ||
381 | case -ERESTARTSYS: | ||
382 | case -ERESTARTNOINTR: | ||
383 | case -ERESTART_RESTARTBLOCK: | ||
384 | regs->regs[0] = regs->orig_x0; | ||
385 | regs->pc = restart_addr; | ||
386 | break; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * Get the signal to deliver. When running under ptrace, at this point | ||
392 | * the debugger may change all of our registers. | ||
393 | */ | ||
394 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
395 | if (signr > 0) { | ||
396 | /* | ||
397 | * Depending on the signal settings, we may need to revert the | ||
398 | * decision to restart the system call, but skip this if a | ||
399 | * debugger has chosen to restart at a different PC. | ||
400 | */ | ||
401 | if (regs->pc == restart_addr && | ||
402 | (retval == -ERESTARTNOHAND || | ||
403 | retval == -ERESTART_RESTARTBLOCK || | ||
404 | (retval == -ERESTARTSYS && | ||
405 | !(ka.sa.sa_flags & SA_RESTART)))) { | ||
406 | regs->regs[0] = -EINTR; | ||
407 | regs->pc = continue_addr; | ||
408 | } | ||
409 | |||
410 | handle_signal(signr, &ka, &info, regs); | ||
411 | return; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Handle restarting a different system call. As above, if a debugger | ||
416 | * has chosen to restart at a different PC, ignore the restart. | ||
417 | */ | ||
418 | if (syscall >= 0 && regs->pc == restart_addr) { | ||
419 | if (retval == -ERESTART_RESTARTBLOCK) | ||
420 | setup_restart_syscall(regs); | ||
421 | user_rewind_single_step(current); | ||
422 | } | ||
423 | |||
424 | restore_saved_sigmask(); | ||
425 | } | ||
426 | |||
427 | asmlinkage void do_notify_resume(struct pt_regs *regs, | ||
428 | unsigned int thread_flags) | ||
429 | { | ||
430 | if (thread_flags & _TIF_SIGPENDING) | ||
431 | do_signal(regs); | ||
432 | |||
433 | if (thread_flags & _TIF_NOTIFY_RESUME) { | ||
434 | clear_thread_flag(TIF_NOTIFY_RESUME); | ||
435 | tracehook_notify_resume(regs); | ||
436 | } | ||
437 | } | ||
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c new file mode 100644 index 000000000000..ac74c2f261e3 --- /dev/null +++ b/arch/arm64/kernel/signal32.c | |||
@@ -0,0 +1,876 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/signal.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2009 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * Modified by Will Deacon <will.deacon@arm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #define __SYSCALL_COMPAT | ||
22 | |||
23 | #include <linux/compat.h> | ||
24 | #include <linux/signal.h> | ||
25 | #include <linux/syscalls.h> | ||
26 | #include <linux/ratelimit.h> | ||
27 | |||
28 | #include <asm/fpsimd.h> | ||
29 | #include <asm/signal32.h> | ||
30 | #include <asm/uaccess.h> | ||
31 | #include <asm/unistd.h> | ||
32 | |||
33 | typedef struct compat_siginfo { | ||
34 | int si_signo; | ||
35 | int si_errno; | ||
36 | int si_code; | ||
37 | |||
38 | union { | ||
39 | /* The padding is the same size as AArch64. */ | ||
40 | int _pad[SI_PAD_SIZE]; | ||
41 | |||
42 | /* kill() */ | ||
43 | struct { | ||
44 | compat_pid_t _pid; /* sender's pid */ | ||
45 | __compat_uid32_t _uid; /* sender's uid */ | ||
46 | } _kill; | ||
47 | |||
48 | /* POSIX.1b timers */ | ||
49 | struct { | ||
50 | compat_timer_t _tid; /* timer id */ | ||
51 | int _overrun; /* overrun count */ | ||
52 | compat_sigval_t _sigval; /* same as below */ | ||
53 | int _sys_private; /* not to be passed to user */ | ||
54 | } _timer; | ||
55 | |||
56 | /* POSIX.1b signals */ | ||
57 | struct { | ||
58 | compat_pid_t _pid; /* sender's pid */ | ||
59 | __compat_uid32_t _uid; /* sender's uid */ | ||
60 | compat_sigval_t _sigval; | ||
61 | } _rt; | ||
62 | |||
63 | /* SIGCHLD */ | ||
64 | struct { | ||
65 | compat_pid_t _pid; /* which child */ | ||
66 | __compat_uid32_t _uid; /* sender's uid */ | ||
67 | int _status; /* exit code */ | ||
68 | compat_clock_t _utime; | ||
69 | compat_clock_t _stime; | ||
70 | } _sigchld; | ||
71 | |||
72 | /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ | ||
73 | struct { | ||
74 | compat_uptr_t _addr; /* faulting insn/memory ref. */ | ||
75 | short _addr_lsb; /* LSB of the reported address */ | ||
76 | } _sigfault; | ||
77 | |||
78 | /* SIGPOLL */ | ||
79 | struct { | ||
80 | compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */ | ||
81 | int _fd; | ||
82 | } _sigpoll; | ||
83 | } _sifields; | ||
84 | } compat_siginfo_t; | ||
85 | |||
86 | struct compat_sigaction { | ||
87 | compat_uptr_t sa_handler; | ||
88 | compat_ulong_t sa_flags; | ||
89 | compat_uptr_t sa_restorer; | ||
90 | compat_sigset_t sa_mask; | ||
91 | }; | ||
92 | |||
93 | struct compat_old_sigaction { | ||
94 | compat_uptr_t sa_handler; | ||
95 | compat_old_sigset_t sa_mask; | ||
96 | compat_ulong_t sa_flags; | ||
97 | compat_uptr_t sa_restorer; | ||
98 | }; | ||
99 | |||
100 | typedef struct compat_sigaltstack { | ||
101 | compat_uptr_t ss_sp; | ||
102 | int ss_flags; | ||
103 | compat_size_t ss_size; | ||
104 | } compat_stack_t; | ||
105 | |||
106 | struct compat_sigcontext { | ||
107 | /* We always set these two fields to 0 */ | ||
108 | compat_ulong_t trap_no; | ||
109 | compat_ulong_t error_code; | ||
110 | |||
111 | compat_ulong_t oldmask; | ||
112 | compat_ulong_t arm_r0; | ||
113 | compat_ulong_t arm_r1; | ||
114 | compat_ulong_t arm_r2; | ||
115 | compat_ulong_t arm_r3; | ||
116 | compat_ulong_t arm_r4; | ||
117 | compat_ulong_t arm_r5; | ||
118 | compat_ulong_t arm_r6; | ||
119 | compat_ulong_t arm_r7; | ||
120 | compat_ulong_t arm_r8; | ||
121 | compat_ulong_t arm_r9; | ||
122 | compat_ulong_t arm_r10; | ||
123 | compat_ulong_t arm_fp; | ||
124 | compat_ulong_t arm_ip; | ||
125 | compat_ulong_t arm_sp; | ||
126 | compat_ulong_t arm_lr; | ||
127 | compat_ulong_t arm_pc; | ||
128 | compat_ulong_t arm_cpsr; | ||
129 | compat_ulong_t fault_address; | ||
130 | }; | ||
131 | |||
132 | struct compat_ucontext { | ||
133 | compat_ulong_t uc_flags; | ||
134 | struct compat_ucontext *uc_link; | ||
135 | compat_stack_t uc_stack; | ||
136 | struct compat_sigcontext uc_mcontext; | ||
137 | compat_sigset_t uc_sigmask; | ||
138 | int __unused[32 - (sizeof (compat_sigset_t) / sizeof (int))]; | ||
139 | compat_ulong_t uc_regspace[128] __attribute__((__aligned__(8))); | ||
140 | }; | ||
141 | |||
142 | struct compat_vfp_sigframe { | ||
143 | compat_ulong_t magic; | ||
144 | compat_ulong_t size; | ||
145 | struct compat_user_vfp { | ||
146 | compat_u64 fpregs[32]; | ||
147 | compat_ulong_t fpscr; | ||
148 | } ufp; | ||
149 | struct compat_user_vfp_exc { | ||
150 | compat_ulong_t fpexc; | ||
151 | compat_ulong_t fpinst; | ||
152 | compat_ulong_t fpinst2; | ||
153 | } ufp_exc; | ||
154 | } __attribute__((__aligned__(8))); | ||
155 | |||
156 | #define VFP_MAGIC 0x56465001 | ||
157 | #define VFP_STORAGE_SIZE sizeof(struct compat_vfp_sigframe) | ||
158 | |||
159 | struct compat_aux_sigframe { | ||
160 | struct compat_vfp_sigframe vfp; | ||
161 | |||
162 | /* Something that isn't a valid magic number for any coprocessor. */ | ||
163 | unsigned long end_magic; | ||
164 | } __attribute__((__aligned__(8))); | ||
165 | |||
166 | struct compat_sigframe { | ||
167 | struct compat_ucontext uc; | ||
168 | compat_ulong_t retcode[2]; | ||
169 | }; | ||
170 | |||
171 | struct compat_rt_sigframe { | ||
172 | struct compat_siginfo info; | ||
173 | struct compat_sigframe sig; | ||
174 | }; | ||
175 | |||
176 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
177 | |||
178 | /* | ||
179 | * For ARM syscalls, the syscall number has to be loaded into r7. | ||
180 | * We do not support an OABI userspace. | ||
181 | */ | ||
182 | #define MOV_R7_NR_SIGRETURN (0xe3a07000 | __NR_sigreturn) | ||
183 | #define SVC_SYS_SIGRETURN (0xef000000 | __NR_sigreturn) | ||
184 | #define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | __NR_rt_sigreturn) | ||
185 | #define SVC_SYS_RT_SIGRETURN (0xef000000 | __NR_rt_sigreturn) | ||
186 | |||
187 | /* | ||
188 | * For Thumb syscalls, we also pass the syscall number via r7. We therefore | ||
189 | * need two 16-bit instructions. | ||
190 | */ | ||
191 | #define SVC_THUMB_SIGRETURN (((0xdf00 | __NR_sigreturn) << 16) | \ | ||
192 | 0x2700 | __NR_sigreturn) | ||
193 | #define SVC_THUMB_RT_SIGRETURN (((0xdf00 | __NR_rt_sigreturn) << 16) | \ | ||
194 | 0x2700 | __NR_rt_sigreturn) | ||
195 | |||
196 | const compat_ulong_t aarch32_sigret_code[6] = { | ||
197 | /* | ||
198 | * AArch32 sigreturn code. | ||
199 | * We don't construct an OABI SWI - instead we just set the imm24 field | ||
200 | * to the EABI syscall number so that we create a sane disassembly. | ||
201 | */ | ||
202 | MOV_R7_NR_SIGRETURN, SVC_SYS_SIGRETURN, SVC_THUMB_SIGRETURN, | ||
203 | MOV_R7_NR_RT_SIGRETURN, SVC_SYS_RT_SIGRETURN, SVC_THUMB_RT_SIGRETURN, | ||
204 | }; | ||
205 | |||
206 | static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set) | ||
207 | { | ||
208 | compat_sigset_t cset; | ||
209 | |||
210 | cset.sig[0] = set->sig[0] & 0xffffffffull; | ||
211 | cset.sig[1] = set->sig[0] >> 32; | ||
212 | |||
213 | return copy_to_user(uset, &cset, sizeof(*uset)); | ||
214 | } | ||
215 | |||
216 | static inline int get_sigset_t(sigset_t *set, | ||
217 | const compat_sigset_t __user *uset) | ||
218 | { | ||
219 | compat_sigset_t s32; | ||
220 | |||
221 | if (copy_from_user(&s32, uset, sizeof(*uset))) | ||
222 | return -EFAULT; | ||
223 | |||
224 | set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) | ||
229 | { | ||
230 | int err; | ||
231 | |||
232 | if (!access_ok(VERIFY_WRITE, to, sizeof(*to))) | ||
233 | return -EFAULT; | ||
234 | |||
235 | /* If you change siginfo_t structure, please be sure | ||
236 | * this code is fixed accordingly. | ||
237 | * It should never copy any pad contained in the structure | ||
238 | * to avoid security leaks, but must copy the generic | ||
239 | * 3 ints plus the relevant union member. | ||
240 | * This routine must convert siginfo from 64bit to 32bit as well | ||
241 | * at the same time. | ||
242 | */ | ||
243 | err = __put_user(from->si_signo, &to->si_signo); | ||
244 | err |= __put_user(from->si_errno, &to->si_errno); | ||
245 | err |= __put_user((short)from->si_code, &to->si_code); | ||
246 | if (from->si_code < 0) | ||
247 | err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, | ||
248 | SI_PAD_SIZE); | ||
249 | else switch (from->si_code & __SI_MASK) { | ||
250 | case __SI_KILL: | ||
251 | err |= __put_user(from->si_pid, &to->si_pid); | ||
252 | err |= __put_user(from->si_uid, &to->si_uid); | ||
253 | break; | ||
254 | case __SI_TIMER: | ||
255 | err |= __put_user(from->si_tid, &to->si_tid); | ||
256 | err |= __put_user(from->si_overrun, &to->si_overrun); | ||
257 | err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, | ||
258 | &to->si_ptr); | ||
259 | break; | ||
260 | case __SI_POLL: | ||
261 | err |= __put_user(from->si_band, &to->si_band); | ||
262 | err |= __put_user(from->si_fd, &to->si_fd); | ||
263 | break; | ||
264 | case __SI_FAULT: | ||
265 | err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr, | ||
266 | &to->si_addr); | ||
267 | #ifdef BUS_MCEERR_AO | ||
268 | /* | ||
269 | * Other callers might not initialize the si_lsb field, | ||
270 | * so check explicitely for the right codes here. | ||
271 | */ | ||
272 | if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) | ||
273 | err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); | ||
274 | #endif | ||
275 | break; | ||
276 | case __SI_CHLD: | ||
277 | err |= __put_user(from->si_pid, &to->si_pid); | ||
278 | err |= __put_user(from->si_uid, &to->si_uid); | ||
279 | err |= __put_user(from->si_status, &to->si_status); | ||
280 | err |= __put_user(from->si_utime, &to->si_utime); | ||
281 | err |= __put_user(from->si_stime, &to->si_stime); | ||
282 | break; | ||
283 | case __SI_RT: /* This is not generated by the kernel as of now. */ | ||
284 | case __SI_MESGQ: /* But this is */ | ||
285 | err |= __put_user(from->si_pid, &to->si_pid); | ||
286 | err |= __put_user(from->si_uid, &to->si_uid); | ||
287 | err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, &to->si_ptr); | ||
288 | break; | ||
289 | default: /* this is just in case for now ... */ | ||
290 | err |= __put_user(from->si_pid, &to->si_pid); | ||
291 | err |= __put_user(from->si_uid, &to->si_uid); | ||
292 | break; | ||
293 | } | ||
294 | return err; | ||
295 | } | ||
296 | |||
297 | int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | ||
298 | { | ||
299 | memset(to, 0, sizeof *to); | ||
300 | |||
301 | if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) || | ||
302 | copy_from_user(to->_sifields._pad, | ||
303 | from->_sifields._pad, SI_PAD_SIZE)) | ||
304 | return -EFAULT; | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * VFP save/restore code. | ||
311 | */ | ||
312 | static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame) | ||
313 | { | ||
314 | struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state; | ||
315 | compat_ulong_t magic = VFP_MAGIC; | ||
316 | compat_ulong_t size = VFP_STORAGE_SIZE; | ||
317 | compat_ulong_t fpscr, fpexc; | ||
318 | int err = 0; | ||
319 | |||
320 | /* | ||
321 | * Save the hardware registers to the fpsimd_state structure. | ||
322 | * Note that this also saves V16-31, which aren't visible | ||
323 | * in AArch32. | ||
324 | */ | ||
325 | fpsimd_save_state(fpsimd); | ||
326 | |||
327 | /* Place structure header on the stack */ | ||
328 | __put_user_error(magic, &frame->magic, err); | ||
329 | __put_user_error(size, &frame->size, err); | ||
330 | |||
331 | /* | ||
332 | * Now copy the FP registers. Since the registers are packed, | ||
333 | * we can copy the prefix we want (V0-V15) as it is. | ||
334 | * FIXME: Won't work if big endian. | ||
335 | */ | ||
336 | err |= __copy_to_user(&frame->ufp.fpregs, fpsimd->vregs, | ||
337 | sizeof(frame->ufp.fpregs)); | ||
338 | |||
339 | /* Create an AArch32 fpscr from the fpsr and the fpcr. */ | ||
340 | fpscr = (fpsimd->fpsr & VFP_FPSCR_STAT_MASK) | | ||
341 | (fpsimd->fpcr & VFP_FPSCR_CTRL_MASK); | ||
342 | __put_user_error(fpscr, &frame->ufp.fpscr, err); | ||
343 | |||
344 | /* | ||
345 | * The exception register aren't available so we fake up a | ||
346 | * basic FPEXC and zero everything else. | ||
347 | */ | ||
348 | fpexc = (1 << 30); | ||
349 | __put_user_error(fpexc, &frame->ufp_exc.fpexc, err); | ||
350 | __put_user_error(0, &frame->ufp_exc.fpinst, err); | ||
351 | __put_user_error(0, &frame->ufp_exc.fpinst2, err); | ||
352 | |||
353 | return err ? -EFAULT : 0; | ||
354 | } | ||
355 | |||
356 | static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame) | ||
357 | { | ||
358 | struct fpsimd_state fpsimd; | ||
359 | compat_ulong_t magic = VFP_MAGIC; | ||
360 | compat_ulong_t size = VFP_STORAGE_SIZE; | ||
361 | compat_ulong_t fpscr; | ||
362 | int err = 0; | ||
363 | |||
364 | __get_user_error(magic, &frame->magic, err); | ||
365 | __get_user_error(size, &frame->size, err); | ||
366 | |||
367 | if (err) | ||
368 | return -EFAULT; | ||
369 | if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) | ||
370 | return -EINVAL; | ||
371 | |||
372 | /* | ||
373 | * Copy the FP registers into the start of the fpsimd_state. | ||
374 | * FIXME: Won't work if big endian. | ||
375 | */ | ||
376 | err |= __copy_from_user(fpsimd.vregs, frame->ufp.fpregs, | ||
377 | sizeof(frame->ufp.fpregs)); | ||
378 | |||
379 | /* Extract the fpsr and the fpcr from the fpscr */ | ||
380 | __get_user_error(fpscr, &frame->ufp.fpscr, err); | ||
381 | fpsimd.fpsr = fpscr & VFP_FPSCR_STAT_MASK; | ||
382 | fpsimd.fpcr = fpscr & VFP_FPSCR_CTRL_MASK; | ||
383 | |||
384 | /* | ||
385 | * We don't need to touch the exception register, so | ||
386 | * reload the hardware state. | ||
387 | */ | ||
388 | if (!err) { | ||
389 | preempt_disable(); | ||
390 | fpsimd_load_state(&fpsimd); | ||
391 | preempt_enable(); | ||
392 | } | ||
393 | |||
394 | return err ? -EFAULT : 0; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * atomically swap in the new signal mask, and wait for a signal. | ||
399 | */ | ||
400 | asmlinkage int compat_sys_sigsuspend(int restart, compat_ulong_t oldmask, | ||
401 | compat_old_sigset_t mask) | ||
402 | { | ||
403 | sigset_t blocked; | ||
404 | |||
405 | siginitset(¤t->blocked, mask); | ||
406 | return sigsuspend(&blocked); | ||
407 | } | ||
408 | |||
409 | asmlinkage int compat_sys_sigaction(int sig, | ||
410 | const struct compat_old_sigaction __user *act, | ||
411 | struct compat_old_sigaction __user *oact) | ||
412 | { | ||
413 | struct k_sigaction new_ka, old_ka; | ||
414 | int ret; | ||
415 | compat_old_sigset_t mask; | ||
416 | compat_uptr_t handler, restorer; | ||
417 | |||
418 | if (act) { | ||
419 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
420 | __get_user(handler, &act->sa_handler) || | ||
421 | __get_user(restorer, &act->sa_restorer) || | ||
422 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
423 | __get_user(mask, &act->sa_mask)) | ||
424 | return -EFAULT; | ||
425 | |||
426 | new_ka.sa.sa_handler = compat_ptr(handler); | ||
427 | new_ka.sa.sa_restorer = compat_ptr(restorer); | ||
428 | siginitset(&new_ka.sa.sa_mask, mask); | ||
429 | } | ||
430 | |||
431 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
432 | |||
433 | if (!ret && oact) { | ||
434 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
435 | __put_user(ptr_to_compat(old_ka.sa.sa_handler), | ||
436 | &oact->sa_handler) || | ||
437 | __put_user(ptr_to_compat(old_ka.sa.sa_restorer), | ||
438 | &oact->sa_restorer) || | ||
439 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
440 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
441 | return -EFAULT; | ||
442 | } | ||
443 | |||
444 | return ret; | ||
445 | } | ||
446 | |||
447 | asmlinkage int compat_sys_rt_sigaction(int sig, | ||
448 | const struct compat_sigaction __user *act, | ||
449 | struct compat_sigaction __user *oact, | ||
450 | compat_size_t sigsetsize) | ||
451 | { | ||
452 | struct k_sigaction new_ka, old_ka; | ||
453 | int ret; | ||
454 | |||
455 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
456 | if (sigsetsize != sizeof(compat_sigset_t)) | ||
457 | return -EINVAL; | ||
458 | |||
459 | if (act) { | ||
460 | compat_uptr_t handler, restorer; | ||
461 | |||
462 | ret = get_user(handler, &act->sa_handler); | ||
463 | new_ka.sa.sa_handler = compat_ptr(handler); | ||
464 | ret |= get_user(restorer, &act->sa_restorer); | ||
465 | new_ka.sa.sa_restorer = compat_ptr(restorer); | ||
466 | ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask); | ||
467 | ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
468 | if (ret) | ||
469 | return -EFAULT; | ||
470 | } | ||
471 | |||
472 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
473 | if (!ret && oact) { | ||
474 | ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); | ||
475 | ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask); | ||
476 | ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
477 | } | ||
478 | return ret; | ||
479 | } | ||
480 | |||
481 | int compat_do_sigaltstack(compat_uptr_t compat_uss, compat_uptr_t compat_uoss, | ||
482 | compat_ulong_t sp) | ||
483 | { | ||
484 | compat_stack_t __user *newstack = compat_ptr(compat_uss); | ||
485 | compat_stack_t __user *oldstack = compat_ptr(compat_uoss); | ||
486 | compat_uptr_t ss_sp; | ||
487 | int ret; | ||
488 | mm_segment_t old_fs; | ||
489 | stack_t uss, uoss; | ||
490 | |||
491 | /* Marshall the compat new stack into a stack_t */ | ||
492 | if (newstack) { | ||
493 | if (get_user(ss_sp, &newstack->ss_sp) || | ||
494 | __get_user(uss.ss_flags, &newstack->ss_flags) || | ||
495 | __get_user(uss.ss_size, &newstack->ss_size)) | ||
496 | return -EFAULT; | ||
497 | uss.ss_sp = compat_ptr(ss_sp); | ||
498 | } | ||
499 | |||
500 | old_fs = get_fs(); | ||
501 | set_fs(KERNEL_DS); | ||
502 | /* The __user pointer casts are valid because of the set_fs() */ | ||
503 | ret = do_sigaltstack( | ||
504 | newstack ? (stack_t __user *) &uss : NULL, | ||
505 | oldstack ? (stack_t __user *) &uoss : NULL, | ||
506 | (unsigned long)sp); | ||
507 | set_fs(old_fs); | ||
508 | |||
509 | /* Convert the old stack_t into a compat stack. */ | ||
510 | if (!ret && oldstack && | ||
511 | (put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) || | ||
512 | __put_user(uoss.ss_flags, &oldstack->ss_flags) || | ||
513 | __put_user(uoss.ss_size, &oldstack->ss_size))) | ||
514 | return -EFAULT; | ||
515 | return ret; | ||
516 | } | ||
517 | |||
518 | static int compat_restore_sigframe(struct pt_regs *regs, | ||
519 | struct compat_sigframe __user *sf) | ||
520 | { | ||
521 | int err; | ||
522 | sigset_t set; | ||
523 | struct compat_aux_sigframe __user *aux; | ||
524 | |||
525 | err = get_sigset_t(&set, &sf->uc.uc_sigmask); | ||
526 | if (err == 0) { | ||
527 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
528 | set_current_blocked(&set); | ||
529 | } | ||
530 | |||
531 | __get_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err); | ||
532 | __get_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err); | ||
533 | __get_user_error(regs->regs[2], &sf->uc.uc_mcontext.arm_r2, err); | ||
534 | __get_user_error(regs->regs[3], &sf->uc.uc_mcontext.arm_r3, err); | ||
535 | __get_user_error(regs->regs[4], &sf->uc.uc_mcontext.arm_r4, err); | ||
536 | __get_user_error(regs->regs[5], &sf->uc.uc_mcontext.arm_r5, err); | ||
537 | __get_user_error(regs->regs[6], &sf->uc.uc_mcontext.arm_r6, err); | ||
538 | __get_user_error(regs->regs[7], &sf->uc.uc_mcontext.arm_r7, err); | ||
539 | __get_user_error(regs->regs[8], &sf->uc.uc_mcontext.arm_r8, err); | ||
540 | __get_user_error(regs->regs[9], &sf->uc.uc_mcontext.arm_r9, err); | ||
541 | __get_user_error(regs->regs[10], &sf->uc.uc_mcontext.arm_r10, err); | ||
542 | __get_user_error(regs->regs[11], &sf->uc.uc_mcontext.arm_fp, err); | ||
543 | __get_user_error(regs->regs[12], &sf->uc.uc_mcontext.arm_ip, err); | ||
544 | __get_user_error(regs->compat_sp, &sf->uc.uc_mcontext.arm_sp, err); | ||
545 | __get_user_error(regs->compat_lr, &sf->uc.uc_mcontext.arm_lr, err); | ||
546 | __get_user_error(regs->pc, &sf->uc.uc_mcontext.arm_pc, err); | ||
547 | __get_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err); | ||
548 | |||
549 | /* | ||
550 | * Avoid compat_sys_sigreturn() restarting. | ||
551 | */ | ||
552 | regs->syscallno = ~0UL; | ||
553 | |||
554 | err |= !valid_user_regs(®s->user_regs); | ||
555 | |||
556 | aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace; | ||
557 | if (err == 0) | ||
558 | err |= compat_restore_vfp_context(&aux->vfp); | ||
559 | |||
560 | return err; | ||
561 | } | ||
562 | |||
563 | asmlinkage int compat_sys_sigreturn(struct pt_regs *regs) | ||
564 | { | ||
565 | struct compat_sigframe __user *frame; | ||
566 | |||
567 | /* Always make any pending restarted system calls return -EINTR */ | ||
568 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
569 | |||
570 | /* | ||
571 | * Since we stacked the signal on a 64-bit boundary, | ||
572 | * then 'sp' should be word aligned here. If it's | ||
573 | * not, then the user is trying to mess with us. | ||
574 | */ | ||
575 | if (regs->compat_sp & 7) | ||
576 | goto badframe; | ||
577 | |||
578 | frame = (struct compat_sigframe __user *)regs->compat_sp; | ||
579 | |||
580 | if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) | ||
581 | goto badframe; | ||
582 | |||
583 | if (compat_restore_sigframe(regs, frame)) | ||
584 | goto badframe; | ||
585 | |||
586 | return regs->regs[0]; | ||
587 | |||
588 | badframe: | ||
589 | if (show_unhandled_signals) | ||
590 | pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n", | ||
591 | current->comm, task_pid_nr(current), __func__, | ||
592 | regs->pc, regs->sp); | ||
593 | force_sig(SIGSEGV, current); | ||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs) | ||
598 | { | ||
599 | struct compat_rt_sigframe __user *frame; | ||
600 | |||
601 | /* Always make any pending restarted system calls return -EINTR */ | ||
602 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
603 | |||
604 | /* | ||
605 | * Since we stacked the signal on a 64-bit boundary, | ||
606 | * then 'sp' should be word aligned here. If it's | ||
607 | * not, then the user is trying to mess with us. | ||
608 | */ | ||
609 | if (regs->compat_sp & 7) | ||
610 | goto badframe; | ||
611 | |||
612 | frame = (struct compat_rt_sigframe __user *)regs->compat_sp; | ||
613 | |||
614 | if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) | ||
615 | goto badframe; | ||
616 | |||
617 | if (compat_restore_sigframe(regs, &frame->sig)) | ||
618 | goto badframe; | ||
619 | |||
620 | if (compat_do_sigaltstack(ptr_to_compat(&frame->sig.uc.uc_stack), | ||
621 | ptr_to_compat((void __user *)NULL), | ||
622 | regs->compat_sp) == -EFAULT) | ||
623 | goto badframe; | ||
624 | |||
625 | return regs->regs[0]; | ||
626 | |||
627 | badframe: | ||
628 | if (show_unhandled_signals) | ||
629 | pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n", | ||
630 | current->comm, task_pid_nr(current), __func__, | ||
631 | regs->pc, regs->sp); | ||
632 | force_sig(SIGSEGV, current); | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | static inline void __user *compat_get_sigframe(struct k_sigaction *ka, | ||
637 | struct pt_regs *regs, | ||
638 | int framesize) | ||
639 | { | ||
640 | compat_ulong_t sp = regs->compat_sp; | ||
641 | void __user *frame; | ||
642 | |||
643 | /* | ||
644 | * This is the X/Open sanctioned signal stack switching. | ||
645 | */ | ||
646 | if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) | ||
647 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
648 | |||
649 | /* | ||
650 | * ATPCS B01 mandates 8-byte alignment | ||
651 | */ | ||
652 | frame = compat_ptr((compat_uptr_t)((sp - framesize) & ~7)); | ||
653 | |||
654 | /* | ||
655 | * Check that we can actually write to the signal frame. | ||
656 | */ | ||
657 | if (!access_ok(VERIFY_WRITE, frame, framesize)) | ||
658 | frame = NULL; | ||
659 | |||
660 | return frame; | ||
661 | } | ||
662 | |||
663 | static int compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka, | ||
664 | compat_ulong_t __user *rc, void __user *frame, | ||
665 | int usig) | ||
666 | { | ||
667 | compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler); | ||
668 | compat_ulong_t retcode; | ||
669 | compat_ulong_t spsr = regs->pstate & ~PSR_f; | ||
670 | int thumb; | ||
671 | |||
672 | /* Check if the handler is written for ARM or Thumb */ | ||
673 | thumb = handler & 1; | ||
674 | |||
675 | if (thumb) { | ||
676 | spsr |= COMPAT_PSR_T_BIT; | ||
677 | spsr &= ~COMPAT_PSR_IT_MASK; | ||
678 | } else { | ||
679 | spsr &= ~COMPAT_PSR_T_BIT; | ||
680 | } | ||
681 | |||
682 | if (ka->sa.sa_flags & SA_RESTORER) { | ||
683 | retcode = ptr_to_compat(ka->sa.sa_restorer); | ||
684 | } else { | ||
685 | /* Set up sigreturn pointer */ | ||
686 | unsigned int idx = thumb << 1; | ||
687 | |||
688 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
689 | idx += 3; | ||
690 | |||
691 | retcode = AARCH32_VECTORS_BASE + | ||
692 | AARCH32_KERN_SIGRET_CODE_OFFSET + | ||
693 | (idx << 2) + thumb; | ||
694 | } | ||
695 | |||
696 | regs->regs[0] = usig; | ||
697 | regs->compat_sp = ptr_to_compat(frame); | ||
698 | regs->compat_lr = retcode; | ||
699 | regs->pc = handler; | ||
700 | regs->pstate = spsr; | ||
701 | |||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | static int compat_setup_sigframe(struct compat_sigframe __user *sf, | ||
706 | struct pt_regs *regs, sigset_t *set) | ||
707 | { | ||
708 | struct compat_aux_sigframe __user *aux; | ||
709 | int err = 0; | ||
710 | |||
711 | __put_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err); | ||
712 | __put_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err); | ||
713 | __put_user_error(regs->regs[2], &sf->uc.uc_mcontext.arm_r2, err); | ||
714 | __put_user_error(regs->regs[3], &sf->uc.uc_mcontext.arm_r3, err); | ||
715 | __put_user_error(regs->regs[4], &sf->uc.uc_mcontext.arm_r4, err); | ||
716 | __put_user_error(regs->regs[5], &sf->uc.uc_mcontext.arm_r5, err); | ||
717 | __put_user_error(regs->regs[6], &sf->uc.uc_mcontext.arm_r6, err); | ||
718 | __put_user_error(regs->regs[7], &sf->uc.uc_mcontext.arm_r7, err); | ||
719 | __put_user_error(regs->regs[8], &sf->uc.uc_mcontext.arm_r8, err); | ||
720 | __put_user_error(regs->regs[9], &sf->uc.uc_mcontext.arm_r9, err); | ||
721 | __put_user_error(regs->regs[10], &sf->uc.uc_mcontext.arm_r10, err); | ||
722 | __put_user_error(regs->regs[11], &sf->uc.uc_mcontext.arm_fp, err); | ||
723 | __put_user_error(regs->regs[12], &sf->uc.uc_mcontext.arm_ip, err); | ||
724 | __put_user_error(regs->compat_sp, &sf->uc.uc_mcontext.arm_sp, err); | ||
725 | __put_user_error(regs->compat_lr, &sf->uc.uc_mcontext.arm_lr, err); | ||
726 | __put_user_error(regs->pc, &sf->uc.uc_mcontext.arm_pc, err); | ||
727 | __put_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err); | ||
728 | |||
729 | __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.trap_no, err); | ||
730 | __put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.error_code, err); | ||
731 | __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err); | ||
732 | __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err); | ||
733 | |||
734 | err |= put_sigset_t(&sf->uc.uc_sigmask, set); | ||
735 | |||
736 | aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace; | ||
737 | |||
738 | if (err == 0) | ||
739 | err |= compat_preserve_vfp_context(&aux->vfp); | ||
740 | __put_user_error(0, &aux->end_magic, err); | ||
741 | |||
742 | return err; | ||
743 | } | ||
744 | |||
745 | /* | ||
746 | * 32-bit signal handling routines called from signal.c | ||
747 | */ | ||
748 | int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | ||
749 | sigset_t *set, struct pt_regs *regs) | ||
750 | { | ||
751 | struct compat_rt_sigframe __user *frame; | ||
752 | compat_stack_t stack; | ||
753 | int err = 0; | ||
754 | |||
755 | frame = compat_get_sigframe(ka, regs, sizeof(*frame)); | ||
756 | |||
757 | if (!frame) | ||
758 | return 1; | ||
759 | |||
760 | err |= copy_siginfo_to_user32(&frame->info, info); | ||
761 | |||
762 | __put_user_error(0, &frame->sig.uc.uc_flags, err); | ||
763 | __put_user_error(NULL, &frame->sig.uc.uc_link, err); | ||
764 | |||
765 | memset(&stack, 0, sizeof(stack)); | ||
766 | stack.ss_sp = (compat_uptr_t)current->sas_ss_sp; | ||
767 | stack.ss_flags = sas_ss_flags(regs->compat_sp); | ||
768 | stack.ss_size = current->sas_ss_size; | ||
769 | err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack)); | ||
770 | |||
771 | err |= compat_setup_sigframe(&frame->sig, regs, set); | ||
772 | if (err == 0) | ||
773 | err = compat_setup_return(regs, ka, frame->sig.retcode, frame, | ||
774 | usig); | ||
775 | |||
776 | if (err == 0) { | ||
777 | regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info; | ||
778 | regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc; | ||
779 | } | ||
780 | |||
781 | return err; | ||
782 | } | ||
783 | |||
784 | int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, | ||
785 | struct pt_regs *regs) | ||
786 | { | ||
787 | struct compat_sigframe __user *frame; | ||
788 | int err = 0; | ||
789 | |||
790 | frame = compat_get_sigframe(ka, regs, sizeof(*frame)); | ||
791 | |||
792 | if (!frame) | ||
793 | return 1; | ||
794 | |||
795 | __put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err); | ||
796 | |||
797 | err |= compat_setup_sigframe(frame, regs, set); | ||
798 | if (err == 0) | ||
799 | err = compat_setup_return(regs, ka, frame->retcode, frame, usig); | ||
800 | |||
801 | return err; | ||
802 | } | ||
803 | |||
804 | /* | ||
805 | * RT signals don't have generic compat wrappers. | ||
806 | * See arch/powerpc/kernel/signal_32.c | ||
807 | */ | ||
808 | asmlinkage int compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, | ||
809 | compat_sigset_t __user *oset, | ||
810 | compat_size_t sigsetsize) | ||
811 | { | ||
812 | sigset_t s; | ||
813 | sigset_t __user *up; | ||
814 | int ret; | ||
815 | mm_segment_t old_fs = get_fs(); | ||
816 | |||
817 | if (set) { | ||
818 | if (get_sigset_t(&s, set)) | ||
819 | return -EFAULT; | ||
820 | } | ||
821 | |||
822 | set_fs(KERNEL_DS); | ||
823 | /* This is valid because of the set_fs() */ | ||
824 | up = (sigset_t __user *) &s; | ||
825 | ret = sys_rt_sigprocmask(how, set ? up : NULL, oset ? up : NULL, | ||
826 | sigsetsize); | ||
827 | set_fs(old_fs); | ||
828 | if (ret) | ||
829 | return ret; | ||
830 | if (oset) { | ||
831 | if (put_sigset_t(oset, &s)) | ||
832 | return -EFAULT; | ||
833 | } | ||
834 | return 0; | ||
835 | } | ||
836 | |||
837 | asmlinkage int compat_sys_rt_sigpending(compat_sigset_t __user *set, | ||
838 | compat_size_t sigsetsize) | ||
839 | { | ||
840 | sigset_t s; | ||
841 | int ret; | ||
842 | mm_segment_t old_fs = get_fs(); | ||
843 | |||
844 | set_fs(KERNEL_DS); | ||
845 | /* The __user pointer cast is valid because of the set_fs() */ | ||
846 | ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize); | ||
847 | set_fs(old_fs); | ||
848 | if (!ret) { | ||
849 | if (put_sigset_t(set, &s)) | ||
850 | return -EFAULT; | ||
851 | } | ||
852 | return ret; | ||
853 | } | ||
854 | |||
855 | asmlinkage int compat_sys_rt_sigqueueinfo(int pid, int sig, | ||
856 | compat_siginfo_t __user *uinfo) | ||
857 | { | ||
858 | siginfo_t info; | ||
859 | int ret; | ||
860 | mm_segment_t old_fs = get_fs(); | ||
861 | |||
862 | ret = copy_siginfo_from_user32(&info, uinfo); | ||
863 | if (unlikely(ret)) | ||
864 | return ret; | ||
865 | |||
866 | set_fs (KERNEL_DS); | ||
867 | /* The __user pointer cast is valid because of the set_fs() */ | ||
868 | ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); | ||
869 | set_fs (old_fs); | ||
870 | return ret; | ||
871 | } | ||
872 | |||
873 | void compat_setup_restart_syscall(struct pt_regs *regs) | ||
874 | { | ||
875 | regs->regs[7] = __NR_restart_syscall; | ||
876 | } | ||
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c new file mode 100644 index 000000000000..b711525be21f --- /dev/null +++ b/arch/arm64/kernel/smp.c | |||
@@ -0,0 +1,469 @@ | |||
1 | /* | ||
2 | * SMP initialisation and IPI support | ||
3 | * Based on arch/arm/kernel/smp.c | ||
4 | * | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/cache.h> | ||
26 | #include <linux/profile.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/err.h> | ||
30 | #include <linux/cpu.h> | ||
31 | #include <linux/smp.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/irq.h> | ||
34 | #include <linux/percpu.h> | ||
35 | #include <linux/clockchips.h> | ||
36 | #include <linux/completion.h> | ||
37 | #include <linux/of.h> | ||
38 | |||
39 | #include <asm/atomic.h> | ||
40 | #include <asm/cacheflush.h> | ||
41 | #include <asm/cputype.h> | ||
42 | #include <asm/mmu_context.h> | ||
43 | #include <asm/pgtable.h> | ||
44 | #include <asm/pgalloc.h> | ||
45 | #include <asm/processor.h> | ||
46 | #include <asm/sections.h> | ||
47 | #include <asm/tlbflush.h> | ||
48 | #include <asm/ptrace.h> | ||
49 | #include <asm/mmu_context.h> | ||
50 | |||
51 | /* | ||
52 | * as from 2.5, kernels no longer have an init_tasks structure | ||
53 | * so we need some other way of telling a new secondary core | ||
54 | * where to place its SVC stack | ||
55 | */ | ||
56 | struct secondary_data secondary_data; | ||
57 | volatile unsigned long secondary_holding_pen_release = -1; | ||
58 | |||
59 | enum ipi_msg_type { | ||
60 | IPI_RESCHEDULE, | ||
61 | IPI_CALL_FUNC, | ||
62 | IPI_CALL_FUNC_SINGLE, | ||
63 | IPI_CPU_STOP, | ||
64 | }; | ||
65 | |||
66 | static DEFINE_RAW_SPINLOCK(boot_lock); | ||
67 | |||
68 | /* | ||
69 | * Write secondary_holding_pen_release in a way that is guaranteed to be | ||
70 | * visible to all observers, irrespective of whether they're taking part | ||
71 | * in coherency or not. This is necessary for the hotplug code to work | ||
72 | * reliably. | ||
73 | */ | ||
74 | static void __cpuinit write_pen_release(int val) | ||
75 | { | ||
76 | void *start = (void *)&secondary_holding_pen_release; | ||
77 | unsigned long size = sizeof(secondary_holding_pen_release); | ||
78 | |||
79 | secondary_holding_pen_release = val; | ||
80 | __flush_dcache_area(start, size); | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Boot a secondary CPU, and assign it the specified idle task. | ||
85 | * This also gives us the initial stack to use for this CPU. | ||
86 | */ | ||
87 | static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
88 | { | ||
89 | unsigned long timeout; | ||
90 | |||
91 | /* | ||
92 | * Set synchronisation state between this boot processor | ||
93 | * and the secondary one | ||
94 | */ | ||
95 | raw_spin_lock(&boot_lock); | ||
96 | |||
97 | /* | ||
98 | * Update the pen release flag. | ||
99 | */ | ||
100 | write_pen_release(cpu); | ||
101 | |||
102 | /* | ||
103 | * Send an event, causing the secondaries to read pen_release. | ||
104 | */ | ||
105 | sev(); | ||
106 | |||
107 | timeout = jiffies + (1 * HZ); | ||
108 | while (time_before(jiffies, timeout)) { | ||
109 | if (secondary_holding_pen_release == -1UL) | ||
110 | break; | ||
111 | udelay(10); | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Now the secondary core is starting up let it run its | ||
116 | * calibrations, then wait for it to finish | ||
117 | */ | ||
118 | raw_spin_unlock(&boot_lock); | ||
119 | |||
120 | return secondary_holding_pen_release != -1 ? -ENOSYS : 0; | ||
121 | } | ||
122 | |||
123 | static DECLARE_COMPLETION(cpu_running); | ||
124 | |||
125 | int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | /* | ||
130 | * We need to tell the secondary core where to find its stack and the | ||
131 | * page tables. | ||
132 | */ | ||
133 | secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; | ||
134 | __flush_dcache_area(&secondary_data, sizeof(secondary_data)); | ||
135 | |||
136 | /* | ||
137 | * Now bring the CPU into our world. | ||
138 | */ | ||
139 | ret = boot_secondary(cpu, idle); | ||
140 | if (ret == 0) { | ||
141 | /* | ||
142 | * CPU was successfully started, wait for it to come online or | ||
143 | * time out. | ||
144 | */ | ||
145 | wait_for_completion_timeout(&cpu_running, | ||
146 | msecs_to_jiffies(1000)); | ||
147 | |||
148 | if (!cpu_online(cpu)) { | ||
149 | pr_crit("CPU%u: failed to come online\n", cpu); | ||
150 | ret = -EIO; | ||
151 | } | ||
152 | } else { | ||
153 | pr_err("CPU%u: failed to boot: %d\n", cpu, ret); | ||
154 | } | ||
155 | |||
156 | secondary_data.stack = NULL; | ||
157 | |||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * This is the secondary CPU boot entry. We're using this CPUs | ||
163 | * idle thread stack, but a set of temporary page tables. | ||
164 | */ | ||
165 | asmlinkage void __cpuinit secondary_start_kernel(void) | ||
166 | { | ||
167 | struct mm_struct *mm = &init_mm; | ||
168 | unsigned int cpu = smp_processor_id(); | ||
169 | |||
170 | printk("CPU%u: Booted secondary processor\n", cpu); | ||
171 | |||
172 | /* | ||
173 | * All kernel threads share the same mm context; grab a | ||
174 | * reference and switch to it. | ||
175 | */ | ||
176 | atomic_inc(&mm->mm_count); | ||
177 | current->active_mm = mm; | ||
178 | cpumask_set_cpu(cpu, mm_cpumask(mm)); | ||
179 | |||
180 | /* | ||
181 | * TTBR0 is only used for the identity mapping at this stage. Make it | ||
182 | * point to zero page to avoid speculatively fetching new entries. | ||
183 | */ | ||
184 | cpu_set_reserved_ttbr0(); | ||
185 | flush_tlb_all(); | ||
186 | |||
187 | preempt_disable(); | ||
188 | trace_hardirqs_off(); | ||
189 | |||
190 | /* | ||
191 | * Let the primary processor know we're out of the | ||
192 | * pen, then head off into the C entry point | ||
193 | */ | ||
194 | write_pen_release(-1); | ||
195 | |||
196 | /* | ||
197 | * Synchronise with the boot thread. | ||
198 | */ | ||
199 | raw_spin_lock(&boot_lock); | ||
200 | raw_spin_unlock(&boot_lock); | ||
201 | |||
202 | /* | ||
203 | * Enable local interrupts. | ||
204 | */ | ||
205 | notify_cpu_starting(cpu); | ||
206 | local_irq_enable(); | ||
207 | local_fiq_enable(); | ||
208 | |||
209 | /* | ||
210 | * OK, now it's safe to let the boot CPU continue. Wait for | ||
211 | * the CPU migration code to notice that the CPU is online | ||
212 | * before we continue. | ||
213 | */ | ||
214 | set_cpu_online(cpu, true); | ||
215 | while (!cpu_active(cpu)) | ||
216 | cpu_relax(); | ||
217 | |||
218 | /* | ||
219 | * OK, it's off to the idle thread for us | ||
220 | */ | ||
221 | cpu_idle(); | ||
222 | } | ||
223 | |||
224 | void __init smp_cpus_done(unsigned int max_cpus) | ||
225 | { | ||
226 | unsigned long bogosum = loops_per_jiffy * num_online_cpus(); | ||
227 | |||
228 | pr_info("SMP: Total of %d processors activated (%lu.%02lu BogoMIPS).\n", | ||
229 | num_online_cpus(), bogosum / (500000/HZ), | ||
230 | (bogosum / (5000/HZ)) % 100); | ||
231 | } | ||
232 | |||
233 | void __init smp_prepare_boot_cpu(void) | ||
234 | { | ||
235 | } | ||
236 | |||
237 | static void (*smp_cross_call)(const struct cpumask *, unsigned int); | ||
238 | static phys_addr_t cpu_release_addr[NR_CPUS]; | ||
239 | |||
240 | /* | ||
241 | * Enumerate the possible CPU set from the device tree. | ||
242 | */ | ||
243 | void __init smp_init_cpus(void) | ||
244 | { | ||
245 | const char *enable_method; | ||
246 | struct device_node *dn = NULL; | ||
247 | int cpu = 0; | ||
248 | |||
249 | while ((dn = of_find_node_by_type(dn, "cpu"))) { | ||
250 | if (cpu >= NR_CPUS) | ||
251 | goto next; | ||
252 | |||
253 | /* | ||
254 | * We currently support only the "spin-table" enable-method. | ||
255 | */ | ||
256 | enable_method = of_get_property(dn, "enable-method", NULL); | ||
257 | if (!enable_method || strcmp(enable_method, "spin-table")) { | ||
258 | pr_err("CPU %d: missing or invalid enable-method property: %s\n", | ||
259 | cpu, enable_method); | ||
260 | goto next; | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * Determine the address from which the CPU is polling. | ||
265 | */ | ||
266 | if (of_property_read_u64(dn, "cpu-release-addr", | ||
267 | &cpu_release_addr[cpu])) { | ||
268 | pr_err("CPU %d: missing or invalid cpu-release-addr property\n", | ||
269 | cpu); | ||
270 | goto next; | ||
271 | } | ||
272 | |||
273 | set_cpu_possible(cpu, true); | ||
274 | next: | ||
275 | cpu++; | ||
276 | } | ||
277 | |||
278 | /* sanity check */ | ||
279 | if (cpu > NR_CPUS) | ||
280 | pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n", | ||
281 | cpu, NR_CPUS); | ||
282 | } | ||
283 | |||
284 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
285 | { | ||
286 | int cpu; | ||
287 | void **release_addr; | ||
288 | unsigned int ncores = num_possible_cpus(); | ||
289 | |||
290 | /* | ||
291 | * are we trying to boot more cores than exist? | ||
292 | */ | ||
293 | if (max_cpus > ncores) | ||
294 | max_cpus = ncores; | ||
295 | |||
296 | /* | ||
297 | * Initialise the present map (which describes the set of CPUs | ||
298 | * actually populated at the present time) and release the | ||
299 | * secondaries from the bootloader. | ||
300 | */ | ||
301 | for_each_possible_cpu(cpu) { | ||
302 | if (max_cpus == 0) | ||
303 | break; | ||
304 | |||
305 | if (!cpu_release_addr[cpu]) | ||
306 | continue; | ||
307 | |||
308 | release_addr = __va(cpu_release_addr[cpu]); | ||
309 | release_addr[0] = (void *)__pa(secondary_holding_pen); | ||
310 | __flush_dcache_area(release_addr, sizeof(release_addr[0])); | ||
311 | |||
312 | set_cpu_present(cpu, true); | ||
313 | max_cpus--; | ||
314 | } | ||
315 | |||
316 | /* | ||
317 | * Send an event to wake up the secondaries. | ||
318 | */ | ||
319 | sev(); | ||
320 | } | ||
321 | |||
322 | |||
323 | void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) | ||
324 | { | ||
325 | smp_cross_call = fn; | ||
326 | } | ||
327 | |||
328 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | ||
329 | { | ||
330 | smp_cross_call(mask, IPI_CALL_FUNC); | ||
331 | } | ||
332 | |||
333 | void arch_send_call_function_single_ipi(int cpu) | ||
334 | { | ||
335 | smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); | ||
336 | } | ||
337 | |||
338 | static const char *ipi_types[NR_IPI] = { | ||
339 | #define S(x,s) [x - IPI_RESCHEDULE] = s | ||
340 | S(IPI_RESCHEDULE, "Rescheduling interrupts"), | ||
341 | S(IPI_CALL_FUNC, "Function call interrupts"), | ||
342 | S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"), | ||
343 | S(IPI_CPU_STOP, "CPU stop interrupts"), | ||
344 | }; | ||
345 | |||
346 | void show_ipi_list(struct seq_file *p, int prec) | ||
347 | { | ||
348 | unsigned int cpu, i; | ||
349 | |||
350 | for (i = 0; i < NR_IPI; i++) { | ||
351 | seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i + IPI_RESCHEDULE, | ||
352 | prec >= 4 ? " " : ""); | ||
353 | for_each_present_cpu(cpu) | ||
354 | seq_printf(p, "%10u ", | ||
355 | __get_irq_stat(cpu, ipi_irqs[i])); | ||
356 | seq_printf(p, " %s\n", ipi_types[i]); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | u64 smp_irq_stat_cpu(unsigned int cpu) | ||
361 | { | ||
362 | u64 sum = 0; | ||
363 | int i; | ||
364 | |||
365 | for (i = 0; i < NR_IPI; i++) | ||
366 | sum += __get_irq_stat(cpu, ipi_irqs[i]); | ||
367 | |||
368 | return sum; | ||
369 | } | ||
370 | |||
371 | static DEFINE_RAW_SPINLOCK(stop_lock); | ||
372 | |||
373 | /* | ||
374 | * ipi_cpu_stop - handle IPI from smp_send_stop() | ||
375 | */ | ||
376 | static void ipi_cpu_stop(unsigned int cpu) | ||
377 | { | ||
378 | if (system_state == SYSTEM_BOOTING || | ||
379 | system_state == SYSTEM_RUNNING) { | ||
380 | raw_spin_lock(&stop_lock); | ||
381 | pr_crit("CPU%u: stopping\n", cpu); | ||
382 | dump_stack(); | ||
383 | raw_spin_unlock(&stop_lock); | ||
384 | } | ||
385 | |||
386 | set_cpu_online(cpu, false); | ||
387 | |||
388 | local_fiq_disable(); | ||
389 | local_irq_disable(); | ||
390 | |||
391 | while (1) | ||
392 | cpu_relax(); | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * Main handler for inter-processor interrupts | ||
397 | */ | ||
398 | void handle_IPI(int ipinr, struct pt_regs *regs) | ||
399 | { | ||
400 | unsigned int cpu = smp_processor_id(); | ||
401 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
402 | |||
403 | if (ipinr >= IPI_RESCHEDULE && ipinr < IPI_RESCHEDULE + NR_IPI) | ||
404 | __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_RESCHEDULE]); | ||
405 | |||
406 | switch (ipinr) { | ||
407 | case IPI_RESCHEDULE: | ||
408 | scheduler_ipi(); | ||
409 | break; | ||
410 | |||
411 | case IPI_CALL_FUNC: | ||
412 | irq_enter(); | ||
413 | generic_smp_call_function_interrupt(); | ||
414 | irq_exit(); | ||
415 | break; | ||
416 | |||
417 | case IPI_CALL_FUNC_SINGLE: | ||
418 | irq_enter(); | ||
419 | generic_smp_call_function_single_interrupt(); | ||
420 | irq_exit(); | ||
421 | break; | ||
422 | |||
423 | case IPI_CPU_STOP: | ||
424 | irq_enter(); | ||
425 | ipi_cpu_stop(cpu); | ||
426 | irq_exit(); | ||
427 | break; | ||
428 | |||
429 | default: | ||
430 | pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); | ||
431 | break; | ||
432 | } | ||
433 | set_irq_regs(old_regs); | ||
434 | } | ||
435 | |||
436 | void smp_send_reschedule(int cpu) | ||
437 | { | ||
438 | smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); | ||
439 | } | ||
440 | |||
441 | void smp_send_stop(void) | ||
442 | { | ||
443 | unsigned long timeout; | ||
444 | |||
445 | if (num_online_cpus() > 1) { | ||
446 | cpumask_t mask; | ||
447 | |||
448 | cpumask_copy(&mask, cpu_online_mask); | ||
449 | cpu_clear(smp_processor_id(), mask); | ||
450 | |||
451 | smp_cross_call(&mask, IPI_CPU_STOP); | ||
452 | } | ||
453 | |||
454 | /* Wait up to one second for other CPUs to stop */ | ||
455 | timeout = USEC_PER_SEC; | ||
456 | while (num_online_cpus() > 1 && timeout--) | ||
457 | udelay(1); | ||
458 | |||
459 | if (num_online_cpus() > 1) | ||
460 | pr_warning("SMP: failed to stop secondary CPUs\n"); | ||
461 | } | ||
462 | |||
463 | /* | ||
464 | * not supported here | ||
465 | */ | ||
466 | int setup_profiling_timer(unsigned int multiplier) | ||
467 | { | ||
468 | return -EINVAL; | ||
469 | } | ||
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c new file mode 100644 index 000000000000..d25459ff57fc --- /dev/null +++ b/arch/arm64/kernel/stacktrace.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /* | ||
2 | * Stack tracing support | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/export.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/stacktrace.h> | ||
22 | |||
23 | #include <asm/stacktrace.h> | ||
24 | |||
25 | /* | ||
26 | * AArch64 PCS assigns the frame pointer to x29. | ||
27 | * | ||
28 | * A simple function prologue looks like this: | ||
29 | * sub sp, sp, #0x10 | ||
30 | * stp x29, x30, [sp] | ||
31 | * mov x29, sp | ||
32 | * | ||
33 | * A simple function epilogue looks like this: | ||
34 | * mov sp, x29 | ||
35 | * ldp x29, x30, [sp] | ||
36 | * add sp, sp, #0x10 | ||
37 | */ | ||
38 | int unwind_frame(struct stackframe *frame) | ||
39 | { | ||
40 | unsigned long high, low; | ||
41 | unsigned long fp = frame->fp; | ||
42 | |||
43 | low = frame->sp; | ||
44 | high = ALIGN(low, THREAD_SIZE); | ||
45 | |||
46 | if (fp < low || fp > high || fp & 0xf) | ||
47 | return -EINVAL; | ||
48 | |||
49 | frame->sp = fp + 0x10; | ||
50 | frame->fp = *(unsigned long *)(fp); | ||
51 | frame->pc = *(unsigned long *)(fp + 8); | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | void notrace walk_stackframe(struct stackframe *frame, | ||
57 | int (*fn)(struct stackframe *, void *), void *data) | ||
58 | { | ||
59 | while (1) { | ||
60 | int ret; | ||
61 | |||
62 | if (fn(frame, data)) | ||
63 | break; | ||
64 | ret = unwind_frame(frame); | ||
65 | if (ret < 0) | ||
66 | break; | ||
67 | } | ||
68 | } | ||
69 | EXPORT_SYMBOL(walk_stackframe); | ||
70 | |||
71 | #ifdef CONFIG_STACKTRACE | ||
72 | struct stack_trace_data { | ||
73 | struct stack_trace *trace; | ||
74 | unsigned int no_sched_functions; | ||
75 | unsigned int skip; | ||
76 | }; | ||
77 | |||
78 | static int save_trace(struct stackframe *frame, void *d) | ||
79 | { | ||
80 | struct stack_trace_data *data = d; | ||
81 | struct stack_trace *trace = data->trace; | ||
82 | unsigned long addr = frame->pc; | ||
83 | |||
84 | if (data->no_sched_functions && in_sched_functions(addr)) | ||
85 | return 0; | ||
86 | if (data->skip) { | ||
87 | data->skip--; | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | trace->entries[trace->nr_entries++] = addr; | ||
92 | |||
93 | return trace->nr_entries >= trace->max_entries; | ||
94 | } | ||
95 | |||
96 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | ||
97 | { | ||
98 | struct stack_trace_data data; | ||
99 | struct stackframe frame; | ||
100 | |||
101 | data.trace = trace; | ||
102 | data.skip = trace->skip; | ||
103 | |||
104 | if (tsk != current) { | ||
105 | data.no_sched_functions = 1; | ||
106 | frame.fp = thread_saved_fp(tsk); | ||
107 | frame.sp = thread_saved_sp(tsk); | ||
108 | frame.pc = thread_saved_pc(tsk); | ||
109 | } else { | ||
110 | register unsigned long current_sp asm("sp"); | ||
111 | data.no_sched_functions = 0; | ||
112 | frame.fp = (unsigned long)__builtin_frame_address(0); | ||
113 | frame.sp = current_sp; | ||
114 | frame.pc = (unsigned long)save_stack_trace_tsk; | ||
115 | } | ||
116 | |||
117 | walk_stackframe(&frame, save_trace, &data); | ||
118 | if (trace->nr_entries < trace->max_entries) | ||
119 | trace->entries[trace->nr_entries++] = ULONG_MAX; | ||
120 | } | ||
121 | |||
122 | void save_stack_trace(struct stack_trace *trace) | ||
123 | { | ||
124 | save_stack_trace_tsk(current, trace); | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||
127 | #endif | ||
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c new file mode 100644 index 000000000000..905fcfb0ddd0 --- /dev/null +++ b/arch/arm64/kernel/sys.c | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * AArch64-specific system calls implementation | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/compiler.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/mm.h> | ||
24 | #include <linux/export.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/syscalls.h> | ||
28 | |||
29 | /* | ||
30 | * Clone a task - this clones the calling program thread. | ||
31 | */ | ||
32 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
33 | int __user *parent_tidptr, unsigned long tls_val, | ||
34 | int __user *child_tidptr, struct pt_regs *regs) | ||
35 | { | ||
36 | if (!newsp) | ||
37 | newsp = regs->sp; | ||
38 | /* 16-byte aligned stack mandatory on AArch64 */ | ||
39 | if (newsp & 15) | ||
40 | return -EINVAL; | ||
41 | return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); | ||
42 | } | ||
43 | |||
44 | /* | ||
45 | * sys_execve() executes a new program. | ||
46 | */ | ||
47 | asmlinkage long sys_execve(const char __user *filenamei, | ||
48 | const char __user *const __user *argv, | ||
49 | const char __user *const __user *envp, | ||
50 | struct pt_regs *regs) | ||
51 | { | ||
52 | long error; | ||
53 | char * filename; | ||
54 | |||
55 | filename = getname(filenamei); | ||
56 | error = PTR_ERR(filename); | ||
57 | if (IS_ERR(filename)) | ||
58 | goto out; | ||
59 | error = do_execve(filename, argv, envp, regs); | ||
60 | putname(filename); | ||
61 | out: | ||
62 | return error; | ||
63 | } | ||
64 | |||
65 | int kernel_execve(const char *filename, | ||
66 | const char *const argv[], | ||
67 | const char *const envp[]) | ||
68 | { | ||
69 | struct pt_regs regs; | ||
70 | int ret; | ||
71 | |||
72 | memset(®s, 0, sizeof(struct pt_regs)); | ||
73 | ret = do_execve(filename, | ||
74 | (const char __user *const __user *)argv, | ||
75 | (const char __user *const __user *)envp, ®s); | ||
76 | if (ret < 0) | ||
77 | goto out; | ||
78 | |||
79 | /* | ||
80 | * Save argc to the register structure for userspace. | ||
81 | */ | ||
82 | regs.regs[0] = ret; | ||
83 | |||
84 | /* | ||
85 | * We were successful. We won't be returning to our caller, but | ||
86 | * instead to user space by manipulating the kernel stack. | ||
87 | */ | ||
88 | asm( "add x0, %0, %1\n\t" | ||
89 | "mov x1, %2\n\t" | ||
90 | "mov x2, %3\n\t" | ||
91 | "bl memmove\n\t" /* copy regs to top of stack */ | ||
92 | "mov x27, #0\n\t" /* not a syscall */ | ||
93 | "mov x28, %0\n\t" /* thread structure */ | ||
94 | "mov sp, x0\n\t" /* reposition stack pointer */ | ||
95 | "b ret_to_user" | ||
96 | : | ||
97 | : "r" (current_thread_info()), | ||
98 | "Ir" (THREAD_START_SP - sizeof(regs)), | ||
99 | "r" (®s), | ||
100 | "Ir" (sizeof(regs)) | ||
101 | : "x0", "x1", "x2", "x27", "x28", "x30", "memory"); | ||
102 | |||
103 | out: | ||
104 | return ret; | ||
105 | } | ||
106 | EXPORT_SYMBOL(kernel_execve); | ||
107 | |||
108 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | ||
109 | unsigned long prot, unsigned long flags, | ||
110 | unsigned long fd, off_t off) | ||
111 | { | ||
112 | if (offset_in_page(off) != 0) | ||
113 | return -EINVAL; | ||
114 | |||
115 | return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Wrappers to pass the pt_regs argument. | ||
120 | */ | ||
121 | #define sys_execve sys_execve_wrapper | ||
122 | #define sys_clone sys_clone_wrapper | ||
123 | #define sys_rt_sigreturn sys_rt_sigreturn_wrapper | ||
124 | #define sys_sigaltstack sys_sigaltstack_wrapper | ||
125 | |||
126 | #include <asm/syscalls.h> | ||
127 | |||
128 | #undef __SYSCALL | ||
129 | #define __SYSCALL(nr, sym) [nr] = sym, | ||
130 | |||
131 | /* | ||
132 | * The sys_call_table array must be 4K aligned to be accessible from | ||
133 | * kernel/entry.S. | ||
134 | */ | ||
135 | void *sys_call_table[__NR_syscalls] __aligned(4096) = { | ||
136 | [0 ... __NR_syscalls - 1] = sys_ni_syscall, | ||
137 | #include <asm/unistd.h> | ||
138 | }; | ||
diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S new file mode 100644 index 000000000000..5e4dc93cc31f --- /dev/null +++ b/arch/arm64/kernel/sys32.S | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | * Compat system call wrappers | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * Authors: Will Deacon <will.deacon@arm.com> | ||
6 | * Catalin Marinas <catalin.marinas@arm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/linkage.h> | ||
22 | |||
23 | #include <asm/assembler.h> | ||
24 | #include <asm/asm-offsets.h> | ||
25 | |||
26 | /* | ||
27 | * System call wrappers for the AArch32 compatibility layer. | ||
28 | */ | ||
29 | compat_sys_fork_wrapper: | ||
30 | mov x0, sp | ||
31 | b compat_sys_fork | ||
32 | ENDPROC(compat_sys_fork_wrapper) | ||
33 | |||
34 | compat_sys_vfork_wrapper: | ||
35 | mov x0, sp | ||
36 | b compat_sys_vfork | ||
37 | ENDPROC(compat_sys_vfork_wrapper) | ||
38 | |||
39 | compat_sys_execve_wrapper: | ||
40 | mov x3, sp | ||
41 | b compat_sys_execve | ||
42 | ENDPROC(compat_sys_execve_wrapper) | ||
43 | |||
44 | compat_sys_clone_wrapper: | ||
45 | mov x5, sp | ||
46 | b compat_sys_clone | ||
47 | ENDPROC(compat_sys_clone_wrapper) | ||
48 | |||
49 | compat_sys_sigreturn_wrapper: | ||
50 | mov x0, sp | ||
51 | mov x27, #0 // prevent syscall restart handling (why) | ||
52 | b compat_sys_sigreturn | ||
53 | ENDPROC(compat_sys_sigreturn_wrapper) | ||
54 | |||
55 | compat_sys_rt_sigreturn_wrapper: | ||
56 | mov x0, sp | ||
57 | mov x27, #0 // prevent syscall restart handling (why) | ||
58 | b compat_sys_rt_sigreturn | ||
59 | ENDPROC(compat_sys_rt_sigreturn_wrapper) | ||
60 | |||
61 | compat_sys_sigaltstack_wrapper: | ||
62 | ldr x2, [sp, #S_COMPAT_SP] | ||
63 | b compat_do_sigaltstack | ||
64 | ENDPROC(compat_sys_sigaltstack_wrapper) | ||
65 | |||
66 | compat_sys_statfs64_wrapper: | ||
67 | mov w3, #84 | ||
68 | cmp w1, #88 | ||
69 | csel w1, w3, w1, eq | ||
70 | b compat_sys_statfs64 | ||
71 | ENDPROC(compat_sys_statfs64_wrapper) | ||
72 | |||
73 | compat_sys_fstatfs64_wrapper: | ||
74 | mov w3, #84 | ||
75 | cmp w1, #88 | ||
76 | csel w1, w3, w1, eq | ||
77 | b compat_sys_fstatfs64 | ||
78 | ENDPROC(compat_sys_fstatfs64_wrapper) | ||
79 | |||
80 | /* | ||
81 | * Wrappers for AArch32 syscalls that either take 64-bit parameters | ||
82 | * in registers or that take 32-bit parameters which require sign | ||
83 | * extension. | ||
84 | */ | ||
85 | compat_sys_lseek_wrapper: | ||
86 | sxtw x1, w1 | ||
87 | b sys_lseek | ||
88 | ENDPROC(compat_sys_lseek_wrapper) | ||
89 | |||
90 | compat_sys_pread64_wrapper: | ||
91 | orr x3, x4, x5, lsl #32 | ||
92 | b sys_pread64 | ||
93 | ENDPROC(compat_sys_pread64_wrapper) | ||
94 | |||
95 | compat_sys_pwrite64_wrapper: | ||
96 | orr x3, x4, x5, lsl #32 | ||
97 | b sys_pwrite64 | ||
98 | ENDPROC(compat_sys_pwrite64_wrapper) | ||
99 | |||
100 | compat_sys_truncate64_wrapper: | ||
101 | orr x1, x2, x3, lsl #32 | ||
102 | b sys_truncate | ||
103 | ENDPROC(compat_sys_truncate64_wrapper) | ||
104 | |||
105 | compat_sys_ftruncate64_wrapper: | ||
106 | orr x1, x2, x3, lsl #32 | ||
107 | b sys_ftruncate | ||
108 | ENDPROC(compat_sys_ftruncate64_wrapper) | ||
109 | |||
110 | compat_sys_readahead_wrapper: | ||
111 | orr x1, x2, x3, lsl #32 | ||
112 | mov w2, w4 | ||
113 | b sys_readahead | ||
114 | ENDPROC(compat_sys_readahead_wrapper) | ||
115 | |||
116 | compat_sys_lookup_dcookie: | ||
117 | orr x0, x0, x1, lsl #32 | ||
118 | mov w1, w2 | ||
119 | mov w2, w3 | ||
120 | b sys_lookup_dcookie | ||
121 | ENDPROC(compat_sys_lookup_dcookie) | ||
122 | |||
123 | compat_sys_fadvise64_64_wrapper: | ||
124 | mov w6, w1 | ||
125 | orr x1, x2, x3, lsl #32 | ||
126 | orr x2, x4, x5, lsl #32 | ||
127 | mov w3, w6 | ||
128 | b sys_fadvise64_64 | ||
129 | ENDPROC(compat_sys_fadvise64_64_wrapper) | ||
130 | |||
131 | compat_sys_sync_file_range2_wrapper: | ||
132 | orr x2, x2, x3, lsl #32 | ||
133 | orr x3, x4, x5, lsl #32 | ||
134 | b sys_sync_file_range2 | ||
135 | ENDPROC(compat_sys_sync_file_range2_wrapper) | ||
136 | |||
137 | compat_sys_fallocate_wrapper: | ||
138 | orr x2, x2, x3, lsl #32 | ||
139 | orr x3, x4, x5, lsl #32 | ||
140 | b sys_fallocate | ||
141 | ENDPROC(compat_sys_fallocate_wrapper) | ||
142 | |||
143 | compat_sys_fanotify_mark_wrapper: | ||
144 | orr x2, x2, x3, lsl #32 | ||
145 | mov w3, w4 | ||
146 | mov w4, w5 | ||
147 | b sys_fanotify_mark | ||
148 | ENDPROC(compat_sys_fanotify_mark_wrapper) | ||
149 | |||
150 | /* | ||
151 | * Use the compat system call wrappers. | ||
152 | */ | ||
153 | #define sys_fork compat_sys_fork_wrapper | ||
154 | #define sys_open compat_sys_open | ||
155 | #define sys_execve compat_sys_execve_wrapper | ||
156 | #define sys_lseek compat_sys_lseek_wrapper | ||
157 | #define sys_mount compat_sys_mount | ||
158 | #define sys_ptrace compat_sys_ptrace | ||
159 | #define sys_times compat_sys_times | ||
160 | #define sys_ioctl compat_sys_ioctl | ||
161 | #define sys_fcntl compat_sys_fcntl | ||
162 | #define sys_ustat compat_sys_ustat | ||
163 | #define sys_sigaction compat_sys_sigaction | ||
164 | #define sys_sigsuspend compat_sys_sigsuspend | ||
165 | #define sys_sigpending compat_sys_sigpending | ||
166 | #define sys_setrlimit compat_sys_setrlimit | ||
167 | #define sys_getrusage compat_sys_getrusage | ||
168 | #define sys_gettimeofday compat_sys_gettimeofday | ||
169 | #define sys_settimeofday compat_sys_settimeofday | ||
170 | #define sys_statfs compat_sys_statfs | ||
171 | #define sys_fstatfs compat_sys_fstatfs | ||
172 | #define sys_setitimer compat_sys_setitimer | ||
173 | #define sys_getitimer compat_sys_getitimer | ||
174 | #define sys_newstat compat_sys_newstat | ||
175 | #define sys_newlstat compat_sys_newlstat | ||
176 | #define sys_newfstat compat_sys_newfstat | ||
177 | #define sys_wait4 compat_sys_wait4 | ||
178 | #define sys_sysinfo compat_sys_sysinfo | ||
179 | #define sys_sigreturn compat_sys_sigreturn_wrapper | ||
180 | #define sys_clone compat_sys_clone_wrapper | ||
181 | #define sys_adjtimex compat_sys_adjtimex | ||
182 | #define sys_sigprocmask compat_sys_sigprocmask | ||
183 | #define sys_getdents compat_sys_getdents | ||
184 | #define sys_select compat_sys_select | ||
185 | #define sys_readv compat_sys_readv | ||
186 | #define sys_writev compat_sys_writev | ||
187 | #define sys_sysctl compat_sys_sysctl | ||
188 | #define sys_sched_rr_get_interval compat_sys_sched_rr_get_interval | ||
189 | #define sys_nanosleep compat_sys_nanosleep | ||
190 | #define sys_rt_sigreturn compat_sys_rt_sigreturn_wrapper | ||
191 | #define sys_rt_sigaction compat_sys_rt_sigaction | ||
192 | #define sys_rt_sigprocmask compat_sys_rt_sigprocmask | ||
193 | #define sys_rt_sigpending compat_sys_rt_sigpending | ||
194 | #define sys_rt_sigtimedwait compat_sys_rt_sigtimedwait | ||
195 | #define sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo | ||
196 | #define sys_rt_sigsuspend compat_sys_rt_sigsuspend | ||
197 | #define sys_pread64 compat_sys_pread64_wrapper | ||
198 | #define sys_pwrite64 compat_sys_pwrite64_wrapper | ||
199 | #define sys_sigaltstack compat_sys_sigaltstack_wrapper | ||
200 | #define sys_sendfile compat_sys_sendfile | ||
201 | #define sys_vfork compat_sys_vfork_wrapper | ||
202 | #define sys_getrlimit compat_sys_getrlimit | ||
203 | #define sys_mmap2 sys_mmap_pgoff | ||
204 | #define sys_truncate64 compat_sys_truncate64_wrapper | ||
205 | #define sys_ftruncate64 compat_sys_ftruncate64_wrapper | ||
206 | #define sys_getdents64 compat_sys_getdents64 | ||
207 | #define sys_fcntl64 compat_sys_fcntl64 | ||
208 | #define sys_readahead compat_sys_readahead_wrapper | ||
209 | #define sys_futex compat_sys_futex | ||
210 | #define sys_sched_setaffinity compat_sys_sched_setaffinity | ||
211 | #define sys_sched_getaffinity compat_sys_sched_getaffinity | ||
212 | #define sys_io_setup compat_sys_io_setup | ||
213 | #define sys_io_getevents compat_sys_io_getevents | ||
214 | #define sys_io_submit compat_sys_io_submit | ||
215 | #define sys_lookup_dcookie compat_sys_lookup_dcookie | ||
216 | #define sys_timer_create compat_sys_timer_create | ||
217 | #define sys_timer_settime compat_sys_timer_settime | ||
218 | #define sys_timer_gettime compat_sys_timer_gettime | ||
219 | #define sys_clock_settime compat_sys_clock_settime | ||
220 | #define sys_clock_gettime compat_sys_clock_gettime | ||
221 | #define sys_clock_getres compat_sys_clock_getres | ||
222 | #define sys_clock_nanosleep compat_sys_clock_nanosleep | ||
223 | #define sys_statfs64 compat_sys_statfs64_wrapper | ||
224 | #define sys_fstatfs64 compat_sys_fstatfs64_wrapper | ||
225 | #define sys_utimes compat_sys_utimes | ||
226 | #define sys_fadvise64_64 compat_sys_fadvise64_64_wrapper | ||
227 | #define sys_mq_open compat_sys_mq_open | ||
228 | #define sys_mq_timedsend compat_sys_mq_timedsend | ||
229 | #define sys_mq_timedreceive compat_sys_mq_timedreceive | ||
230 | #define sys_mq_notify compat_sys_mq_notify | ||
231 | #define sys_mq_getsetattr compat_sys_mq_getsetattr | ||
232 | #define sys_waitid compat_sys_waitid | ||
233 | #define sys_recv compat_sys_recv | ||
234 | #define sys_recvfrom compat_sys_recvfrom | ||
235 | #define sys_setsockopt compat_sys_setsockopt | ||
236 | #define sys_getsockopt compat_sys_getsockopt | ||
237 | #define sys_sendmsg compat_sys_sendmsg | ||
238 | #define sys_recvmsg compat_sys_recvmsg | ||
239 | #define sys_semctl compat_sys_semctl | ||
240 | #define sys_msgsnd compat_sys_msgsnd | ||
241 | #define sys_msgrcv compat_sys_msgrcv | ||
242 | #define sys_msgctl compat_sys_msgctl | ||
243 | #define sys_shmat compat_sys_shmat | ||
244 | #define sys_shmctl compat_sys_shmctl | ||
245 | #define sys_keyctl compat_sys_keyctl | ||
246 | #define sys_semtimedop compat_sys_semtimedop | ||
247 | #define sys_mbind compat_sys_mbind | ||
248 | #define sys_get_mempolicy compat_sys_get_mempolicy | ||
249 | #define sys_set_mempolicy compat_sys_set_mempolicy | ||
250 | #define sys_openat compat_sys_openat | ||
251 | #define sys_futimesat compat_sys_futimesat | ||
252 | #define sys_pselect6 compat_sys_pselect6 | ||
253 | #define sys_ppoll compat_sys_ppoll | ||
254 | #define sys_set_robust_list compat_sys_set_robust_list | ||
255 | #define sys_get_robust_list compat_sys_get_robust_list | ||
256 | #define sys_sync_file_range2 compat_sys_sync_file_range2_wrapper | ||
257 | #define sys_vmsplice compat_sys_vmsplice | ||
258 | #define sys_move_pages compat_sys_move_pages | ||
259 | #define sys_epoll_pwait compat_sys_epoll_pwait | ||
260 | #define sys_kexec_load compat_sys_kexec_load | ||
261 | #define sys_utimensat compat_sys_utimensat | ||
262 | #define sys_signalfd compat_sys_signalfd | ||
263 | #define sys_fallocate compat_sys_fallocate_wrapper | ||
264 | #define sys_timerfd_settime compat_sys_timerfd_settime | ||
265 | #define sys_timerfd_gettime compat_sys_timerfd_gettime | ||
266 | #define sys_signalfd4 compat_sys_signalfd4 | ||
267 | #define sys_preadv compat_sys_preadv | ||
268 | #define sys_pwritev compat_sys_pwritev | ||
269 | #define sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo | ||
270 | #define sys_recvmmsg compat_sys_recvmmsg | ||
271 | #define sys_fanotify_mark compat_sys_fanotify_mark_wrapper | ||
272 | |||
273 | #undef __SYSCALL | ||
274 | #define __SYSCALL(x, y) .quad y // x | ||
275 | #define __SYSCALL_COMPAT | ||
276 | |||
277 | /* | ||
278 | * The system calls table must be 4KB aligned. | ||
279 | */ | ||
280 | .align 12 | ||
281 | ENTRY(compat_sys_call_table) | ||
282 | #include <asm/unistd.h> | ||
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c new file mode 100644 index 000000000000..967e92fdff01 --- /dev/null +++ b/arch/arm64/kernel/sys_compat.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/sys_arm.c | ||
3 | * | ||
4 | * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c | ||
5 | * Copyright (C) 1995, 1996 Russell King. | ||
6 | * Copyright (C) 2012 ARM Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #define __SYSCALL_COMPAT | ||
22 | |||
23 | #include <linux/compat.h> | ||
24 | #include <linux/personality.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/syscalls.h> | ||
28 | #include <linux/uaccess.h> | ||
29 | |||
30 | #include <asm/cacheflush.h> | ||
31 | #include <asm/unistd.h> | ||
32 | |||
33 | asmlinkage int compat_sys_fork(struct pt_regs *regs) | ||
34 | { | ||
35 | return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL); | ||
36 | } | ||
37 | |||
38 | asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
39 | int __user *parent_tidptr, int tls_val, | ||
40 | int __user *child_tidptr, struct pt_regs *regs) | ||
41 | { | ||
42 | if (!newsp) | ||
43 | newsp = regs->compat_sp; | ||
44 | |||
45 | return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); | ||
46 | } | ||
47 | |||
48 | asmlinkage int compat_sys_vfork(struct pt_regs *regs) | ||
49 | { | ||
50 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp, | ||
51 | regs, 0, NULL, NULL); | ||
52 | } | ||
53 | |||
54 | asmlinkage int compat_sys_execve(const char __user *filenamei, | ||
55 | compat_uptr_t argv, compat_uptr_t envp, | ||
56 | struct pt_regs *regs) | ||
57 | { | ||
58 | int error; | ||
59 | char * filename; | ||
60 | |||
61 | filename = getname(filenamei); | ||
62 | error = PTR_ERR(filename); | ||
63 | if (IS_ERR(filename)) | ||
64 | goto out; | ||
65 | error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp), | ||
66 | regs); | ||
67 | putname(filename); | ||
68 | out: | ||
69 | return error; | ||
70 | } | ||
71 | |||
72 | asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid, | ||
73 | struct compat_timespec __user *interval) | ||
74 | { | ||
75 | struct timespec t; | ||
76 | int ret; | ||
77 | mm_segment_t old_fs = get_fs(); | ||
78 | |||
79 | set_fs(KERNEL_DS); | ||
80 | ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); | ||
81 | set_fs(old_fs); | ||
82 | if (put_compat_timespec(&t, interval)) | ||
83 | return -EFAULT; | ||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | asmlinkage int compat_sys_sendfile(int out_fd, int in_fd, | ||
88 | compat_off_t __user *offset, s32 count) | ||
89 | { | ||
90 | mm_segment_t old_fs = get_fs(); | ||
91 | int ret; | ||
92 | off_t of; | ||
93 | |||
94 | if (offset && get_user(of, offset)) | ||
95 | return -EFAULT; | ||
96 | |||
97 | set_fs(KERNEL_DS); | ||
98 | ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, | ||
99 | count); | ||
100 | set_fs(old_fs); | ||
101 | |||
102 | if (offset && put_user(of, offset)) | ||
103 | return -EFAULT; | ||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static inline void | ||
108 | do_compat_cache_op(unsigned long start, unsigned long end, int flags) | ||
109 | { | ||
110 | struct mm_struct *mm = current->active_mm; | ||
111 | struct vm_area_struct *vma; | ||
112 | |||
113 | if (end < start || flags) | ||
114 | return; | ||
115 | |||
116 | down_read(&mm->mmap_sem); | ||
117 | vma = find_vma(mm, start); | ||
118 | if (vma && vma->vm_start < end) { | ||
119 | if (start < vma->vm_start) | ||
120 | start = vma->vm_start; | ||
121 | if (end > vma->vm_end) | ||
122 | end = vma->vm_end; | ||
123 | up_read(&mm->mmap_sem); | ||
124 | __flush_cache_user_range(start & PAGE_MASK, PAGE_ALIGN(end)); | ||
125 | return; | ||
126 | } | ||
127 | up_read(&mm->mmap_sem); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Handle all unrecognised system calls. | ||
132 | */ | ||
133 | long compat_arm_syscall(struct pt_regs *regs) | ||
134 | { | ||
135 | unsigned int no = regs->regs[7]; | ||
136 | |||
137 | switch (no) { | ||
138 | /* | ||
139 | * Flush a region from virtual address 'r0' to virtual address 'r1' | ||
140 | * _exclusive_. There is no alignment requirement on either address; | ||
141 | * user space does not need to know the hardware cache layout. | ||
142 | * | ||
143 | * r2 contains flags. It should ALWAYS be passed as ZERO until it | ||
144 | * is defined to be something else. For now we ignore it, but may | ||
145 | * the fires of hell burn in your belly if you break this rule. ;) | ||
146 | * | ||
147 | * (at a later date, we may want to allow this call to not flush | ||
148 | * various aspects of the cache. Passing '0' will guarantee that | ||
149 | * everything necessary gets flushed to maintain consistency in | ||
150 | * the specified region). | ||
151 | */ | ||
152 | case __ARM_NR_compat_cacheflush: | ||
153 | do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]); | ||
154 | return 0; | ||
155 | |||
156 | case __ARM_NR_compat_set_tls: | ||
157 | current->thread.tp_value = regs->regs[0]; | ||
158 | asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); | ||
159 | return 0; | ||
160 | |||
161 | default: | ||
162 | return -ENOSYS; | ||
163 | } | ||
164 | } | ||
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c new file mode 100644 index 000000000000..3b4b7258f492 --- /dev/null +++ b/arch/arm64/kernel/time.c | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/time.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
5 | * Modifications for ARM (C) 1994-2001 Russell King | ||
6 | * Copyright (C) 2012 ARM Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/export.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/time.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/smp.h> | ||
28 | #include <linux/timex.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/profile.h> | ||
31 | #include <linux/syscore_ops.h> | ||
32 | #include <linux/timer.h> | ||
33 | #include <linux/irq.h> | ||
34 | |||
35 | #include <clocksource/arm_generic.h> | ||
36 | |||
37 | #include <asm/thread_info.h> | ||
38 | #include <asm/stacktrace.h> | ||
39 | |||
40 | #ifdef CONFIG_SMP | ||
41 | unsigned long profile_pc(struct pt_regs *regs) | ||
42 | { | ||
43 | struct stackframe frame; | ||
44 | |||
45 | if (!in_lock_functions(regs->pc)) | ||
46 | return regs->pc; | ||
47 | |||
48 | frame.fp = regs->regs[29]; | ||
49 | frame.sp = regs->sp; | ||
50 | frame.pc = regs->pc; | ||
51 | do { | ||
52 | int ret = unwind_frame(&frame); | ||
53 | if (ret < 0) | ||
54 | return 0; | ||
55 | } while (in_lock_functions(frame.pc)); | ||
56 | |||
57 | return frame.pc; | ||
58 | } | ||
59 | EXPORT_SYMBOL(profile_pc); | ||
60 | #endif | ||
61 | |||
62 | void __init time_init(void) | ||
63 | { | ||
64 | arm_generic_timer_init(); | ||
65 | } | ||
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c new file mode 100644 index 000000000000..3883f842434f --- /dev/null +++ b/arch/arm64/kernel/traps.c | |||
@@ -0,0 +1,348 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/kernel/traps.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2009 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/signal.h> | ||
21 | #include <linux/personality.h> | ||
22 | #include <linux/kallsyms.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | #include <linux/hardirq.h> | ||
26 | #include <linux/kdebug.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/kexec.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/syscalls.h> | ||
33 | |||
34 | #include <asm/atomic.h> | ||
35 | #include <asm/traps.h> | ||
36 | #include <asm/stacktrace.h> | ||
37 | #include <asm/exception.h> | ||
38 | #include <asm/system_misc.h> | ||
39 | |||
40 | static const char *handler[]= { | ||
41 | "Synchronous Abort", | ||
42 | "IRQ", | ||
43 | "FIQ", | ||
44 | "Error" | ||
45 | }; | ||
46 | |||
47 | int show_unhandled_signals = 1; | ||
48 | |||
49 | /* | ||
50 | * Dump out the contents of some memory nicely... | ||
51 | */ | ||
52 | static void dump_mem(const char *lvl, const char *str, unsigned long bottom, | ||
53 | unsigned long top) | ||
54 | { | ||
55 | unsigned long first; | ||
56 | mm_segment_t fs; | ||
57 | int i; | ||
58 | |||
59 | /* | ||
60 | * We need to switch to kernel mode so that we can use __get_user | ||
61 | * to safely read from kernel space. Note that we now dump the | ||
62 | * code first, just in case the backtrace kills us. | ||
63 | */ | ||
64 | fs = get_fs(); | ||
65 | set_fs(KERNEL_DS); | ||
66 | |||
67 | printk("%s%s(0x%016lx to 0x%016lx)\n", lvl, str, bottom, top); | ||
68 | |||
69 | for (first = bottom & ~31; first < top; first += 32) { | ||
70 | unsigned long p; | ||
71 | char str[sizeof(" 12345678") * 8 + 1]; | ||
72 | |||
73 | memset(str, ' ', sizeof(str)); | ||
74 | str[sizeof(str) - 1] = '\0'; | ||
75 | |||
76 | for (p = first, i = 0; i < 8 && p < top; i++, p += 4) { | ||
77 | if (p >= bottom && p < top) { | ||
78 | unsigned int val; | ||
79 | if (__get_user(val, (unsigned int *)p) == 0) | ||
80 | sprintf(str + i * 9, " %08x", val); | ||
81 | else | ||
82 | sprintf(str + i * 9, " ????????"); | ||
83 | } | ||
84 | } | ||
85 | printk("%s%04lx:%s\n", lvl, first & 0xffff, str); | ||
86 | } | ||
87 | |||
88 | set_fs(fs); | ||
89 | } | ||
90 | |||
91 | static void dump_backtrace_entry(unsigned long where, unsigned long stack) | ||
92 | { | ||
93 | print_ip_sym(where); | ||
94 | if (in_exception_text(where)) | ||
95 | dump_mem("", "Exception stack", stack, | ||
96 | stack + sizeof(struct pt_regs)); | ||
97 | } | ||
98 | |||
99 | static void dump_instr(const char *lvl, struct pt_regs *regs) | ||
100 | { | ||
101 | unsigned long addr = instruction_pointer(regs); | ||
102 | mm_segment_t fs; | ||
103 | char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; | ||
104 | int i; | ||
105 | |||
106 | /* | ||
107 | * We need to switch to kernel mode so that we can use __get_user | ||
108 | * to safely read from kernel space. Note that we now dump the | ||
109 | * code first, just in case the backtrace kills us. | ||
110 | */ | ||
111 | fs = get_fs(); | ||
112 | set_fs(KERNEL_DS); | ||
113 | |||
114 | for (i = -4; i < 1; i++) { | ||
115 | unsigned int val, bad; | ||
116 | |||
117 | bad = __get_user(val, &((u32 *)addr)[i]); | ||
118 | |||
119 | if (!bad) | ||
120 | p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val); | ||
121 | else { | ||
122 | p += sprintf(p, "bad PC value"); | ||
123 | break; | ||
124 | } | ||
125 | } | ||
126 | printk("%sCode: %s\n", lvl, str); | ||
127 | |||
128 | set_fs(fs); | ||
129 | } | ||
130 | |||
131 | static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | ||
132 | { | ||
133 | struct stackframe frame; | ||
134 | const register unsigned long current_sp asm ("sp"); | ||
135 | |||
136 | pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); | ||
137 | |||
138 | if (!tsk) | ||
139 | tsk = current; | ||
140 | |||
141 | if (regs) { | ||
142 | frame.fp = regs->regs[29]; | ||
143 | frame.sp = regs->sp; | ||
144 | frame.pc = regs->pc; | ||
145 | } else if (tsk == current) { | ||
146 | frame.fp = (unsigned long)__builtin_frame_address(0); | ||
147 | frame.sp = current_sp; | ||
148 | frame.pc = (unsigned long)dump_backtrace; | ||
149 | } else { | ||
150 | /* | ||
151 | * task blocked in __switch_to | ||
152 | */ | ||
153 | frame.fp = thread_saved_fp(tsk); | ||
154 | frame.sp = thread_saved_sp(tsk); | ||
155 | frame.pc = thread_saved_pc(tsk); | ||
156 | } | ||
157 | |||
158 | printk("Call trace:\n"); | ||
159 | while (1) { | ||
160 | unsigned long where = frame.pc; | ||
161 | int ret; | ||
162 | |||
163 | ret = unwind_frame(&frame); | ||
164 | if (ret < 0) | ||
165 | break; | ||
166 | dump_backtrace_entry(where, frame.sp); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | void dump_stack(void) | ||
171 | { | ||
172 | dump_backtrace(NULL, NULL); | ||
173 | } | ||
174 | |||
175 | EXPORT_SYMBOL(dump_stack); | ||
176 | |||
177 | void show_stack(struct task_struct *tsk, unsigned long *sp) | ||
178 | { | ||
179 | dump_backtrace(NULL, tsk); | ||
180 | barrier(); | ||
181 | } | ||
182 | |||
183 | #ifdef CONFIG_PREEMPT | ||
184 | #define S_PREEMPT " PREEMPT" | ||
185 | #else | ||
186 | #define S_PREEMPT "" | ||
187 | #endif | ||
188 | #ifdef CONFIG_SMP | ||
189 | #define S_SMP " SMP" | ||
190 | #else | ||
191 | #define S_SMP "" | ||
192 | #endif | ||
193 | |||
194 | static int __die(const char *str, int err, struct thread_info *thread, | ||
195 | struct pt_regs *regs) | ||
196 | { | ||
197 | struct task_struct *tsk = thread->task; | ||
198 | static int die_counter; | ||
199 | int ret; | ||
200 | |||
201 | pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", | ||
202 | str, err, ++die_counter); | ||
203 | |||
204 | /* trap and error numbers are mostly meaningless on ARM */ | ||
205 | ret = notify_die(DIE_OOPS, str, regs, err, 0, SIGSEGV); | ||
206 | if (ret == NOTIFY_STOP) | ||
207 | return ret; | ||
208 | |||
209 | print_modules(); | ||
210 | __show_regs(regs); | ||
211 | pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", | ||
212 | TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1); | ||
213 | |||
214 | if (!user_mode(regs) || in_interrupt()) { | ||
215 | dump_mem(KERN_EMERG, "Stack: ", regs->sp, | ||
216 | THREAD_SIZE + (unsigned long)task_stack_page(tsk)); | ||
217 | dump_backtrace(regs, tsk); | ||
218 | dump_instr(KERN_EMERG, regs); | ||
219 | } | ||
220 | |||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | static DEFINE_RAW_SPINLOCK(die_lock); | ||
225 | |||
226 | /* | ||
227 | * This function is protected against re-entrancy. | ||
228 | */ | ||
229 | void die(const char *str, struct pt_regs *regs, int err) | ||
230 | { | ||
231 | struct thread_info *thread = current_thread_info(); | ||
232 | int ret; | ||
233 | |||
234 | oops_enter(); | ||
235 | |||
236 | raw_spin_lock_irq(&die_lock); | ||
237 | console_verbose(); | ||
238 | bust_spinlocks(1); | ||
239 | ret = __die(str, err, thread, regs); | ||
240 | |||
241 | if (regs && kexec_should_crash(thread->task)) | ||
242 | crash_kexec(regs); | ||
243 | |||
244 | bust_spinlocks(0); | ||
245 | add_taint(TAINT_DIE); | ||
246 | raw_spin_unlock_irq(&die_lock); | ||
247 | oops_exit(); | ||
248 | |||
249 | if (in_interrupt()) | ||
250 | panic("Fatal exception in interrupt"); | ||
251 | if (panic_on_oops) | ||
252 | panic("Fatal exception"); | ||
253 | if (ret != NOTIFY_STOP) | ||
254 | do_exit(SIGSEGV); | ||
255 | } | ||
256 | |||
257 | void arm64_notify_die(const char *str, struct pt_regs *regs, | ||
258 | struct siginfo *info, int err) | ||
259 | { | ||
260 | if (user_mode(regs)) | ||
261 | force_sig_info(info->si_signo, info, current); | ||
262 | else | ||
263 | die(str, regs, err); | ||
264 | } | ||
265 | |||
266 | asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | ||
267 | { | ||
268 | siginfo_t info; | ||
269 | void __user *pc = (void __user *)instruction_pointer(regs); | ||
270 | |||
271 | #ifdef CONFIG_COMPAT | ||
272 | /* check for AArch32 breakpoint instructions */ | ||
273 | if (compat_user_mode(regs) && aarch32_break_trap(regs) == 0) | ||
274 | return; | ||
275 | #endif | ||
276 | |||
277 | if (show_unhandled_signals) { | ||
278 | pr_info("%s[%d]: undefined instruction: pc=%p\n", | ||
279 | current->comm, task_pid_nr(current), pc); | ||
280 | dump_instr(KERN_INFO, regs); | ||
281 | } | ||
282 | |||
283 | info.si_signo = SIGILL; | ||
284 | info.si_errno = 0; | ||
285 | info.si_code = ILL_ILLOPC; | ||
286 | info.si_addr = pc; | ||
287 | |||
288 | arm64_notify_die("Oops - undefined instruction", regs, &info, 0); | ||
289 | } | ||
290 | |||
291 | long compat_arm_syscall(struct pt_regs *regs); | ||
292 | |||
293 | asmlinkage long do_ni_syscall(struct pt_regs *regs) | ||
294 | { | ||
295 | #ifdef CONFIG_COMPAT | ||
296 | long ret; | ||
297 | if (is_compat_task()) { | ||
298 | ret = compat_arm_syscall(regs); | ||
299 | if (ret != -ENOSYS) | ||
300 | return ret; | ||
301 | } | ||
302 | #endif | ||
303 | |||
304 | if (show_unhandled_signals) { | ||
305 | pr_info("%s[%d]: syscall %d\n", current->comm, | ||
306 | task_pid_nr(current), (int)regs->syscallno); | ||
307 | dump_instr("", regs); | ||
308 | if (user_mode(regs)) | ||
309 | __show_regs(regs); | ||
310 | } | ||
311 | |||
312 | return sys_ni_syscall(); | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * bad_mode handles the impossible case in the exception vector. | ||
317 | */ | ||
318 | asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr) | ||
319 | { | ||
320 | console_verbose(); | ||
321 | |||
322 | pr_crit("Bad mode in %s handler detected, code 0x%08x\n", | ||
323 | handler[reason], esr); | ||
324 | |||
325 | die("Oops - bad mode", regs, 0); | ||
326 | local_irq_disable(); | ||
327 | panic("bad mode"); | ||
328 | } | ||
329 | |||
330 | void __pte_error(const char *file, int line, unsigned long val) | ||
331 | { | ||
332 | printk("%s:%d: bad pte %016lx.\n", file, line, val); | ||
333 | } | ||
334 | |||
335 | void __pmd_error(const char *file, int line, unsigned long val) | ||
336 | { | ||
337 | printk("%s:%d: bad pmd %016lx.\n", file, line, val); | ||
338 | } | ||
339 | |||
340 | void __pgd_error(const char *file, int line, unsigned long val) | ||
341 | { | ||
342 | printk("%s:%d: bad pgd %016lx.\n", file, line, val); | ||
343 | } | ||
344 | |||
345 | void __init trap_init(void) | ||
346 | { | ||
347 | return; | ||
348 | } | ||
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c new file mode 100644 index 000000000000..17948fc7d663 --- /dev/null +++ b/arch/arm64/kernel/vdso.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * VDSO implementation for AArch64 and vector page setup for AArch32. | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Limited | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Author: Will Deacon <will.deacon@arm.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/clocksource.h> | ||
23 | #include <linux/elf.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/gfp.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/signal.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/vmalloc.h> | ||
32 | |||
33 | #include <asm/cacheflush.h> | ||
34 | #include <asm/signal32.h> | ||
35 | #include <asm/vdso.h> | ||
36 | #include <asm/vdso_datapage.h> | ||
37 | |||
38 | extern char vdso_start, vdso_end; | ||
39 | static unsigned long vdso_pages; | ||
40 | static struct page **vdso_pagelist; | ||
41 | |||
42 | /* | ||
43 | * The vDSO data page. | ||
44 | */ | ||
45 | static union { | ||
46 | struct vdso_data data; | ||
47 | u8 page[PAGE_SIZE]; | ||
48 | } vdso_data_store __page_aligned_data; | ||
49 | struct vdso_data *vdso_data = &vdso_data_store.data; | ||
50 | |||
51 | #ifdef CONFIG_COMPAT | ||
52 | /* | ||
53 | * Create and map the vectors page for AArch32 tasks. | ||
54 | */ | ||
55 | static struct page *vectors_page[1]; | ||
56 | |||
57 | static int alloc_vectors_page(void) | ||
58 | { | ||
59 | extern char __kuser_helper_start[], __kuser_helper_end[]; | ||
60 | int kuser_sz = __kuser_helper_end - __kuser_helper_start; | ||
61 | unsigned long vpage; | ||
62 | |||
63 | vpage = get_zeroed_page(GFP_ATOMIC); | ||
64 | |||
65 | if (!vpage) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | /* kuser helpers */ | ||
69 | memcpy((void *)vpage + 0x1000 - kuser_sz, __kuser_helper_start, | ||
70 | kuser_sz); | ||
71 | |||
72 | /* sigreturn code */ | ||
73 | memcpy((void *)vpage + AARCH32_KERN_SIGRET_CODE_OFFSET, | ||
74 | aarch32_sigret_code, sizeof(aarch32_sigret_code)); | ||
75 | |||
76 | flush_icache_range(vpage, vpage + PAGE_SIZE); | ||
77 | vectors_page[0] = virt_to_page(vpage); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | arch_initcall(alloc_vectors_page); | ||
82 | |||
83 | int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) | ||
84 | { | ||
85 | struct mm_struct *mm = current->mm; | ||
86 | unsigned long addr = AARCH32_VECTORS_BASE; | ||
87 | int ret; | ||
88 | |||
89 | down_write(&mm->mmap_sem); | ||
90 | current->mm->context.vdso = (void *)addr; | ||
91 | |||
92 | /* Map vectors page at the high address. */ | ||
93 | ret = install_special_mapping(mm, addr, PAGE_SIZE, | ||
94 | VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC, | ||
95 | vectors_page); | ||
96 | |||
97 | up_write(&mm->mmap_sem); | ||
98 | |||
99 | return ret; | ||
100 | } | ||
101 | #endif /* CONFIG_COMPAT */ | ||
102 | |||
103 | static int __init vdso_init(void) | ||
104 | { | ||
105 | struct page *pg; | ||
106 | char *vbase; | ||
107 | int i, ret = 0; | ||
108 | |||
109 | vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT; | ||
110 | pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n", | ||
111 | vdso_pages + 1, vdso_pages, 1L, &vdso_start); | ||
112 | |||
113 | /* Allocate the vDSO pagelist, plus a page for the data. */ | ||
114 | vdso_pagelist = kzalloc(sizeof(struct page *) * (vdso_pages + 1), | ||
115 | GFP_KERNEL); | ||
116 | if (vdso_pagelist == NULL) { | ||
117 | pr_err("Failed to allocate vDSO pagelist!\n"); | ||
118 | return -ENOMEM; | ||
119 | } | ||
120 | |||
121 | /* Grab the vDSO code pages. */ | ||
122 | for (i = 0; i < vdso_pages; i++) { | ||
123 | pg = virt_to_page(&vdso_start + i*PAGE_SIZE); | ||
124 | ClearPageReserved(pg); | ||
125 | get_page(pg); | ||
126 | vdso_pagelist[i] = pg; | ||
127 | } | ||
128 | |||
129 | /* Sanity check the shared object header. */ | ||
130 | vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL); | ||
131 | if (vbase == NULL) { | ||
132 | pr_err("Failed to map vDSO pagelist!\n"); | ||
133 | return -ENOMEM; | ||
134 | } else if (memcmp(vbase, "\177ELF", 4)) { | ||
135 | pr_err("vDSO is not a valid ELF object!\n"); | ||
136 | ret = -EINVAL; | ||
137 | goto unmap; | ||
138 | } | ||
139 | |||
140 | /* Grab the vDSO data page. */ | ||
141 | pg = virt_to_page(vdso_data); | ||
142 | get_page(pg); | ||
143 | vdso_pagelist[i] = pg; | ||
144 | |||
145 | unmap: | ||
146 | vunmap(vbase); | ||
147 | return ret; | ||
148 | } | ||
149 | arch_initcall(vdso_init); | ||
150 | |||
151 | int arch_setup_additional_pages(struct linux_binprm *bprm, | ||
152 | int uses_interp) | ||
153 | { | ||
154 | struct mm_struct *mm = current->mm; | ||
155 | unsigned long vdso_base, vdso_mapping_len; | ||
156 | int ret; | ||
157 | |||
158 | /* Be sure to map the data page */ | ||
159 | vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT; | ||
160 | |||
161 | down_write(&mm->mmap_sem); | ||
162 | vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0); | ||
163 | if (IS_ERR_VALUE(vdso_base)) { | ||
164 | ret = vdso_base; | ||
165 | goto up_fail; | ||
166 | } | ||
167 | mm->context.vdso = (void *)vdso_base; | ||
168 | |||
169 | ret = install_special_mapping(mm, vdso_base, vdso_mapping_len, | ||
170 | VM_READ|VM_EXEC| | ||
171 | VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, | ||
172 | vdso_pagelist); | ||
173 | if (ret) { | ||
174 | mm->context.vdso = NULL; | ||
175 | goto up_fail; | ||
176 | } | ||
177 | |||
178 | up_fail: | ||
179 | up_write(&mm->mmap_sem); | ||
180 | |||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | const char *arch_vma_name(struct vm_area_struct *vma) | ||
185 | { | ||
186 | /* | ||
187 | * We can re-use the vdso pointer in mm_context_t for identifying | ||
188 | * the vectors page for compat applications. The vDSO will always | ||
189 | * sit above TASK_UNMAPPED_BASE and so we don't need to worry about | ||
190 | * it conflicting with the vectors base. | ||
191 | */ | ||
192 | if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { | ||
193 | #ifdef CONFIG_COMPAT | ||
194 | if (vma->vm_start == AARCH32_VECTORS_BASE) | ||
195 | return "[vectors]"; | ||
196 | #endif | ||
197 | return "[vdso]"; | ||
198 | } | ||
199 | |||
200 | return NULL; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * We define AT_SYSINFO_EHDR, so we need these function stubs to keep | ||
205 | * Linux happy. | ||
206 | */ | ||
207 | int in_gate_area_no_mm(unsigned long addr) | ||
208 | { | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
213 | { | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
218 | { | ||
219 | return NULL; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * Update the vDSO data page to keep in sync with kernel timekeeping. | ||
224 | */ | ||
225 | void update_vsyscall(struct timespec *ts, struct timespec *wtm, | ||
226 | struct clocksource *clock, u32 mult) | ||
227 | { | ||
228 | struct timespec xtime_coarse; | ||
229 | u32 use_syscall = strcmp(clock->name, "arch_sys_counter"); | ||
230 | |||
231 | ++vdso_data->tb_seq_count; | ||
232 | smp_wmb(); | ||
233 | |||
234 | xtime_coarse = __current_kernel_time(); | ||
235 | vdso_data->use_syscall = use_syscall; | ||
236 | vdso_data->xtime_coarse_sec = xtime_coarse.tv_sec; | ||
237 | vdso_data->xtime_coarse_nsec = xtime_coarse.tv_nsec; | ||
238 | |||
239 | if (!use_syscall) { | ||
240 | vdso_data->cs_cycle_last = clock->cycle_last; | ||
241 | vdso_data->xtime_clock_sec = ts->tv_sec; | ||
242 | vdso_data->xtime_clock_nsec = ts->tv_nsec; | ||
243 | vdso_data->cs_mult = mult; | ||
244 | vdso_data->cs_shift = clock->shift; | ||
245 | vdso_data->wtm_clock_sec = wtm->tv_sec; | ||
246 | vdso_data->wtm_clock_nsec = wtm->tv_nsec; | ||
247 | } | ||
248 | |||
249 | smp_wmb(); | ||
250 | ++vdso_data->tb_seq_count; | ||
251 | } | ||
252 | |||
253 | void update_vsyscall_tz(void) | ||
254 | { | ||
255 | ++vdso_data->tb_seq_count; | ||
256 | smp_wmb(); | ||
257 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; | ||
258 | vdso_data->tz_dsttime = sys_tz.tz_dsttime; | ||
259 | smp_wmb(); | ||
260 | ++vdso_data->tb_seq_count; | ||
261 | } | ||
diff --git a/arch/arm64/kernel/vdso/.gitignore b/arch/arm64/kernel/vdso/.gitignore new file mode 100644 index 000000000000..b8cc94e9698b --- /dev/null +++ b/arch/arm64/kernel/vdso/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | vdso.lds | ||
2 | vdso-offsets.h | ||
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile new file mode 100644 index 000000000000..d8064af42e62 --- /dev/null +++ b/arch/arm64/kernel/vdso/Makefile | |||
@@ -0,0 +1,63 @@ | |||
1 | # | ||
2 | # Building a vDSO image for AArch64. | ||
3 | # | ||
4 | # Author: Will Deacon <will.deacon@arm.com> | ||
5 | # Heavily based on the vDSO Makefiles for other archs. | ||
6 | # | ||
7 | |||
8 | obj-vdso := gettimeofday.o note.o sigreturn.o | ||
9 | |||
10 | # Build rules | ||
11 | targets := $(obj-vdso) vdso.so vdso.so.dbg | ||
12 | obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) | ||
13 | |||
14 | ccflags-y := -shared -fno-common -fno-builtin | ||
15 | ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \ | ||
16 | $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) | ||
17 | |||
18 | obj-y += vdso.o | ||
19 | extra-y += vdso.lds vdso-offsets.h | ||
20 | CPPFLAGS_vdso.lds += -P -C -U$(ARCH) | ||
21 | |||
22 | # Force dependency (incbin is bad) | ||
23 | $(obj)/vdso.o : $(obj)/vdso.so | ||
24 | |||
25 | # Link rule for the .so file, .lds has to be first | ||
26 | $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) | ||
27 | $(call if_changed,vdsold) | ||
28 | |||
29 | # Strip rule for the .so file | ||
30 | $(obj)/%.so: OBJCOPYFLAGS := -S | ||
31 | $(obj)/%.so: $(obj)/%.so.dbg FORCE | ||
32 | $(call if_changed,objcopy) | ||
33 | |||
34 | # Generate VDSO offsets using helper script | ||
35 | gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh | ||
36 | quiet_cmd_vdsosym = VDSOSYM $@ | ||
37 | define cmd_vdsosym | ||
38 | $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \ | ||
39 | cp $@ include/generated/ | ||
40 | endef | ||
41 | |||
42 | $(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE | ||
43 | $(call if_changed,vdsosym) | ||
44 | |||
45 | # Assembly rules for the .S files | ||
46 | $(obj-vdso): %.o: %.S | ||
47 | $(call if_changed_dep,vdsoas) | ||
48 | |||
49 | # Actual build commands | ||
50 | quiet_cmd_vdsold = VDSOL $@ | ||
51 | cmd_vdsold = $(CC) $(c_flags) -Wl,-T $^ -o $@ | ||
52 | quiet_cmd_vdsoas = VDSOA $@ | ||
53 | cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $< | ||
54 | |||
55 | # Install commands for the unstripped file | ||
56 | quiet_cmd_vdso_install = INSTALL $@ | ||
57 | cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ | ||
58 | |||
59 | vdso.so: $(obj)/vdso.so.dbg | ||
60 | @mkdir -p $(MODLIB)/vdso | ||
61 | $(call cmd,vdso_install) | ||
62 | |||
63 | vdso_install: vdso.so | ||
diff --git a/arch/arm64/kernel/vdso/gen_vdso_offsets.sh b/arch/arm64/kernel/vdso/gen_vdso_offsets.sh new file mode 100755 index 000000000000..01924ff071ad --- /dev/null +++ b/arch/arm64/kernel/vdso/gen_vdso_offsets.sh | |||
@@ -0,0 +1,15 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # | ||
4 | # Match symbols in the DSO that look like VDSO_*; produce a header file | ||
5 | # of constant offsets into the shared object. | ||
6 | # | ||
7 | # Doing this inside the Makefile will break the $(filter-out) function, | ||
8 | # causing Kbuild to rebuild the vdso-offsets header file every time. | ||
9 | # | ||
10 | # Author: Will Deacon <will.deacon@arm.com | ||
11 | # | ||
12 | |||
13 | LC_ALL=C | ||
14 | sed -n -e 's/^00*/0/' -e \ | ||
15 | 's/^\([0-9a-fA-F]*\) . VDSO_\([a-zA-Z0-9_]*\)$/\#define vdso_offset_\2\t0x\1/p' | ||
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S new file mode 100644 index 000000000000..dcb8c203a3b2 --- /dev/null +++ b/arch/arm64/kernel/vdso/gettimeofday.S | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * Userspace implementations of gettimeofday() and friends. | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Limited | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Author: Will Deacon <will.deacon@arm.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/linkage.h> | ||
22 | #include <asm/asm-offsets.h> | ||
23 | #include <asm/unistd.h> | ||
24 | |||
25 | #define NSEC_PER_SEC_LO16 0xca00 | ||
26 | #define NSEC_PER_SEC_HI16 0x3b9a | ||
27 | |||
28 | vdso_data .req x6 | ||
29 | use_syscall .req w7 | ||
30 | seqcnt .req w8 | ||
31 | |||
32 | .macro seqcnt_acquire | ||
33 | 9999: ldr seqcnt, [vdso_data, #VDSO_TB_SEQ_COUNT] | ||
34 | tbnz seqcnt, #0, 9999b | ||
35 | dmb ishld | ||
36 | ldr use_syscall, [vdso_data, #VDSO_USE_SYSCALL] | ||
37 | .endm | ||
38 | |||
39 | .macro seqcnt_read, cnt | ||
40 | dmb ishld | ||
41 | ldr \cnt, [vdso_data, #VDSO_TB_SEQ_COUNT] | ||
42 | .endm | ||
43 | |||
44 | .macro seqcnt_check, cnt, fail | ||
45 | cmp \cnt, seqcnt | ||
46 | b.ne \fail | ||
47 | .endm | ||
48 | |||
49 | .text | ||
50 | |||
51 | /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */ | ||
52 | ENTRY(__kernel_gettimeofday) | ||
53 | .cfi_startproc | ||
54 | mov x2, x30 | ||
55 | .cfi_register x30, x2 | ||
56 | |||
57 | /* Acquire the sequence counter and get the timespec. */ | ||
58 | adr vdso_data, _vdso_data | ||
59 | 1: seqcnt_acquire | ||
60 | cbnz use_syscall, 4f | ||
61 | |||
62 | /* If tv is NULL, skip to the timezone code. */ | ||
63 | cbz x0, 2f | ||
64 | bl __do_get_tspec | ||
65 | seqcnt_check w13, 1b | ||
66 | |||
67 | /* Convert ns to us. */ | ||
68 | mov x11, #1000 | ||
69 | udiv x10, x10, x11 | ||
70 | stp x9, x10, [x0, #TVAL_TV_SEC] | ||
71 | 2: | ||
72 | /* If tz is NULL, return 0. */ | ||
73 | cbz x1, 3f | ||
74 | ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST] | ||
75 | seqcnt_read w13 | ||
76 | seqcnt_check w13, 1b | ||
77 | stp w4, w5, [x1, #TZ_MINWEST] | ||
78 | 3: | ||
79 | mov x0, xzr | ||
80 | ret x2 | ||
81 | 4: | ||
82 | /* Syscall fallback. */ | ||
83 | mov x8, #__NR_gettimeofday | ||
84 | svc #0 | ||
85 | ret x2 | ||
86 | .cfi_endproc | ||
87 | ENDPROC(__kernel_gettimeofday) | ||
88 | |||
89 | /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */ | ||
90 | ENTRY(__kernel_clock_gettime) | ||
91 | .cfi_startproc | ||
92 | cmp w0, #CLOCK_REALTIME | ||
93 | ccmp w0, #CLOCK_MONOTONIC, #0x4, ne | ||
94 | b.ne 2f | ||
95 | |||
96 | mov x2, x30 | ||
97 | .cfi_register x30, x2 | ||
98 | |||
99 | /* Get kernel timespec. */ | ||
100 | adr vdso_data, _vdso_data | ||
101 | 1: seqcnt_acquire | ||
102 | cbnz use_syscall, 7f | ||
103 | |||
104 | bl __do_get_tspec | ||
105 | seqcnt_check w13, 1b | ||
106 | |||
107 | cmp w0, #CLOCK_MONOTONIC | ||
108 | b.ne 6f | ||
109 | |||
110 | /* Get wtm timespec. */ | ||
111 | ldp x14, x15, [vdso_data, #VDSO_WTM_CLK_SEC] | ||
112 | |||
113 | /* Check the sequence counter. */ | ||
114 | seqcnt_read w13 | ||
115 | seqcnt_check w13, 1b | ||
116 | b 4f | ||
117 | 2: | ||
118 | cmp w0, #CLOCK_REALTIME_COARSE | ||
119 | ccmp w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne | ||
120 | b.ne 8f | ||
121 | |||
122 | /* Get coarse timespec. */ | ||
123 | adr vdso_data, _vdso_data | ||
124 | 3: seqcnt_acquire | ||
125 | ldp x9, x10, [vdso_data, #VDSO_XTIME_CRS_SEC] | ||
126 | |||
127 | cmp w0, #CLOCK_MONOTONIC_COARSE | ||
128 | b.ne 6f | ||
129 | |||
130 | /* Get wtm timespec. */ | ||
131 | ldp x14, x15, [vdso_data, #VDSO_WTM_CLK_SEC] | ||
132 | |||
133 | /* Check the sequence counter. */ | ||
134 | seqcnt_read w13 | ||
135 | seqcnt_check w13, 3b | ||
136 | 4: | ||
137 | /* Add on wtm timespec. */ | ||
138 | add x9, x9, x14 | ||
139 | add x10, x10, x15 | ||
140 | |||
141 | /* Normalise the new timespec. */ | ||
142 | mov x14, #NSEC_PER_SEC_LO16 | ||
143 | movk x14, #NSEC_PER_SEC_HI16, lsl #16 | ||
144 | cmp x10, x14 | ||
145 | b.lt 5f | ||
146 | sub x10, x10, x14 | ||
147 | add x9, x9, #1 | ||
148 | 5: | ||
149 | cmp x10, #0 | ||
150 | b.ge 6f | ||
151 | add x10, x10, x14 | ||
152 | sub x9, x9, #1 | ||
153 | |||
154 | 6: /* Store to the user timespec. */ | ||
155 | stp x9, x10, [x1, #TSPEC_TV_SEC] | ||
156 | mov x0, xzr | ||
157 | ret x2 | ||
158 | 7: | ||
159 | mov x30, x2 | ||
160 | 8: /* Syscall fallback. */ | ||
161 | mov x8, #__NR_clock_gettime | ||
162 | svc #0 | ||
163 | ret | ||
164 | .cfi_endproc | ||
165 | ENDPROC(__kernel_clock_gettime) | ||
166 | |||
167 | /* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */ | ||
168 | ENTRY(__kernel_clock_getres) | ||
169 | .cfi_startproc | ||
170 | cbz w1, 3f | ||
171 | |||
172 | cmp w0, #CLOCK_REALTIME | ||
173 | ccmp w0, #CLOCK_MONOTONIC, #0x4, ne | ||
174 | b.ne 1f | ||
175 | |||
176 | ldr x2, 5f | ||
177 | b 2f | ||
178 | 1: | ||
179 | cmp w0, #CLOCK_REALTIME_COARSE | ||
180 | ccmp w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne | ||
181 | b.ne 4f | ||
182 | ldr x2, 6f | ||
183 | 2: | ||
184 | stp xzr, x2, [x1] | ||
185 | |||
186 | 3: /* res == NULL. */ | ||
187 | mov w0, wzr | ||
188 | ret | ||
189 | |||
190 | 4: /* Syscall fallback. */ | ||
191 | mov x8, #__NR_clock_getres | ||
192 | svc #0 | ||
193 | ret | ||
194 | 5: | ||
195 | .quad CLOCK_REALTIME_RES | ||
196 | 6: | ||
197 | .quad CLOCK_COARSE_RES | ||
198 | .cfi_endproc | ||
199 | ENDPROC(__kernel_clock_getres) | ||
200 | |||
201 | /* | ||
202 | * Read the current time from the architected counter. | ||
203 | * Expects vdso_data to be initialised. | ||
204 | * Clobbers the temporary registers (x9 - x15). | ||
205 | * Returns: | ||
206 | * - (x9, x10) = (ts->tv_sec, ts->tv_nsec) | ||
207 | * - (x11, x12) = (xtime->tv_sec, xtime->tv_nsec) | ||
208 | * - w13 = vDSO sequence counter | ||
209 | */ | ||
210 | ENTRY(__do_get_tspec) | ||
211 | .cfi_startproc | ||
212 | |||
213 | /* Read from the vDSO data page. */ | ||
214 | ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST] | ||
215 | ldp x11, x12, [vdso_data, #VDSO_XTIME_CLK_SEC] | ||
216 | ldp w14, w15, [vdso_data, #VDSO_CS_MULT] | ||
217 | seqcnt_read w13 | ||
218 | |||
219 | /* Read the physical counter. */ | ||
220 | isb | ||
221 | mrs x9, cntpct_el0 | ||
222 | |||
223 | /* Calculate cycle delta and convert to ns. */ | ||
224 | sub x10, x9, x10 | ||
225 | /* We can only guarantee 56 bits of precision. */ | ||
226 | movn x9, #0xff0, lsl #48 | ||
227 | and x10, x9, x10 | ||
228 | mul x10, x10, x14 | ||
229 | lsr x10, x10, x15 | ||
230 | |||
231 | /* Use the kernel time to calculate the new timespec. */ | ||
232 | add x10, x12, x10 | ||
233 | mov x14, #NSEC_PER_SEC_LO16 | ||
234 | movk x14, #NSEC_PER_SEC_HI16, lsl #16 | ||
235 | udiv x15, x10, x14 | ||
236 | add x9, x15, x11 | ||
237 | mul x14, x14, x15 | ||
238 | sub x10, x10, x14 | ||
239 | |||
240 | ret | ||
241 | .cfi_endproc | ||
242 | ENDPROC(__do_get_tspec) | ||
diff --git a/arch/arm64/kernel/vdso/note.S b/arch/arm64/kernel/vdso/note.S new file mode 100644 index 000000000000..b82c85e5d972 --- /dev/null +++ b/arch/arm64/kernel/vdso/note.S | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Limited | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | * | ||
16 | * Author: Will Deacon <will.deacon@arm.com> | ||
17 | * | ||
18 | * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. | ||
19 | * Here we can supply some information useful to userland. | ||
20 | */ | ||
21 | |||
22 | #include <linux/uts.h> | ||
23 | #include <linux/version.h> | ||
24 | #include <linux/elfnote.h> | ||
25 | |||
26 | ELFNOTE_START(Linux, 0, "a") | ||
27 | .long LINUX_VERSION_CODE | ||
28 | ELFNOTE_END | ||
diff --git a/arch/arm64/kernel/vdso/sigreturn.S b/arch/arm64/kernel/vdso/sigreturn.S new file mode 100644 index 000000000000..20d98effa7dd --- /dev/null +++ b/arch/arm64/kernel/vdso/sigreturn.S | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Sigreturn trampoline for returning from a signal when the SA_RESTORER | ||
3 | * flag is not set. | ||
4 | * | ||
5 | * Copyright (C) 2012 ARM Limited | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | * | ||
19 | * Author: Will Deacon <will.deacon@arm.com> | ||
20 | */ | ||
21 | |||
22 | #include <linux/linkage.h> | ||
23 | #include <asm/unistd.h> | ||
24 | |||
25 | .text | ||
26 | |||
27 | nop | ||
28 | ENTRY(__kernel_rt_sigreturn) | ||
29 | .cfi_startproc | ||
30 | .cfi_signal_frame | ||
31 | .cfi_def_cfa x29, 0 | ||
32 | .cfi_offset x29, 0 * 8 | ||
33 | .cfi_offset x30, 1 * 8 | ||
34 | mov x8, #__NR_rt_sigreturn | ||
35 | svc #0 | ||
36 | .cfi_endproc | ||
37 | ENDPROC(__kernel_rt_sigreturn) | ||
diff --git a/arch/arm64/kernel/vdso/vdso.S b/arch/arm64/kernel/vdso/vdso.S new file mode 100644 index 000000000000..60c1db54b41a --- /dev/null +++ b/arch/arm64/kernel/vdso/vdso.S | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Limited | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | * | ||
16 | * Author: Will Deacon <will.deacon@arm.com> | ||
17 | */ | ||
18 | |||
19 | #include <linux/init.h> | ||
20 | #include <linux/linkage.h> | ||
21 | #include <linux/const.h> | ||
22 | #include <asm/page.h> | ||
23 | |||
24 | __PAGE_ALIGNED_DATA | ||
25 | |||
26 | .globl vdso_start, vdso_end | ||
27 | .balign PAGE_SIZE | ||
28 | vdso_start: | ||
29 | .incbin "arch/arm64/kernel/vdso/vdso.so" | ||
30 | .balign PAGE_SIZE | ||
31 | vdso_end: | ||
32 | |||
33 | .previous | ||
diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S new file mode 100644 index 000000000000..8154b8d1c826 --- /dev/null +++ b/arch/arm64/kernel/vdso/vdso.lds.S | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * GNU linker script for the VDSO library. | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Limited | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Author: Will Deacon <will.deacon@arm.com> | ||
19 | * Heavily based on the vDSO linker scripts for other archs. | ||
20 | */ | ||
21 | |||
22 | #include <linux/const.h> | ||
23 | #include <asm/page.h> | ||
24 | #include <asm/vdso.h> | ||
25 | |||
26 | OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64") | ||
27 | OUTPUT_ARCH(aarch64) | ||
28 | |||
29 | SECTIONS | ||
30 | { | ||
31 | . = VDSO_LBASE + SIZEOF_HEADERS; | ||
32 | |||
33 | .hash : { *(.hash) } :text | ||
34 | .gnu.hash : { *(.gnu.hash) } | ||
35 | .dynsym : { *(.dynsym) } | ||
36 | .dynstr : { *(.dynstr) } | ||
37 | .gnu.version : { *(.gnu.version) } | ||
38 | .gnu.version_d : { *(.gnu.version_d) } | ||
39 | .gnu.version_r : { *(.gnu.version_r) } | ||
40 | |||
41 | .note : { *(.note.*) } :text :note | ||
42 | |||
43 | . = ALIGN(16); | ||
44 | |||
45 | .text : { *(.text*) } :text =0xd503201f | ||
46 | PROVIDE (__etext = .); | ||
47 | PROVIDE (_etext = .); | ||
48 | PROVIDE (etext = .); | ||
49 | |||
50 | .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr | ||
51 | .eh_frame : { KEEP (*(.eh_frame)) } :text | ||
52 | |||
53 | .dynamic : { *(.dynamic) } :text :dynamic | ||
54 | |||
55 | .rodata : { *(.rodata*) } :text | ||
56 | |||
57 | _end = .; | ||
58 | PROVIDE(end = .); | ||
59 | |||
60 | . = ALIGN(PAGE_SIZE); | ||
61 | PROVIDE(_vdso_data = .); | ||
62 | |||
63 | /DISCARD/ : { | ||
64 | *(.note.GNU-stack) | ||
65 | *(.data .data.* .gnu.linkonce.d.* .sdata*) | ||
66 | *(.bss .sbss .dynbss .dynsbss) | ||
67 | } | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * We must supply the ELF program headers explicitly to get just one | ||
72 | * PT_LOAD segment, and set the flags explicitly to make segments read-only. | ||
73 | */ | ||
74 | PHDRS | ||
75 | { | ||
76 | text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */ | ||
77 | dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ | ||
78 | note PT_NOTE FLAGS(4); /* PF_R */ | ||
79 | eh_frame_hdr PT_GNU_EH_FRAME; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * This controls what symbols we export from the DSO. | ||
84 | */ | ||
85 | VERSION | ||
86 | { | ||
87 | LINUX_2.6.39 { | ||
88 | global: | ||
89 | __kernel_rt_sigreturn; | ||
90 | __kernel_gettimeofday; | ||
91 | __kernel_clock_gettime; | ||
92 | __kernel_clock_getres; | ||
93 | local: *; | ||
94 | }; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * Make the sigreturn code visible to the kernel. | ||
99 | */ | ||
100 | VDSO_sigtramp = __kernel_rt_sigreturn; | ||
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..3fae2be8b016 --- /dev/null +++ b/arch/arm64/kernel/vmlinux.lds.S | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * ld script to make ARM Linux kernel | ||
3 | * taken from the i386 version by Russell King | ||
4 | * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> | ||
5 | */ | ||
6 | |||
7 | #include <asm-generic/vmlinux.lds.h> | ||
8 | #include <asm/thread_info.h> | ||
9 | #include <asm/memory.h> | ||
10 | #include <asm/page.h> | ||
11 | |||
12 | #define ARM_EXIT_KEEP(x) | ||
13 | #define ARM_EXIT_DISCARD(x) x | ||
14 | |||
15 | OUTPUT_ARCH(aarch64) | ||
16 | ENTRY(stext) | ||
17 | |||
18 | jiffies = jiffies_64; | ||
19 | |||
20 | SECTIONS | ||
21 | { | ||
22 | /* | ||
23 | * XXX: The linker does not define how output sections are | ||
24 | * assigned to input sections when there are multiple statements | ||
25 | * matching the same input section name. There is no documented | ||
26 | * order of matching. | ||
27 | */ | ||
28 | /DISCARD/ : { | ||
29 | ARM_EXIT_DISCARD(EXIT_TEXT) | ||
30 | ARM_EXIT_DISCARD(EXIT_DATA) | ||
31 | EXIT_CALL | ||
32 | *(.discard) | ||
33 | *(.discard.*) | ||
34 | } | ||
35 | |||
36 | . = PAGE_OFFSET + TEXT_OFFSET; | ||
37 | |||
38 | .head.text : { | ||
39 | _text = .; | ||
40 | HEAD_TEXT | ||
41 | } | ||
42 | .text : { /* Real text segment */ | ||
43 | _stext = .; /* Text and read-only data */ | ||
44 | *(.smp.pen.text) | ||
45 | __exception_text_start = .; | ||
46 | *(.exception.text) | ||
47 | __exception_text_end = .; | ||
48 | IRQENTRY_TEXT | ||
49 | TEXT_TEXT | ||
50 | SCHED_TEXT | ||
51 | LOCK_TEXT | ||
52 | *(.fixup) | ||
53 | *(.gnu.warning) | ||
54 | . = ALIGN(16); | ||
55 | *(.got) /* Global offset table */ | ||
56 | } | ||
57 | |||
58 | RO_DATA(PAGE_SIZE) | ||
59 | |||
60 | _etext = .; /* End of text and rodata section */ | ||
61 | |||
62 | . = ALIGN(PAGE_SIZE); | ||
63 | __init_begin = .; | ||
64 | |||
65 | INIT_TEXT_SECTION(8) | ||
66 | .exit.text : { | ||
67 | ARM_EXIT_KEEP(EXIT_TEXT) | ||
68 | } | ||
69 | . = ALIGN(16); | ||
70 | .init.data : { | ||
71 | INIT_DATA | ||
72 | INIT_SETUP(16) | ||
73 | INIT_CALLS | ||
74 | CON_INITCALL | ||
75 | SECURITY_INITCALL | ||
76 | INIT_RAM_FS | ||
77 | } | ||
78 | .exit.data : { | ||
79 | ARM_EXIT_KEEP(EXIT_DATA) | ||
80 | } | ||
81 | |||
82 | PERCPU_SECTION(64) | ||
83 | |||
84 | __init_end = .; | ||
85 | . = ALIGN(THREAD_SIZE); | ||
86 | __data_loc = .; | ||
87 | |||
88 | .data : AT(__data_loc) { | ||
89 | _data = .; /* address in memory */ | ||
90 | _sdata = .; | ||
91 | |||
92 | /* | ||
93 | * first, the init task union, aligned | ||
94 | * to an 8192 byte boundary. | ||
95 | */ | ||
96 | INIT_TASK_DATA(THREAD_SIZE) | ||
97 | NOSAVE_DATA | ||
98 | CACHELINE_ALIGNED_DATA(64) | ||
99 | READ_MOSTLY_DATA(64) | ||
100 | |||
101 | /* | ||
102 | * The exception fixup table (might need resorting at runtime) | ||
103 | */ | ||
104 | . = ALIGN(32); | ||
105 | __start___ex_table = .; | ||
106 | *(__ex_table) | ||
107 | __stop___ex_table = .; | ||
108 | |||
109 | /* | ||
110 | * and the usual data section | ||
111 | */ | ||
112 | DATA_DATA | ||
113 | CONSTRUCTORS | ||
114 | |||
115 | _edata = .; | ||
116 | } | ||
117 | _edata_loc = __data_loc + SIZEOF(.data); | ||
118 | |||
119 | NOTES | ||
120 | |||
121 | BSS_SECTION(0, 0, 0) | ||
122 | _end = .; | ||
123 | |||
124 | STABS_DEBUG | ||
125 | .comment 0 : { *(.comment) } | ||
126 | } | ||
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile new file mode 100644 index 000000000000..2fb7f6092aae --- /dev/null +++ b/arch/arm64/lib/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | lib-y := bitops.o delay.o \ | ||
2 | strncpy_from_user.o strnlen_user.o clear_user.o \ | ||
3 | copy_from_user.o copy_to_user.o copy_in_user.o \ | ||
4 | copy_page.o clear_page.o | ||
diff --git a/arch/arm64/lib/bitops.c b/arch/arm64/lib/bitops.c new file mode 100644 index 000000000000..aa4965e60acc --- /dev/null +++ b/arch/arm64/lib/bitops.c | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Limited | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/atomic.h> | ||
20 | |||
21 | #ifdef CONFIG_SMP | ||
22 | arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { | ||
23 | [0 ... (ATOMIC_HASH_SIZE-1)] = __ARCH_SPIN_LOCK_UNLOCKED | ||
24 | }; | ||
25 | #endif | ||
diff --git a/arch/arm64/lib/clear_page.S b/arch/arm64/lib/clear_page.S new file mode 100644 index 000000000000..ef08e905e35b --- /dev/null +++ b/arch/arm64/lib/clear_page.S | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <linux/const.h> | ||
19 | #include <asm/assembler.h> | ||
20 | #include <asm/page.h> | ||
21 | |||
22 | /* | ||
23 | * Clear page @dest | ||
24 | * | ||
25 | * Parameters: | ||
26 | * x0 - dest | ||
27 | */ | ||
28 | ENTRY(clear_page) | ||
29 | mrs x1, dczid_el0 | ||
30 | and w1, w1, #0xf | ||
31 | mov x2, #4 | ||
32 | lsl x1, x2, x1 | ||
33 | |||
34 | 1: dc zva, x0 | ||
35 | add x0, x0, x1 | ||
36 | tst x0, #(PAGE_SIZE - 1) | ||
37 | b.ne 1b | ||
38 | ret | ||
39 | ENDPROC(clear_page) | ||
diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S new file mode 100644 index 000000000000..6e0ed93d51fe --- /dev/null +++ b/arch/arm64/lib/clear_user.S | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/lib/clear_user.S | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | #include <linux/linkage.h> | ||
19 | #include <asm/assembler.h> | ||
20 | |||
21 | .text | ||
22 | |||
23 | /* Prototype: int __clear_user(void *addr, size_t sz) | ||
24 | * Purpose : clear some user memory | ||
25 | * Params : addr - user memory address to clear | ||
26 | * : sz - number of bytes to clear | ||
27 | * Returns : number of bytes NOT cleared | ||
28 | * | ||
29 | * Alignment fixed up by hardware. | ||
30 | */ | ||
31 | ENTRY(__clear_user) | ||
32 | mov x2, x1 // save the size for fixup return | ||
33 | subs x1, x1, #8 | ||
34 | b.mi 2f | ||
35 | 1: | ||
36 | USER(9f, str xzr, [x0], #8 ) | ||
37 | subs x1, x1, #8 | ||
38 | b.pl 1b | ||
39 | 2: adds x1, x1, #4 | ||
40 | b.mi 3f | ||
41 | USER(9f, str wzr, [x0], #4 ) | ||
42 | sub x1, x1, #4 | ||
43 | 3: adds x1, x1, #2 | ||
44 | b.mi 4f | ||
45 | USER(9f, strh wzr, [x0], #2 ) | ||
46 | sub x1, x1, #2 | ||
47 | 4: adds x1, x1, #1 | ||
48 | b.mi 5f | ||
49 | strb wzr, [x0] | ||
50 | 5: mov x0, #0 | ||
51 | ret | ||
52 | ENDPROC(__clear_user) | ||
53 | |||
54 | .section .fixup,"ax" | ||
55 | .align 2 | ||
56 | 9: mov x0, x2 // return the original size | ||
57 | ret | ||
58 | .previous | ||
diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S new file mode 100644 index 000000000000..5e27add9d362 --- /dev/null +++ b/arch/arm64/lib/copy_from_user.S | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <asm/assembler.h> | ||
19 | |||
20 | /* | ||
21 | * Copy from user space to a kernel buffer (alignment handled by the hardware) | ||
22 | * | ||
23 | * Parameters: | ||
24 | * x0 - to | ||
25 | * x1 - from | ||
26 | * x2 - n | ||
27 | * Returns: | ||
28 | * x0 - bytes not copied | ||
29 | */ | ||
30 | ENTRY(__copy_from_user) | ||
31 | add x4, x1, x2 // upper user buffer boundary | ||
32 | subs x2, x2, #8 | ||
33 | b.mi 2f | ||
34 | 1: | ||
35 | USER(9f, ldr x3, [x1], #8 ) | ||
36 | subs x2, x2, #8 | ||
37 | str x3, [x0], #8 | ||
38 | b.pl 1b | ||
39 | 2: adds x2, x2, #4 | ||
40 | b.mi 3f | ||
41 | USER(9f, ldr w3, [x1], #4 ) | ||
42 | sub x2, x2, #4 | ||
43 | str w3, [x0], #4 | ||
44 | 3: adds x2, x2, #2 | ||
45 | b.mi 4f | ||
46 | USER(9f, ldrh w3, [x1], #2 ) | ||
47 | sub x2, x2, #2 | ||
48 | strh w3, [x0], #2 | ||
49 | 4: adds x2, x2, #1 | ||
50 | b.mi 5f | ||
51 | USER(9f, ldrb w3, [x1] ) | ||
52 | strb w3, [x0] | ||
53 | 5: mov x0, #0 | ||
54 | ret | ||
55 | ENDPROC(__copy_from_user) | ||
56 | |||
57 | .section .fixup,"ax" | ||
58 | .align 2 | ||
59 | 9: sub x2, x4, x1 | ||
60 | mov x3, x2 | ||
61 | 10: strb wzr, [x0], #1 // zero remaining buffer space | ||
62 | subs x3, x3, #1 | ||
63 | b.ne 10b | ||
64 | mov x0, x2 // bytes not copied | ||
65 | ret | ||
66 | .previous | ||
diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S new file mode 100644 index 000000000000..84b6c9bb9b93 --- /dev/null +++ b/arch/arm64/lib/copy_in_user.S | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copy from user space to user space | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/linkage.h> | ||
20 | #include <asm/assembler.h> | ||
21 | |||
22 | /* | ||
23 | * Copy from user space to user space (alignment handled by the hardware) | ||
24 | * | ||
25 | * Parameters: | ||
26 | * x0 - to | ||
27 | * x1 - from | ||
28 | * x2 - n | ||
29 | * Returns: | ||
30 | * x0 - bytes not copied | ||
31 | */ | ||
32 | ENTRY(__copy_in_user) | ||
33 | add x4, x0, x2 // upper user buffer boundary | ||
34 | subs x2, x2, #8 | ||
35 | b.mi 2f | ||
36 | 1: | ||
37 | USER(9f, ldr x3, [x1], #8 ) | ||
38 | subs x2, x2, #8 | ||
39 | USER(9f, str x3, [x0], #8 ) | ||
40 | b.pl 1b | ||
41 | 2: adds x2, x2, #4 | ||
42 | b.mi 3f | ||
43 | USER(9f, ldr w3, [x1], #4 ) | ||
44 | sub x2, x2, #4 | ||
45 | USER(9f, str w3, [x0], #4 ) | ||
46 | 3: adds x2, x2, #2 | ||
47 | b.mi 4f | ||
48 | USER(9f, ldrh w3, [x1], #2 ) | ||
49 | sub x2, x2, #2 | ||
50 | USER(9f, strh w3, [x0], #2 ) | ||
51 | 4: adds x2, x2, #1 | ||
52 | b.mi 5f | ||
53 | USER(9f, ldrb w3, [x1] ) | ||
54 | USER(9f, strb w3, [x0] ) | ||
55 | 5: mov x0, #0 | ||
56 | ret | ||
57 | ENDPROC(__copy_in_user) | ||
58 | |||
59 | .section .fixup,"ax" | ||
60 | .align 2 | ||
61 | 9: sub x0, x4, x0 // bytes not copied | ||
62 | ret | ||
63 | .previous | ||
diff --git a/arch/arm64/lib/copy_page.S b/arch/arm64/lib/copy_page.S new file mode 100644 index 000000000000..512b9a7b980e --- /dev/null +++ b/arch/arm64/lib/copy_page.S | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <linux/const.h> | ||
19 | #include <asm/assembler.h> | ||
20 | #include <asm/page.h> | ||
21 | |||
22 | /* | ||
23 | * Copy a page from src to dest (both are page aligned) | ||
24 | * | ||
25 | * Parameters: | ||
26 | * x0 - dest | ||
27 | * x1 - src | ||
28 | */ | ||
29 | ENTRY(copy_page) | ||
30 | /* Assume cache line size is 64 bytes. */ | ||
31 | prfm pldl1strm, [x1, #64] | ||
32 | 1: ldp x2, x3, [x1] | ||
33 | ldp x4, x5, [x1, #16] | ||
34 | ldp x6, x7, [x1, #32] | ||
35 | ldp x8, x9, [x1, #48] | ||
36 | add x1, x1, #64 | ||
37 | prfm pldl1strm, [x1, #64] | ||
38 | stnp x2, x3, [x0] | ||
39 | stnp x4, x5, [x0, #16] | ||
40 | stnp x6, x7, [x0, #32] | ||
41 | stnp x8, x9, [x0, #48] | ||
42 | add x0, x0, #64 | ||
43 | tst x1, #(PAGE_SIZE - 1) | ||
44 | b.ne 1b | ||
45 | ret | ||
46 | ENDPROC(copy_page) | ||
diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S new file mode 100644 index 000000000000..a0aeeb9b7a28 --- /dev/null +++ b/arch/arm64/lib/copy_to_user.S | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <asm/assembler.h> | ||
19 | |||
20 | /* | ||
21 | * Copy to user space from a kernel buffer (alignment handled by the hardware) | ||
22 | * | ||
23 | * Parameters: | ||
24 | * x0 - to | ||
25 | * x1 - from | ||
26 | * x2 - n | ||
27 | * Returns: | ||
28 | * x0 - bytes not copied | ||
29 | */ | ||
30 | ENTRY(__copy_to_user) | ||
31 | add x4, x0, x2 // upper user buffer boundary | ||
32 | subs x2, x2, #8 | ||
33 | b.mi 2f | ||
34 | 1: | ||
35 | ldr x3, [x1], #8 | ||
36 | subs x2, x2, #8 | ||
37 | USER(9f, str x3, [x0], #8 ) | ||
38 | b.pl 1b | ||
39 | 2: adds x2, x2, #4 | ||
40 | b.mi 3f | ||
41 | ldr w3, [x1], #4 | ||
42 | sub x2, x2, #4 | ||
43 | USER(9f, str w3, [x0], #4 ) | ||
44 | 3: adds x2, x2, #2 | ||
45 | b.mi 4f | ||
46 | ldrh w3, [x1], #2 | ||
47 | sub x2, x2, #2 | ||
48 | USER(9f, strh w3, [x0], #2 ) | ||
49 | 4: adds x2, x2, #1 | ||
50 | b.mi 5f | ||
51 | ldrb w3, [x1] | ||
52 | USER(9f, strb w3, [x0] ) | ||
53 | 5: mov x0, #0 | ||
54 | ret | ||
55 | ENDPROC(__copy_to_user) | ||
56 | |||
57 | .section .fixup,"ax" | ||
58 | .align 2 | ||
59 | 9: sub x0, x4, x0 // bytes not copied | ||
60 | ret | ||
61 | .previous | ||
diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c new file mode 100644 index 000000000000..dad4ec9bbfd1 --- /dev/null +++ b/arch/arm64/lib/delay.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Delay loops based on the OpenRISC implementation. | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Limited | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * Author: Will Deacon <will.deacon@arm.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/timex.h> | ||
26 | |||
27 | void __delay(unsigned long cycles) | ||
28 | { | ||
29 | cycles_t start = get_cycles(); | ||
30 | |||
31 | while ((get_cycles() - start) < cycles) | ||
32 | cpu_relax(); | ||
33 | } | ||
34 | EXPORT_SYMBOL(__delay); | ||
35 | |||
36 | inline void __const_udelay(unsigned long xloops) | ||
37 | { | ||
38 | unsigned long loops; | ||
39 | |||
40 | loops = xloops * loops_per_jiffy * HZ; | ||
41 | __delay(loops >> 32); | ||
42 | } | ||
43 | EXPORT_SYMBOL(__const_udelay); | ||
44 | |||
45 | void __udelay(unsigned long usecs) | ||
46 | { | ||
47 | __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */ | ||
48 | } | ||
49 | EXPORT_SYMBOL(__udelay); | ||
50 | |||
51 | void __ndelay(unsigned long nsecs) | ||
52 | { | ||
53 | __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */ | ||
54 | } | ||
55 | EXPORT_SYMBOL(__ndelay); | ||
diff --git a/arch/arm64/lib/strncpy_from_user.S b/arch/arm64/lib/strncpy_from_user.S new file mode 100644 index 000000000000..56e448a831a0 --- /dev/null +++ b/arch/arm64/lib/strncpy_from_user.S | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/lib/strncpy_from_user.S | ||
3 | * | ||
4 | * Copyright (C) 1995-2000 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/linkage.h> | ||
21 | #include <asm/assembler.h> | ||
22 | #include <asm/errno.h> | ||
23 | |||
24 | .text | ||
25 | .align 5 | ||
26 | |||
27 | /* | ||
28 | * Copy a string from user space to kernel space. | ||
29 | * x0 = dst, x1 = src, x2 = byte length | ||
30 | * returns the number of characters copied (strlen of copied string), | ||
31 | * -EFAULT on exception, or "len" if we fill the whole buffer | ||
32 | */ | ||
33 | ENTRY(__strncpy_from_user) | ||
34 | mov x4, x1 | ||
35 | 1: subs x2, x2, #1 | ||
36 | bmi 2f | ||
37 | USER(9f, ldrb w3, [x1], #1 ) | ||
38 | strb w3, [x0], #1 | ||
39 | cbnz w3, 1b | ||
40 | sub x1, x1, #1 // take NUL character out of count | ||
41 | 2: sub x0, x1, x4 | ||
42 | ret | ||
43 | ENDPROC(__strncpy_from_user) | ||
44 | |||
45 | .section .fixup,"ax" | ||
46 | .align 0 | ||
47 | 9: strb wzr, [x0] // null terminate | ||
48 | mov x0, #-EFAULT | ||
49 | ret | ||
50 | .previous | ||
diff --git a/arch/arm64/lib/strnlen_user.S b/arch/arm64/lib/strnlen_user.S new file mode 100644 index 000000000000..7f7b176a5646 --- /dev/null +++ b/arch/arm64/lib/strnlen_user.S | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/lib/strnlen_user.S | ||
3 | * | ||
4 | * Copyright (C) 1995-2000 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/linkage.h> | ||
21 | #include <asm/assembler.h> | ||
22 | #include <asm/errno.h> | ||
23 | |||
24 | .text | ||
25 | .align 5 | ||
26 | |||
27 | /* Prototype: unsigned long __strnlen_user(const char *str, long n) | ||
28 | * Purpose : get length of a string in user memory | ||
29 | * Params : str - address of string in user memory | ||
30 | * Returns : length of string *including terminator* | ||
31 | * or zero on exception, or n if too long | ||
32 | */ | ||
33 | ENTRY(__strnlen_user) | ||
34 | mov x2, x0 | ||
35 | 1: subs x1, x1, #1 | ||
36 | b.mi 2f | ||
37 | USER(9f, ldrb w3, [x0], #1 ) | ||
38 | cbnz w3, 1b | ||
39 | 2: sub x0, x0, x2 | ||
40 | ret | ||
41 | ENDPROC(__strnlen_user) | ||
42 | |||
43 | .section .fixup,"ax" | ||
44 | .align 0 | ||
45 | 9: mov x0, #0 | ||
46 | ret | ||
47 | .previous | ||
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile new file mode 100644 index 000000000000..3140a2abcdc2 --- /dev/null +++ b/arch/arm64/mm/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | obj-y := dma-mapping.o extable.o fault.o init.o \ | ||
2 | cache.o copypage.o flush.o \ | ||
3 | ioremap.o mmap.o pgd.o mmu.o \ | ||
4 | context.o tlb.o proc.o | ||
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S new file mode 100644 index 000000000000..abe69b80cf7f --- /dev/null +++ b/arch/arm64/mm/cache.S | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Cache maintenance | ||
3 | * | ||
4 | * Copyright (C) 2001 Deep Blue Solutions Ltd. | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/linkage.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <asm/assembler.h> | ||
23 | |||
24 | #include "proc-macros.S" | ||
25 | |||
26 | /* | ||
27 | * __flush_dcache_all() | ||
28 | * | ||
29 | * Flush the whole D-cache. | ||
30 | * | ||
31 | * Corrupted registers: x0-x7, x9-x11 | ||
32 | */ | ||
33 | ENTRY(__flush_dcache_all) | ||
34 | dsb sy // ensure ordering with previous memory accesses | ||
35 | mrs x0, clidr_el1 // read clidr | ||
36 | and x3, x0, #0x7000000 // extract loc from clidr | ||
37 | lsr x3, x3, #23 // left align loc bit field | ||
38 | cbz x3, finished // if loc is 0, then no need to clean | ||
39 | mov x10, #0 // start clean at cache level 0 | ||
40 | loop1: | ||
41 | add x2, x10, x10, lsr #1 // work out 3x current cache level | ||
42 | lsr x1, x0, x2 // extract cache type bits from clidr | ||
43 | and x1, x1, #7 // mask of the bits for current cache only | ||
44 | cmp x1, #2 // see what cache we have at this level | ||
45 | b.lt skip // skip if no cache, or just i-cache | ||
46 | save_and_disable_irqs x9 // make CSSELR and CCSIDR access atomic | ||
47 | msr csselr_el1, x10 // select current cache level in csselr | ||
48 | isb // isb to sych the new cssr&csidr | ||
49 | mrs x1, ccsidr_el1 // read the new ccsidr | ||
50 | restore_irqs x9 | ||
51 | and x2, x1, #7 // extract the length of the cache lines | ||
52 | add x2, x2, #4 // add 4 (line length offset) | ||
53 | mov x4, #0x3ff | ||
54 | and x4, x4, x1, lsr #3 // find maximum number on the way size | ||
55 | clz x5, x4 // find bit position of way size increment | ||
56 | mov x7, #0x7fff | ||
57 | and x7, x7, x1, lsr #13 // extract max number of the index size | ||
58 | loop2: | ||
59 | mov x9, x4 // create working copy of max way size | ||
60 | loop3: | ||
61 | lsl x6, x9, x5 | ||
62 | orr x11, x10, x6 // factor way and cache number into x11 | ||
63 | lsl x6, x7, x2 | ||
64 | orr x11, x11, x6 // factor index number into x11 | ||
65 | dc cisw, x11 // clean & invalidate by set/way | ||
66 | subs x9, x9, #1 // decrement the way | ||
67 | b.ge loop3 | ||
68 | subs x7, x7, #1 // decrement the index | ||
69 | b.ge loop2 | ||
70 | skip: | ||
71 | add x10, x10, #2 // increment cache number | ||
72 | cmp x3, x10 | ||
73 | b.gt loop1 | ||
74 | finished: | ||
75 | mov x10, #0 // swith back to cache level 0 | ||
76 | msr csselr_el1, x10 // select current cache level in csselr | ||
77 | dsb sy | ||
78 | isb | ||
79 | ret | ||
80 | ENDPROC(__flush_dcache_all) | ||
81 | |||
82 | /* | ||
83 | * flush_cache_all() | ||
84 | * | ||
85 | * Flush the entire cache system. The data cache flush is now achieved | ||
86 | * using atomic clean / invalidates working outwards from L1 cache. This | ||
87 | * is done using Set/Way based cache maintainance instructions. The | ||
88 | * instruction cache can still be invalidated back to the point of | ||
89 | * unification in a single instruction. | ||
90 | */ | ||
91 | ENTRY(flush_cache_all) | ||
92 | mov x12, lr | ||
93 | bl __flush_dcache_all | ||
94 | mov x0, #0 | ||
95 | ic ialluis // I+BTB cache invalidate | ||
96 | ret x12 | ||
97 | ENDPROC(flush_cache_all) | ||
98 | |||
99 | /* | ||
100 | * flush_icache_range(start,end) | ||
101 | * | ||
102 | * Ensure that the I and D caches are coherent within specified region. | ||
103 | * This is typically used when code has been written to a memory region, | ||
104 | * and will be executed. | ||
105 | * | ||
106 | * - start - virtual start address of region | ||
107 | * - end - virtual end address of region | ||
108 | */ | ||
109 | ENTRY(flush_icache_range) | ||
110 | /* FALLTHROUGH */ | ||
111 | |||
112 | /* | ||
113 | * __flush_cache_user_range(start,end) | ||
114 | * | ||
115 | * Ensure that the I and D caches are coherent within specified region. | ||
116 | * This is typically used when code has been written to a memory region, | ||
117 | * and will be executed. | ||
118 | * | ||
119 | * - start - virtual start address of region | ||
120 | * - end - virtual end address of region | ||
121 | */ | ||
122 | ENTRY(__flush_cache_user_range) | ||
123 | dcache_line_size x2, x3 | ||
124 | sub x3, x2, #1 | ||
125 | bic x4, x0, x3 | ||
126 | 1: | ||
127 | USER(9f, dc cvau, x4 ) // clean D line to PoU | ||
128 | add x4, x4, x2 | ||
129 | cmp x4, x1 | ||
130 | b.lo 1b | ||
131 | dsb sy | ||
132 | |||
133 | icache_line_size x2, x3 | ||
134 | sub x3, x2, #1 | ||
135 | bic x4, x0, x3 | ||
136 | 1: | ||
137 | USER(9f, ic ivau, x4 ) // invalidate I line PoU | ||
138 | add x4, x4, x2 | ||
139 | cmp x4, x1 | ||
140 | b.lo 1b | ||
141 | 9: // ignore any faulting cache operation | ||
142 | dsb sy | ||
143 | isb | ||
144 | ret | ||
145 | ENDPROC(flush_icache_range) | ||
146 | ENDPROC(__flush_cache_user_range) | ||
147 | |||
148 | /* | ||
149 | * __flush_kern_dcache_page(kaddr) | ||
150 | * | ||
151 | * Ensure that the data held in the page kaddr is written back to the | ||
152 | * page in question. | ||
153 | * | ||
154 | * - kaddr - kernel address | ||
155 | * - size - size in question | ||
156 | */ | ||
157 | ENTRY(__flush_dcache_area) | ||
158 | dcache_line_size x2, x3 | ||
159 | add x1, x0, x1 | ||
160 | sub x3, x2, #1 | ||
161 | bic x0, x0, x3 | ||
162 | 1: dc civac, x0 // clean & invalidate D line / unified line | ||
163 | add x0, x0, x2 | ||
164 | cmp x0, x1 | ||
165 | b.lo 1b | ||
166 | dsb sy | ||
167 | ret | ||
168 | ENDPROC(__flush_dcache_area) | ||
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c new file mode 100644 index 000000000000..baa758d37021 --- /dev/null +++ b/arch/arm64/mm/context.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/context.c | ||
3 | * | ||
4 | * Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved. | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/smp.h> | ||
24 | #include <linux/percpu.h> | ||
25 | |||
26 | #include <asm/mmu_context.h> | ||
27 | #include <asm/tlbflush.h> | ||
28 | #include <asm/cachetype.h> | ||
29 | |||
30 | #define asid_bits(reg) \ | ||
31 | (((read_cpuid(ID_AA64MMFR0_EL1) & 0xf0) >> 2) + 8) | ||
32 | |||
33 | #define ASID_FIRST_VERSION (1 << MAX_ASID_BITS) | ||
34 | |||
35 | static DEFINE_RAW_SPINLOCK(cpu_asid_lock); | ||
36 | unsigned int cpu_last_asid = ASID_FIRST_VERSION; | ||
37 | |||
38 | /* | ||
39 | * We fork()ed a process, and we need a new context for the child to run in. | ||
40 | */ | ||
41 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) | ||
42 | { | ||
43 | mm->context.id = 0; | ||
44 | raw_spin_lock_init(&mm->context.id_lock); | ||
45 | } | ||
46 | |||
47 | static void flush_context(void) | ||
48 | { | ||
49 | /* set the reserved TTBR0 before flushing the TLB */ | ||
50 | cpu_set_reserved_ttbr0(); | ||
51 | flush_tlb_all(); | ||
52 | if (icache_is_aivivt()) | ||
53 | __flush_icache_all(); | ||
54 | } | ||
55 | |||
56 | #ifdef CONFIG_SMP | ||
57 | |||
58 | static void set_mm_context(struct mm_struct *mm, unsigned int asid) | ||
59 | { | ||
60 | unsigned long flags; | ||
61 | |||
62 | /* | ||
63 | * Locking needed for multi-threaded applications where the same | ||
64 | * mm->context.id could be set from different CPUs during the | ||
65 | * broadcast. This function is also called via IPI so the | ||
66 | * mm->context.id_lock has to be IRQ-safe. | ||
67 | */ | ||
68 | raw_spin_lock_irqsave(&mm->context.id_lock, flags); | ||
69 | if (likely((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS)) { | ||
70 | /* | ||
71 | * Old version of ASID found. Set the new one and reset | ||
72 | * mm_cpumask(mm). | ||
73 | */ | ||
74 | mm->context.id = asid; | ||
75 | cpumask_clear(mm_cpumask(mm)); | ||
76 | } | ||
77 | raw_spin_unlock_irqrestore(&mm->context.id_lock, flags); | ||
78 | |||
79 | /* | ||
80 | * Set the mm_cpumask(mm) bit for the current CPU. | ||
81 | */ | ||
82 | cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * Reset the ASID on the current CPU. This function call is broadcast from the | ||
87 | * CPU handling the ASID rollover and holding cpu_asid_lock. | ||
88 | */ | ||
89 | static void reset_context(void *info) | ||
90 | { | ||
91 | unsigned int asid; | ||
92 | unsigned int cpu = smp_processor_id(); | ||
93 | struct mm_struct *mm = current->active_mm; | ||
94 | |||
95 | smp_rmb(); | ||
96 | asid = cpu_last_asid + cpu; | ||
97 | |||
98 | flush_context(); | ||
99 | set_mm_context(mm, asid); | ||
100 | |||
101 | /* set the new ASID */ | ||
102 | cpu_switch_mm(mm->pgd, mm); | ||
103 | } | ||
104 | |||
105 | #else | ||
106 | |||
107 | static inline void set_mm_context(struct mm_struct *mm, unsigned int asid) | ||
108 | { | ||
109 | mm->context.id = asid; | ||
110 | cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id())); | ||
111 | } | ||
112 | |||
113 | #endif | ||
114 | |||
115 | void __new_context(struct mm_struct *mm) | ||
116 | { | ||
117 | unsigned int asid; | ||
118 | unsigned int bits = asid_bits(); | ||
119 | |||
120 | raw_spin_lock(&cpu_asid_lock); | ||
121 | #ifdef CONFIG_SMP | ||
122 | /* | ||
123 | * Check the ASID again, in case the change was broadcast from another | ||
124 | * CPU before we acquired the lock. | ||
125 | */ | ||
126 | if (!unlikely((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS)) { | ||
127 | cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); | ||
128 | raw_spin_unlock(&cpu_asid_lock); | ||
129 | return; | ||
130 | } | ||
131 | #endif | ||
132 | /* | ||
133 | * At this point, it is guaranteed that the current mm (with an old | ||
134 | * ASID) isn't active on any other CPU since the ASIDs are changed | ||
135 | * simultaneously via IPI. | ||
136 | */ | ||
137 | asid = ++cpu_last_asid; | ||
138 | |||
139 | /* | ||
140 | * If we've used up all our ASIDs, we need to start a new version and | ||
141 | * flush the TLB. | ||
142 | */ | ||
143 | if (unlikely((asid & ((1 << bits) - 1)) == 0)) { | ||
144 | /* increment the ASID version */ | ||
145 | cpu_last_asid += (1 << MAX_ASID_BITS) - (1 << bits); | ||
146 | if (cpu_last_asid == 0) | ||
147 | cpu_last_asid = ASID_FIRST_VERSION; | ||
148 | asid = cpu_last_asid + smp_processor_id(); | ||
149 | flush_context(); | ||
150 | #ifdef CONFIG_SMP | ||
151 | smp_wmb(); | ||
152 | smp_call_function(reset_context, NULL, 1); | ||
153 | #endif | ||
154 | cpu_last_asid += NR_CPUS - 1; | ||
155 | } | ||
156 | |||
157 | set_mm_context(mm, asid); | ||
158 | raw_spin_unlock(&cpu_asid_lock); | ||
159 | } | ||
diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c new file mode 100644 index 000000000000..9aecbace4128 --- /dev/null +++ b/arch/arm64/mm/copypage.c | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/copypage.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Deep Blue Solutions Ltd, All Rights Reserved. | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/mm.h> | ||
21 | |||
22 | #include <asm/page.h> | ||
23 | #include <asm/cacheflush.h> | ||
24 | |||
25 | void __cpu_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) | ||
26 | { | ||
27 | copy_page(kto, kfrom); | ||
28 | __flush_dcache_area(kto, PAGE_SIZE); | ||
29 | } | ||
30 | |||
31 | void __cpu_clear_user_page(void *kaddr, unsigned long vaddr) | ||
32 | { | ||
33 | clear_page(kaddr); | ||
34 | } | ||
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c new file mode 100644 index 000000000000..5eb244453a5b --- /dev/null +++ b/arch/arm64/mm/dma-mapping.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * SWIOTLB-based DMA API implementation | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/gfp.h> | ||
21 | #include <linux/export.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/vmalloc.h> | ||
25 | #include <linux/swiotlb.h> | ||
26 | |||
27 | #include <asm/cacheflush.h> | ||
28 | |||
29 | struct dma_map_ops *dma_ops; | ||
30 | EXPORT_SYMBOL(dma_ops); | ||
31 | |||
32 | static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, | ||
33 | dma_addr_t *dma_handle, gfp_t flags, | ||
34 | struct dma_attrs *attrs) | ||
35 | { | ||
36 | if (IS_ENABLED(CONFIG_ZONE_DMA32) && | ||
37 | dev->coherent_dma_mask <= DMA_BIT_MASK(32)) | ||
38 | flags |= GFP_DMA32; | ||
39 | return swiotlb_alloc_coherent(dev, size, dma_handle, flags); | ||
40 | } | ||
41 | |||
42 | static void arm64_swiotlb_free_coherent(struct device *dev, size_t size, | ||
43 | void *vaddr, dma_addr_t dma_handle, | ||
44 | struct dma_attrs *attrs) | ||
45 | { | ||
46 | swiotlb_free_coherent(dev, size, vaddr, dma_handle); | ||
47 | } | ||
48 | |||
49 | static struct dma_map_ops arm64_swiotlb_dma_ops = { | ||
50 | .alloc = arm64_swiotlb_alloc_coherent, | ||
51 | .free = arm64_swiotlb_free_coherent, | ||
52 | .map_page = swiotlb_map_page, | ||
53 | .unmap_page = swiotlb_unmap_page, | ||
54 | .map_sg = swiotlb_map_sg_attrs, | ||
55 | .unmap_sg = swiotlb_unmap_sg_attrs, | ||
56 | .sync_single_for_cpu = swiotlb_sync_single_for_cpu, | ||
57 | .sync_single_for_device = swiotlb_sync_single_for_device, | ||
58 | .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, | ||
59 | .sync_sg_for_device = swiotlb_sync_sg_for_device, | ||
60 | .dma_supported = swiotlb_dma_supported, | ||
61 | .mapping_error = swiotlb_dma_mapping_error, | ||
62 | }; | ||
63 | |||
64 | void __init swiotlb_init_with_default_size(size_t default_size, int verbose); | ||
65 | |||
66 | void __init arm64_swiotlb_init(size_t max_size) | ||
67 | { | ||
68 | dma_ops = &arm64_swiotlb_dma_ops; | ||
69 | swiotlb_init_with_default_size(min((size_t)SZ_64M, max_size), 1); | ||
70 | } | ||
71 | |||
72 | #define PREALLOC_DMA_DEBUG_ENTRIES 4096 | ||
73 | |||
74 | static int __init dma_debug_do_init(void) | ||
75 | { | ||
76 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); | ||
77 | return 0; | ||
78 | } | ||
79 | fs_initcall(dma_debug_do_init); | ||
diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c new file mode 100644 index 000000000000..79444279ba8c --- /dev/null +++ b/arch/arm64/mm/extable.c | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/extable.c | ||
3 | */ | ||
4 | |||
5 | #include <linux/module.h> | ||
6 | #include <linux/uaccess.h> | ||
7 | |||
8 | int fixup_exception(struct pt_regs *regs) | ||
9 | { | ||
10 | const struct exception_table_entry *fixup; | ||
11 | |||
12 | fixup = search_exception_tables(instruction_pointer(regs)); | ||
13 | if (fixup) | ||
14 | regs->pc = fixup->fixup; | ||
15 | |||
16 | return fixup != NULL; | ||
17 | } | ||
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c new file mode 100644 index 000000000000..1909a69983ca --- /dev/null +++ b/arch/arm64/mm/fault.c | |||
@@ -0,0 +1,534 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/fault.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | ||
5 | * Copyright (C) 1995-2004 Russell King | ||
6 | * Copyright (C) 2012 ARM Ltd. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/signal.h> | ||
23 | #include <linux/mm.h> | ||
24 | #include <linux/hardirq.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/kprobes.h> | ||
27 | #include <linux/uaccess.h> | ||
28 | #include <linux/page-flags.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/highmem.h> | ||
31 | #include <linux/perf_event.h> | ||
32 | |||
33 | #include <asm/exception.h> | ||
34 | #include <asm/debug-monitors.h> | ||
35 | #include <asm/system_misc.h> | ||
36 | #include <asm/pgtable.h> | ||
37 | #include <asm/tlbflush.h> | ||
38 | |||
39 | /* | ||
40 | * Dump out the page tables associated with 'addr' in mm 'mm'. | ||
41 | */ | ||
42 | void show_pte(struct mm_struct *mm, unsigned long addr) | ||
43 | { | ||
44 | pgd_t *pgd; | ||
45 | |||
46 | if (!mm) | ||
47 | mm = &init_mm; | ||
48 | |||
49 | pr_alert("pgd = %p\n", mm->pgd); | ||
50 | pgd = pgd_offset(mm, addr); | ||
51 | pr_alert("[%08lx] *pgd=%016llx", addr, pgd_val(*pgd)); | ||
52 | |||
53 | do { | ||
54 | pud_t *pud; | ||
55 | pmd_t *pmd; | ||
56 | pte_t *pte; | ||
57 | |||
58 | if (pgd_none_or_clear_bad(pgd)) | ||
59 | break; | ||
60 | |||
61 | pud = pud_offset(pgd, addr); | ||
62 | if (pud_none_or_clear_bad(pud)) | ||
63 | break; | ||
64 | |||
65 | pmd = pmd_offset(pud, addr); | ||
66 | printk(", *pmd=%016llx", pmd_val(*pmd)); | ||
67 | if (pmd_none_or_clear_bad(pmd)) | ||
68 | break; | ||
69 | |||
70 | pte = pte_offset_map(pmd, addr); | ||
71 | printk(", *pte=%016llx", pte_val(*pte)); | ||
72 | pte_unmap(pte); | ||
73 | } while(0); | ||
74 | |||
75 | printk("\n"); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * The kernel tried to access some page that wasn't present. | ||
80 | */ | ||
81 | static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, | ||
82 | unsigned int esr, struct pt_regs *regs) | ||
83 | { | ||
84 | /* | ||
85 | * Are we prepared to handle this kernel fault? | ||
86 | */ | ||
87 | if (fixup_exception(regs)) | ||
88 | return; | ||
89 | |||
90 | /* | ||
91 | * No handler, we'll have to terminate things with extreme prejudice. | ||
92 | */ | ||
93 | bust_spinlocks(1); | ||
94 | pr_alert("Unable to handle kernel %s at virtual address %08lx\n", | ||
95 | (addr < PAGE_SIZE) ? "NULL pointer dereference" : | ||
96 | "paging request", addr); | ||
97 | |||
98 | show_pte(mm, addr); | ||
99 | die("Oops", regs, esr); | ||
100 | bust_spinlocks(0); | ||
101 | do_exit(SIGKILL); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Something tried to access memory that isn't in our memory map. User mode | ||
106 | * accesses just cause a SIGSEGV | ||
107 | */ | ||
108 | static void __do_user_fault(struct task_struct *tsk, unsigned long addr, | ||
109 | unsigned int esr, unsigned int sig, int code, | ||
110 | struct pt_regs *regs) | ||
111 | { | ||
112 | struct siginfo si; | ||
113 | |||
114 | if (show_unhandled_signals) { | ||
115 | pr_info("%s[%d]: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n", | ||
116 | tsk->comm, task_pid_nr(tsk), sig, addr, esr); | ||
117 | show_pte(tsk->mm, addr); | ||
118 | show_regs(regs); | ||
119 | } | ||
120 | |||
121 | tsk->thread.fault_address = addr; | ||
122 | si.si_signo = sig; | ||
123 | si.si_errno = 0; | ||
124 | si.si_code = code; | ||
125 | si.si_addr = (void __user *)addr; | ||
126 | force_sig_info(sig, &si, tsk); | ||
127 | } | ||
128 | |||
129 | void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) | ||
130 | { | ||
131 | struct task_struct *tsk = current; | ||
132 | struct mm_struct *mm = tsk->active_mm; | ||
133 | |||
134 | /* | ||
135 | * If we are in kernel mode at this point, we have no context to | ||
136 | * handle this fault with. | ||
137 | */ | ||
138 | if (user_mode(regs)) | ||
139 | __do_user_fault(tsk, addr, esr, SIGSEGV, SEGV_MAPERR, regs); | ||
140 | else | ||
141 | __do_kernel_fault(mm, addr, esr, regs); | ||
142 | } | ||
143 | |||
144 | #define VM_FAULT_BADMAP 0x010000 | ||
145 | #define VM_FAULT_BADACCESS 0x020000 | ||
146 | |||
147 | #define ESR_WRITE (1 << 6) | ||
148 | #define ESR_LNX_EXEC (1 << 24) | ||
149 | |||
150 | /* | ||
151 | * Check that the permissions on the VMA allow for the fault which occurred. | ||
152 | * If we encountered a write fault, we must have write permission, otherwise | ||
153 | * we allow any permission. | ||
154 | */ | ||
155 | static inline bool access_error(unsigned int esr, struct vm_area_struct *vma) | ||
156 | { | ||
157 | unsigned int mask = VM_READ | VM_WRITE | VM_EXEC; | ||
158 | |||
159 | if (esr & ESR_WRITE) | ||
160 | mask = VM_WRITE; | ||
161 | if (esr & ESR_LNX_EXEC) | ||
162 | mask = VM_EXEC; | ||
163 | |||
164 | return vma->vm_flags & mask ? false : true; | ||
165 | } | ||
166 | |||
167 | static int __do_page_fault(struct mm_struct *mm, unsigned long addr, | ||
168 | unsigned int esr, unsigned int flags, | ||
169 | struct task_struct *tsk) | ||
170 | { | ||
171 | struct vm_area_struct *vma; | ||
172 | int fault; | ||
173 | |||
174 | vma = find_vma(mm, addr); | ||
175 | fault = VM_FAULT_BADMAP; | ||
176 | if (unlikely(!vma)) | ||
177 | goto out; | ||
178 | if (unlikely(vma->vm_start > addr)) | ||
179 | goto check_stack; | ||
180 | |||
181 | /* | ||
182 | * Ok, we have a good vm_area for this memory access, so we can handle | ||
183 | * it. | ||
184 | */ | ||
185 | good_area: | ||
186 | if (access_error(esr, vma)) { | ||
187 | fault = VM_FAULT_BADACCESS; | ||
188 | goto out; | ||
189 | } | ||
190 | |||
191 | return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); | ||
192 | |||
193 | check_stack: | ||
194 | if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) | ||
195 | goto good_area; | ||
196 | out: | ||
197 | return fault; | ||
198 | } | ||
199 | |||
200 | static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, | ||
201 | struct pt_regs *regs) | ||
202 | { | ||
203 | struct task_struct *tsk; | ||
204 | struct mm_struct *mm; | ||
205 | int fault, sig, code; | ||
206 | int write = esr & ESR_WRITE; | ||
207 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | | ||
208 | (write ? FAULT_FLAG_WRITE : 0); | ||
209 | |||
210 | tsk = current; | ||
211 | mm = tsk->mm; | ||
212 | |||
213 | /* Enable interrupts if they were enabled in the parent context. */ | ||
214 | if (interrupts_enabled(regs)) | ||
215 | local_irq_enable(); | ||
216 | |||
217 | /* | ||
218 | * If we're in an interrupt or have no user context, we must not take | ||
219 | * the fault. | ||
220 | */ | ||
221 | if (in_atomic() || !mm) | ||
222 | goto no_context; | ||
223 | |||
224 | /* | ||
225 | * As per x86, we may deadlock here. However, since the kernel only | ||
226 | * validly references user space from well defined areas of the code, | ||
227 | * we can bug out early if this is from code which shouldn't. | ||
228 | */ | ||
229 | if (!down_read_trylock(&mm->mmap_sem)) { | ||
230 | if (!user_mode(regs) && !search_exception_tables(regs->pc)) | ||
231 | goto no_context; | ||
232 | retry: | ||
233 | down_read(&mm->mmap_sem); | ||
234 | } else { | ||
235 | /* | ||
236 | * The above down_read_trylock() might have succeeded in which | ||
237 | * case, we'll have missed the might_sleep() from down_read(). | ||
238 | */ | ||
239 | might_sleep(); | ||
240 | #ifdef CONFIG_DEBUG_VM | ||
241 | if (!user_mode(regs) && !search_exception_tables(regs->pc)) | ||
242 | goto no_context; | ||
243 | #endif | ||
244 | } | ||
245 | |||
246 | fault = __do_page_fault(mm, addr, esr, flags, tsk); | ||
247 | |||
248 | /* | ||
249 | * If we need to retry but a fatal signal is pending, handle the | ||
250 | * signal first. We do not need to release the mmap_sem because it | ||
251 | * would already be released in __lock_page_or_retry in mm/filemap.c. | ||
252 | */ | ||
253 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
254 | return 0; | ||
255 | |||
256 | /* | ||
257 | * Major/minor page fault accounting is only done on the initial | ||
258 | * attempt. If we go through a retry, it is extremely likely that the | ||
259 | * page will be found in page cache at that point. | ||
260 | */ | ||
261 | |||
262 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); | ||
263 | if (flags & FAULT_FLAG_ALLOW_RETRY) { | ||
264 | if (fault & VM_FAULT_MAJOR) { | ||
265 | tsk->maj_flt++; | ||
266 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, | ||
267 | addr); | ||
268 | } else { | ||
269 | tsk->min_flt++; | ||
270 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, | ||
271 | addr); | ||
272 | } | ||
273 | if (fault & VM_FAULT_RETRY) { | ||
274 | /* | ||
275 | * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk of | ||
276 | * starvation. | ||
277 | */ | ||
278 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
279 | goto retry; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | up_read(&mm->mmap_sem); | ||
284 | |||
285 | /* | ||
286 | * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR | ||
287 | */ | ||
288 | if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | | ||
289 | VM_FAULT_BADACCESS)))) | ||
290 | return 0; | ||
291 | |||
292 | if (fault & VM_FAULT_OOM) { | ||
293 | /* | ||
294 | * We ran out of memory, call the OOM killer, and return to | ||
295 | * userspace (which will retry the fault, or kill us if we got | ||
296 | * oom-killed). | ||
297 | */ | ||
298 | pagefault_out_of_memory(); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * If we are in kernel mode at this point, we have no context to | ||
304 | * handle this fault with. | ||
305 | */ | ||
306 | if (!user_mode(regs)) | ||
307 | goto no_context; | ||
308 | |||
309 | if (fault & VM_FAULT_SIGBUS) { | ||
310 | /* | ||
311 | * We had some memory, but were unable to successfully fix up | ||
312 | * this page fault. | ||
313 | */ | ||
314 | sig = SIGBUS; | ||
315 | code = BUS_ADRERR; | ||
316 | } else { | ||
317 | /* | ||
318 | * Something tried to access memory that isn't in our memory | ||
319 | * map. | ||
320 | */ | ||
321 | sig = SIGSEGV; | ||
322 | code = fault == VM_FAULT_BADACCESS ? | ||
323 | SEGV_ACCERR : SEGV_MAPERR; | ||
324 | } | ||
325 | |||
326 | __do_user_fault(tsk, addr, esr, sig, code, regs); | ||
327 | return 0; | ||
328 | |||
329 | no_context: | ||
330 | __do_kernel_fault(mm, addr, esr, regs); | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * First Level Translation Fault Handler | ||
336 | * | ||
337 | * We enter here because the first level page table doesn't contain a valid | ||
338 | * entry for the address. | ||
339 | * | ||
340 | * If the address is in kernel space (>= TASK_SIZE), then we are probably | ||
341 | * faulting in the vmalloc() area. | ||
342 | * | ||
343 | * If the init_task's first level page tables contains the relevant entry, we | ||
344 | * copy the it to this task. If not, we send the process a signal, fixup the | ||
345 | * exception, or oops the kernel. | ||
346 | * | ||
347 | * NOTE! We MUST NOT take any locks for this case. We may be in an interrupt | ||
348 | * or a critical region, and should only copy the information from the master | ||
349 | * page table, nothing more. | ||
350 | */ | ||
351 | static int __kprobes do_translation_fault(unsigned long addr, | ||
352 | unsigned int esr, | ||
353 | struct pt_regs *regs) | ||
354 | { | ||
355 | if (addr < TASK_SIZE) | ||
356 | return do_page_fault(addr, esr, regs); | ||
357 | |||
358 | do_bad_area(addr, esr, regs); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * Some section permission faults need to be handled gracefully. They can | ||
364 | * happen due to a __{get,put}_user during an oops. | ||
365 | */ | ||
366 | static int do_sect_fault(unsigned long addr, unsigned int esr, | ||
367 | struct pt_regs *regs) | ||
368 | { | ||
369 | do_bad_area(addr, esr, regs); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | /* | ||
374 | * This abort handler always returns "fault". | ||
375 | */ | ||
376 | static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) | ||
377 | { | ||
378 | return 1; | ||
379 | } | ||
380 | |||
381 | static struct fault_info { | ||
382 | int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); | ||
383 | int sig; | ||
384 | int code; | ||
385 | const char *name; | ||
386 | } fault_info[] = { | ||
387 | { do_bad, SIGBUS, 0, "ttbr address size fault" }, | ||
388 | { do_bad, SIGBUS, 0, "level 1 address size fault" }, | ||
389 | { do_bad, SIGBUS, 0, "level 2 address size fault" }, | ||
390 | { do_bad, SIGBUS, 0, "level 3 address size fault" }, | ||
391 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "input address range fault" }, | ||
392 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" }, | ||
393 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" }, | ||
394 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, | ||
395 | { do_bad, SIGBUS, 0, "reserved access flag fault" }, | ||
396 | { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, | ||
397 | { do_bad, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, | ||
398 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" }, | ||
399 | { do_bad, SIGBUS, 0, "reserved permission fault" }, | ||
400 | { do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" }, | ||
401 | { do_sect_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" }, | ||
402 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" }, | ||
403 | { do_bad, SIGBUS, 0, "synchronous external abort" }, | ||
404 | { do_bad, SIGBUS, 0, "asynchronous external abort" }, | ||
405 | { do_bad, SIGBUS, 0, "unknown 18" }, | ||
406 | { do_bad, SIGBUS, 0, "unknown 19" }, | ||
407 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, | ||
408 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, | ||
409 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, | ||
410 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, | ||
411 | { do_bad, SIGBUS, 0, "synchronous parity error" }, | ||
412 | { do_bad, SIGBUS, 0, "asynchronous parity error" }, | ||
413 | { do_bad, SIGBUS, 0, "unknown 26" }, | ||
414 | { do_bad, SIGBUS, 0, "unknown 27" }, | ||
415 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, | ||
416 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, | ||
417 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, | ||
418 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, | ||
419 | { do_bad, SIGBUS, 0, "unknown 32" }, | ||
420 | { do_bad, SIGBUS, BUS_ADRALN, "alignment fault" }, | ||
421 | { do_bad, SIGBUS, 0, "debug event" }, | ||
422 | { do_bad, SIGBUS, 0, "unknown 35" }, | ||
423 | { do_bad, SIGBUS, 0, "unknown 36" }, | ||
424 | { do_bad, SIGBUS, 0, "unknown 37" }, | ||
425 | { do_bad, SIGBUS, 0, "unknown 38" }, | ||
426 | { do_bad, SIGBUS, 0, "unknown 39" }, | ||
427 | { do_bad, SIGBUS, 0, "unknown 40" }, | ||
428 | { do_bad, SIGBUS, 0, "unknown 41" }, | ||
429 | { do_bad, SIGBUS, 0, "unknown 42" }, | ||
430 | { do_bad, SIGBUS, 0, "unknown 43" }, | ||
431 | { do_bad, SIGBUS, 0, "unknown 44" }, | ||
432 | { do_bad, SIGBUS, 0, "unknown 45" }, | ||
433 | { do_bad, SIGBUS, 0, "unknown 46" }, | ||
434 | { do_bad, SIGBUS, 0, "unknown 47" }, | ||
435 | { do_bad, SIGBUS, 0, "unknown 48" }, | ||
436 | { do_bad, SIGBUS, 0, "unknown 49" }, | ||
437 | { do_bad, SIGBUS, 0, "unknown 50" }, | ||
438 | { do_bad, SIGBUS, 0, "unknown 51" }, | ||
439 | { do_bad, SIGBUS, 0, "implementation fault (lockdown abort)" }, | ||
440 | { do_bad, SIGBUS, 0, "unknown 53" }, | ||
441 | { do_bad, SIGBUS, 0, "unknown 54" }, | ||
442 | { do_bad, SIGBUS, 0, "unknown 55" }, | ||
443 | { do_bad, SIGBUS, 0, "unknown 56" }, | ||
444 | { do_bad, SIGBUS, 0, "unknown 57" }, | ||
445 | { do_bad, SIGBUS, 0, "implementation fault (coprocessor abort)" }, | ||
446 | { do_bad, SIGBUS, 0, "unknown 59" }, | ||
447 | { do_bad, SIGBUS, 0, "unknown 60" }, | ||
448 | { do_bad, SIGBUS, 0, "unknown 61" }, | ||
449 | { do_bad, SIGBUS, 0, "unknown 62" }, | ||
450 | { do_bad, SIGBUS, 0, "unknown 63" }, | ||
451 | }; | ||
452 | |||
453 | /* | ||
454 | * Dispatch a data abort to the relevant handler. | ||
455 | */ | ||
456 | asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, | ||
457 | struct pt_regs *regs) | ||
458 | { | ||
459 | const struct fault_info *inf = fault_info + (esr & 63); | ||
460 | struct siginfo info; | ||
461 | |||
462 | if (!inf->fn(addr, esr, regs)) | ||
463 | return; | ||
464 | |||
465 | pr_alert("Unhandled fault: %s (0x%08x) at 0x%016lx\n", | ||
466 | inf->name, esr, addr); | ||
467 | |||
468 | info.si_signo = inf->sig; | ||
469 | info.si_errno = 0; | ||
470 | info.si_code = inf->code; | ||
471 | info.si_addr = (void __user *)addr; | ||
472 | arm64_notify_die("", regs, &info, esr); | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * Handle stack alignment exceptions. | ||
477 | */ | ||
478 | asmlinkage void __exception do_sp_pc_abort(unsigned long addr, | ||
479 | unsigned int esr, | ||
480 | struct pt_regs *regs) | ||
481 | { | ||
482 | struct siginfo info; | ||
483 | |||
484 | info.si_signo = SIGBUS; | ||
485 | info.si_errno = 0; | ||
486 | info.si_code = BUS_ADRALN; | ||
487 | info.si_addr = (void __user *)addr; | ||
488 | arm64_notify_die("", regs, &info, esr); | ||
489 | } | ||
490 | |||
491 | static struct fault_info debug_fault_info[] = { | ||
492 | { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware breakpoint" }, | ||
493 | { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware single-step" }, | ||
494 | { do_bad, SIGTRAP, TRAP_HWBKPT, "hardware watchpoint" }, | ||
495 | { do_bad, SIGBUS, 0, "unknown 3" }, | ||
496 | { do_bad, SIGTRAP, TRAP_BRKPT, "aarch32 BKPT" }, | ||
497 | { do_bad, SIGTRAP, 0, "aarch32 vector catch" }, | ||
498 | { do_bad, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" }, | ||
499 | { do_bad, SIGBUS, 0, "unknown 7" }, | ||
500 | }; | ||
501 | |||
502 | void __init hook_debug_fault_code(int nr, | ||
503 | int (*fn)(unsigned long, unsigned int, struct pt_regs *), | ||
504 | int sig, int code, const char *name) | ||
505 | { | ||
506 | BUG_ON(nr < 0 || nr >= ARRAY_SIZE(debug_fault_info)); | ||
507 | |||
508 | debug_fault_info[nr].fn = fn; | ||
509 | debug_fault_info[nr].sig = sig; | ||
510 | debug_fault_info[nr].code = code; | ||
511 | debug_fault_info[nr].name = name; | ||
512 | } | ||
513 | |||
514 | asmlinkage int __exception do_debug_exception(unsigned long addr, | ||
515 | unsigned int esr, | ||
516 | struct pt_regs *regs) | ||
517 | { | ||
518 | const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr); | ||
519 | struct siginfo info; | ||
520 | |||
521 | if (!inf->fn(addr, esr, regs)) | ||
522 | return 1; | ||
523 | |||
524 | pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n", | ||
525 | inf->name, esr, addr); | ||
526 | |||
527 | info.si_signo = inf->sig; | ||
528 | info.si_errno = 0; | ||
529 | info.si_code = inf->code; | ||
530 | info.si_addr = (void __user *)addr; | ||
531 | arm64_notify_die("", regs, &info, esr); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c new file mode 100644 index 000000000000..c144adb1682f --- /dev/null +++ b/arch/arm64/mm/flush.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/flush.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2002 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/export.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/pagemap.h> | ||
23 | |||
24 | #include <asm/cacheflush.h> | ||
25 | #include <asm/cachetype.h> | ||
26 | #include <asm/tlbflush.h> | ||
27 | |||
28 | #include "mm.h" | ||
29 | |||
30 | void flush_cache_mm(struct mm_struct *mm) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | void flush_cache_range(struct vm_area_struct *vma, unsigned long start, | ||
35 | unsigned long end) | ||
36 | { | ||
37 | if (vma->vm_flags & VM_EXEC) | ||
38 | __flush_icache_all(); | ||
39 | } | ||
40 | |||
41 | void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, | ||
42 | unsigned long pfn) | ||
43 | { | ||
44 | } | ||
45 | |||
46 | static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | ||
47 | unsigned long uaddr, void *kaddr, | ||
48 | unsigned long len) | ||
49 | { | ||
50 | if (vma->vm_flags & VM_EXEC) { | ||
51 | unsigned long addr = (unsigned long)kaddr; | ||
52 | if (icache_is_aliasing()) { | ||
53 | __flush_dcache_area(kaddr, len); | ||
54 | __flush_icache_all(); | ||
55 | } else { | ||
56 | flush_icache_range(addr, addr + len); | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Copy user data from/to a page which is mapped into a different processes | ||
63 | * address space. Really, we want to allow our "user space" model to handle | ||
64 | * this. | ||
65 | * | ||
66 | * Note that this code needs to run on the current CPU. | ||
67 | */ | ||
68 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | ||
69 | unsigned long uaddr, void *dst, const void *src, | ||
70 | unsigned long len) | ||
71 | { | ||
72 | #ifdef CONFIG_SMP | ||
73 | preempt_disable(); | ||
74 | #endif | ||
75 | memcpy(dst, src, len); | ||
76 | flush_ptrace_access(vma, page, uaddr, dst, len); | ||
77 | #ifdef CONFIG_SMP | ||
78 | preempt_enable(); | ||
79 | #endif | ||
80 | } | ||
81 | |||
82 | void __flush_dcache_page(struct page *page) | ||
83 | { | ||
84 | __flush_dcache_area(page_address(page), PAGE_SIZE); | ||
85 | } | ||
86 | |||
87 | void __sync_icache_dcache(pte_t pte, unsigned long addr) | ||
88 | { | ||
89 | unsigned long pfn; | ||
90 | struct page *page; | ||
91 | |||
92 | pfn = pte_pfn(pte); | ||
93 | if (!pfn_valid(pfn)) | ||
94 | return; | ||
95 | |||
96 | page = pfn_to_page(pfn); | ||
97 | if (!test_and_set_bit(PG_dcache_clean, &page->flags)) { | ||
98 | __flush_dcache_page(page); | ||
99 | __flush_icache_all(); | ||
100 | } else if (icache_is_aivivt()) { | ||
101 | __flush_icache_all(); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Ensure cache coherency between kernel mapping and userspace mapping of this | ||
107 | * page. | ||
108 | */ | ||
109 | void flush_dcache_page(struct page *page) | ||
110 | { | ||
111 | struct address_space *mapping; | ||
112 | |||
113 | /* | ||
114 | * The zero page is never written to, so never has any dirty cache | ||
115 | * lines, and therefore never needs to be flushed. | ||
116 | */ | ||
117 | if (page == ZERO_PAGE(0)) | ||
118 | return; | ||
119 | |||
120 | mapping = page_mapping(page); | ||
121 | if (mapping && mapping_mapped(mapping)) { | ||
122 | __flush_dcache_page(page); | ||
123 | __flush_icache_all(); | ||
124 | set_bit(PG_dcache_clean, &page->flags); | ||
125 | } else { | ||
126 | clear_bit(PG_dcache_clean, &page->flags); | ||
127 | } | ||
128 | } | ||
129 | EXPORT_SYMBOL(flush_dcache_page); | ||
130 | |||
131 | /* | ||
132 | * Additional functions defined in assembly. | ||
133 | */ | ||
134 | EXPORT_SYMBOL(flush_cache_all); | ||
135 | EXPORT_SYMBOL(flush_icache_range); | ||
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c new file mode 100644 index 000000000000..5f719ba949bc --- /dev/null +++ b/arch/arm64/mm/init.c | |||
@@ -0,0 +1,437 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/init.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2005 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/export.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/swap.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/bootmem.h> | ||
26 | #include <linux/mman.h> | ||
27 | #include <linux/nodemask.h> | ||
28 | #include <linux/initrd.h> | ||
29 | #include <linux/gfp.h> | ||
30 | #include <linux/memblock.h> | ||
31 | #include <linux/sort.h> | ||
32 | #include <linux/of_fdt.h> | ||
33 | |||
34 | #include <asm/prom.h> | ||
35 | #include <asm/sections.h> | ||
36 | #include <asm/setup.h> | ||
37 | #include <asm/sizes.h> | ||
38 | #include <asm/tlb.h> | ||
39 | |||
40 | #include "mm.h" | ||
41 | |||
42 | static unsigned long phys_initrd_start __initdata = 0; | ||
43 | static unsigned long phys_initrd_size __initdata = 0; | ||
44 | |||
45 | phys_addr_t memstart_addr __read_mostly = 0; | ||
46 | |||
47 | void __init early_init_dt_setup_initrd_arch(unsigned long start, | ||
48 | unsigned long end) | ||
49 | { | ||
50 | phys_initrd_start = start; | ||
51 | phys_initrd_size = end - start; | ||
52 | } | ||
53 | |||
54 | static int __init early_initrd(char *p) | ||
55 | { | ||
56 | unsigned long start, size; | ||
57 | char *endp; | ||
58 | |||
59 | start = memparse(p, &endp); | ||
60 | if (*endp == ',') { | ||
61 | size = memparse(endp + 1, NULL); | ||
62 | |||
63 | phys_initrd_start = start; | ||
64 | phys_initrd_size = size; | ||
65 | } | ||
66 | return 0; | ||
67 | } | ||
68 | early_param("initrd", early_initrd); | ||
69 | |||
70 | #define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT) | ||
71 | |||
72 | static void __init zone_sizes_init(unsigned long min, unsigned long max) | ||
73 | { | ||
74 | struct memblock_region *reg; | ||
75 | unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; | ||
76 | unsigned long max_dma32 = min; | ||
77 | |||
78 | memset(zone_size, 0, sizeof(zone_size)); | ||
79 | |||
80 | #ifdef CONFIG_ZONE_DMA32 | ||
81 | /* 4GB maximum for 32-bit only capable devices */ | ||
82 | max_dma32 = min(max, MAX_DMA32_PFN); | ||
83 | zone_size[ZONE_DMA32] = max_dma32 - min; | ||
84 | #endif | ||
85 | zone_size[ZONE_NORMAL] = max - max_dma32; | ||
86 | |||
87 | memcpy(zhole_size, zone_size, sizeof(zhole_size)); | ||
88 | |||
89 | for_each_memblock(memory, reg) { | ||
90 | unsigned long start = memblock_region_memory_base_pfn(reg); | ||
91 | unsigned long end = memblock_region_memory_end_pfn(reg); | ||
92 | |||
93 | if (start >= max) | ||
94 | continue; | ||
95 | #ifdef CONFIG_ZONE_DMA32 | ||
96 | if (start < max_dma32) { | ||
97 | unsigned long dma_end = min(end, max_dma32); | ||
98 | zhole_size[ZONE_DMA32] -= dma_end - start; | ||
99 | } | ||
100 | #endif | ||
101 | if (end > max_dma32) { | ||
102 | unsigned long normal_end = min(end, max); | ||
103 | unsigned long normal_start = max(start, max_dma32); | ||
104 | zhole_size[ZONE_NORMAL] -= normal_end - normal_start; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | free_area_init_node(0, zone_size, min, zhole_size); | ||
109 | } | ||
110 | |||
111 | #ifdef CONFIG_HAVE_ARCH_PFN_VALID | ||
112 | int pfn_valid(unsigned long pfn) | ||
113 | { | ||
114 | return memblock_is_memory(pfn << PAGE_SHIFT); | ||
115 | } | ||
116 | EXPORT_SYMBOL(pfn_valid); | ||
117 | #endif | ||
118 | |||
119 | #ifndef CONFIG_SPARSEMEM | ||
120 | static void arm64_memory_present(void) | ||
121 | { | ||
122 | } | ||
123 | #else | ||
124 | static void arm64_memory_present(void) | ||
125 | { | ||
126 | struct memblock_region *reg; | ||
127 | |||
128 | for_each_memblock(memory, reg) | ||
129 | memory_present(0, memblock_region_memory_base_pfn(reg), | ||
130 | memblock_region_memory_end_pfn(reg)); | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | void __init arm64_memblock_init(void) | ||
135 | { | ||
136 | u64 *reserve_map, base, size; | ||
137 | |||
138 | /* Register the kernel text, kernel data and initrd with memblock */ | ||
139 | memblock_reserve(__pa(_text), _end - _text); | ||
140 | #ifdef CONFIG_BLK_DEV_INITRD | ||
141 | if (phys_initrd_size) { | ||
142 | memblock_reserve(phys_initrd_start, phys_initrd_size); | ||
143 | |||
144 | /* Now convert initrd to virtual addresses */ | ||
145 | initrd_start = __phys_to_virt(phys_initrd_start); | ||
146 | initrd_end = initrd_start + phys_initrd_size; | ||
147 | } | ||
148 | #endif | ||
149 | |||
150 | /* | ||
151 | * Reserve the page tables. These are already in use, | ||
152 | * and can only be in node 0. | ||
153 | */ | ||
154 | memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE); | ||
155 | memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE); | ||
156 | |||
157 | /* Reserve the dtb region */ | ||
158 | memblock_reserve(virt_to_phys(initial_boot_params), | ||
159 | be32_to_cpu(initial_boot_params->totalsize)); | ||
160 | |||
161 | /* | ||
162 | * Process the reserve map. This will probably overlap the initrd | ||
163 | * and dtb locations which are already reserved, but overlapping | ||
164 | * doesn't hurt anything | ||
165 | */ | ||
166 | reserve_map = ((void*)initial_boot_params) + | ||
167 | be32_to_cpu(initial_boot_params->off_mem_rsvmap); | ||
168 | while (1) { | ||
169 | base = be64_to_cpup(reserve_map++); | ||
170 | size = be64_to_cpup(reserve_map++); | ||
171 | if (!size) | ||
172 | break; | ||
173 | memblock_reserve(base, size); | ||
174 | } | ||
175 | |||
176 | memblock_allow_resize(); | ||
177 | memblock_dump_all(); | ||
178 | } | ||
179 | |||
180 | void __init bootmem_init(void) | ||
181 | { | ||
182 | unsigned long min, max; | ||
183 | |||
184 | min = PFN_UP(memblock_start_of_DRAM()); | ||
185 | max = PFN_DOWN(memblock_end_of_DRAM()); | ||
186 | |||
187 | /* | ||
188 | * Sparsemem tries to allocate bootmem in memory_present(), so must be | ||
189 | * done after the fixed reservations. | ||
190 | */ | ||
191 | arm64_memory_present(); | ||
192 | |||
193 | sparse_init(); | ||
194 | zone_sizes_init(min, max); | ||
195 | |||
196 | high_memory = __va((max << PAGE_SHIFT) - 1) + 1; | ||
197 | max_pfn = max_low_pfn = max; | ||
198 | } | ||
199 | |||
200 | static inline int free_area(unsigned long pfn, unsigned long end, char *s) | ||
201 | { | ||
202 | unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10); | ||
203 | |||
204 | for (; pfn < end; pfn++) { | ||
205 | struct page *page = pfn_to_page(pfn); | ||
206 | ClearPageReserved(page); | ||
207 | init_page_count(page); | ||
208 | __free_page(page); | ||
209 | pages++; | ||
210 | } | ||
211 | |||
212 | if (size && s) | ||
213 | pr_info("Freeing %s memory: %dK\n", s, size); | ||
214 | |||
215 | return pages; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * Poison init memory with an undefined instruction (0x0). | ||
220 | */ | ||
221 | static inline void poison_init_mem(void *s, size_t count) | ||
222 | { | ||
223 | memset(s, 0, count); | ||
224 | } | ||
225 | |||
226 | #ifndef CONFIG_SPARSEMEM_VMEMMAP | ||
227 | static inline void free_memmap(unsigned long start_pfn, unsigned long end_pfn) | ||
228 | { | ||
229 | struct page *start_pg, *end_pg; | ||
230 | unsigned long pg, pgend; | ||
231 | |||
232 | /* | ||
233 | * Convert start_pfn/end_pfn to a struct page pointer. | ||
234 | */ | ||
235 | start_pg = pfn_to_page(start_pfn - 1) + 1; | ||
236 | end_pg = pfn_to_page(end_pfn - 1) + 1; | ||
237 | |||
238 | /* | ||
239 | * Convert to physical addresses, and round start upwards and end | ||
240 | * downwards. | ||
241 | */ | ||
242 | pg = (unsigned long)PAGE_ALIGN(__pa(start_pg)); | ||
243 | pgend = (unsigned long)__pa(end_pg) & PAGE_MASK; | ||
244 | |||
245 | /* | ||
246 | * If there are free pages between these, free the section of the | ||
247 | * memmap array. | ||
248 | */ | ||
249 | if (pg < pgend) | ||
250 | free_bootmem(pg, pgend - pg); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * The mem_map array can get very big. Free the unused area of the memory map. | ||
255 | */ | ||
256 | static void __init free_unused_memmap(void) | ||
257 | { | ||
258 | unsigned long start, prev_end = 0; | ||
259 | struct memblock_region *reg; | ||
260 | |||
261 | for_each_memblock(memory, reg) { | ||
262 | start = __phys_to_pfn(reg->base); | ||
263 | |||
264 | #ifdef CONFIG_SPARSEMEM | ||
265 | /* | ||
266 | * Take care not to free memmap entries that don't exist due | ||
267 | * to SPARSEMEM sections which aren't present. | ||
268 | */ | ||
269 | start = min(start, ALIGN(prev_end, PAGES_PER_SECTION)); | ||
270 | #endif | ||
271 | /* | ||
272 | * If we had a previous bank, and there is a space between the | ||
273 | * current bank and the previous, free it. | ||
274 | */ | ||
275 | if (prev_end && prev_end < start) | ||
276 | free_memmap(prev_end, start); | ||
277 | |||
278 | /* | ||
279 | * Align up here since the VM subsystem insists that the | ||
280 | * memmap entries are valid from the bank end aligned to | ||
281 | * MAX_ORDER_NR_PAGES. | ||
282 | */ | ||
283 | prev_end = ALIGN(start + __phys_to_pfn(reg->size), | ||
284 | MAX_ORDER_NR_PAGES); | ||
285 | } | ||
286 | |||
287 | #ifdef CONFIG_SPARSEMEM | ||
288 | if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION)) | ||
289 | free_memmap(prev_end, ALIGN(prev_end, PAGES_PER_SECTION)); | ||
290 | #endif | ||
291 | } | ||
292 | #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ | ||
293 | |||
294 | /* | ||
295 | * mem_init() marks the free areas in the mem_map and tells us how much memory | ||
296 | * is free. This is done after various parts of the system have claimed their | ||
297 | * memory after the kernel image. | ||
298 | */ | ||
299 | void __init mem_init(void) | ||
300 | { | ||
301 | unsigned long reserved_pages, free_pages; | ||
302 | struct memblock_region *reg; | ||
303 | |||
304 | #if CONFIG_SWIOTLB | ||
305 | extern void __init arm64_swiotlb_init(size_t max_size); | ||
306 | arm64_swiotlb_init(max_pfn << (PAGE_SHIFT - 1)); | ||
307 | #endif | ||
308 | |||
309 | max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; | ||
310 | |||
311 | #ifndef CONFIG_SPARSEMEM_VMEMMAP | ||
312 | /* this will put all unused low memory onto the freelists */ | ||
313 | free_unused_memmap(); | ||
314 | #endif | ||
315 | |||
316 | totalram_pages += free_all_bootmem(); | ||
317 | |||
318 | reserved_pages = free_pages = 0; | ||
319 | |||
320 | for_each_memblock(memory, reg) { | ||
321 | unsigned int pfn1, pfn2; | ||
322 | struct page *page, *end; | ||
323 | |||
324 | pfn1 = __phys_to_pfn(reg->base); | ||
325 | pfn2 = pfn1 + __phys_to_pfn(reg->size); | ||
326 | |||
327 | page = pfn_to_page(pfn1); | ||
328 | end = pfn_to_page(pfn2 - 1) + 1; | ||
329 | |||
330 | do { | ||
331 | if (PageReserved(page)) | ||
332 | reserved_pages++; | ||
333 | else if (!page_count(page)) | ||
334 | free_pages++; | ||
335 | page++; | ||
336 | } while (page < end); | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Since our memory may not be contiguous, calculate the real number | ||
341 | * of pages we have in this system. | ||
342 | */ | ||
343 | pr_info("Memory:"); | ||
344 | num_physpages = 0; | ||
345 | for_each_memblock(memory, reg) { | ||
346 | unsigned long pages = memblock_region_memory_end_pfn(reg) - | ||
347 | memblock_region_memory_base_pfn(reg); | ||
348 | num_physpages += pages; | ||
349 | printk(" %ldMB", pages >> (20 - PAGE_SHIFT)); | ||
350 | } | ||
351 | printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); | ||
352 | |||
353 | pr_notice("Memory: %luk/%luk available, %luk reserved\n", | ||
354 | nr_free_pages() << (PAGE_SHIFT-10), | ||
355 | free_pages << (PAGE_SHIFT-10), | ||
356 | reserved_pages << (PAGE_SHIFT-10)); | ||
357 | |||
358 | #define MLK(b, t) b, t, ((t) - (b)) >> 10 | ||
359 | #define MLM(b, t) b, t, ((t) - (b)) >> 20 | ||
360 | #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) | ||
361 | |||
362 | pr_notice("Virtual kernel memory layout:\n" | ||
363 | " vmalloc : 0x%16lx - 0x%16lx (%6ld MB)\n" | ||
364 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
365 | " vmemmap : 0x%16lx - 0x%16lx (%6ld MB)\n" | ||
366 | #endif | ||
367 | " modules : 0x%16lx - 0x%16lx (%6ld MB)\n" | ||
368 | " memory : 0x%16lx - 0x%16lx (%6ld MB)\n" | ||
369 | " .init : 0x%p" " - 0x%p" " (%6ld kB)\n" | ||
370 | " .text : 0x%p" " - 0x%p" " (%6ld kB)\n" | ||
371 | " .data : 0x%p" " - 0x%p" " (%6ld kB)\n", | ||
372 | MLM(VMALLOC_START, VMALLOC_END), | ||
373 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
374 | MLM((unsigned long)virt_to_page(PAGE_OFFSET), | ||
375 | (unsigned long)virt_to_page(high_memory)), | ||
376 | #endif | ||
377 | MLM(MODULES_VADDR, MODULES_END), | ||
378 | MLM(PAGE_OFFSET, (unsigned long)high_memory), | ||
379 | |||
380 | MLK_ROUNDUP(__init_begin, __init_end), | ||
381 | MLK_ROUNDUP(_text, _etext), | ||
382 | MLK_ROUNDUP(_sdata, _edata)); | ||
383 | |||
384 | #undef MLK | ||
385 | #undef MLM | ||
386 | #undef MLK_ROUNDUP | ||
387 | |||
388 | /* | ||
389 | * Check boundaries twice: Some fundamental inconsistencies can be | ||
390 | * detected at build time already. | ||
391 | */ | ||
392 | #ifdef CONFIG_COMPAT | ||
393 | BUILD_BUG_ON(TASK_SIZE_32 > TASK_SIZE_64); | ||
394 | #endif | ||
395 | BUILD_BUG_ON(TASK_SIZE_64 > MODULES_VADDR); | ||
396 | BUG_ON(TASK_SIZE_64 > MODULES_VADDR); | ||
397 | |||
398 | if (PAGE_SIZE >= 16384 && num_physpages <= 128) { | ||
399 | extern int sysctl_overcommit_memory; | ||
400 | /* | ||
401 | * On a machine this small we won't get anywhere without | ||
402 | * overcommit, so turn it on by default. | ||
403 | */ | ||
404 | sysctl_overcommit_memory = OVERCOMMIT_ALWAYS; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | void free_initmem(void) | ||
409 | { | ||
410 | poison_init_mem(__init_begin, __init_end - __init_begin); | ||
411 | totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)), | ||
412 | __phys_to_pfn(__pa(__init_end)), | ||
413 | "init"); | ||
414 | } | ||
415 | |||
416 | #ifdef CONFIG_BLK_DEV_INITRD | ||
417 | |||
418 | static int keep_initrd; | ||
419 | |||
420 | void free_initrd_mem(unsigned long start, unsigned long end) | ||
421 | { | ||
422 | if (!keep_initrd) { | ||
423 | poison_init_mem((void *)start, PAGE_ALIGN(end) - start); | ||
424 | totalram_pages += free_area(__phys_to_pfn(__pa(start)), | ||
425 | __phys_to_pfn(__pa(end)), | ||
426 | "initrd"); | ||
427 | } | ||
428 | } | ||
429 | |||
430 | static int __init keepinitrd_setup(char *__unused) | ||
431 | { | ||
432 | keep_initrd = 1; | ||
433 | return 1; | ||
434 | } | ||
435 | |||
436 | __setup("keepinitrd", keepinitrd_setup); | ||
437 | #endif | ||
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c new file mode 100644 index 000000000000..1725cd6db37a --- /dev/null +++ b/arch/arm64/mm/ioremap.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/ioremap.c | ||
3 | * | ||
4 | * (C) Copyright 1995 1996 Linus Torvalds | ||
5 | * Hacked for ARM by Phil Blundell <philb@gnu.org> | ||
6 | * Hacked to allow all architectures to build, and various cleanups | ||
7 | * by Russell King | ||
8 | * Copyright (C) 2012 ARM Ltd. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | */ | ||
22 | |||
23 | #include <linux/export.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/vmalloc.h> | ||
26 | #include <linux/io.h> | ||
27 | |||
28 | static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, | ||
29 | pgprot_t prot, void *caller) | ||
30 | { | ||
31 | unsigned long last_addr; | ||
32 | unsigned long offset = phys_addr & ~PAGE_MASK; | ||
33 | int err; | ||
34 | unsigned long addr; | ||
35 | struct vm_struct *area; | ||
36 | |||
37 | /* | ||
38 | * Page align the mapping address and size, taking account of any | ||
39 | * offset. | ||
40 | */ | ||
41 | phys_addr &= PAGE_MASK; | ||
42 | size = PAGE_ALIGN(size + offset); | ||
43 | |||
44 | /* | ||
45 | * Don't allow wraparound, zero size or outside PHYS_MASK. | ||
46 | */ | ||
47 | last_addr = phys_addr + size - 1; | ||
48 | if (!size || last_addr < phys_addr || (last_addr & ~PHYS_MASK)) | ||
49 | return NULL; | ||
50 | |||
51 | /* | ||
52 | * Don't allow RAM to be mapped. | ||
53 | */ | ||
54 | if (WARN_ON(pfn_valid(__phys_to_pfn(phys_addr)))) | ||
55 | return NULL; | ||
56 | |||
57 | area = get_vm_area_caller(size, VM_IOREMAP, caller); | ||
58 | if (!area) | ||
59 | return NULL; | ||
60 | addr = (unsigned long)area->addr; | ||
61 | |||
62 | err = ioremap_page_range(addr, addr + size, phys_addr, prot); | ||
63 | if (err) { | ||
64 | vunmap((void *)addr); | ||
65 | return NULL; | ||
66 | } | ||
67 | |||
68 | return (void __iomem *)(offset + addr); | ||
69 | } | ||
70 | |||
71 | void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot) | ||
72 | { | ||
73 | return __ioremap_caller(phys_addr, size, prot, | ||
74 | __builtin_return_address(0)); | ||
75 | } | ||
76 | EXPORT_SYMBOL(__ioremap); | ||
77 | |||
78 | void __iounmap(volatile void __iomem *io_addr) | ||
79 | { | ||
80 | void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); | ||
81 | |||
82 | vunmap(addr); | ||
83 | } | ||
84 | EXPORT_SYMBOL(__iounmap); | ||
diff --git a/arch/arm64/mm/mm.h b/arch/arm64/mm/mm.h new file mode 100644 index 000000000000..d8d6e7851c14 --- /dev/null +++ b/arch/arm64/mm/mm.h | |||
@@ -0,0 +1,2 @@ | |||
1 | extern void __flush_dcache_page(struct page *page); | ||
2 | extern void __init bootmem_init(void); | ||
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c new file mode 100644 index 000000000000..7c7be7855638 --- /dev/null +++ b/arch/arm64/mm/mmap.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/mmap.c | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/elf.h> | ||
20 | #include <linux/fs.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/mman.h> | ||
23 | #include <linux/export.h> | ||
24 | #include <linux/shm.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/personality.h> | ||
28 | #include <linux/random.h> | ||
29 | |||
30 | #include <asm/cputype.h> | ||
31 | |||
32 | /* | ||
33 | * Leave enough space between the mmap area and the stack to honour ulimit in | ||
34 | * the face of randomisation. | ||
35 | */ | ||
36 | #define MIN_GAP (SZ_128M + ((STACK_RND_MASK << PAGE_SHIFT) + 1)) | ||
37 | #define MAX_GAP (STACK_TOP/6*5) | ||
38 | |||
39 | static int mmap_is_legacy(void) | ||
40 | { | ||
41 | if (current->personality & ADDR_COMPAT_LAYOUT) | ||
42 | return 1; | ||
43 | |||
44 | if (rlimit(RLIMIT_STACK) == RLIM_INFINITY) | ||
45 | return 1; | ||
46 | |||
47 | return sysctl_legacy_va_layout; | ||
48 | } | ||
49 | |||
50 | /* | ||
51 | * Since get_random_int() returns the same value within a 1 jiffy window, we | ||
52 | * will almost always get the same randomisation for the stack and mmap | ||
53 | * region. This will mean the relative distance between stack and mmap will be | ||
54 | * the same. | ||
55 | * | ||
56 | * To avoid this we can shift the randomness by 1 bit. | ||
57 | */ | ||
58 | static unsigned long mmap_rnd(void) | ||
59 | { | ||
60 | unsigned long rnd = 0; | ||
61 | |||
62 | if (current->flags & PF_RANDOMIZE) | ||
63 | rnd = (long)get_random_int() & (STACK_RND_MASK >> 1); | ||
64 | |||
65 | return rnd << (PAGE_SHIFT + 1); | ||
66 | } | ||
67 | |||
68 | static unsigned long mmap_base(void) | ||
69 | { | ||
70 | unsigned long gap = rlimit(RLIMIT_STACK); | ||
71 | |||
72 | if (gap < MIN_GAP) | ||
73 | gap = MIN_GAP; | ||
74 | else if (gap > MAX_GAP) | ||
75 | gap = MAX_GAP; | ||
76 | |||
77 | return PAGE_ALIGN(STACK_TOP - gap - mmap_rnd()); | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * This function, called very early during the creation of a new process VM | ||
82 | * image, sets up which VM layout function to use: | ||
83 | */ | ||
84 | void arch_pick_mmap_layout(struct mm_struct *mm) | ||
85 | { | ||
86 | /* | ||
87 | * Fall back to the standard layout if the personality bit is set, or | ||
88 | * if the expected stack growth is unlimited: | ||
89 | */ | ||
90 | if (mmap_is_legacy()) { | ||
91 | mm->mmap_base = TASK_UNMAPPED_BASE; | ||
92 | mm->get_unmapped_area = arch_get_unmapped_area; | ||
93 | mm->unmap_area = arch_unmap_area; | ||
94 | } else { | ||
95 | mm->mmap_base = mmap_base(); | ||
96 | mm->get_unmapped_area = arch_get_unmapped_area_topdown; | ||
97 | mm->unmap_area = arch_unmap_area_topdown; | ||
98 | } | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(arch_pick_mmap_layout); | ||
101 | |||
102 | |||
103 | /* | ||
104 | * You really shouldn't be using read() or write() on /dev/mem. This might go | ||
105 | * away in the future. | ||
106 | */ | ||
107 | int valid_phys_addr_range(unsigned long addr, size_t size) | ||
108 | { | ||
109 | if (addr < PHYS_OFFSET) | ||
110 | return 0; | ||
111 | if (addr + size > __pa(high_memory - 1) + 1) | ||
112 | return 0; | ||
113 | |||
114 | return 1; | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * Do not allow /dev/mem mappings beyond the supported physical range. | ||
119 | */ | ||
120 | int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) | ||
121 | { | ||
122 | return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK); | ||
123 | } | ||
124 | |||
125 | #ifdef CONFIG_STRICT_DEVMEM | ||
126 | |||
127 | #include <linux/ioport.h> | ||
128 | |||
129 | /* | ||
130 | * devmem_is_allowed() checks to see if /dev/mem access to a certain address | ||
131 | * is valid. The argument is a physical page number. We mimic x86 here by | ||
132 | * disallowing access to system RAM as well as device-exclusive MMIO regions. | ||
133 | * This effectively disable read()/write() on /dev/mem. | ||
134 | */ | ||
135 | int devmem_is_allowed(unsigned long pfn) | ||
136 | { | ||
137 | if (iomem_is_exclusive(pfn << PAGE_SHIFT)) | ||
138 | return 0; | ||
139 | if (!page_is_ram(pfn)) | ||
140 | return 1; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | #endif | ||
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c new file mode 100644 index 000000000000..a6885d896ab6 --- /dev/null +++ b/arch/arm64/mm/mmu.c | |||
@@ -0,0 +1,395 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/mmu.c | ||
3 | * | ||
4 | * Copyright (C) 1995-2005 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/export.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/mman.h> | ||
25 | #include <linux/nodemask.h> | ||
26 | #include <linux/memblock.h> | ||
27 | #include <linux/fs.h> | ||
28 | |||
29 | #include <asm/cputype.h> | ||
30 | #include <asm/sections.h> | ||
31 | #include <asm/setup.h> | ||
32 | #include <asm/sizes.h> | ||
33 | #include <asm/tlb.h> | ||
34 | #include <asm/mmu_context.h> | ||
35 | |||
36 | #include "mm.h" | ||
37 | |||
38 | /* | ||
39 | * Empty_zero_page is a special page that is used for zero-initialized data | ||
40 | * and COW. | ||
41 | */ | ||
42 | struct page *empty_zero_page; | ||
43 | EXPORT_SYMBOL(empty_zero_page); | ||
44 | |||
45 | pgprot_t pgprot_default; | ||
46 | EXPORT_SYMBOL(pgprot_default); | ||
47 | |||
48 | static pmdval_t prot_sect_kernel; | ||
49 | |||
50 | struct cachepolicy { | ||
51 | const char policy[16]; | ||
52 | u64 mair; | ||
53 | u64 tcr; | ||
54 | }; | ||
55 | |||
56 | static struct cachepolicy cache_policies[] __initdata = { | ||
57 | { | ||
58 | .policy = "uncached", | ||
59 | .mair = 0x44, /* inner, outer non-cacheable */ | ||
60 | .tcr = TCR_IRGN_NC | TCR_ORGN_NC, | ||
61 | }, { | ||
62 | .policy = "writethrough", | ||
63 | .mair = 0xaa, /* inner, outer write-through, read-allocate */ | ||
64 | .tcr = TCR_IRGN_WT | TCR_ORGN_WT, | ||
65 | }, { | ||
66 | .policy = "writeback", | ||
67 | .mair = 0xee, /* inner, outer write-back, read-allocate */ | ||
68 | .tcr = TCR_IRGN_WBnWA | TCR_ORGN_WBnWA, | ||
69 | } | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * These are useful for identifying cache coherency problems by allowing the | ||
74 | * cache or the cache and writebuffer to be turned off. It changes the Normal | ||
75 | * memory caching attributes in the MAIR_EL1 register. | ||
76 | */ | ||
77 | static int __init early_cachepolicy(char *p) | ||
78 | { | ||
79 | int i; | ||
80 | u64 tmp; | ||
81 | |||
82 | for (i = 0; i < ARRAY_SIZE(cache_policies); i++) { | ||
83 | int len = strlen(cache_policies[i].policy); | ||
84 | |||
85 | if (memcmp(p, cache_policies[i].policy, len) == 0) | ||
86 | break; | ||
87 | } | ||
88 | if (i == ARRAY_SIZE(cache_policies)) { | ||
89 | pr_err("ERROR: unknown or unsupported cache policy: %s\n", p); | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | flush_cache_all(); | ||
94 | |||
95 | /* | ||
96 | * Modify MT_NORMAL attributes in MAIR_EL1. | ||
97 | */ | ||
98 | asm volatile( | ||
99 | " mrs %0, mair_el1\n" | ||
100 | " bfi %0, %1, #%2, #8\n" | ||
101 | " msr mair_el1, %0\n" | ||
102 | " isb\n" | ||
103 | : "=&r" (tmp) | ||
104 | : "r" (cache_policies[i].mair), "i" (MT_NORMAL * 8)); | ||
105 | |||
106 | /* | ||
107 | * Modify TCR PTW cacheability attributes. | ||
108 | */ | ||
109 | asm volatile( | ||
110 | " mrs %0, tcr_el1\n" | ||
111 | " bic %0, %0, %2\n" | ||
112 | " orr %0, %0, %1\n" | ||
113 | " msr tcr_el1, %0\n" | ||
114 | " isb\n" | ||
115 | : "=&r" (tmp) | ||
116 | : "r" (cache_policies[i].tcr), "r" (TCR_IRGN_MASK | TCR_ORGN_MASK)); | ||
117 | |||
118 | flush_cache_all(); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | early_param("cachepolicy", early_cachepolicy); | ||
123 | |||
124 | /* | ||
125 | * Adjust the PMD section entries according to the CPU in use. | ||
126 | */ | ||
127 | static void __init init_mem_pgprot(void) | ||
128 | { | ||
129 | pteval_t default_pgprot; | ||
130 | int i; | ||
131 | |||
132 | default_pgprot = PTE_ATTRINDX(MT_NORMAL); | ||
133 | prot_sect_kernel = PMD_TYPE_SECT | PMD_SECT_AF | PMD_ATTRINDX(MT_NORMAL); | ||
134 | |||
135 | #ifdef CONFIG_SMP | ||
136 | /* | ||
137 | * Mark memory with the "shared" attribute for SMP systems | ||
138 | */ | ||
139 | default_pgprot |= PTE_SHARED; | ||
140 | prot_sect_kernel |= PMD_SECT_S; | ||
141 | #endif | ||
142 | |||
143 | for (i = 0; i < 16; i++) { | ||
144 | unsigned long v = pgprot_val(protection_map[i]); | ||
145 | protection_map[i] = __pgprot(v | default_pgprot); | ||
146 | } | ||
147 | |||
148 | pgprot_default = __pgprot(PTE_TYPE_PAGE | PTE_AF | default_pgprot); | ||
149 | } | ||
150 | |||
151 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
152 | unsigned long size, pgprot_t vma_prot) | ||
153 | { | ||
154 | if (!pfn_valid(pfn)) | ||
155 | return pgprot_noncached(vma_prot); | ||
156 | else if (file->f_flags & O_SYNC) | ||
157 | return pgprot_writecombine(vma_prot); | ||
158 | return vma_prot; | ||
159 | } | ||
160 | EXPORT_SYMBOL(phys_mem_access_prot); | ||
161 | |||
162 | static void __init *early_alloc(unsigned long sz) | ||
163 | { | ||
164 | void *ptr = __va(memblock_alloc(sz, sz)); | ||
165 | memset(ptr, 0, sz); | ||
166 | return ptr; | ||
167 | } | ||
168 | |||
169 | static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | ||
170 | unsigned long end, unsigned long pfn) | ||
171 | { | ||
172 | pte_t *pte; | ||
173 | |||
174 | if (pmd_none(*pmd)) { | ||
175 | pte = early_alloc(PTRS_PER_PTE * sizeof(pte_t)); | ||
176 | __pmd_populate(pmd, __pa(pte), PMD_TYPE_TABLE); | ||
177 | } | ||
178 | BUG_ON(pmd_bad(*pmd)); | ||
179 | |||
180 | pte = pte_offset_kernel(pmd, addr); | ||
181 | do { | ||
182 | set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); | ||
183 | pfn++; | ||
184 | } while (pte++, addr += PAGE_SIZE, addr != end); | ||
185 | } | ||
186 | |||
187 | static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, | ||
188 | unsigned long end, phys_addr_t phys) | ||
189 | { | ||
190 | pmd_t *pmd; | ||
191 | unsigned long next; | ||
192 | |||
193 | /* | ||
194 | * Check for initial section mappings in the pgd/pud and remove them. | ||
195 | */ | ||
196 | if (pud_none(*pud) || pud_bad(*pud)) { | ||
197 | pmd = early_alloc(PTRS_PER_PMD * sizeof(pmd_t)); | ||
198 | pud_populate(&init_mm, pud, pmd); | ||
199 | } | ||
200 | |||
201 | pmd = pmd_offset(pud, addr); | ||
202 | do { | ||
203 | next = pmd_addr_end(addr, end); | ||
204 | /* try section mapping first */ | ||
205 | if (((addr | next | phys) & ~SECTION_MASK) == 0) | ||
206 | set_pmd(pmd, __pmd(phys | prot_sect_kernel)); | ||
207 | else | ||
208 | alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys)); | ||
209 | phys += next - addr; | ||
210 | } while (pmd++, addr = next, addr != end); | ||
211 | } | ||
212 | |||
213 | static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, | ||
214 | unsigned long end, unsigned long phys) | ||
215 | { | ||
216 | pud_t *pud = pud_offset(pgd, addr); | ||
217 | unsigned long next; | ||
218 | |||
219 | do { | ||
220 | next = pud_addr_end(addr, end); | ||
221 | alloc_init_pmd(pud, addr, next, phys); | ||
222 | phys += next - addr; | ||
223 | } while (pud++, addr = next, addr != end); | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * Create the page directory entries and any necessary page tables for the | ||
228 | * mapping specified by 'md'. | ||
229 | */ | ||
230 | static void __init create_mapping(phys_addr_t phys, unsigned long virt, | ||
231 | phys_addr_t size) | ||
232 | { | ||
233 | unsigned long addr, length, end, next; | ||
234 | pgd_t *pgd; | ||
235 | |||
236 | if (virt < VMALLOC_START) { | ||
237 | pr_warning("BUG: not creating mapping for 0x%016llx at 0x%016lx - outside kernel range\n", | ||
238 | phys, virt); | ||
239 | return; | ||
240 | } | ||
241 | |||
242 | addr = virt & PAGE_MASK; | ||
243 | length = PAGE_ALIGN(size + (virt & ~PAGE_MASK)); | ||
244 | |||
245 | pgd = pgd_offset_k(addr); | ||
246 | end = addr + length; | ||
247 | do { | ||
248 | next = pgd_addr_end(addr, end); | ||
249 | alloc_init_pud(pgd, addr, next, phys); | ||
250 | phys += next - addr; | ||
251 | } while (pgd++, addr = next, addr != end); | ||
252 | } | ||
253 | |||
254 | static void __init map_mem(void) | ||
255 | { | ||
256 | struct memblock_region *reg; | ||
257 | |||
258 | /* map all the memory banks */ | ||
259 | for_each_memblock(memory, reg) { | ||
260 | phys_addr_t start = reg->base; | ||
261 | phys_addr_t end = start + reg->size; | ||
262 | |||
263 | if (start >= end) | ||
264 | break; | ||
265 | |||
266 | create_mapping(start, __phys_to_virt(start), end - start); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * paging_init() sets up the page tables, initialises the zone memory | ||
272 | * maps and sets up the zero page. | ||
273 | */ | ||
274 | void __init paging_init(void) | ||
275 | { | ||
276 | void *zero_page; | ||
277 | |||
278 | /* | ||
279 | * Maximum PGDIR_SIZE addressable via the initial direct kernel | ||
280 | * mapping in swapper_pg_dir. | ||
281 | */ | ||
282 | memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE); | ||
283 | |||
284 | init_mem_pgprot(); | ||
285 | map_mem(); | ||
286 | |||
287 | /* | ||
288 | * Finally flush the caches and tlb to ensure that we're in a | ||
289 | * consistent state. | ||
290 | */ | ||
291 | flush_cache_all(); | ||
292 | flush_tlb_all(); | ||
293 | |||
294 | /* allocate the zero page. */ | ||
295 | zero_page = early_alloc(PAGE_SIZE); | ||
296 | |||
297 | bootmem_init(); | ||
298 | |||
299 | empty_zero_page = virt_to_page(zero_page); | ||
300 | __flush_dcache_page(empty_zero_page); | ||
301 | |||
302 | /* | ||
303 | * TTBR0 is only used for the identity mapping at this stage. Make it | ||
304 | * point to zero page to avoid speculatively fetching new entries. | ||
305 | */ | ||
306 | cpu_set_reserved_ttbr0(); | ||
307 | flush_tlb_all(); | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Enable the identity mapping to allow the MMU disabling. | ||
312 | */ | ||
313 | void setup_mm_for_reboot(void) | ||
314 | { | ||
315 | cpu_switch_mm(idmap_pg_dir, &init_mm); | ||
316 | flush_tlb_all(); | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * Check whether a kernel address is valid (derived from arch/x86/). | ||
321 | */ | ||
322 | int kern_addr_valid(unsigned long addr) | ||
323 | { | ||
324 | pgd_t *pgd; | ||
325 | pud_t *pud; | ||
326 | pmd_t *pmd; | ||
327 | pte_t *pte; | ||
328 | |||
329 | if ((((long)addr) >> VA_BITS) != -1UL) | ||
330 | return 0; | ||
331 | |||
332 | pgd = pgd_offset_k(addr); | ||
333 | if (pgd_none(*pgd)) | ||
334 | return 0; | ||
335 | |||
336 | pud = pud_offset(pgd, addr); | ||
337 | if (pud_none(*pud)) | ||
338 | return 0; | ||
339 | |||
340 | pmd = pmd_offset(pud, addr); | ||
341 | if (pmd_none(*pmd)) | ||
342 | return 0; | ||
343 | |||
344 | pte = pte_offset_kernel(pmd, addr); | ||
345 | if (pte_none(*pte)) | ||
346 | return 0; | ||
347 | |||
348 | return pfn_valid(pte_pfn(*pte)); | ||
349 | } | ||
350 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
351 | #ifdef CONFIG_ARM64_64K_PAGES | ||
352 | int __meminit vmemmap_populate(struct page *start_page, | ||
353 | unsigned long size, int node) | ||
354 | { | ||
355 | return vmemmap_populate_basepages(start_page, size, node); | ||
356 | } | ||
357 | #else /* !CONFIG_ARM64_64K_PAGES */ | ||
358 | int __meminit vmemmap_populate(struct page *start_page, | ||
359 | unsigned long size, int node) | ||
360 | { | ||
361 | unsigned long addr = (unsigned long)start_page; | ||
362 | unsigned long end = (unsigned long)(start_page + size); | ||
363 | unsigned long next; | ||
364 | pgd_t *pgd; | ||
365 | pud_t *pud; | ||
366 | pmd_t *pmd; | ||
367 | |||
368 | do { | ||
369 | next = pmd_addr_end(addr, end); | ||
370 | |||
371 | pgd = vmemmap_pgd_populate(addr, node); | ||
372 | if (!pgd) | ||
373 | return -ENOMEM; | ||
374 | |||
375 | pud = vmemmap_pud_populate(pgd, addr, node); | ||
376 | if (!pud) | ||
377 | return -ENOMEM; | ||
378 | |||
379 | pmd = pmd_offset(pud, addr); | ||
380 | if (pmd_none(*pmd)) { | ||
381 | void *p = NULL; | ||
382 | |||
383 | p = vmemmap_alloc_block_buf(PMD_SIZE, node); | ||
384 | if (!p) | ||
385 | return -ENOMEM; | ||
386 | |||
387 | set_pmd(pmd, __pmd(__pa(p) | prot_sect_kernel)); | ||
388 | } else | ||
389 | vmemmap_verify((pte_t *)pmd, node, addr, next); | ||
390 | } while (addr = next, addr != end); | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | #endif /* CONFIG_ARM64_64K_PAGES */ | ||
395 | #endif /* CONFIG_SPARSEMEM_VMEMMAP */ | ||
diff --git a/arch/arm64/mm/pgd.c b/arch/arm64/mm/pgd.c new file mode 100644 index 000000000000..7083cdada657 --- /dev/null +++ b/arch/arm64/mm/pgd.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * PGD allocation/freeing | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/mm.h> | ||
21 | #include <linux/gfp.h> | ||
22 | #include <linux/highmem.h> | ||
23 | #include <linux/slab.h> | ||
24 | |||
25 | #include <asm/pgalloc.h> | ||
26 | #include <asm/page.h> | ||
27 | #include <asm/tlbflush.h> | ||
28 | |||
29 | #include "mm.h" | ||
30 | |||
31 | #define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t)) | ||
32 | |||
33 | pgd_t *pgd_alloc(struct mm_struct *mm) | ||
34 | { | ||
35 | pgd_t *new_pgd; | ||
36 | |||
37 | if (PGD_SIZE == PAGE_SIZE) | ||
38 | new_pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL); | ||
39 | else | ||
40 | new_pgd = kzalloc(PGD_SIZE, GFP_KERNEL); | ||
41 | |||
42 | if (!new_pgd) | ||
43 | return NULL; | ||
44 | |||
45 | return new_pgd; | ||
46 | } | ||
47 | |||
48 | void pgd_free(struct mm_struct *mm, pgd_t *pgd) | ||
49 | { | ||
50 | if (PGD_SIZE == PAGE_SIZE) | ||
51 | free_page((unsigned long)pgd); | ||
52 | else | ||
53 | kfree(pgd); | ||
54 | } | ||
diff --git a/arch/arm64/mm/proc-macros.S b/arch/arm64/mm/proc-macros.S new file mode 100644 index 000000000000..8957b822010b --- /dev/null +++ b/arch/arm64/mm/proc-macros.S | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/proc-macros.S | ||
3 | * | ||
4 | * Copyright (C) 2012 ARM Ltd. | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <asm/asm-offsets.h> | ||
20 | #include <asm/thread_info.h> | ||
21 | |||
22 | /* | ||
23 | * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm) | ||
24 | */ | ||
25 | .macro vma_vm_mm, rd, rn | ||
26 | ldr \rd, [\rn, #VMA_VM_MM] | ||
27 | .endm | ||
28 | |||
29 | /* | ||
30 | * mmid - get context id from mm pointer (mm->context.id) | ||
31 | */ | ||
32 | .macro mmid, rd, rn | ||
33 | ldr \rd, [\rn, #MM_CONTEXT_ID] | ||
34 | .endm | ||
35 | |||
36 | /* | ||
37 | * dcache_line_size - get the minimum D-cache line size from the CTR register. | ||
38 | */ | ||
39 | .macro dcache_line_size, reg, tmp | ||
40 | mrs \tmp, ctr_el0 // read CTR | ||
41 | lsr \tmp, \tmp, #16 | ||
42 | and \tmp, \tmp, #0xf // cache line size encoding | ||
43 | mov \reg, #4 // bytes per word | ||
44 | lsl \reg, \reg, \tmp // actual cache line size | ||
45 | .endm | ||
46 | |||
47 | /* | ||
48 | * icache_line_size - get the minimum I-cache line size from the CTR register. | ||
49 | */ | ||
50 | .macro icache_line_size, reg, tmp | ||
51 | mrs \tmp, ctr_el0 // read CTR | ||
52 | and \tmp, \tmp, #0xf // cache line size encoding | ||
53 | mov \reg, #4 // bytes per word | ||
54 | lsl \reg, \reg, \tmp // actual cache line size | ||
55 | .endm | ||
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S new file mode 100644 index 000000000000..f1d8b9bbfdad --- /dev/null +++ b/arch/arm64/mm/proc.S | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/proc.S | ||
3 | * | ||
4 | * Copyright (C) 2001 Deep Blue Solutions Ltd. | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/linkage.h> | ||
23 | #include <asm/assembler.h> | ||
24 | #include <asm/asm-offsets.h> | ||
25 | #include <asm/hwcap.h> | ||
26 | #include <asm/pgtable-hwdef.h> | ||
27 | #include <asm/pgtable.h> | ||
28 | |||
29 | #include "proc-macros.S" | ||
30 | |||
31 | #ifndef CONFIG_SMP | ||
32 | /* PTWs cacheable, inner/outer WBWA not shareable */ | ||
33 | #define TCR_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA | ||
34 | #else | ||
35 | /* PTWs cacheable, inner/outer WBWA shareable */ | ||
36 | #define TCR_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA | TCR_SHARED | ||
37 | #endif | ||
38 | |||
39 | #define MAIR(attr, mt) ((attr) << ((mt) * 8)) | ||
40 | |||
41 | /* | ||
42 | * cpu_cache_off() | ||
43 | * | ||
44 | * Turn the CPU D-cache off. | ||
45 | */ | ||
46 | ENTRY(cpu_cache_off) | ||
47 | mrs x0, sctlr_el1 | ||
48 | bic x0, x0, #1 << 2 // clear SCTLR.C | ||
49 | msr sctlr_el1, x0 | ||
50 | isb | ||
51 | ret | ||
52 | ENDPROC(cpu_cache_off) | ||
53 | |||
54 | /* | ||
55 | * cpu_reset(loc) | ||
56 | * | ||
57 | * Perform a soft reset of the system. Put the CPU into the same state | ||
58 | * as it would be if it had been reset, and branch to what would be the | ||
59 | * reset vector. It must be executed with the flat identity mapping. | ||
60 | * | ||
61 | * - loc - location to jump to for soft reset | ||
62 | */ | ||
63 | .align 5 | ||
64 | ENTRY(cpu_reset) | ||
65 | mrs x1, sctlr_el1 | ||
66 | bic x1, x1, #1 | ||
67 | msr sctlr_el1, x1 // disable the MMU | ||
68 | isb | ||
69 | ret x0 | ||
70 | ENDPROC(cpu_reset) | ||
71 | |||
72 | /* | ||
73 | * cpu_do_idle() | ||
74 | * | ||
75 | * Idle the processor (wait for interrupt). | ||
76 | */ | ||
77 | ENTRY(cpu_do_idle) | ||
78 | dsb sy // WFI may enter a low-power mode | ||
79 | wfi | ||
80 | ret | ||
81 | ENDPROC(cpu_do_idle) | ||
82 | |||
83 | /* | ||
84 | * cpu_switch_mm(pgd_phys, tsk) | ||
85 | * | ||
86 | * Set the translation table base pointer to be pgd_phys. | ||
87 | * | ||
88 | * - pgd_phys - physical address of new TTB | ||
89 | */ | ||
90 | ENTRY(cpu_do_switch_mm) | ||
91 | mmid w1, x1 // get mm->context.id | ||
92 | bfi x0, x1, #48, #16 // set the ASID | ||
93 | msr ttbr0_el1, x0 // set TTBR0 | ||
94 | isb | ||
95 | ret | ||
96 | ENDPROC(cpu_do_switch_mm) | ||
97 | |||
98 | cpu_name: | ||
99 | .ascii "AArch64 Processor" | ||
100 | .align | ||
101 | |||
102 | .section ".text.init", #alloc, #execinstr | ||
103 | |||
104 | /* | ||
105 | * __cpu_setup | ||
106 | * | ||
107 | * Initialise the processor for turning the MMU on. Return in x0 the | ||
108 | * value of the SCTLR_EL1 register. | ||
109 | */ | ||
110 | ENTRY(__cpu_setup) | ||
111 | /* | ||
112 | * Preserve the link register across the function call. | ||
113 | */ | ||
114 | mov x28, lr | ||
115 | bl __flush_dcache_all | ||
116 | mov lr, x28 | ||
117 | ic iallu // I+BTB cache invalidate | ||
118 | dsb sy | ||
119 | |||
120 | mov x0, #3 << 20 | ||
121 | msr cpacr_el1, x0 // Enable FP/ASIMD | ||
122 | mov x0, #1 | ||
123 | msr oslar_el1, x0 // Set the debug OS lock | ||
124 | tlbi vmalle1is // invalidate I + D TLBs | ||
125 | /* | ||
126 | * Memory region attributes for LPAE: | ||
127 | * | ||
128 | * n = AttrIndx[2:0] | ||
129 | * n MAIR | ||
130 | * DEVICE_nGnRnE 000 00000000 | ||
131 | * DEVICE_nGnRE 001 00000100 | ||
132 | * DEVICE_GRE 010 00001100 | ||
133 | * NORMAL_NC 011 01000100 | ||
134 | * NORMAL 100 11111111 | ||
135 | */ | ||
136 | ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \ | ||
137 | MAIR(0x04, MT_DEVICE_nGnRE) | \ | ||
138 | MAIR(0x0c, MT_DEVICE_GRE) | \ | ||
139 | MAIR(0x44, MT_NORMAL_NC) | \ | ||
140 | MAIR(0xff, MT_NORMAL) | ||
141 | msr mair_el1, x5 | ||
142 | /* | ||
143 | * Prepare SCTLR | ||
144 | */ | ||
145 | adr x5, crval | ||
146 | ldp w5, w6, [x5] | ||
147 | mrs x0, sctlr_el1 | ||
148 | bic x0, x0, x5 // clear bits | ||
149 | orr x0, x0, x6 // set bits | ||
150 | /* | ||
151 | * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for | ||
152 | * both user and kernel. | ||
153 | */ | ||
154 | ldr x10, =TCR_TxSZ(VA_BITS) | TCR_FLAGS | TCR_IPS_40BIT | \ | ||
155 | TCR_ASID16 | (1 << 31) | ||
156 | #ifdef CONFIG_ARM64_64K_PAGES | ||
157 | orr x10, x10, TCR_TG0_64K | ||
158 | orr x10, x10, TCR_TG1_64K | ||
159 | #endif | ||
160 | msr tcr_el1, x10 | ||
161 | ret // return to head.S | ||
162 | ENDPROC(__cpu_setup) | ||
163 | |||
164 | /* | ||
165 | * n n T | ||
166 | * U E WT T UD US IHBS | ||
167 | * CE0 XWHW CZ ME TEEA S | ||
168 | * .... .IEE .... NEAI TE.I ..AD DEN0 ACAM | ||
169 | * 0011 0... 1101 ..0. ..0. 10.. .... .... < hardware reserved | ||
170 | * .... .100 .... 01.1 11.1 ..01 0001 1101 < software settings | ||
171 | */ | ||
172 | .type crval, #object | ||
173 | crval: | ||
174 | .word 0x030802e2 // clear | ||
175 | .word 0x0405d11d // set | ||
diff --git a/arch/arm64/mm/tlb.S b/arch/arm64/mm/tlb.S new file mode 100644 index 000000000000..8ae80a18e8ec --- /dev/null +++ b/arch/arm64/mm/tlb.S | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * Based on arch/arm/mm/tlb.S | ||
3 | * | ||
4 | * Copyright (C) 1997-2002 Russell King | ||
5 | * Copyright (C) 2012 ARM Ltd. | ||
6 | * Written by Catalin Marinas <catalin.marinas@arm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | #include <linux/linkage.h> | ||
21 | #include <asm/assembler.h> | ||
22 | #include <asm/asm-offsets.h> | ||
23 | #include <asm/page.h> | ||
24 | #include <asm/tlbflush.h> | ||
25 | #include "proc-macros.S" | ||
26 | |||
27 | /* | ||
28 | * __cpu_flush_user_tlb_range(start, end, vma) | ||
29 | * | ||
30 | * Invalidate a range of TLB entries in the specified address space. | ||
31 | * | ||
32 | * - start - start address (may not be aligned) | ||
33 | * - end - end address (exclusive, may not be aligned) | ||
34 | * - vma - vma_struct describing address range | ||
35 | */ | ||
36 | ENTRY(__cpu_flush_user_tlb_range) | ||
37 | vma_vm_mm x3, x2 // get vma->vm_mm | ||
38 | mmid x3, x3 // get vm_mm->context.id | ||
39 | dsb sy | ||
40 | lsr x0, x0, #12 // align address | ||
41 | lsr x1, x1, #12 | ||
42 | bfi x0, x3, #48, #16 // start VA and ASID | ||
43 | bfi x1, x3, #48, #16 // end VA and ASID | ||
44 | 1: tlbi vae1is, x0 // TLB invalidate by address and ASID | ||
45 | add x0, x0, #1 | ||
46 | cmp x0, x1 | ||
47 | b.lo 1b | ||
48 | dsb sy | ||
49 | ret | ||
50 | ENDPROC(__cpu_flush_user_tlb_range) | ||
51 | |||
52 | /* | ||
53 | * __cpu_flush_kern_tlb_range(start,end) | ||
54 | * | ||
55 | * Invalidate a range of kernel TLB entries. | ||
56 | * | ||
57 | * - start - start address (may not be aligned) | ||
58 | * - end - end address (exclusive, may not be aligned) | ||
59 | */ | ||
60 | ENTRY(__cpu_flush_kern_tlb_range) | ||
61 | dsb sy | ||
62 | lsr x0, x0, #12 // align address | ||
63 | lsr x1, x1, #12 | ||
64 | 1: tlbi vaae1is, x0 // TLB invalidate by address | ||
65 | add x0, x0, #1 | ||
66 | cmp x0, x1 | ||
67 | b.lo 1b | ||
68 | dsb sy | ||
69 | isb | ||
70 | ret | ||
71 | ENDPROC(__cpu_flush_kern_tlb_range) | ||
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index f34861920634..c7092e6057c5 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig | |||
@@ -38,6 +38,7 @@ config BLACKFIN | |||
38 | select GENERIC_ATOMIC64 | 38 | select GENERIC_ATOMIC64 |
39 | select GENERIC_IRQ_PROBE | 39 | select GENERIC_IRQ_PROBE |
40 | select IRQ_PER_CPU if SMP | 40 | select IRQ_PER_CPU if SMP |
41 | select USE_GENERIC_SMP_HELPERS if SMP | ||
41 | select HAVE_NMI_WATCHDOG if NMI_WATCHDOG | 42 | select HAVE_NMI_WATCHDOG if NMI_WATCHDOG |
42 | select GENERIC_SMP_IDLE_THREAD | 43 | select GENERIC_SMP_IDLE_THREAD |
43 | select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS | 44 | select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS |
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index d3d7e64ca96d..66cf00095b84 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile | |||
@@ -20,7 +20,6 @@ endif | |||
20 | KBUILD_AFLAGS += $(call cc-option,-mno-fdpic) | 20 | KBUILD_AFLAGS += $(call cc-option,-mno-fdpic) |
21 | KBUILD_CFLAGS_MODULE += -mlong-calls | 21 | KBUILD_CFLAGS_MODULE += -mlong-calls |
22 | LDFLAGS += -m elf32bfin | 22 | LDFLAGS += -m elf32bfin |
23 | KALLSYMS += --symbol-prefix=_ | ||
24 | 23 | ||
25 | KBUILD_DEFCONFIG := BF537-STAMP_defconfig | 24 | KBUILD_DEFCONFIG := BF537-STAMP_defconfig |
26 | 25 | ||
diff --git a/arch/blackfin/include/asm/smp.h b/arch/blackfin/include/asm/smp.h index dc3d144b4bb5..9631598dcc5d 100644 --- a/arch/blackfin/include/asm/smp.h +++ b/arch/blackfin/include/asm/smp.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #define raw_smp_processor_id() blackfin_core_id() | 18 | #define raw_smp_processor_id() blackfin_core_id() |
19 | 19 | ||
20 | extern void bfin_relocate_coreb_l1_mem(void); | 20 | extern void bfin_relocate_coreb_l1_mem(void); |
21 | extern void arch_send_call_function_single_ipi(int cpu); | ||
22 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | ||
21 | 23 | ||
22 | #if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1) | 24 | #if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1) |
23 | asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr); | 25 | asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr); |
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 00bbe672b3b3..a40151306b77 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c | |||
@@ -48,10 +48,13 @@ unsigned long blackfin_iflush_l1_entry[NR_CPUS]; | |||
48 | 48 | ||
49 | struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; | 49 | struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; |
50 | 50 | ||
51 | #define BFIN_IPI_TIMER 0 | 51 | enum ipi_message_type { |
52 | #define BFIN_IPI_RESCHEDULE 1 | 52 | BFIN_IPI_TIMER, |
53 | #define BFIN_IPI_CALL_FUNC 2 | 53 | BFIN_IPI_RESCHEDULE, |
54 | #define BFIN_IPI_CPU_STOP 3 | 54 | BFIN_IPI_CALL_FUNC, |
55 | BFIN_IPI_CALL_FUNC_SINGLE, | ||
56 | BFIN_IPI_CPU_STOP, | ||
57 | }; | ||
55 | 58 | ||
56 | struct blackfin_flush_data { | 59 | struct blackfin_flush_data { |
57 | unsigned long start; | 60 | unsigned long start; |
@@ -60,35 +63,20 @@ struct blackfin_flush_data { | |||
60 | 63 | ||
61 | void *secondary_stack; | 64 | void *secondary_stack; |
62 | 65 | ||
63 | |||
64 | struct smp_call_struct { | ||
65 | void (*func)(void *info); | ||
66 | void *info; | ||
67 | int wait; | ||
68 | cpumask_t *waitmask; | ||
69 | }; | ||
70 | |||
71 | static struct blackfin_flush_data smp_flush_data; | 66 | static struct blackfin_flush_data smp_flush_data; |
72 | 67 | ||
73 | static DEFINE_SPINLOCK(stop_lock); | 68 | static DEFINE_SPINLOCK(stop_lock); |
74 | 69 | ||
75 | struct ipi_message { | ||
76 | unsigned long type; | ||
77 | struct smp_call_struct call_struct; | ||
78 | }; | ||
79 | |||
80 | /* A magic number - stress test shows this is safe for common cases */ | 70 | /* A magic number - stress test shows this is safe for common cases */ |
81 | #define BFIN_IPI_MSGQ_LEN 5 | 71 | #define BFIN_IPI_MSGQ_LEN 5 |
82 | 72 | ||
83 | /* Simple FIFO buffer, overflow leads to panic */ | 73 | /* Simple FIFO buffer, overflow leads to panic */ |
84 | struct ipi_message_queue { | 74 | struct ipi_data { |
85 | spinlock_t lock; | ||
86 | unsigned long count; | 75 | unsigned long count; |
87 | unsigned long head; /* head of the queue */ | 76 | unsigned long bits; |
88 | struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN]; | ||
89 | }; | 77 | }; |
90 | 78 | ||
91 | static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue); | 79 | static DEFINE_PER_CPU(struct ipi_data, bfin_ipi); |
92 | 80 | ||
93 | static void ipi_cpu_stop(unsigned int cpu) | 81 | static void ipi_cpu_stop(unsigned int cpu) |
94 | { | 82 | { |
@@ -129,28 +117,6 @@ static void ipi_flush_icache(void *info) | |||
129 | blackfin_icache_flush_range(fdata->start, fdata->end); | 117 | blackfin_icache_flush_range(fdata->start, fdata->end); |
130 | } | 118 | } |
131 | 119 | ||
132 | static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) | ||
133 | { | ||
134 | int wait; | ||
135 | void (*func)(void *info); | ||
136 | void *info; | ||
137 | func = msg->call_struct.func; | ||
138 | info = msg->call_struct.info; | ||
139 | wait = msg->call_struct.wait; | ||
140 | func(info); | ||
141 | if (wait) { | ||
142 | #ifdef __ARCH_SYNC_CORE_DCACHE | ||
143 | /* | ||
144 | * 'wait' usually means synchronization between CPUs. | ||
145 | * Invalidate D cache in case shared data was changed | ||
146 | * by func() to ensure cache coherence. | ||
147 | */ | ||
148 | resync_core_dcache(); | ||
149 | #endif | ||
150 | cpumask_clear_cpu(cpu, msg->call_struct.waitmask); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | /* Use IRQ_SUPPLE_0 to request reschedule. | 120 | /* Use IRQ_SUPPLE_0 to request reschedule. |
155 | * When returning from interrupt to user space, | 121 | * When returning from interrupt to user space, |
156 | * there is chance to reschedule */ | 122 | * there is chance to reschedule */ |
@@ -172,152 +138,95 @@ void ipi_timer(void) | |||
172 | 138 | ||
173 | static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) | 139 | static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) |
174 | { | 140 | { |
175 | struct ipi_message *msg; | 141 | struct ipi_data *bfin_ipi_data; |
176 | struct ipi_message_queue *msg_queue; | ||
177 | unsigned int cpu = smp_processor_id(); | 142 | unsigned int cpu = smp_processor_id(); |
178 | unsigned long flags; | 143 | unsigned long pending; |
144 | unsigned long msg; | ||
179 | 145 | ||
180 | platform_clear_ipi(cpu, IRQ_SUPPLE_1); | 146 | platform_clear_ipi(cpu, IRQ_SUPPLE_1); |
181 | 147 | ||
182 | msg_queue = &__get_cpu_var(ipi_msg_queue); | 148 | bfin_ipi_data = &__get_cpu_var(bfin_ipi); |
183 | 149 | ||
184 | spin_lock_irqsave(&msg_queue->lock, flags); | 150 | while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) { |
185 | 151 | msg = 0; | |
186 | while (msg_queue->count) { | 152 | do { |
187 | msg = &msg_queue->ipi_message[msg_queue->head]; | 153 | msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1); |
188 | switch (msg->type) { | 154 | switch (msg) { |
189 | case BFIN_IPI_TIMER: | 155 | case BFIN_IPI_TIMER: |
190 | ipi_timer(); | 156 | ipi_timer(); |
191 | break; | 157 | break; |
192 | case BFIN_IPI_RESCHEDULE: | 158 | case BFIN_IPI_RESCHEDULE: |
193 | scheduler_ipi(); | 159 | scheduler_ipi(); |
194 | break; | 160 | break; |
195 | case BFIN_IPI_CALL_FUNC: | 161 | case BFIN_IPI_CALL_FUNC: |
196 | ipi_call_function(cpu, msg); | 162 | generic_smp_call_function_interrupt(); |
197 | break; | 163 | break; |
198 | case BFIN_IPI_CPU_STOP: | 164 | |
199 | ipi_cpu_stop(cpu); | 165 | case BFIN_IPI_CALL_FUNC_SINGLE: |
200 | break; | 166 | generic_smp_call_function_single_interrupt(); |
201 | default: | 167 | break; |
202 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n", | 168 | |
203 | cpu, msg->type); | 169 | case BFIN_IPI_CPU_STOP: |
204 | break; | 170 | ipi_cpu_stop(cpu); |
205 | } | 171 | break; |
206 | msg_queue->head++; | 172 | } |
207 | msg_queue->head %= BFIN_IPI_MSGQ_LEN; | 173 | } while (msg < BITS_PER_LONG); |
208 | msg_queue->count--; | 174 | |
175 | smp_mb(); | ||
209 | } | 176 | } |
210 | spin_unlock_irqrestore(&msg_queue->lock, flags); | ||
211 | return IRQ_HANDLED; | 177 | return IRQ_HANDLED; |
212 | } | 178 | } |
213 | 179 | ||
214 | static void ipi_queue_init(void) | 180 | static void bfin_ipi_init(void) |
215 | { | 181 | { |
216 | unsigned int cpu; | 182 | unsigned int cpu; |
217 | struct ipi_message_queue *msg_queue; | 183 | struct ipi_data *bfin_ipi_data; |
218 | for_each_possible_cpu(cpu) { | 184 | for_each_possible_cpu(cpu) { |
219 | msg_queue = &per_cpu(ipi_msg_queue, cpu); | 185 | bfin_ipi_data = &per_cpu(bfin_ipi, cpu); |
220 | spin_lock_init(&msg_queue->lock); | 186 | bfin_ipi_data->bits = 0; |
221 | msg_queue->count = 0; | 187 | bfin_ipi_data->count = 0; |
222 | msg_queue->head = 0; | ||
223 | } | 188 | } |
224 | } | 189 | } |
225 | 190 | ||
226 | static inline void smp_send_message(cpumask_t callmap, unsigned long type, | 191 | void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg) |
227 | void (*func) (void *info), void *info, int wait) | ||
228 | { | 192 | { |
229 | unsigned int cpu; | 193 | unsigned int cpu; |
230 | struct ipi_message_queue *msg_queue; | 194 | struct ipi_data *bfin_ipi_data; |
231 | struct ipi_message *msg; | 195 | unsigned long flags; |
232 | unsigned long flags, next_msg; | 196 | |
233 | cpumask_t waitmask; /* waitmask is shared by all cpus */ | 197 | local_irq_save(flags); |
234 | 198 | ||
235 | cpumask_copy(&waitmask, &callmap); | 199 | for_each_cpu(cpu, cpumask) { |
236 | for_each_cpu(cpu, &callmap) { | 200 | bfin_ipi_data = &per_cpu(bfin_ipi, cpu); |
237 | msg_queue = &per_cpu(ipi_msg_queue, cpu); | 201 | smp_mb(); |
238 | spin_lock_irqsave(&msg_queue->lock, flags); | 202 | set_bit(msg, &bfin_ipi_data->bits); |
239 | if (msg_queue->count < BFIN_IPI_MSGQ_LEN) { | 203 | bfin_ipi_data->count++; |
240 | next_msg = (msg_queue->head + msg_queue->count) | ||
241 | % BFIN_IPI_MSGQ_LEN; | ||
242 | msg = &msg_queue->ipi_message[next_msg]; | ||
243 | msg->type = type; | ||
244 | if (type == BFIN_IPI_CALL_FUNC) { | ||
245 | msg->call_struct.func = func; | ||
246 | msg->call_struct.info = info; | ||
247 | msg->call_struct.wait = wait; | ||
248 | msg->call_struct.waitmask = &waitmask; | ||
249 | } | ||
250 | msg_queue->count++; | ||
251 | } else | ||
252 | panic("IPI message queue overflow\n"); | ||
253 | spin_unlock_irqrestore(&msg_queue->lock, flags); | ||
254 | platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1); | 204 | platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1); |
255 | } | 205 | } |
256 | 206 | ||
257 | if (wait) { | 207 | local_irq_restore(flags); |
258 | while (!cpumask_empty(&waitmask)) | ||
259 | blackfin_dcache_invalidate_range( | ||
260 | (unsigned long)(&waitmask), | ||
261 | (unsigned long)(&waitmask)); | ||
262 | #ifdef __ARCH_SYNC_CORE_DCACHE | ||
263 | /* | ||
264 | * Invalidate D cache in case shared data was changed by | ||
265 | * other processors to ensure cache coherence. | ||
266 | */ | ||
267 | resync_core_dcache(); | ||
268 | #endif | ||
269 | } | ||
270 | } | 208 | } |
271 | 209 | ||
272 | int smp_call_function(void (*func)(void *info), void *info, int wait) | 210 | void arch_send_call_function_single_ipi(int cpu) |
273 | { | 211 | { |
274 | cpumask_t callmap; | 212 | send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC_SINGLE); |
275 | |||
276 | preempt_disable(); | ||
277 | cpumask_copy(&callmap, cpu_online_mask); | ||
278 | cpumask_clear_cpu(smp_processor_id(), &callmap); | ||
279 | if (!cpumask_empty(&callmap)) | ||
280 | smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); | ||
281 | |||
282 | preempt_enable(); | ||
283 | |||
284 | return 0; | ||
285 | } | 213 | } |
286 | EXPORT_SYMBOL_GPL(smp_call_function); | ||
287 | 214 | ||
288 | int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, | 215 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) |
289 | int wait) | ||
290 | { | 216 | { |
291 | unsigned int cpu = cpuid; | 217 | send_ipi(mask, BFIN_IPI_CALL_FUNC); |
292 | cpumask_t callmap; | ||
293 | |||
294 | if (cpu_is_offline(cpu)) | ||
295 | return 0; | ||
296 | cpumask_clear(&callmap); | ||
297 | cpumask_set_cpu(cpu, &callmap); | ||
298 | |||
299 | smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait); | ||
300 | |||
301 | return 0; | ||
302 | } | 218 | } |
303 | EXPORT_SYMBOL_GPL(smp_call_function_single); | ||
304 | 219 | ||
305 | void smp_send_reschedule(int cpu) | 220 | void smp_send_reschedule(int cpu) |
306 | { | 221 | { |
307 | cpumask_t callmap; | 222 | send_ipi(cpumask_of(cpu), BFIN_IPI_RESCHEDULE); |
308 | /* simply trigger an ipi */ | ||
309 | |||
310 | cpumask_clear(&callmap); | ||
311 | cpumask_set_cpu(cpu, &callmap); | ||
312 | |||
313 | smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0); | ||
314 | 223 | ||
315 | return; | 224 | return; |
316 | } | 225 | } |
317 | 226 | ||
318 | void smp_send_msg(const struct cpumask *mask, unsigned long type) | 227 | void smp_send_msg(const struct cpumask *mask, unsigned long type) |
319 | { | 228 | { |
320 | smp_send_message(*mask, type, NULL, NULL, 0); | 229 | send_ipi(mask, type); |
321 | } | 230 | } |
322 | 231 | ||
323 | void smp_timer_broadcast(const struct cpumask *mask) | 232 | void smp_timer_broadcast(const struct cpumask *mask) |
@@ -333,7 +242,7 @@ void smp_send_stop(void) | |||
333 | cpumask_copy(&callmap, cpu_online_mask); | 242 | cpumask_copy(&callmap, cpu_online_mask); |
334 | cpumask_clear_cpu(smp_processor_id(), &callmap); | 243 | cpumask_clear_cpu(smp_processor_id(), &callmap); |
335 | if (!cpumask_empty(&callmap)) | 244 | if (!cpumask_empty(&callmap)) |
336 | smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0); | 245 | send_ipi(&callmap, BFIN_IPI_CPU_STOP); |
337 | 246 | ||
338 | preempt_enable(); | 247 | preempt_enable(); |
339 | 248 | ||
@@ -436,7 +345,7 @@ void __init smp_prepare_boot_cpu(void) | |||
436 | void __init smp_prepare_cpus(unsigned int max_cpus) | 345 | void __init smp_prepare_cpus(unsigned int max_cpus) |
437 | { | 346 | { |
438 | platform_prepare_cpus(max_cpus); | 347 | platform_prepare_cpus(max_cpus); |
439 | ipi_queue_init(); | 348 | bfin_ipi_init(); |
440 | platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0); | 349 | platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0); |
441 | platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1); | 350 | platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1); |
442 | } | 351 | } |
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index 3af601e31e66..f08e89183cda 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild | |||
@@ -2,6 +2,7 @@ include include/asm-generic/Kbuild.asm | |||
2 | 2 | ||
3 | generic-y += atomic.h | 3 | generic-y += atomic.h |
4 | generic-y += auxvec.h | 4 | generic-y += auxvec.h |
5 | generic-y += barrier.h | ||
5 | generic-y += bitsperlong.h | 6 | generic-y += bitsperlong.h |
6 | generic-y += bugs.h | 7 | generic-y += bugs.h |
7 | generic-y += cputime.h | 8 | generic-y += cputime.h |
diff --git a/arch/c6x/include/asm/barrier.h b/arch/c6x/include/asm/barrier.h deleted file mode 100644 index 538240e85909..000000000000 --- a/arch/c6x/include/asm/barrier.h +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * Port on Texas Instruments TMS320C6x architecture | ||
3 | * | ||
4 | * Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated | ||
5 | * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #ifndef _ASM_C6X_BARRIER_H | ||
12 | #define _ASM_C6X_BARRIER_H | ||
13 | |||
14 | #define nop() asm("NOP\n"); | ||
15 | |||
16 | #define mb() barrier() | ||
17 | #define rmb() barrier() | ||
18 | #define wmb() barrier() | ||
19 | #define set_mb(var, value) do { var = value; mb(); } while (0) | ||
20 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | ||
21 | |||
22 | #define smp_mb() barrier() | ||
23 | #define smp_rmb() barrier() | ||
24 | #define smp_wmb() barrier() | ||
25 | #define smp_read_barrier_depends() do { } while (0) | ||
26 | |||
27 | #endif /* _ASM_C6X_BARRIER_H */ | ||
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 66fd01728790..7f65be6f7f17 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/elfcore.h> | 25 | #include <linux/elfcore.h> |
26 | #include <linux/mqueue.h> | 26 | #include <linux/mqueue.h> |
27 | #include <linux/reboot.h> | 27 | #include <linux/reboot.h> |
28 | #include <linux/rcupdate.h> | ||
28 | 29 | ||
29 | //#define DEBUG | 30 | //#define DEBUG |
30 | 31 | ||
@@ -74,6 +75,7 @@ void cpu_idle (void) | |||
74 | { | 75 | { |
75 | /* endless idle loop with no priority at all */ | 76 | /* endless idle loop with no priority at all */ |
76 | while (1) { | 77 | while (1) { |
78 | rcu_idle_enter(); | ||
77 | while (!need_resched()) { | 79 | while (!need_resched()) { |
78 | void (*idle)(void); | 80 | void (*idle)(void); |
79 | /* | 81 | /* |
@@ -86,6 +88,7 @@ void cpu_idle (void) | |||
86 | idle = default_idle; | 88 | idle = default_idle; |
87 | idle(); | 89 | idle(); |
88 | } | 90 | } |
91 | rcu_idle_exit(); | ||
89 | schedule_preempt_disabled(); | 92 | schedule_preempt_disabled(); |
90 | } | 93 | } |
91 | } | 94 | } |
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index ff95f50efea5..2eb7fa5bf9d8 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/reboot.h> | 25 | #include <linux/reboot.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
28 | #include <linux/rcupdate.h> | ||
28 | 29 | ||
29 | #include <asm/asm-offsets.h> | 30 | #include <asm/asm-offsets.h> |
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
@@ -69,12 +70,14 @@ void cpu_idle(void) | |||
69 | { | 70 | { |
70 | /* endless idle loop with no priority at all */ | 71 | /* endless idle loop with no priority at all */ |
71 | while (1) { | 72 | while (1) { |
73 | rcu_idle_enter(); | ||
72 | while (!need_resched()) { | 74 | while (!need_resched()) { |
73 | check_pgt_cache(); | 75 | check_pgt_cache(); |
74 | 76 | ||
75 | if (!frv_dma_inprogress && idle) | 77 | if (!frv_dma_inprogress && idle) |
76 | idle(); | 78 | idle(); |
77 | } | 79 | } |
80 | rcu_idle_exit(); | ||
78 | 81 | ||
79 | schedule_preempt_disabled(); | 82 | schedule_preempt_disabled(); |
80 | } | 83 | } |
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 0e9c315be104..f153ed1a4c08 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/reboot.h> | 36 | #include <linux/reboot.h> |
37 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/rcupdate.h> | ||
39 | 40 | ||
40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
41 | #include <asm/traps.h> | 42 | #include <asm/traps.h> |
@@ -78,8 +79,10 @@ void (*idle)(void) = default_idle; | |||
78 | void cpu_idle(void) | 79 | void cpu_idle(void) |
79 | { | 80 | { |
80 | while (1) { | 81 | while (1) { |
82 | rcu_idle_enter(); | ||
81 | while (!need_resched()) | 83 | while (!need_resched()) |
82 | idle(); | 84 | idle(); |
85 | rcu_idle_exit(); | ||
83 | schedule_preempt_disabled(); | 86 | schedule_preempt_disabled(); |
84 | } | 87 | } |
85 | } | 88 | } |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 310cf5781fad..3c720ef6c32d 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -25,6 +25,7 @@ config IA64 | |||
25 | select HAVE_GENERIC_HARDIRQS | 25 | select HAVE_GENERIC_HARDIRQS |
26 | select HAVE_MEMBLOCK | 26 | select HAVE_MEMBLOCK |
27 | select HAVE_MEMBLOCK_NODE_MAP | 27 | select HAVE_MEMBLOCK_NODE_MAP |
28 | select HAVE_VIRT_CPU_ACCOUNTING | ||
28 | select ARCH_DISCARD_MEMBLOCK | 29 | select ARCH_DISCARD_MEMBLOCK |
29 | select GENERIC_IRQ_PROBE | 30 | select GENERIC_IRQ_PROBE |
30 | select GENERIC_PENDING_IRQ if SMP | 31 | select GENERIC_PENDING_IRQ if SMP |
@@ -340,17 +341,6 @@ config FORCE_MAX_ZONEORDER | |||
340 | default "17" if HUGETLB_PAGE | 341 | default "17" if HUGETLB_PAGE |
341 | default "11" | 342 | default "11" |
342 | 343 | ||
343 | config VIRT_CPU_ACCOUNTING | ||
344 | bool "Deterministic task and CPU time accounting" | ||
345 | default n | ||
346 | help | ||
347 | Select this option to enable more accurate task and CPU time | ||
348 | accounting. This is done by reading a CPU counter on each | ||
349 | kernel entry and exit and on transitions within the kernel | ||
350 | between system, softirq and hardirq state, so there is a | ||
351 | small performance impact. | ||
352 | If in doubt, say N here. | ||
353 | |||
354 | config SMP | 344 | config SMP |
355 | bool "Symmetric multi-processing support" | 345 | bool "Symmetric multi-processing support" |
356 | select USE_GENERIC_SMP_HELPERS | 346 | select USE_GENERIC_SMP_HELPERS |
diff --git a/arch/ia64/include/asm/switch_to.h b/arch/ia64/include/asm/switch_to.h index cb2412fcd17f..d38c7ea5eea5 100644 --- a/arch/ia64/include/asm/switch_to.h +++ b/arch/ia64/include/asm/switch_to.h | |||
@@ -30,13 +30,6 @@ extern struct task_struct *ia64_switch_to (void *next_task); | |||
30 | extern void ia64_save_extra (struct task_struct *task); | 30 | extern void ia64_save_extra (struct task_struct *task); |
31 | extern void ia64_load_extra (struct task_struct *task); | 31 | extern void ia64_load_extra (struct task_struct *task); |
32 | 32 | ||
33 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
34 | extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next); | ||
35 | # define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n) | ||
36 | #else | ||
37 | # define IA64_ACCOUNT_ON_SWITCH(p,n) | ||
38 | #endif | ||
39 | |||
40 | #ifdef CONFIG_PERFMON | 33 | #ifdef CONFIG_PERFMON |
41 | DECLARE_PER_CPU(unsigned long, pfm_syst_info); | 34 | DECLARE_PER_CPU(unsigned long, pfm_syst_info); |
42 | # define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1) | 35 | # define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1) |
@@ -49,7 +42,6 @@ extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct | |||
49 | || PERFMON_IS_SYSWIDE()) | 42 | || PERFMON_IS_SYSWIDE()) |
50 | 43 | ||
51 | #define __switch_to(prev,next,last) do { \ | 44 | #define __switch_to(prev,next,last) do { \ |
52 | IA64_ACCOUNT_ON_SWITCH(prev, next); \ | ||
53 | if (IA64_HAS_EXTRA_STATE(prev)) \ | 45 | if (IA64_HAS_EXTRA_STATE(prev)) \ |
54 | ia64_save_extra(prev); \ | 46 | ia64_save_extra(prev); \ |
55 | if (IA64_HAS_EXTRA_STATE(next)) \ | 47 | if (IA64_HAS_EXTRA_STATE(next)) \ |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index dd6fc1449741..3e316ec0b835 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/kdebug.h> | 29 | #include <linux/kdebug.h> |
30 | #include <linux/utsname.h> | 30 | #include <linux/utsname.h> |
31 | #include <linux/tracehook.h> | 31 | #include <linux/tracehook.h> |
32 | #include <linux/rcupdate.h> | ||
32 | 33 | ||
33 | #include <asm/cpu.h> | 34 | #include <asm/cpu.h> |
34 | #include <asm/delay.h> | 35 | #include <asm/delay.h> |
@@ -279,6 +280,7 @@ cpu_idle (void) | |||
279 | 280 | ||
280 | /* endless idle loop with no priority at all */ | 281 | /* endless idle loop with no priority at all */ |
281 | while (1) { | 282 | while (1) { |
283 | rcu_idle_enter(); | ||
282 | if (can_do_pal_halt) { | 284 | if (can_do_pal_halt) { |
283 | current_thread_info()->status &= ~TS_POLLING; | 285 | current_thread_info()->status &= ~TS_POLLING; |
284 | /* | 286 | /* |
@@ -309,6 +311,7 @@ cpu_idle (void) | |||
309 | normal_xtp(); | 311 | normal_xtp(); |
310 | #endif | 312 | #endif |
311 | } | 313 | } |
314 | rcu_idle_exit(); | ||
312 | schedule_preempt_disabled(); | 315 | schedule_preempt_disabled(); |
313 | check_pgt_cache(); | 316 | check_pgt_cache(); |
314 | if (cpu_is_offline(cpu)) | 317 | if (cpu_is_offline(cpu)) |
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index ecc904b33c5f..80ff9acc5edf 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
@@ -83,32 +83,36 @@ static struct clocksource *itc_clocksource; | |||
83 | 83 | ||
84 | extern cputime_t cycle_to_cputime(u64 cyc); | 84 | extern cputime_t cycle_to_cputime(u64 cyc); |
85 | 85 | ||
86 | static void vtime_account_user(struct task_struct *tsk) | ||
87 | { | ||
88 | cputime_t delta_utime; | ||
89 | struct thread_info *ti = task_thread_info(tsk); | ||
90 | |||
91 | if (ti->ac_utime) { | ||
92 | delta_utime = cycle_to_cputime(ti->ac_utime); | ||
93 | account_user_time(tsk, delta_utime, delta_utime); | ||
94 | ti->ac_utime = 0; | ||
95 | } | ||
96 | } | ||
97 | |||
86 | /* | 98 | /* |
87 | * Called from the context switch with interrupts disabled, to charge all | 99 | * Called from the context switch with interrupts disabled, to charge all |
88 | * accumulated times to the current process, and to prepare accounting on | 100 | * accumulated times to the current process, and to prepare accounting on |
89 | * the next process. | 101 | * the next process. |
90 | */ | 102 | */ |
91 | void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next) | 103 | void vtime_task_switch(struct task_struct *prev) |
92 | { | 104 | { |
93 | struct thread_info *pi = task_thread_info(prev); | 105 | struct thread_info *pi = task_thread_info(prev); |
94 | struct thread_info *ni = task_thread_info(next); | 106 | struct thread_info *ni = task_thread_info(current); |
95 | cputime_t delta_stime, delta_utime; | ||
96 | __u64 now; | ||
97 | 107 | ||
98 | now = ia64_get_itc(); | ||
99 | |||
100 | delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp)); | ||
101 | if (idle_task(smp_processor_id()) != prev) | 108 | if (idle_task(smp_processor_id()) != prev) |
102 | account_system_time(prev, 0, delta_stime, delta_stime); | 109 | vtime_account_system(prev); |
103 | else | 110 | else |
104 | account_idle_time(delta_stime); | 111 | vtime_account_idle(prev); |
105 | 112 | ||
106 | if (pi->ac_utime) { | 113 | vtime_account_user(prev); |
107 | delta_utime = cycle_to_cputime(pi->ac_utime); | ||
108 | account_user_time(prev, delta_utime, delta_utime); | ||
109 | } | ||
110 | 114 | ||
111 | pi->ac_stamp = ni->ac_stamp = now; | 115 | pi->ac_stamp = ni->ac_stamp; |
112 | ni->ac_stime = ni->ac_utime = 0; | 116 | ni->ac_stime = ni->ac_utime = 0; |
113 | } | 117 | } |
114 | 118 | ||
@@ -116,29 +120,32 @@ void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next) | |||
116 | * Account time for a transition between system, hard irq or soft irq state. | 120 | * Account time for a transition between system, hard irq or soft irq state. |
117 | * Note that this function is called with interrupts enabled. | 121 | * Note that this function is called with interrupts enabled. |
118 | */ | 122 | */ |
119 | void account_system_vtime(struct task_struct *tsk) | 123 | static cputime_t vtime_delta(struct task_struct *tsk) |
120 | { | 124 | { |
121 | struct thread_info *ti = task_thread_info(tsk); | 125 | struct thread_info *ti = task_thread_info(tsk); |
122 | unsigned long flags; | ||
123 | cputime_t delta_stime; | 126 | cputime_t delta_stime; |
124 | __u64 now; | 127 | __u64 now; |
125 | 128 | ||
126 | local_irq_save(flags); | ||
127 | |||
128 | now = ia64_get_itc(); | 129 | now = ia64_get_itc(); |
129 | 130 | ||
130 | delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); | 131 | delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); |
131 | if (irq_count() || idle_task(smp_processor_id()) != tsk) | ||
132 | account_system_time(tsk, 0, delta_stime, delta_stime); | ||
133 | else | ||
134 | account_idle_time(delta_stime); | ||
135 | ti->ac_stime = 0; | 132 | ti->ac_stime = 0; |
136 | |||
137 | ti->ac_stamp = now; | 133 | ti->ac_stamp = now; |
138 | 134 | ||
139 | local_irq_restore(flags); | 135 | return delta_stime; |
136 | } | ||
137 | |||
138 | void vtime_account_system(struct task_struct *tsk) | ||
139 | { | ||
140 | cputime_t delta = vtime_delta(tsk); | ||
141 | |||
142 | account_system_time(tsk, 0, delta, delta); | ||
143 | } | ||
144 | |||
145 | void vtime_account_idle(struct task_struct *tsk) | ||
146 | { | ||
147 | account_idle_time(vtime_delta(tsk)); | ||
140 | } | 148 | } |
141 | EXPORT_SYMBOL_GPL(account_system_vtime); | ||
142 | 149 | ||
143 | /* | 150 | /* |
144 | * Called from the timer interrupt handler to charge accumulated user time | 151 | * Called from the timer interrupt handler to charge accumulated user time |
@@ -146,14 +153,7 @@ EXPORT_SYMBOL_GPL(account_system_vtime); | |||
146 | */ | 153 | */ |
147 | void account_process_tick(struct task_struct *p, int user_tick) | 154 | void account_process_tick(struct task_struct *p, int user_tick) |
148 | { | 155 | { |
149 | struct thread_info *ti = task_thread_info(p); | 156 | vtime_account_user(p); |
150 | cputime_t delta_utime; | ||
151 | |||
152 | if (ti->ac_utime) { | ||
153 | delta_utime = cycle_to_cputime(ti->ac_utime); | ||
154 | account_user_time(p, delta_utime, delta_utime); | ||
155 | ti->ac_utime = 0; | ||
156 | } | ||
157 | } | 157 | } |
158 | 158 | ||
159 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | 159 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ |
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 3a4a32b27208..384e63f3a4c4 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
27 | #include <linux/unistd.h> | 27 | #include <linux/unistd.h> |
28 | #include <linux/hardirq.h> | 28 | #include <linux/hardirq.h> |
29 | #include <linux/rcupdate.h> | ||
29 | 30 | ||
30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
@@ -82,6 +83,7 @@ void cpu_idle (void) | |||
82 | { | 83 | { |
83 | /* endless idle loop with no priority at all */ | 84 | /* endless idle loop with no priority at all */ |
84 | while (1) { | 85 | while (1) { |
86 | rcu_idle_enter(); | ||
85 | while (!need_resched()) { | 87 | while (!need_resched()) { |
86 | void (*idle)(void) = pm_idle; | 88 | void (*idle)(void) = pm_idle; |
87 | 89 | ||
@@ -90,6 +92,7 @@ void cpu_idle (void) | |||
90 | 92 | ||
91 | idle(); | 93 | idle(); |
92 | } | 94 | } |
95 | rcu_idle_exit(); | ||
93 | schedule_preempt_disabled(); | 96 | schedule_preempt_disabled(); |
94 | } | 97 | } |
95 | } | 98 | } |
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index c488e3cfab53..ac2892e49c7c 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/reboot.h> | 25 | #include <linux/reboot.h> |
26 | #include <linux/init_task.h> | 26 | #include <linux/init_task.h> |
27 | #include <linux/mqueue.h> | 27 | #include <linux/mqueue.h> |
28 | #include <linux/rcupdate.h> | ||
28 | 29 | ||
29 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
30 | #include <asm/traps.h> | 31 | #include <asm/traps.h> |
@@ -75,8 +76,10 @@ void cpu_idle(void) | |||
75 | { | 76 | { |
76 | /* endless idle loop with no priority at all */ | 77 | /* endless idle loop with no priority at all */ |
77 | while (1) { | 78 | while (1) { |
79 | rcu_idle_enter(); | ||
78 | while (!need_resched()) | 80 | while (!need_resched()) |
79 | idle(); | 81 | idle(); |
82 | rcu_idle_exit(); | ||
80 | schedule_preempt_disabled(); | 83 | schedule_preempt_disabled(); |
81 | } | 84 | } |
82 | } | 85 | } |
diff --git a/arch/m68k/platform/coldfire/clk.c b/arch/m68k/platform/coldfire/clk.c index 75f9ee967ea7..9cd13b4ce42b 100644 --- a/arch/m68k/platform/coldfire/clk.c +++ b/arch/m68k/platform/coldfire/clk.c | |||
@@ -146,9 +146,3 @@ struct clk_ops clk_ops1 = { | |||
146 | }; | 146 | }; |
147 | #endif /* MCFPM_PPMCR1 */ | 147 | #endif /* MCFPM_PPMCR1 */ |
148 | #endif /* MCFPM_PPMCR0 */ | 148 | #endif /* MCFPM_PPMCR0 */ |
149 | |||
150 | struct clk *devm_clk_get(struct device *dev, const char *id) | ||
151 | { | ||
152 | return NULL; | ||
153 | } | ||
154 | EXPORT_SYMBOL(devm_clk_get); | ||
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index e7e03ecf5495..afc379ca3753 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c | |||
@@ -102,7 +102,7 @@ static void cmp_init_secondary(void) | |||
102 | c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE; | 102 | c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE; |
103 | #endif | 103 | #endif |
104 | #ifdef CONFIG_MIPS_MT_SMTC | 104 | #ifdef CONFIG_MIPS_MT_SMTC |
105 | c->tc_id = (read_c0_tcbind() >> TCBIND_CURTC_SHIFT) & TCBIND_CURTC; | 105 | c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT; |
106 | #endif | 106 | #endif |
107 | } | 107 | } |
108 | 108 | ||
diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c index 33aadbcf170b..dcfd573871c1 100644 --- a/arch/mips/mm/gup.c +++ b/arch/mips/mm/gup.c | |||
@@ -152,6 +152,8 @@ static int gup_huge_pud(pud_t pud, unsigned long addr, unsigned long end, | |||
152 | do { | 152 | do { |
153 | VM_BUG_ON(compound_head(page) != head); | 153 | VM_BUG_ON(compound_head(page) != head); |
154 | pages[*nr] = page; | 154 | pages[*nr] = page; |
155 | if (PageTail(page)) | ||
156 | get_huge_page_tail(page); | ||
155 | (*nr)++; | 157 | (*nr)++; |
156 | page++; | 158 | page++; |
157 | refs++; | 159 | refs++; |
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 7b13a4caeea4..fea823f18479 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c | |||
@@ -273,16 +273,19 @@ asmlinkage void plat_irq_dispatch(void) | |||
273 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; | 273 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; |
274 | int irq; | 274 | int irq; |
275 | 275 | ||
276 | if (unlikely(!pending)) { | ||
277 | spurious_interrupt(); | ||
278 | return; | ||
279 | } | ||
280 | |||
276 | irq = irq_ffs(pending); | 281 | irq = irq_ffs(pending); |
277 | 282 | ||
278 | if (irq == MIPSCPU_INT_I8259A) | 283 | if (irq == MIPSCPU_INT_I8259A) |
279 | malta_hw0_irqdispatch(); | 284 | malta_hw0_irqdispatch(); |
280 | else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) | 285 | else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) |
281 | malta_ipi_irqdispatch(); | 286 | malta_ipi_irqdispatch(); |
282 | else if (irq >= 0) | ||
283 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | ||
284 | else | 287 | else |
285 | spurious_interrupt(); | 288 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); |
286 | } | 289 | } |
287 | 290 | ||
288 | #ifdef CONFIG_MIPS_MT_SMP | 291 | #ifdef CONFIG_MIPS_MT_SMP |
diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c index 4c35301720e7..80562b81f0f2 100644 --- a/arch/mips/mti-malta/malta-platform.c +++ b/arch/mips/mti-malta/malta-platform.c | |||
@@ -138,11 +138,6 @@ static int __init malta_add_devices(void) | |||
138 | if (err) | 138 | if (err) |
139 | return err; | 139 | return err; |
140 | 140 | ||
141 | /* | ||
142 | * Set RTC to BCD mode to support current alarm code. | ||
143 | */ | ||
144 | CMOS_WRITE(CMOS_READ(RTC_CONTROL) & ~RTC_DM_BINARY, RTC_CONTROL); | ||
145 | |||
146 | return 0; | 141 | return 0; |
147 | } | 142 | } |
148 | 143 | ||
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 7dab0cd36466..e9cceba193b6 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/rcupdate.h> | ||
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
29 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
@@ -107,6 +108,7 @@ void cpu_idle(void) | |||
107 | { | 108 | { |
108 | /* endless idle loop with no priority at all */ | 109 | /* endless idle loop with no priority at all */ |
109 | for (;;) { | 110 | for (;;) { |
111 | rcu_idle_enter(); | ||
110 | while (!need_resched()) { | 112 | while (!need_resched()) { |
111 | void (*idle)(void); | 113 | void (*idle)(void); |
112 | 114 | ||
@@ -121,6 +123,7 @@ void cpu_idle(void) | |||
121 | } | 123 | } |
122 | idle(); | 124 | idle(); |
123 | } | 125 | } |
126 | rcu_idle_exit(); | ||
124 | 127 | ||
125 | schedule_preempt_disabled(); | 128 | schedule_preempt_disabled(); |
126 | } | 129 | } |
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 2c05a9292a81..8c6b6b6561f0 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/unistd.h> | 48 | #include <linux/unistd.h> |
49 | #include <linux/kallsyms.h> | 49 | #include <linux/kallsyms.h> |
50 | #include <linux/uaccess.h> | 50 | #include <linux/uaccess.h> |
51 | #include <linux/rcupdate.h> | ||
51 | 52 | ||
52 | #include <asm/io.h> | 53 | #include <asm/io.h> |
53 | #include <asm/asm-offsets.h> | 54 | #include <asm/asm-offsets.h> |
@@ -69,8 +70,10 @@ void cpu_idle(void) | |||
69 | 70 | ||
70 | /* endless idle loop with no priority at all */ | 71 | /* endless idle loop with no priority at all */ |
71 | while (1) { | 72 | while (1) { |
73 | rcu_idle_enter(); | ||
72 | while (!need_resched()) | 74 | while (!need_resched()) |
73 | barrier(); | 75 | barrier(); |
76 | rcu_idle_exit(); | ||
74 | schedule_preempt_disabled(); | 77 | schedule_preempt_disabled(); |
75 | check_pgt_cache(); | 78 | check_pgt_cache(); |
76 | } | 79 | } |
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 1c1aadc8c48f..c32ae5ce9fff 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore | |||
@@ -1,10 +1,6 @@ | |||
1 | addnote | 1 | addnote |
2 | empty.c | 2 | empty.c |
3 | hack-coff | 3 | hack-coff |
4 | infblock.c | ||
5 | infblock.h | ||
6 | infcodes.c | ||
7 | infcodes.h | ||
8 | inffast.c | 4 | inffast.c |
9 | inffast.h | 5 | inffast.h |
10 | inffixed.h | 6 | inffixed.h |
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h index 3b4b4a8da922..c1f267694acb 100644 --- a/arch/powerpc/include/asm/time.h +++ b/arch/powerpc/include/asm/time.h | |||
@@ -197,12 +197,6 @@ struct cpu_usage { | |||
197 | 197 | ||
198 | DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); | 198 | DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); |
199 | 199 | ||
200 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING) | ||
201 | #define account_process_vtime(tsk) account_process_tick(tsk, 0) | ||
202 | #else | ||
203 | #define account_process_vtime(tsk) do { } while (0) | ||
204 | #endif | ||
205 | |||
206 | extern void secondary_cpu_time_init(void); | 200 | extern void secondary_cpu_time_init(void); |
207 | 201 | ||
208 | DECLARE_PER_CPU(u64, decrementers_next_tb); | 202 | DECLARE_PER_CPU(u64, decrementers_next_tb); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 1a1f2ddfb581..e9cb51f5f801 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -514,9 +514,6 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
514 | 514 | ||
515 | local_irq_save(flags); | 515 | local_irq_save(flags); |
516 | 516 | ||
517 | account_system_vtime(current); | ||
518 | account_process_vtime(current); | ||
519 | |||
520 | /* | 517 | /* |
521 | * We can't take a PMU exception inside _switch() since there is a | 518 | * We can't take a PMU exception inside _switch() since there is a |
522 | * window where the kernel stack SLB and the kernel stack are out | 519 | * window where the kernel stack SLB and the kernel stack are out |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index e49e93191b69..eaa9d0e6abca 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -291,13 +291,12 @@ static inline u64 calculate_stolen_time(u64 stop_tb) | |||
291 | * Account time for a transition between system, hard irq | 291 | * Account time for a transition between system, hard irq |
292 | * or soft irq state. | 292 | * or soft irq state. |
293 | */ | 293 | */ |
294 | void account_system_vtime(struct task_struct *tsk) | 294 | static u64 vtime_delta(struct task_struct *tsk, |
295 | u64 *sys_scaled, u64 *stolen) | ||
295 | { | 296 | { |
296 | u64 now, nowscaled, delta, deltascaled; | 297 | u64 now, nowscaled, deltascaled; |
297 | unsigned long flags; | 298 | u64 udelta, delta, user_scaled; |
298 | u64 stolen, udelta, sys_scaled, user_scaled; | ||
299 | 299 | ||
300 | local_irq_save(flags); | ||
301 | now = mftb(); | 300 | now = mftb(); |
302 | nowscaled = read_spurr(now); | 301 | nowscaled = read_spurr(now); |
303 | get_paca()->system_time += now - get_paca()->starttime; | 302 | get_paca()->system_time += now - get_paca()->starttime; |
@@ -305,7 +304,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
305 | deltascaled = nowscaled - get_paca()->startspurr; | 304 | deltascaled = nowscaled - get_paca()->startspurr; |
306 | get_paca()->startspurr = nowscaled; | 305 | get_paca()->startspurr = nowscaled; |
307 | 306 | ||
308 | stolen = calculate_stolen_time(now); | 307 | *stolen = calculate_stolen_time(now); |
309 | 308 | ||
310 | delta = get_paca()->system_time; | 309 | delta = get_paca()->system_time; |
311 | get_paca()->system_time = 0; | 310 | get_paca()->system_time = 0; |
@@ -322,35 +321,45 @@ void account_system_vtime(struct task_struct *tsk) | |||
322 | * the user ticks get saved up in paca->user_time_scaled to be | 321 | * the user ticks get saved up in paca->user_time_scaled to be |
323 | * used by account_process_tick. | 322 | * used by account_process_tick. |
324 | */ | 323 | */ |
325 | sys_scaled = delta; | 324 | *sys_scaled = delta; |
326 | user_scaled = udelta; | 325 | user_scaled = udelta; |
327 | if (deltascaled != delta + udelta) { | 326 | if (deltascaled != delta + udelta) { |
328 | if (udelta) { | 327 | if (udelta) { |
329 | sys_scaled = deltascaled * delta / (delta + udelta); | 328 | *sys_scaled = deltascaled * delta / (delta + udelta); |
330 | user_scaled = deltascaled - sys_scaled; | 329 | user_scaled = deltascaled - *sys_scaled; |
331 | } else { | 330 | } else { |
332 | sys_scaled = deltascaled; | 331 | *sys_scaled = deltascaled; |
333 | } | 332 | } |
334 | } | 333 | } |
335 | get_paca()->user_time_scaled += user_scaled; | 334 | get_paca()->user_time_scaled += user_scaled; |
336 | 335 | ||
337 | if (in_interrupt() || idle_task(smp_processor_id()) != tsk) { | 336 | return delta; |
338 | account_system_time(tsk, 0, delta, sys_scaled); | 337 | } |
339 | if (stolen) | 338 | |
340 | account_steal_time(stolen); | 339 | void vtime_account_system(struct task_struct *tsk) |
341 | } else { | 340 | { |
342 | account_idle_time(delta + stolen); | 341 | u64 delta, sys_scaled, stolen; |
343 | } | 342 | |
344 | local_irq_restore(flags); | 343 | delta = vtime_delta(tsk, &sys_scaled, &stolen); |
344 | account_system_time(tsk, 0, delta, sys_scaled); | ||
345 | if (stolen) | ||
346 | account_steal_time(stolen); | ||
347 | } | ||
348 | |||
349 | void vtime_account_idle(struct task_struct *tsk) | ||
350 | { | ||
351 | u64 delta, sys_scaled, stolen; | ||
352 | |||
353 | delta = vtime_delta(tsk, &sys_scaled, &stolen); | ||
354 | account_idle_time(delta + stolen); | ||
345 | } | 355 | } |
346 | EXPORT_SYMBOL_GPL(account_system_vtime); | ||
347 | 356 | ||
348 | /* | 357 | /* |
349 | * Transfer the user and system times accumulated in the paca | 358 | * Transfer the user and system times accumulated in the paca |
350 | * by the exception entry and exit code to the generic process | 359 | * by the exception entry and exit code to the generic process |
351 | * user and system time records. | 360 | * user and system time records. |
352 | * Must be called with interrupts disabled. | 361 | * Must be called with interrupts disabled. |
353 | * Assumes that account_system_vtime() has been called recently | 362 | * Assumes that vtime_account() has been called recently |
354 | * (i.e. since the last entry from usermode) so that | 363 | * (i.e. since the last entry from usermode) so that |
355 | * get_paca()->user_time_scaled is up to date. | 364 | * get_paca()->user_time_scaled is up to date. |
356 | */ | 365 | */ |
@@ -366,6 +375,12 @@ void account_process_tick(struct task_struct *tsk, int user_tick) | |||
366 | account_user_time(tsk, utime, utimescaled); | 375 | account_user_time(tsk, utime, utimescaled); |
367 | } | 376 | } |
368 | 377 | ||
378 | void vtime_task_switch(struct task_struct *prev) | ||
379 | { | ||
380 | vtime_account(prev); | ||
381 | account_process_tick(prev, 0); | ||
382 | } | ||
383 | |||
369 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ | 384 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ |
370 | #define calc_cputime_factors() | 385 | #define calc_cputime_factors() |
371 | #endif | 386 | #endif |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 30fd01de6bed..72afd2888cad 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -1,6 +1,7 @@ | |||
1 | config PPC64 | 1 | config PPC64 |
2 | bool "64-bit kernel" | 2 | bool "64-bit kernel" |
3 | default n | 3 | default n |
4 | select HAVE_VIRT_CPU_ACCOUNTING | ||
4 | help | 5 | help |
5 | This option selects whether a 32-bit or a 64-bit kernel | 6 | This option selects whether a 32-bit or a 64-bit kernel |
6 | will be built. | 7 | will be built. |
@@ -337,21 +338,6 @@ config PPC_MM_SLICES | |||
337 | default y if (!PPC_FSL_BOOK3E && PPC64 && HUGETLB_PAGE) || (PPC_STD_MMU_64 && PPC_64K_PAGES) | 338 | default y if (!PPC_FSL_BOOK3E && PPC64 && HUGETLB_PAGE) || (PPC_STD_MMU_64 && PPC_64K_PAGES) |
338 | default n | 339 | default n |
339 | 340 | ||
340 | config VIRT_CPU_ACCOUNTING | ||
341 | bool "Deterministic task and CPU time accounting" | ||
342 | depends on PPC64 | ||
343 | default y | ||
344 | help | ||
345 | Select this option to enable more accurate task and CPU time | ||
346 | accounting. This is done by reading a CPU counter on each | ||
347 | kernel entry and exit and on transitions within the kernel | ||
348 | between system, softirq and hardirq state, so there is a | ||
349 | small performance impact. This also enables accounting of | ||
350 | stolen time on logically-partitioned systems running on | ||
351 | IBM POWER5-based machines. | ||
352 | |||
353 | If in doubt, say Y here. | ||
354 | |||
355 | config PPC_HAVE_PMU_SUPPORT | 341 | config PPC_HAVE_PMU_SUPPORT |
356 | bool | 342 | bool |
357 | 343 | ||
diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild index 9858476fa0fe..cc45d25487b0 100644 --- a/arch/s390/Kbuild +++ b/arch/s390/Kbuild | |||
@@ -5,3 +5,4 @@ obj-$(CONFIG_CRYPTO_HW) += crypto/ | |||
5 | obj-$(CONFIG_S390_HYPFS_FS) += hypfs/ | 5 | obj-$(CONFIG_S390_HYPFS_FS) += hypfs/ |
6 | obj-$(CONFIG_APPLDATA_BASE) += appldata/ | 6 | obj-$(CONFIG_APPLDATA_BASE) += appldata/ |
7 | obj-$(CONFIG_MATHEMU) += math-emu/ | 7 | obj-$(CONFIG_MATHEMU) += math-emu/ |
8 | obj-y += net/ | ||
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 107610e01a29..f9acddd9ace3 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -49,10 +49,13 @@ config GENERIC_LOCKBREAK | |||
49 | config PGSTE | 49 | config PGSTE |
50 | def_bool y if KVM | 50 | def_bool y if KVM |
51 | 51 | ||
52 | config VIRT_CPU_ACCOUNTING | 52 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC |
53 | def_bool y | 53 | def_bool y |
54 | 54 | ||
55 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | 55 | config KEXEC |
56 | def_bool y | ||
57 | |||
58 | config AUDIT_ARCH | ||
56 | def_bool y | 59 | def_bool y |
57 | 60 | ||
58 | config S390 | 61 | config S390 |
@@ -84,11 +87,15 @@ config S390 | |||
84 | select HAVE_KERNEL_XZ | 87 | select HAVE_KERNEL_XZ |
85 | select HAVE_ARCH_MUTEX_CPU_RELAX | 88 | select HAVE_ARCH_MUTEX_CPU_RELAX |
86 | select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 | 89 | select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 |
90 | select HAVE_BPF_JIT if 64BIT && PACK_STACK | ||
87 | select ARCH_SAVE_PAGE_KEYS if HIBERNATION | 91 | select ARCH_SAVE_PAGE_KEYS if HIBERNATION |
88 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 92 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
89 | select HAVE_MEMBLOCK | 93 | select HAVE_MEMBLOCK |
90 | select HAVE_MEMBLOCK_NODE_MAP | 94 | select HAVE_MEMBLOCK_NODE_MAP |
91 | select HAVE_CMPXCHG_LOCAL | 95 | select HAVE_CMPXCHG_LOCAL |
96 | select HAVE_CMPXCHG_DOUBLE | ||
97 | select HAVE_VIRT_CPU_ACCOUNTING | ||
98 | select VIRT_CPU_ACCOUNTING | ||
92 | select ARCH_DISCARD_MEMBLOCK | 99 | select ARCH_DISCARD_MEMBLOCK |
93 | select BUILDTIME_EXTABLE_SORT | 100 | select BUILDTIME_EXTABLE_SORT |
94 | select ARCH_INLINE_SPIN_TRYLOCK | 101 | select ARCH_INLINE_SPIN_TRYLOCK |
@@ -133,9 +140,79 @@ source "init/Kconfig" | |||
133 | 140 | ||
134 | source "kernel/Kconfig.freezer" | 141 | source "kernel/Kconfig.freezer" |
135 | 142 | ||
136 | menu "Base setup" | 143 | menu "Processor type and features" |
144 | |||
145 | config HAVE_MARCH_Z900_FEATURES | ||
146 | def_bool n | ||
147 | |||
148 | config HAVE_MARCH_Z990_FEATURES | ||
149 | def_bool n | ||
150 | select HAVE_MARCH_Z900_FEATURES | ||
151 | |||
152 | config HAVE_MARCH_Z9_109_FEATURES | ||
153 | def_bool n | ||
154 | select HAVE_MARCH_Z990_FEATURES | ||
155 | |||
156 | config HAVE_MARCH_Z10_FEATURES | ||
157 | def_bool n | ||
158 | select HAVE_MARCH_Z9_109_FEATURES | ||
159 | |||
160 | config HAVE_MARCH_Z196_FEATURES | ||
161 | def_bool n | ||
162 | select HAVE_MARCH_Z10_FEATURES | ||
163 | |||
164 | choice | ||
165 | prompt "Processor type" | ||
166 | default MARCH_G5 | ||
167 | |||
168 | config MARCH_G5 | ||
169 | bool "System/390 model G5 and G6" | ||
170 | depends on !64BIT | ||
171 | help | ||
172 | Select this to build a 31 bit kernel that works | ||
173 | on all ESA/390 and z/Architecture machines. | ||
137 | 174 | ||
138 | comment "Processor type and features" | 175 | config MARCH_Z900 |
176 | bool "IBM zSeries model z800 and z900" | ||
177 | select HAVE_MARCH_Z900_FEATURES if 64BIT | ||
178 | help | ||
179 | Select this to enable optimizations for model z800/z900 (2064 and | ||
180 | 2066 series). This will enable some optimizations that are not | ||
181 | available on older ESA/390 (31 Bit) only CPUs. | ||
182 | |||
183 | config MARCH_Z990 | ||
184 | bool "IBM zSeries model z890 and z990" | ||
185 | select HAVE_MARCH_Z990_FEATURES if 64BIT | ||
186 | help | ||
187 | Select this to enable optimizations for model z890/z990 (2084 and | ||
188 | 2086 series). The kernel will be slightly faster but will not work | ||
189 | on older machines. | ||
190 | |||
191 | config MARCH_Z9_109 | ||
192 | bool "IBM System z9" | ||
193 | select HAVE_MARCH_Z9_109_FEATURES if 64BIT | ||
194 | help | ||
195 | Select this to enable optimizations for IBM System z9 (2094 and | ||
196 | 2096 series). The kernel will be slightly faster but will not work | ||
197 | on older machines. | ||
198 | |||
199 | config MARCH_Z10 | ||
200 | bool "IBM System z10" | ||
201 | select HAVE_MARCH_Z10_FEATURES if 64BIT | ||
202 | help | ||
203 | Select this to enable optimizations for IBM System z10 (2097 and | ||
204 | 2098 series). The kernel will be slightly faster but will not work | ||
205 | on older machines. | ||
206 | |||
207 | config MARCH_Z196 | ||
208 | bool "IBM zEnterprise 114 and 196" | ||
209 | select HAVE_MARCH_Z196_FEATURES if 64BIT | ||
210 | help | ||
211 | Select this to enable optimizations for IBM zEnterprise 114 and 196 | ||
212 | (2818 and 2817 series). The kernel will be slightly faster but will | ||
213 | not work on older machines. | ||
214 | |||
215 | endchoice | ||
139 | 216 | ||
140 | config 64BIT | 217 | config 64BIT |
141 | def_bool y | 218 | def_bool y |
@@ -147,6 +224,24 @@ config 64BIT | |||
147 | config 32BIT | 224 | config 32BIT |
148 | def_bool y if !64BIT | 225 | def_bool y if !64BIT |
149 | 226 | ||
227 | config COMPAT | ||
228 | def_bool y | ||
229 | prompt "Kernel support for 31 bit emulation" | ||
230 | depends on 64BIT | ||
231 | select COMPAT_BINFMT_ELF if BINFMT_ELF | ||
232 | select ARCH_WANT_OLD_COMPAT_IPC | ||
233 | help | ||
234 | Select this option if you want to enable your system kernel to | ||
235 | handle system-calls from ELF binaries for 31 bit ESA. This option | ||
236 | (and some other stuff like libraries and such) is needed for | ||
237 | executing 31 bit applications. It is safe to say "Y". | ||
238 | |||
239 | config SYSVIPC_COMPAT | ||
240 | def_bool y if COMPAT && SYSVIPC | ||
241 | |||
242 | config KEYS_COMPAT | ||
243 | def_bool y if COMPAT && KEYS | ||
244 | |||
150 | config SMP | 245 | config SMP |
151 | def_bool y | 246 | def_bool y |
152 | prompt "Symmetric multi-processing support" | 247 | prompt "Symmetric multi-processing support" |
@@ -202,6 +297,8 @@ config SCHED_BOOK | |||
202 | Book scheduler support improves the CPU scheduler's decision making | 297 | Book scheduler support improves the CPU scheduler's decision making |
203 | when dealing with machines that have several books. | 298 | when dealing with machines that have several books. |
204 | 299 | ||
300 | source kernel/Kconfig.preempt | ||
301 | |||
205 | config MATHEMU | 302 | config MATHEMU |
206 | def_bool y | 303 | def_bool y |
207 | prompt "IEEE FPU emulation" | 304 | prompt "IEEE FPU emulation" |
@@ -211,100 +308,35 @@ config MATHEMU | |||
211 | on older ESA/390 machines. Say Y unless you know your machine doesn't | 308 | on older ESA/390 machines. Say Y unless you know your machine doesn't |
212 | need this. | 309 | need this. |
213 | 310 | ||
214 | config COMPAT | 311 | source kernel/Kconfig.hz |
215 | def_bool y | ||
216 | prompt "Kernel support for 31 bit emulation" | ||
217 | depends on 64BIT | ||
218 | select COMPAT_BINFMT_ELF if BINFMT_ELF | ||
219 | select ARCH_WANT_OLD_COMPAT_IPC | ||
220 | help | ||
221 | Select this option if you want to enable your system kernel to | ||
222 | handle system-calls from ELF binaries for 31 bit ESA. This option | ||
223 | (and some other stuff like libraries and such) is needed for | ||
224 | executing 31 bit applications. It is safe to say "Y". | ||
225 | 312 | ||
226 | config SYSVIPC_COMPAT | 313 | endmenu |
227 | def_bool y if COMPAT && SYSVIPC | ||
228 | 314 | ||
229 | config KEYS_COMPAT | 315 | menu "Memory setup" |
230 | def_bool y if COMPAT && KEYS | ||
231 | 316 | ||
232 | config AUDIT_ARCH | 317 | config ARCH_SPARSEMEM_ENABLE |
233 | def_bool y | 318 | def_bool y |
319 | select SPARSEMEM_VMEMMAP_ENABLE | ||
320 | select SPARSEMEM_VMEMMAP | ||
321 | select SPARSEMEM_STATIC if !64BIT | ||
234 | 322 | ||
235 | config HAVE_MARCH_Z900_FEATURES | 323 | config ARCH_SPARSEMEM_DEFAULT |
236 | def_bool n | 324 | def_bool y |
237 | |||
238 | config HAVE_MARCH_Z990_FEATURES | ||
239 | def_bool n | ||
240 | select HAVE_MARCH_Z900_FEATURES | ||
241 | |||
242 | config HAVE_MARCH_Z9_109_FEATURES | ||
243 | def_bool n | ||
244 | select HAVE_MARCH_Z990_FEATURES | ||
245 | |||
246 | config HAVE_MARCH_Z10_FEATURES | ||
247 | def_bool n | ||
248 | select HAVE_MARCH_Z9_109_FEATURES | ||
249 | |||
250 | config HAVE_MARCH_Z196_FEATURES | ||
251 | def_bool n | ||
252 | select HAVE_MARCH_Z10_FEATURES | ||
253 | |||
254 | comment "Code generation options" | ||
255 | |||
256 | choice | ||
257 | prompt "Processor type" | ||
258 | default MARCH_G5 | ||
259 | |||
260 | config MARCH_G5 | ||
261 | bool "System/390 model G5 and G6" | ||
262 | depends on !64BIT | ||
263 | help | ||
264 | Select this to build a 31 bit kernel that works | ||
265 | on all ESA/390 and z/Architecture machines. | ||
266 | |||
267 | config MARCH_Z900 | ||
268 | bool "IBM zSeries model z800 and z900" | ||
269 | select HAVE_MARCH_Z900_FEATURES if 64BIT | ||
270 | help | ||
271 | Select this to enable optimizations for model z800/z900 (2064 and | ||
272 | 2066 series). This will enable some optimizations that are not | ||
273 | available on older ESA/390 (31 Bit) only CPUs. | ||
274 | 325 | ||
275 | config MARCH_Z990 | 326 | config ARCH_SELECT_MEMORY_MODEL |
276 | bool "IBM zSeries model z890 and z990" | 327 | def_bool y |
277 | select HAVE_MARCH_Z990_FEATURES if 64BIT | ||
278 | help | ||
279 | Select this to enable optimizations for model z890/z990 (2084 and | ||
280 | 2086 series). The kernel will be slightly faster but will not work | ||
281 | on older machines. | ||
282 | 328 | ||
283 | config MARCH_Z9_109 | 329 | config ARCH_ENABLE_MEMORY_HOTPLUG |
284 | bool "IBM System z9" | 330 | def_bool y if SPARSEMEM |
285 | select HAVE_MARCH_Z9_109_FEATURES if 64BIT | ||
286 | help | ||
287 | Select this to enable optimizations for IBM System z9 (2094 and | ||
288 | 2096 series). The kernel will be slightly faster but will not work | ||
289 | on older machines. | ||
290 | 331 | ||
291 | config MARCH_Z10 | 332 | config ARCH_ENABLE_MEMORY_HOTREMOVE |
292 | bool "IBM System z10" | 333 | def_bool y |
293 | select HAVE_MARCH_Z10_FEATURES if 64BIT | ||
294 | help | ||
295 | Select this to enable optimizations for IBM System z10 (2097 and | ||
296 | 2098 series). The kernel will be slightly faster but will not work | ||
297 | on older machines. | ||
298 | 334 | ||
299 | config MARCH_Z196 | 335 | config FORCE_MAX_ZONEORDER |
300 | bool "IBM zEnterprise 114 and 196" | 336 | int |
301 | select HAVE_MARCH_Z196_FEATURES if 64BIT | 337 | default "9" |
302 | help | ||
303 | Select this to enable optimizations for IBM zEnterprise 114 and 196 | ||
304 | (2818 and 2817 series). The kernel will be slightly faster but will | ||
305 | not work on older machines. | ||
306 | 338 | ||
307 | endchoice | 339 | source "mm/Kconfig" |
308 | 340 | ||
309 | config PACK_STACK | 341 | config PACK_STACK |
310 | def_bool y | 342 | def_bool y |
@@ -368,34 +400,9 @@ config WARN_DYNAMIC_STACK | |||
368 | 400 | ||
369 | Say N if you are unsure. | 401 | Say N if you are unsure. |
370 | 402 | ||
371 | comment "Kernel preemption" | 403 | endmenu |
372 | |||
373 | source "kernel/Kconfig.preempt" | ||
374 | |||
375 | config ARCH_SPARSEMEM_ENABLE | ||
376 | def_bool y | ||
377 | select SPARSEMEM_VMEMMAP_ENABLE | ||
378 | select SPARSEMEM_VMEMMAP | ||
379 | select SPARSEMEM_STATIC if !64BIT | ||
380 | |||
381 | config ARCH_SPARSEMEM_DEFAULT | ||
382 | def_bool y | ||
383 | |||
384 | config ARCH_SELECT_MEMORY_MODEL | ||
385 | def_bool y | ||
386 | |||
387 | config ARCH_ENABLE_MEMORY_HOTPLUG | ||
388 | def_bool y if SPARSEMEM | ||
389 | |||
390 | config ARCH_ENABLE_MEMORY_HOTREMOVE | ||
391 | def_bool y | ||
392 | |||
393 | config ARCH_HIBERNATION_POSSIBLE | ||
394 | def_bool y if 64BIT | ||
395 | |||
396 | source "mm/Kconfig" | ||
397 | 404 | ||
398 | comment "I/O subsystem configuration" | 405 | menu "I/O subsystem" |
399 | 406 | ||
400 | config QDIO | 407 | config QDIO |
401 | def_tristate y | 408 | def_tristate y |
@@ -426,13 +433,102 @@ config CHSC_SCH | |||
426 | 433 | ||
427 | If unsure, say N. | 434 | If unsure, say N. |
428 | 435 | ||
429 | comment "Misc" | 436 | config SCM_BUS |
437 | def_bool y | ||
438 | depends on 64BIT | ||
439 | prompt "SCM bus driver" | ||
440 | help | ||
441 | Bus driver for Storage Class Memory. | ||
442 | |||
443 | config EADM_SCH | ||
444 | def_tristate m | ||
445 | prompt "Support for EADM subchannels" | ||
446 | depends on SCM_BUS | ||
447 | help | ||
448 | This driver allows usage of EADM subchannels. EADM subchannels act | ||
449 | as a communication vehicle for SCM increments. | ||
450 | |||
451 | To compile this driver as a module, choose M here: the | ||
452 | module will be called eadm_sch. | ||
453 | |||
454 | endmenu | ||
455 | |||
456 | menu "Dump support" | ||
457 | |||
458 | config CRASH_DUMP | ||
459 | bool "kernel crash dumps" | ||
460 | depends on 64BIT && SMP | ||
461 | select KEXEC | ||
462 | help | ||
463 | Generate crash dump after being started by kexec. | ||
464 | Crash dump kernels are loaded in the main kernel with kexec-tools | ||
465 | into a specially reserved region and then later executed after | ||
466 | a crash by kdump/kexec. | ||
467 | For more details see Documentation/kdump/kdump.txt | ||
468 | |||
469 | config ZFCPDUMP | ||
470 | def_bool n | ||
471 | prompt "zfcpdump support" | ||
472 | select SMP | ||
473 | help | ||
474 | Select this option if you want to build an zfcpdump enabled kernel. | ||
475 | Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this. | ||
476 | |||
477 | endmenu | ||
478 | |||
479 | menu "Executable file formats / Emulations" | ||
430 | 480 | ||
431 | source "fs/Kconfig.binfmt" | 481 | source "fs/Kconfig.binfmt" |
432 | 482 | ||
433 | config FORCE_MAX_ZONEORDER | 483 | config SECCOMP |
434 | int | 484 | def_bool y |
435 | default "9" | 485 | prompt "Enable seccomp to safely compute untrusted bytecode" |
486 | depends on PROC_FS | ||
487 | help | ||
488 | This kernel feature is useful for number crunching applications | ||
489 | that may need to compute untrusted bytecode during their | ||
490 | execution. By using pipes or other transports made available to | ||
491 | the process as file descriptors supporting the read/write | ||
492 | syscalls, it's possible to isolate those applications in | ||
493 | their own address space using seccomp. Once seccomp is | ||
494 | enabled via /proc/<pid>/seccomp, it cannot be disabled | ||
495 | and the task is only allowed to execute a few safe syscalls | ||
496 | defined by each seccomp mode. | ||
497 | |||
498 | If unsure, say Y. | ||
499 | |||
500 | endmenu | ||
501 | |||
502 | menu "Power Management" | ||
503 | |||
504 | config ARCH_HIBERNATION_POSSIBLE | ||
505 | def_bool y if 64BIT | ||
506 | |||
507 | source "kernel/power/Kconfig" | ||
508 | |||
509 | endmenu | ||
510 | |||
511 | source "net/Kconfig" | ||
512 | |||
513 | config PCMCIA | ||
514 | def_bool n | ||
515 | |||
516 | config CCW | ||
517 | def_bool y | ||
518 | |||
519 | source "drivers/Kconfig" | ||
520 | |||
521 | source "fs/Kconfig" | ||
522 | |||
523 | source "arch/s390/Kconfig.debug" | ||
524 | |||
525 | source "security/Kconfig" | ||
526 | |||
527 | source "crypto/Kconfig" | ||
528 | |||
529 | source "lib/Kconfig" | ||
530 | |||
531 | menu "Virtualization" | ||
436 | 532 | ||
437 | config PFAULT | 533 | config PFAULT |
438 | def_bool y | 534 | def_bool y |
@@ -448,8 +544,8 @@ config PFAULT | |||
448 | this option. | 544 | this option. |
449 | 545 | ||
450 | config SHARED_KERNEL | 546 | config SHARED_KERNEL |
451 | def_bool y | 547 | bool "VM shared kernel support" |
452 | prompt "VM shared kernel support" | 548 | depends on !JUMP_LABEL |
453 | help | 549 | help |
454 | Select this option, if you want to share the text segment of the | 550 | Select this option, if you want to share the text segment of the |
455 | Linux kernel between different VM guests. This reduces memory | 551 | Linux kernel between different VM guests. This reduces memory |
@@ -544,8 +640,6 @@ config APPLDATA_NET_SUM | |||
544 | This can also be compiled as a module, which will be called | 640 | This can also be compiled as a module, which will be called |
545 | appldata_net_sum.o. | 641 | appldata_net_sum.o. |
546 | 642 | ||
547 | source kernel/Kconfig.hz | ||
548 | |||
549 | config S390_HYPFS_FS | 643 | config S390_HYPFS_FS |
550 | def_bool y | 644 | def_bool y |
551 | prompt "s390 hypervisor file system support" | 645 | prompt "s390 hypervisor file system support" |
@@ -554,90 +648,21 @@ config S390_HYPFS_FS | |||
554 | This is a virtual file system intended to provide accounting | 648 | This is a virtual file system intended to provide accounting |
555 | information in an s390 hypervisor environment. | 649 | information in an s390 hypervisor environment. |
556 | 650 | ||
557 | config KEXEC | 651 | source "arch/s390/kvm/Kconfig" |
558 | def_bool n | ||
559 | prompt "kexec system call" | ||
560 | help | ||
561 | kexec is a system call that implements the ability to shutdown your | ||
562 | current kernel, and to start another kernel. It is like a reboot | ||
563 | but is independent of hardware/microcode support. | ||
564 | |||
565 | config CRASH_DUMP | ||
566 | bool "kernel crash dumps" | ||
567 | depends on 64BIT && SMP | ||
568 | select KEXEC | ||
569 | help | ||
570 | Generate crash dump after being started by kexec. | ||
571 | Crash dump kernels are loaded in the main kernel with kexec-tools | ||
572 | into a specially reserved region and then later executed after | ||
573 | a crash by kdump/kexec. | ||
574 | For more details see Documentation/kdump/kdump.txt | ||
575 | |||
576 | config ZFCPDUMP | ||
577 | def_bool n | ||
578 | prompt "zfcpdump support" | ||
579 | select SMP | ||
580 | help | ||
581 | Select this option if you want to build an zfcpdump enabled kernel. | ||
582 | Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this. | ||
583 | 652 | ||
584 | config S390_GUEST | 653 | config S390_GUEST |
585 | def_bool y | 654 | def_bool y |
586 | prompt "s390 guest support for KVM (EXPERIMENTAL)" | 655 | prompt "s390 support for virtio devices (EXPERIMENTAL)" |
587 | depends on 64BIT && EXPERIMENTAL | 656 | depends on 64BIT && EXPERIMENTAL |
588 | select VIRTUALIZATION | 657 | select VIRTUALIZATION |
589 | select VIRTIO | 658 | select VIRTIO |
590 | select VIRTIO_RING | 659 | select VIRTIO_RING |
591 | select VIRTIO_CONSOLE | 660 | select VIRTIO_CONSOLE |
592 | help | 661 | help |
593 | Select this option if you want to run the kernel as a guest under | 662 | Enabling this option adds support for virtio based paravirtual device |
594 | the KVM hypervisor. This will add detection for KVM as well as a | 663 | drivers on s390. |
595 | virtio transport. If KVM is detected, the virtio console will be | ||
596 | the default console. | ||
597 | |||
598 | config SECCOMP | ||
599 | def_bool y | ||
600 | prompt "Enable seccomp to safely compute untrusted bytecode" | ||
601 | depends on PROC_FS | ||
602 | help | ||
603 | This kernel feature is useful for number crunching applications | ||
604 | that may need to compute untrusted bytecode during their | ||
605 | execution. By using pipes or other transports made available to | ||
606 | the process as file descriptors supporting the read/write | ||
607 | syscalls, it's possible to isolate those applications in | ||
608 | their own address space using seccomp. Once seccomp is | ||
609 | enabled via /proc/<pid>/seccomp, it cannot be disabled | ||
610 | and the task is only allowed to execute a few safe syscalls | ||
611 | defined by each seccomp mode. | ||
612 | |||
613 | If unsure, say Y. | ||
614 | |||
615 | endmenu | ||
616 | 664 | ||
617 | menu "Power Management" | 665 | Select this option if you want to run the kernel as a guest under |
618 | 666 | the KVM hypervisor. | |
619 | source "kernel/power/Kconfig" | ||
620 | 667 | ||
621 | endmenu | 668 | endmenu |
622 | |||
623 | source "net/Kconfig" | ||
624 | |||
625 | config PCMCIA | ||
626 | def_bool n | ||
627 | |||
628 | config CCW | ||
629 | def_bool y | ||
630 | |||
631 | source "drivers/Kconfig" | ||
632 | |||
633 | source "fs/Kconfig" | ||
634 | |||
635 | source "arch/s390/Kconfig.debug" | ||
636 | |||
637 | source "security/Kconfig" | ||
638 | |||
639 | source "crypto/Kconfig" | ||
640 | |||
641 | source "lib/Kconfig" | ||
642 | |||
643 | source "arch/s390/kvm/Kconfig" | ||
diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile index 10e22c4ec4a7..3ad8f61c9985 100644 --- a/arch/s390/boot/compressed/Makefile +++ b/arch/s390/boot/compressed/Makefile | |||
@@ -11,6 +11,7 @@ targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ | |||
11 | sizes.h head$(BITS).o | 11 | sizes.h head$(BITS).o |
12 | 12 | ||
13 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 | 13 | KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 |
14 | KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING | ||
14 | KBUILD_CFLAGS += $(cflags-y) | 15 | KBUILD_CFLAGS += $(cflags-y) |
15 | KBUILD_CFLAGS += $(call cc-option,-mpacked-stack) | 16 | KBUILD_CFLAGS += $(call cc-option,-mpacked-stack) |
16 | KBUILD_CFLAGS += $(call cc-option,-ffreestanding) | 17 | KBUILD_CFLAGS += $(call cc-option,-ffreestanding) |
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c index 465eca756feb..c4c6a1cf221b 100644 --- a/arch/s390/boot/compressed/misc.c +++ b/arch/s390/boot/compressed/misc.c | |||
@@ -71,34 +71,37 @@ void *memset(void *s, int c, size_t n) | |||
71 | { | 71 | { |
72 | char *xs; | 72 | char *xs; |
73 | 73 | ||
74 | if (c == 0) | 74 | xs = s; |
75 | return __builtin_memset(s, 0, n); | 75 | while (n--) |
76 | 76 | *xs++ = c; | |
77 | xs = (char *) s; | ||
78 | if (n > 0) | ||
79 | do { | ||
80 | *xs++ = c; | ||
81 | } while (--n > 0); | ||
82 | return s; | 77 | return s; |
83 | } | 78 | } |
84 | 79 | ||
85 | void *memcpy(void *__dest, __const void *__src, size_t __n) | 80 | void *memcpy(void *dest, const void *src, size_t n) |
86 | { | 81 | { |
87 | return __builtin_memcpy(__dest, __src, __n); | 82 | const char *s = src; |
83 | char *d = dest; | ||
84 | |||
85 | while (n--) | ||
86 | *d++ = *s++; | ||
87 | return dest; | ||
88 | } | 88 | } |
89 | 89 | ||
90 | void *memmove(void *__dest, __const void *__src, size_t __n) | 90 | void *memmove(void *dest, const void *src, size_t n) |
91 | { | 91 | { |
92 | char *d; | 92 | const char *s = src; |
93 | const char *s; | 93 | char *d = dest; |
94 | 94 | ||
95 | if (__dest <= __src) | 95 | if (d <= s) { |
96 | return __builtin_memcpy(__dest, __src, __n); | 96 | while (n--) |
97 | d = __dest + __n; | 97 | *d++ = *s++; |
98 | s = __src + __n; | 98 | } else { |
99 | while (__n--) | 99 | d += n; |
100 | *--d = *--s; | 100 | s += n; |
101 | return __dest; | 101 | while (n--) |
102 | *--d = *--s; | ||
103 | } | ||
104 | return dest; | ||
102 | } | 105 | } |
103 | 106 | ||
104 | static void error(char *x) | 107 | static void error(char *x) |
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index f39cd710980b..b74400e3e035 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
@@ -16,8 +16,8 @@ CONFIG_CGROUPS=y | |||
16 | CONFIG_CPUSETS=y | 16 | CONFIG_CPUSETS=y |
17 | CONFIG_CGROUP_CPUACCT=y | 17 | CONFIG_CGROUP_CPUACCT=y |
18 | CONFIG_RESOURCE_COUNTERS=y | 18 | CONFIG_RESOURCE_COUNTERS=y |
19 | CONFIG_CGROUP_MEMCG=y | 19 | CONFIG_MEMCG=y |
20 | CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y | 20 | CONFIG_MEMCG_SWAP=y |
21 | CONFIG_CGROUP_SCHED=y | 21 | CONFIG_CGROUP_SCHED=y |
22 | CONFIG_RT_GROUP_SCHED=y | 22 | CONFIG_RT_GROUP_SCHED=y |
23 | CONFIG_BLK_CGROUP=y | 23 | CONFIG_BLK_CGROUP=y |
@@ -32,20 +32,19 @@ CONFIG_EXPERT=y | |||
32 | CONFIG_PROFILING=y | 32 | CONFIG_PROFILING=y |
33 | CONFIG_OPROFILE=y | 33 | CONFIG_OPROFILE=y |
34 | CONFIG_KPROBES=y | 34 | CONFIG_KPROBES=y |
35 | CONFIG_JUMP_LABEL=y | ||
35 | CONFIG_MODULES=y | 36 | CONFIG_MODULES=y |
36 | CONFIG_MODULE_UNLOAD=y | 37 | CONFIG_MODULE_UNLOAD=y |
37 | CONFIG_MODVERSIONS=y | 38 | CONFIG_MODVERSIONS=y |
38 | CONFIG_PARTITION_ADVANCED=y | 39 | CONFIG_PARTITION_ADVANCED=y |
39 | CONFIG_IBM_PARTITION=y | 40 | CONFIG_IBM_PARTITION=y |
40 | CONFIG_DEFAULT_DEADLINE=y | 41 | CONFIG_DEFAULT_DEADLINE=y |
41 | CONFIG_PREEMPT=y | 42 | CONFIG_HZ_100=y |
42 | CONFIG_MEMORY_HOTPLUG=y | 43 | CONFIG_MEMORY_HOTPLUG=y |
43 | CONFIG_MEMORY_HOTREMOVE=y | 44 | CONFIG_MEMORY_HOTREMOVE=y |
44 | CONFIG_KSM=y | 45 | CONFIG_KSM=y |
45 | CONFIG_BINFMT_MISC=m | ||
46 | CONFIG_CMM=m | ||
47 | CONFIG_HZ_100=y | ||
48 | CONFIG_CRASH_DUMP=y | 46 | CONFIG_CRASH_DUMP=y |
47 | CONFIG_BINFMT_MISC=m | ||
49 | CONFIG_HIBERNATION=y | 48 | CONFIG_HIBERNATION=y |
50 | CONFIG_PACKET=y | 49 | CONFIG_PACKET=y |
51 | CONFIG_UNIX=y | 50 | CONFIG_UNIX=y |
@@ -75,6 +74,7 @@ CONFIG_NET_CLS_RSVP=m | |||
75 | CONFIG_NET_CLS_RSVP6=m | 74 | CONFIG_NET_CLS_RSVP6=m |
76 | CONFIG_NET_CLS_ACT=y | 75 | CONFIG_NET_CLS_ACT=y |
77 | CONFIG_NET_ACT_POLICE=y | 76 | CONFIG_NET_ACT_POLICE=y |
77 | CONFIG_BPF_JIT=y | ||
78 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 78 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
79 | CONFIG_DEVTMPFS=y | 79 | CONFIG_DEVTMPFS=y |
80 | CONFIG_BLK_DEV_LOOP=m | 80 | CONFIG_BLK_DEV_LOOP=m |
@@ -121,7 +121,6 @@ CONFIG_DEBUG_NOTIFIERS=y | |||
121 | CONFIG_RCU_TRACE=y | 121 | CONFIG_RCU_TRACE=y |
122 | CONFIG_KPROBES_SANITY_TEST=y | 122 | CONFIG_KPROBES_SANITY_TEST=y |
123 | CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y | 123 | CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y |
124 | CONFIG_CPU_NOTIFIER_ERROR_INJECT=m | ||
125 | CONFIG_LATENCYTOP=y | 124 | CONFIG_LATENCYTOP=y |
126 | CONFIG_DEBUG_PAGEALLOC=y | 125 | CONFIG_DEBUG_PAGEALLOC=y |
127 | CONFIG_BLK_DEV_IO_TRACE=y | 126 | CONFIG_BLK_DEV_IO_TRACE=y |
@@ -173,3 +172,4 @@ CONFIG_CRYPTO_SHA512_S390=m | |||
173 | CONFIG_CRYPTO_DES_S390=m | 172 | CONFIG_CRYPTO_DES_S390=m |
174 | CONFIG_CRYPTO_AES_S390=m | 173 | CONFIG_CRYPTO_AES_S390=m |
175 | CONFIG_CRC7=m | 174 | CONFIG_CRC7=m |
175 | CONFIG_CMM=m | ||
diff --git a/arch/s390/include/asm/appldata.h b/arch/s390/include/asm/appldata.h index f328294faeae..32a705987156 100644 --- a/arch/s390/include/asm/appldata.h +++ b/arch/s390/include/asm/appldata.h | |||
@@ -70,7 +70,7 @@ static inline int appldata_asm(struct appldata_product_id *id, | |||
70 | int ry; | 70 | int ry; |
71 | 71 | ||
72 | if (!MACHINE_IS_VM) | 72 | if (!MACHINE_IS_VM) |
73 | return -ENOSYS; | 73 | return -EOPNOTSUPP; |
74 | parm_list.diag = 0xdc; | 74 | parm_list.diag = 0xdc; |
75 | parm_list.function = fn; | 75 | parm_list.function = fn; |
76 | parm_list.parlist_length = sizeof(parm_list); | 76 | parm_list.parlist_length = sizeof(parm_list); |
diff --git a/arch/s390/include/asm/chsc.h b/arch/s390/include/asm/chsc.h index bf115b49f444..aea451fd182e 100644 --- a/arch/s390/include/asm/chsc.h +++ b/arch/s390/include/asm/chsc.h | |||
@@ -125,32 +125,4 @@ struct chsc_cpd_info { | |||
125 | #define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info) | 125 | #define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info) |
126 | #define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal) | 126 | #define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal) |
127 | 127 | ||
128 | #ifdef __KERNEL__ | ||
129 | |||
130 | struct css_general_char { | ||
131 | u64 : 12; | ||
132 | u32 dynio : 1; /* bit 12 */ | ||
133 | u32 : 28; | ||
134 | u32 aif : 1; /* bit 41 */ | ||
135 | u32 : 3; | ||
136 | u32 mcss : 1; /* bit 45 */ | ||
137 | u32 fcs : 1; /* bit 46 */ | ||
138 | u32 : 1; | ||
139 | u32 ext_mb : 1; /* bit 48 */ | ||
140 | u32 : 7; | ||
141 | u32 aif_tdd : 1; /* bit 56 */ | ||
142 | u32 : 1; | ||
143 | u32 qebsm : 1; /* bit 58 */ | ||
144 | u32 : 8; | ||
145 | u32 aif_osa : 1; /* bit 67 */ | ||
146 | u32 : 14; | ||
147 | u32 cib : 1; /* bit 82 */ | ||
148 | u32 : 5; | ||
149 | u32 fcx : 1; /* bit 88 */ | ||
150 | u32 : 7; | ||
151 | }__attribute__((packed)); | ||
152 | |||
153 | extern struct css_general_char css_general_characteristics; | ||
154 | |||
155 | #endif /* __KERNEL__ */ | ||
156 | #endif | 128 | #endif |
diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h index 77043aa44d67..55bde6035216 100644 --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h | |||
@@ -80,6 +80,18 @@ struct erw { | |||
80 | } __attribute__ ((packed)); | 80 | } __attribute__ ((packed)); |
81 | 81 | ||
82 | /** | 82 | /** |
83 | * struct erw_eadm - EADM Subchannel extended report word | ||
84 | * @b: aob error | ||
85 | * @r: arsb error | ||
86 | */ | ||
87 | struct erw_eadm { | ||
88 | __u32 : 16; | ||
89 | __u32 b : 1; | ||
90 | __u32 r : 1; | ||
91 | __u32 : 14; | ||
92 | } __packed; | ||
93 | |||
94 | /** | ||
83 | * struct sublog - subchannel logout area | 95 | * struct sublog - subchannel logout area |
84 | * @res0: reserved | 96 | * @res0: reserved |
85 | * @esf: extended status flags | 97 | * @esf: extended status flags |
@@ -170,9 +182,22 @@ struct esw3 { | |||
170 | } __attribute__ ((packed)); | 182 | } __attribute__ ((packed)); |
171 | 183 | ||
172 | /** | 184 | /** |
185 | * struct esw_eadm - EADM Subchannel Extended Status Word (ESW) | ||
186 | * @sublog: subchannel logout | ||
187 | * @erw: extended report word | ||
188 | */ | ||
189 | struct esw_eadm { | ||
190 | __u32 sublog; | ||
191 | struct erw_eadm erw; | ||
192 | __u32 : 32; | ||
193 | __u32 : 32; | ||
194 | __u32 : 32; | ||
195 | } __packed; | ||
196 | |||
197 | /** | ||
173 | * struct irb - interruption response block | 198 | * struct irb - interruption response block |
174 | * @scsw: subchannel status word | 199 | * @scsw: subchannel status word |
175 | * @esw: extened status word, 4 formats | 200 | * @esw: extened status word |
176 | * @ecw: extended control word | 201 | * @ecw: extended control word |
177 | * | 202 | * |
178 | * The irb that is handed to the device driver when an interrupt occurs. For | 203 | * The irb that is handed to the device driver when an interrupt occurs. For |
@@ -191,6 +216,7 @@ struct irb { | |||
191 | struct esw1 esw1; | 216 | struct esw1 esw1; |
192 | struct esw2 esw2; | 217 | struct esw2 esw2; |
193 | struct esw3 esw3; | 218 | struct esw3 esw3; |
219 | struct esw_eadm eadm; | ||
194 | } esw; | 220 | } esw; |
195 | __u8 ecw[32]; | 221 | __u8 ecw[32]; |
196 | } __attribute__ ((packed,aligned(4))); | 222 | } __attribute__ ((packed,aligned(4))); |
diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h index 8d798e962b63..0f636cbdf342 100644 --- a/arch/s390/include/asm/cmpxchg.h +++ b/arch/s390/include/asm/cmpxchg.h | |||
@@ -7,7 +7,9 @@ | |||
7 | #ifndef __ASM_CMPXCHG_H | 7 | #ifndef __ASM_CMPXCHG_H |
8 | #define __ASM_CMPXCHG_H | 8 | #define __ASM_CMPXCHG_H |
9 | 9 | ||
10 | #include <linux/mmdebug.h> | ||
10 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/bug.h> | ||
11 | 13 | ||
12 | extern void __xchg_called_with_bad_pointer(void); | 14 | extern void __xchg_called_with_bad_pointer(void); |
13 | 15 | ||
@@ -203,6 +205,65 @@ static inline unsigned long long __cmpxchg64(void *ptr, | |||
203 | }) | 205 | }) |
204 | #endif /* CONFIG_64BIT */ | 206 | #endif /* CONFIG_64BIT */ |
205 | 207 | ||
208 | #define __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, insn) \ | ||
209 | ({ \ | ||
210 | register __typeof__(*(p1)) __old1 asm("2") = (o1); \ | ||
211 | register __typeof__(*(p2)) __old2 asm("3") = (o2); \ | ||
212 | register __typeof__(*(p1)) __new1 asm("4") = (n1); \ | ||
213 | register __typeof__(*(p2)) __new2 asm("5") = (n2); \ | ||
214 | int cc; \ | ||
215 | asm volatile( \ | ||
216 | insn " %[old],%[new],%[ptr]\n" \ | ||
217 | " ipm %[cc]\n" \ | ||
218 | " srl %[cc],28" \ | ||
219 | : [cc] "=d" (cc), [old] "+d" (__old1), "+d" (__old2) \ | ||
220 | : [new] "d" (__new1), "d" (__new2), \ | ||
221 | [ptr] "Q" (*(p1)), "Q" (*(p2)) \ | ||
222 | : "memory", "cc"); \ | ||
223 | !cc; \ | ||
224 | }) | ||
225 | |||
226 | #define __cmpxchg_double_4(p1, p2, o1, o2, n1, n2) \ | ||
227 | __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, "cds") | ||
228 | |||
229 | #define __cmpxchg_double_8(p1, p2, o1, o2, n1, n2) \ | ||
230 | __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, "cdsg") | ||
231 | |||
232 | extern void __cmpxchg_double_called_with_bad_pointer(void); | ||
233 | |||
234 | #define __cmpxchg_double(p1, p2, o1, o2, n1, n2) \ | ||
235 | ({ \ | ||
236 | int __ret; \ | ||
237 | switch (sizeof(*(p1))) { \ | ||
238 | case 4: \ | ||
239 | __ret = __cmpxchg_double_4(p1, p2, o1, o2, n1, n2); \ | ||
240 | break; \ | ||
241 | case 8: \ | ||
242 | __ret = __cmpxchg_double_8(p1, p2, o1, o2, n1, n2); \ | ||
243 | break; \ | ||
244 | default: \ | ||
245 | __cmpxchg_double_called_with_bad_pointer(); \ | ||
246 | } \ | ||
247 | __ret; \ | ||
248 | }) | ||
249 | |||
250 | #define cmpxchg_double(p1, p2, o1, o2, n1, n2) \ | ||
251 | ({ \ | ||
252 | __typeof__(p1) __p1 = (p1); \ | ||
253 | __typeof__(p2) __p2 = (p2); \ | ||
254 | int __ret; \ | ||
255 | BUILD_BUG_ON(sizeof(*(p1)) != sizeof(long)); \ | ||
256 | BUILD_BUG_ON(sizeof(*(p2)) != sizeof(long)); \ | ||
257 | VM_BUG_ON((unsigned long)((__p1) + 1) != (unsigned long)(__p2));\ | ||
258 | if (sizeof(long) == 4) \ | ||
259 | __ret = __cmpxchg_double_4(__p1, __p2, o1, o2, n1, n2); \ | ||
260 | else \ | ||
261 | __ret = __cmpxchg_double_8(__p1, __p2, o1, o2, n1, n2); \ | ||
262 | __ret; \ | ||
263 | }) | ||
264 | |||
265 | #define system_has_cmpxchg_double() 1 | ||
266 | |||
206 | #include <asm-generic/cmpxchg-local.h> | 267 | #include <asm-generic/cmpxchg-local.h> |
207 | 268 | ||
208 | static inline unsigned long __cmpxchg_local(void *ptr, | 269 | static inline unsigned long __cmpxchg_local(void *ptr, |
diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h index a3afecdae145..35f0020b7ba7 100644 --- a/arch/s390/include/asm/cpu_mf.h +++ b/arch/s390/include/asm/cpu_mf.h | |||
@@ -21,11 +21,15 @@ | |||
21 | #define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data alert */ | 21 | #define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data alert */ |
22 | #define CPU_MF_INT_CF_CACA (1 << 7) /* counter auth. change alert */ | 22 | #define CPU_MF_INT_CF_CACA (1 << 7) /* counter auth. change alert */ |
23 | #define CPU_MF_INT_CF_LCDA (1 << 6) /* loss of counter data alert */ | 23 | #define CPU_MF_INT_CF_LCDA (1 << 6) /* loss of counter data alert */ |
24 | #define CPU_MF_INT_RI_HALTED (1 << 5) /* run-time instr. halted */ | ||
25 | #define CPU_MF_INT_RI_BUF_FULL (1 << 4) /* run-time instr. program | ||
26 | buffer full */ | ||
24 | 27 | ||
25 | #define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA) | 28 | #define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA) |
26 | #define CPU_MF_INT_SF_MASK (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE| \ | 29 | #define CPU_MF_INT_SF_MASK (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE| \ |
27 | CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA| \ | 30 | CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA| \ |
28 | CPU_MF_INT_SF_LSDA) | 31 | CPU_MF_INT_SF_LSDA) |
32 | #define CPU_MF_INT_RI_MASK (CPU_MF_INT_RI_HALTED|CPU_MF_INT_RI_BUF_FULL) | ||
29 | 33 | ||
30 | /* CPU measurement facility support */ | 34 | /* CPU measurement facility support */ |
31 | static inline int cpum_cf_avail(void) | 35 | static inline int cpum_cf_avail(void) |
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index 8709bdef233c..023d5ae24482 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h | |||
@@ -12,6 +12,9 @@ | |||
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <asm/div64.h> | 13 | #include <asm/div64.h> |
14 | 14 | ||
15 | |||
16 | #define __ARCH_HAS_VTIME_ACCOUNT | ||
17 | |||
15 | /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ | 18 | /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ |
16 | 19 | ||
17 | typedef unsigned long long __nocast cputime_t; | 20 | typedef unsigned long long __nocast cputime_t; |
diff --git a/arch/s390/include/asm/css_chars.h b/arch/s390/include/asm/css_chars.h new file mode 100644 index 000000000000..a06ebc2623fb --- /dev/null +++ b/arch/s390/include/asm/css_chars.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef _ASM_CSS_CHARS_H | ||
2 | #define _ASM_CSS_CHARS_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | #ifdef __KERNEL__ | ||
7 | |||
8 | struct css_general_char { | ||
9 | u64 : 12; | ||
10 | u32 dynio : 1; /* bit 12 */ | ||
11 | u32 : 4; | ||
12 | u32 eadm : 1; /* bit 17 */ | ||
13 | u32 : 23; | ||
14 | u32 aif : 1; /* bit 41 */ | ||
15 | u32 : 3; | ||
16 | u32 mcss : 1; /* bit 45 */ | ||
17 | u32 fcs : 1; /* bit 46 */ | ||
18 | u32 : 1; | ||
19 | u32 ext_mb : 1; /* bit 48 */ | ||
20 | u32 : 7; | ||
21 | u32 aif_tdd : 1; /* bit 56 */ | ||
22 | u32 : 1; | ||
23 | u32 qebsm : 1; /* bit 58 */ | ||
24 | u32 : 8; | ||
25 | u32 aif_osa : 1; /* bit 67 */ | ||
26 | u32 : 12; | ||
27 | u32 eadm_rf : 1; /* bit 80 */ | ||
28 | u32 : 1; | ||
29 | u32 cib : 1; /* bit 82 */ | ||
30 | u32 : 5; | ||
31 | u32 fcx : 1; /* bit 88 */ | ||
32 | u32 : 19; | ||
33 | u32 alt_ssi : 1; /* bit 108 */ | ||
34 | } __packed; | ||
35 | |||
36 | extern struct css_general_char css_general_characteristics; | ||
37 | |||
38 | #endif /* __KERNEL__ */ | ||
39 | #endif | ||
diff --git a/arch/s390/include/asm/eadm.h b/arch/s390/include/asm/eadm.h new file mode 100644 index 000000000000..8d4847191ecc --- /dev/null +++ b/arch/s390/include/asm/eadm.h | |||
@@ -0,0 +1,124 @@ | |||
1 | #ifndef _ASM_S390_EADM_H | ||
2 | #define _ASM_S390_EADM_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <linux/device.h> | ||
6 | |||
7 | struct arqb { | ||
8 | u64 data; | ||
9 | u16 fmt:4; | ||
10 | u16:12; | ||
11 | u16 cmd_code; | ||
12 | u16:16; | ||
13 | u16 msb_count; | ||
14 | u32 reserved[12]; | ||
15 | } __packed; | ||
16 | |||
17 | #define ARQB_CMD_MOVE 1 | ||
18 | |||
19 | struct arsb { | ||
20 | u16 fmt:4; | ||
21 | u32:28; | ||
22 | u8 ef; | ||
23 | u8:8; | ||
24 | u8 ecbi; | ||
25 | u8:8; | ||
26 | u8 fvf; | ||
27 | u16:16; | ||
28 | u8 eqc; | ||
29 | u32:32; | ||
30 | u64 fail_msb; | ||
31 | u64 fail_aidaw; | ||
32 | u64 fail_ms; | ||
33 | u64 fail_scm; | ||
34 | u32 reserved[4]; | ||
35 | } __packed; | ||
36 | |||
37 | struct msb { | ||
38 | u8 fmt:4; | ||
39 | u8 oc:4; | ||
40 | u8 flags; | ||
41 | u16:12; | ||
42 | u16 bs:4; | ||
43 | u32 blk_count; | ||
44 | u64 data_addr; | ||
45 | u64 scm_addr; | ||
46 | u64:64; | ||
47 | } __packed; | ||
48 | |||
49 | struct aidaw { | ||
50 | u8 flags; | ||
51 | u32 :24; | ||
52 | u32 :32; | ||
53 | u64 data_addr; | ||
54 | } __packed; | ||
55 | |||
56 | #define MSB_OC_CLEAR 0 | ||
57 | #define MSB_OC_READ 1 | ||
58 | #define MSB_OC_WRITE 2 | ||
59 | #define MSB_OC_RELEASE 3 | ||
60 | |||
61 | #define MSB_FLAG_BNM 0x80 | ||
62 | #define MSB_FLAG_IDA 0x40 | ||
63 | |||
64 | #define MSB_BS_4K 0 | ||
65 | #define MSB_BS_1M 1 | ||
66 | |||
67 | #define AOB_NR_MSB 124 | ||
68 | |||
69 | struct aob { | ||
70 | struct arqb request; | ||
71 | struct arsb response; | ||
72 | struct msb msb[AOB_NR_MSB]; | ||
73 | } __packed __aligned(PAGE_SIZE); | ||
74 | |||
75 | struct aob_rq_header { | ||
76 | struct scm_device *scmdev; | ||
77 | char data[0]; | ||
78 | }; | ||
79 | |||
80 | struct scm_device { | ||
81 | u64 address; | ||
82 | u64 size; | ||
83 | unsigned int nr_max_block; | ||
84 | struct device dev; | ||
85 | struct { | ||
86 | unsigned int persistence:4; | ||
87 | unsigned int oper_state:4; | ||
88 | unsigned int data_state:4; | ||
89 | unsigned int rank:4; | ||
90 | unsigned int release:1; | ||
91 | unsigned int res_id:8; | ||
92 | } __packed attrs; | ||
93 | }; | ||
94 | |||
95 | #define OP_STATE_GOOD 1 | ||
96 | #define OP_STATE_TEMP_ERR 2 | ||
97 | #define OP_STATE_PERM_ERR 3 | ||
98 | |||
99 | struct scm_driver { | ||
100 | struct device_driver drv; | ||
101 | int (*probe) (struct scm_device *scmdev); | ||
102 | int (*remove) (struct scm_device *scmdev); | ||
103 | void (*notify) (struct scm_device *scmdev); | ||
104 | void (*handler) (struct scm_device *scmdev, void *data, int error); | ||
105 | }; | ||
106 | |||
107 | int scm_driver_register(struct scm_driver *scmdrv); | ||
108 | void scm_driver_unregister(struct scm_driver *scmdrv); | ||
109 | |||
110 | int scm_start_aob(struct aob *aob); | ||
111 | void scm_irq_handler(struct aob *aob, int error); | ||
112 | |||
113 | struct eadm_ops { | ||
114 | int (*eadm_start) (struct aob *aob); | ||
115 | struct module *owner; | ||
116 | }; | ||
117 | |||
118 | int scm_get_ref(void); | ||
119 | void scm_put_ref(void); | ||
120 | |||
121 | void register_eadm_ops(struct eadm_ops *ops); | ||
122 | void unregister_eadm_ops(struct eadm_ops *ops); | ||
123 | |||
124 | #endif /* _ASM_S390_EADM_H */ | ||
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 9b94a160fe7f..178ff966a8ba 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h | |||
@@ -101,6 +101,7 @@ | |||
101 | #define HWCAP_S390_HPAGE 128 | 101 | #define HWCAP_S390_HPAGE 128 |
102 | #define HWCAP_S390_ETF3EH 256 | 102 | #define HWCAP_S390_ETF3EH 256 |
103 | #define HWCAP_S390_HIGH_GPRS 512 | 103 | #define HWCAP_S390_HIGH_GPRS 512 |
104 | #define HWCAP_S390_TE 1024 | ||
104 | 105 | ||
105 | /* | 106 | /* |
106 | * These are used to set parameters in the core dumps. | 107 | * These are used to set parameters in the core dumps. |
@@ -212,4 +213,6 @@ int arch_setup_additional_pages(struct linux_binprm *, int); | |||
212 | extern unsigned long arch_randomize_brk(struct mm_struct *mm); | 213 | extern unsigned long arch_randomize_brk(struct mm_struct *mm); |
213 | #define arch_randomize_brk arch_randomize_brk | 214 | #define arch_randomize_brk arch_randomize_brk |
214 | 215 | ||
216 | void *fill_cpu_elf_notes(void *ptr, struct save_area *sa); | ||
217 | |||
215 | #endif | 218 | #endif |
diff --git a/arch/s390/include/asm/etr.h b/arch/s390/include/asm/etr.h index a24b03b9fb64..629b79a93165 100644 --- a/arch/s390/include/asm/etr.h +++ b/arch/s390/include/asm/etr.h | |||
@@ -140,7 +140,7 @@ struct etr_ptff_qto { | |||
140 | /* Inline assembly helper functions */ | 140 | /* Inline assembly helper functions */ |
141 | static inline int etr_setr(struct etr_eacr *ctrl) | 141 | static inline int etr_setr(struct etr_eacr *ctrl) |
142 | { | 142 | { |
143 | int rc = -ENOSYS; | 143 | int rc = -EOPNOTSUPP; |
144 | 144 | ||
145 | asm volatile( | 145 | asm volatile( |
146 | " .insn s,0xb2160000,%1\n" | 146 | " .insn s,0xb2160000,%1\n" |
@@ -154,7 +154,7 @@ static inline int etr_setr(struct etr_eacr *ctrl) | |||
154 | /* Stores a format 1 aib with 64 bytes */ | 154 | /* Stores a format 1 aib with 64 bytes */ |
155 | static inline int etr_stetr(struct etr_aib *aib) | 155 | static inline int etr_stetr(struct etr_aib *aib) |
156 | { | 156 | { |
157 | int rc = -ENOSYS; | 157 | int rc = -EOPNOTSUPP; |
158 | 158 | ||
159 | asm volatile( | 159 | asm volatile( |
160 | " .insn s,0xb2170000,%1\n" | 160 | " .insn s,0xb2170000,%1\n" |
@@ -169,7 +169,7 @@ static inline int etr_stetr(struct etr_aib *aib) | |||
169 | static inline int etr_steai(struct etr_aib *aib, unsigned int func) | 169 | static inline int etr_steai(struct etr_aib *aib, unsigned int func) |
170 | { | 170 | { |
171 | register unsigned int reg0 asm("0") = func; | 171 | register unsigned int reg0 asm("0") = func; |
172 | int rc = -ENOSYS; | 172 | int rc = -EOPNOTSUPP; |
173 | 173 | ||
174 | asm volatile( | 174 | asm volatile( |
175 | " .insn s,0xb2b30000,%1\n" | 175 | " .insn s,0xb2b30000,%1\n" |
@@ -190,7 +190,7 @@ static inline int etr_ptff(void *ptff_block, unsigned int func) | |||
190 | { | 190 | { |
191 | register unsigned int reg0 asm("0") = func; | 191 | register unsigned int reg0 asm("0") = func; |
192 | register unsigned long reg1 asm("1") = (unsigned long) ptff_block; | 192 | register unsigned long reg1 asm("1") = (unsigned long) ptff_block; |
193 | int rc = -ENOSYS; | 193 | int rc = -EOPNOTSUPP; |
194 | 194 | ||
195 | asm volatile( | 195 | asm volatile( |
196 | " .word 0x0104\n" | 196 | " .word 0x0104\n" |
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h index 799ed0f1643d..2d6e6e380564 100644 --- a/arch/s390/include/asm/hugetlb.h +++ b/arch/s390/include/asm/hugetlb.h | |||
@@ -66,16 +66,6 @@ static inline pte_t huge_ptep_get(pte_t *ptep) | |||
66 | return pte; | 66 | return pte; |
67 | } | 67 | } |
68 | 68 | ||
69 | static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, | ||
70 | unsigned long addr, pte_t *ptep) | ||
71 | { | ||
72 | pte_t pte = huge_ptep_get(ptep); | ||
73 | |||
74 | mm->context.flush_mm = 1; | ||
75 | pmd_clear((pmd_t *) ptep); | ||
76 | return pte; | ||
77 | } | ||
78 | |||
79 | static inline void __pmd_csp(pmd_t *pmdp) | 69 | static inline void __pmd_csp(pmd_t *pmdp) |
80 | { | 70 | { |
81 | register unsigned long reg2 asm("2") = pmd_val(*pmdp); | 71 | register unsigned long reg2 asm("2") = pmd_val(*pmdp); |
@@ -117,6 +107,15 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, | |||
117 | __pmd_csp(pmdp); | 107 | __pmd_csp(pmdp); |
118 | } | 108 | } |
119 | 109 | ||
110 | static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, | ||
111 | unsigned long addr, pte_t *ptep) | ||
112 | { | ||
113 | pte_t pte = huge_ptep_get(ptep); | ||
114 | |||
115 | huge_ptep_invalidate(mm, addr, ptep); | ||
116 | return pte; | ||
117 | } | ||
118 | |||
120 | #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ | 119 | #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ |
121 | ({ \ | 120 | ({ \ |
122 | int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \ | 121 | int __changed = !pte_same(huge_ptep_get(__ptep), __entry); \ |
@@ -131,10 +130,7 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm, | |||
131 | ({ \ | 130 | ({ \ |
132 | pte_t __pte = huge_ptep_get(__ptep); \ | 131 | pte_t __pte = huge_ptep_get(__ptep); \ |
133 | if (pte_write(__pte)) { \ | 132 | if (pte_write(__pte)) { \ |
134 | (__mm)->context.flush_mm = 1; \ | 133 | huge_ptep_invalidate(__mm, __addr, __ptep); \ |
135 | if (atomic_read(&(__mm)->context.attach_count) > 1 || \ | ||
136 | (__mm) != current->active_mm) \ | ||
137 | huge_ptep_invalidate(__mm, __addr, __ptep); \ | ||
138 | set_huge_pte_at(__mm, __addr, __ptep, \ | 134 | set_huge_pte_at(__mm, __addr, __ptep, \ |
139 | huge_pte_wrprotect(__pte)); \ | 135 | huge_pte_wrprotect(__pte)); \ |
140 | } \ | 136 | } \ |
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index 2b9d41899d21..6703dd986fd4 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h | |||
@@ -19,6 +19,7 @@ enum interruption_class { | |||
19 | EXTINT_IUC, | 19 | EXTINT_IUC, |
20 | EXTINT_CMS, | 20 | EXTINT_CMS, |
21 | EXTINT_CMC, | 21 | EXTINT_CMC, |
22 | EXTINT_CMR, | ||
22 | IOINT_CIO, | 23 | IOINT_CIO, |
23 | IOINT_QAI, | 24 | IOINT_QAI, |
24 | IOINT_DAS, | 25 | IOINT_DAS, |
@@ -30,6 +31,7 @@ enum interruption_class { | |||
30 | IOINT_CLW, | 31 | IOINT_CLW, |
31 | IOINT_CTC, | 32 | IOINT_CTC, |
32 | IOINT_APB, | 33 | IOINT_APB, |
34 | IOINT_ADM, | ||
33 | IOINT_CSC, | 35 | IOINT_CSC, |
34 | NMI_NMI, | 36 | NMI_NMI, |
35 | NR_IRQS, | 37 | NR_IRQS, |
diff --git a/arch/s390/include/asm/isc.h b/arch/s390/include/asm/isc.h index 1420a1115948..5ae606456b0a 100644 --- a/arch/s390/include/asm/isc.h +++ b/arch/s390/include/asm/isc.h | |||
@@ -14,6 +14,7 @@ | |||
14 | /* Regular I/O interrupts. */ | 14 | /* Regular I/O interrupts. */ |
15 | #define IO_SCH_ISC 3 /* regular I/O subchannels */ | 15 | #define IO_SCH_ISC 3 /* regular I/O subchannels */ |
16 | #define CONSOLE_ISC 1 /* console I/O subchannel */ | 16 | #define CONSOLE_ISC 1 /* console I/O subchannel */ |
17 | #define EADM_SCH_ISC 4 /* EADM subchannels */ | ||
17 | #define CHSC_SCH_ISC 7 /* CHSC subchannels */ | 18 | #define CHSC_SCH_ISC 7 /* CHSC subchannels */ |
18 | /* Adapter interrupts. */ | 19 | /* Adapter interrupts. */ |
19 | #define QDIO_AIRQ_ISC IO_SCH_ISC /* I/O subchannel in qdio mode */ | 20 | #define QDIO_AIRQ_ISC IO_SCH_ISC /* I/O subchannel in qdio mode */ |
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index aab5555bbbda..bbf8141408cd 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
@@ -329,9 +329,13 @@ struct _lowcore { | |||
329 | __u8 pad_0x1338[0x1340-0x1338]; /* 0x1338 */ | 329 | __u8 pad_0x1338[0x1340-0x1338]; /* 0x1338 */ |
330 | __u32 access_regs_save_area[16]; /* 0x1340 */ | 330 | __u32 access_regs_save_area[16]; /* 0x1340 */ |
331 | __u64 cregs_save_area[16]; /* 0x1380 */ | 331 | __u64 cregs_save_area[16]; /* 0x1380 */ |
332 | __u8 pad_0x1400[0x1800-0x1400]; /* 0x1400 */ | ||
333 | |||
334 | /* Transaction abort diagnostic block */ | ||
335 | __u8 pgm_tdb[256]; /* 0x1800 */ | ||
332 | 336 | ||
333 | /* align to the top of the prefix area */ | 337 | /* align to the top of the prefix area */ |
334 | __u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */ | 338 | __u8 pad_0x1900[0x2000-0x1900]; /* 0x1900 */ |
335 | } __packed; | 339 | } __packed; |
336 | 340 | ||
337 | #endif /* CONFIG_32BIT */ | 341 | #endif /* CONFIG_32BIT */ |
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index b749c5733657..084e7755ed9b 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h | |||
@@ -57,7 +57,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) | |||
57 | pgd_t *pgd = mm->pgd; | 57 | pgd_t *pgd = mm->pgd; |
58 | 58 | ||
59 | S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd); | 59 | S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd); |
60 | if (addressing_mode != HOME_SPACE_MODE) { | 60 | if (s390_user_mode != HOME_SPACE_MODE) { |
61 | /* Load primary space page table origin. */ | 61 | /* Load primary space page table origin. */ |
62 | asm volatile(LCTL_OPCODE" 1,1,%0\n" | 62 | asm volatile(LCTL_OPCODE" 1,1,%0\n" |
63 | : : "m" (S390_lowcore.user_asce) ); | 63 | : : "m" (S390_lowcore.user_asce) ); |
diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h index 6537e72e0853..86fe0ee2cee5 100644 --- a/arch/s390/include/asm/percpu.h +++ b/arch/s390/include/asm/percpu.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #define arch_this_cpu_to_op(pcp, val, op) \ | 22 | #define arch_this_cpu_to_op(pcp, val, op) \ |
23 | do { \ | 23 | ({ \ |
24 | typedef typeof(pcp) pcp_op_T__; \ | 24 | typedef typeof(pcp) pcp_op_T__; \ |
25 | pcp_op_T__ old__, new__, prev__; \ | 25 | pcp_op_T__ old__, new__, prev__; \ |
26 | pcp_op_T__ *ptr__; \ | 26 | pcp_op_T__ *ptr__; \ |
@@ -39,13 +39,19 @@ do { \ | |||
39 | } \ | 39 | } \ |
40 | } while (prev__ != old__); \ | 40 | } while (prev__ != old__); \ |
41 | preempt_enable(); \ | 41 | preempt_enable(); \ |
42 | } while (0) | 42 | new__; \ |
43 | }) | ||
43 | 44 | ||
44 | #define this_cpu_add_1(pcp, val) arch_this_cpu_to_op(pcp, val, +) | 45 | #define this_cpu_add_1(pcp, val) arch_this_cpu_to_op(pcp, val, +) |
45 | #define this_cpu_add_2(pcp, val) arch_this_cpu_to_op(pcp, val, +) | 46 | #define this_cpu_add_2(pcp, val) arch_this_cpu_to_op(pcp, val, +) |
46 | #define this_cpu_add_4(pcp, val) arch_this_cpu_to_op(pcp, val, +) | 47 | #define this_cpu_add_4(pcp, val) arch_this_cpu_to_op(pcp, val, +) |
47 | #define this_cpu_add_8(pcp, val) arch_this_cpu_to_op(pcp, val, +) | 48 | #define this_cpu_add_8(pcp, val) arch_this_cpu_to_op(pcp, val, +) |
48 | 49 | ||
50 | #define this_cpu_add_return_1(pcp, val) arch_this_cpu_to_op(pcp, val, +) | ||
51 | #define this_cpu_add_return_2(pcp, val) arch_this_cpu_to_op(pcp, val, +) | ||
52 | #define this_cpu_add_return_4(pcp, val) arch_this_cpu_to_op(pcp, val, +) | ||
53 | #define this_cpu_add_return_8(pcp, val) arch_this_cpu_to_op(pcp, val, +) | ||
54 | |||
49 | #define this_cpu_and_1(pcp, val) arch_this_cpu_to_op(pcp, val, &) | 55 | #define this_cpu_and_1(pcp, val) arch_this_cpu_to_op(pcp, val, &) |
50 | #define this_cpu_and_2(pcp, val) arch_this_cpu_to_op(pcp, val, &) | 56 | #define this_cpu_and_2(pcp, val) arch_this_cpu_to_op(pcp, val, &) |
51 | #define this_cpu_and_4(pcp, val) arch_this_cpu_to_op(pcp, val, &) | 57 | #define this_cpu_and_4(pcp, val) arch_this_cpu_to_op(pcp, val, &) |
@@ -61,7 +67,7 @@ do { \ | |||
61 | #define this_cpu_xor_4(pcp, val) arch_this_cpu_to_op(pcp, val, ^) | 67 | #define this_cpu_xor_4(pcp, val) arch_this_cpu_to_op(pcp, val, ^) |
62 | #define this_cpu_xor_8(pcp, val) arch_this_cpu_to_op(pcp, val, ^) | 68 | #define this_cpu_xor_8(pcp, val) arch_this_cpu_to_op(pcp, val, ^) |
63 | 69 | ||
64 | #define arch_this_cpu_cmpxchg(pcp, oval, nval) \ | 70 | #define arch_this_cpu_cmpxchg(pcp, oval, nval) \ |
65 | ({ \ | 71 | ({ \ |
66 | typedef typeof(pcp) pcp_op_T__; \ | 72 | typedef typeof(pcp) pcp_op_T__; \ |
67 | pcp_op_T__ ret__; \ | 73 | pcp_op_T__ ret__; \ |
@@ -84,6 +90,44 @@ do { \ | |||
84 | #define this_cpu_cmpxchg_4(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) | 90 | #define this_cpu_cmpxchg_4(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) |
85 | #define this_cpu_cmpxchg_8(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) | 91 | #define this_cpu_cmpxchg_8(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) |
86 | 92 | ||
93 | #define arch_this_cpu_xchg(pcp, nval) \ | ||
94 | ({ \ | ||
95 | typeof(pcp) *ptr__; \ | ||
96 | typeof(pcp) ret__; \ | ||
97 | preempt_disable(); \ | ||
98 | ptr__ = __this_cpu_ptr(&(pcp)); \ | ||
99 | ret__ = xchg(ptr__, nval); \ | ||
100 | preempt_enable(); \ | ||
101 | ret__; \ | ||
102 | }) | ||
103 | |||
104 | #define this_cpu_xchg_1(pcp, nval) arch_this_cpu_xchg(pcp, nval) | ||
105 | #define this_cpu_xchg_2(pcp, nval) arch_this_cpu_xchg(pcp, nval) | ||
106 | #define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval) | ||
107 | #ifdef CONFIG_64BIT | ||
108 | #define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval) | ||
109 | #endif | ||
110 | |||
111 | #define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2) \ | ||
112 | ({ \ | ||
113 | typeof(pcp1) o1__ = (o1), n1__ = (n1); \ | ||
114 | typeof(pcp2) o2__ = (o2), n2__ = (n2); \ | ||
115 | typeof(pcp1) *p1__; \ | ||
116 | typeof(pcp2) *p2__; \ | ||
117 | int ret__; \ | ||
118 | preempt_disable(); \ | ||
119 | p1__ = __this_cpu_ptr(&(pcp1)); \ | ||
120 | p2__ = __this_cpu_ptr(&(pcp2)); \ | ||
121 | ret__ = __cmpxchg_double(p1__, p2__, o1__, o2__, n1__, n2__); \ | ||
122 | preempt_enable(); \ | ||
123 | ret__; \ | ||
124 | }) | ||
125 | |||
126 | #define this_cpu_cmpxchg_double_4 arch_this_cpu_cmpxchg_double | ||
127 | #ifdef CONFIG_64BIT | ||
128 | #define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double | ||
129 | #endif | ||
130 | |||
87 | #include <asm-generic/percpu.h> | 131 | #include <asm-generic/percpu.h> |
88 | 132 | ||
89 | #endif /* __ARCH_S390_PERCPU__ */ | 133 | #endif /* __ARCH_S390_PERCPU__ */ |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 11e4e3236937..f3e0aabfc6bc 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -11,12 +11,15 @@ | |||
11 | #ifndef __ASM_S390_PROCESSOR_H | 11 | #ifndef __ASM_S390_PROCESSOR_H |
12 | #define __ASM_S390_PROCESSOR_H | 12 | #define __ASM_S390_PROCESSOR_H |
13 | 13 | ||
14 | #ifndef __ASSEMBLY__ | ||
15 | |||
14 | #include <linux/linkage.h> | 16 | #include <linux/linkage.h> |
15 | #include <linux/irqflags.h> | 17 | #include <linux/irqflags.h> |
16 | #include <asm/cpu.h> | 18 | #include <asm/cpu.h> |
17 | #include <asm/page.h> | 19 | #include <asm/page.h> |
18 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
19 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
22 | #include <asm/runtime_instr.h> | ||
20 | 23 | ||
21 | /* | 24 | /* |
22 | * Default implementation of macro that returns current | 25 | * Default implementation of macro that returns current |
@@ -75,11 +78,20 @@ struct thread_struct { | |||
75 | unsigned long gmap_addr; /* address of last gmap fault. */ | 78 | unsigned long gmap_addr; /* address of last gmap fault. */ |
76 | struct per_regs per_user; /* User specified PER registers */ | 79 | struct per_regs per_user; /* User specified PER registers */ |
77 | struct per_event per_event; /* Cause of the last PER trap */ | 80 | struct per_event per_event; /* Cause of the last PER trap */ |
81 | unsigned long per_flags; /* Flags to control debug behavior */ | ||
78 | /* pfault_wait is used to block the process on a pfault event */ | 82 | /* pfault_wait is used to block the process on a pfault event */ |
79 | unsigned long pfault_wait; | 83 | unsigned long pfault_wait; |
80 | struct list_head list; | 84 | struct list_head list; |
85 | /* cpu runtime instrumentation */ | ||
86 | struct runtime_instr_cb *ri_cb; | ||
87 | int ri_signum; | ||
88 | #ifdef CONFIG_64BIT | ||
89 | unsigned char trap_tdb[256]; /* Transaction abort diagnose block */ | ||
90 | #endif | ||
81 | }; | 91 | }; |
82 | 92 | ||
93 | #define PER_FLAG_NO_TE 1UL /* Flag to disable transactions. */ | ||
94 | |||
83 | typedef struct thread_struct thread_struct; | 95 | typedef struct thread_struct thread_struct; |
84 | 96 | ||
85 | /* | 97 | /* |
@@ -130,6 +142,12 @@ struct task_struct; | |||
130 | struct mm_struct; | 142 | struct mm_struct; |
131 | struct seq_file; | 143 | struct seq_file; |
132 | 144 | ||
145 | #ifdef CONFIG_64BIT | ||
146 | extern void show_cacheinfo(struct seq_file *m); | ||
147 | #else | ||
148 | static inline void show_cacheinfo(struct seq_file *m) { } | ||
149 | #endif | ||
150 | |||
133 | /* Free all resources held by a thread. */ | 151 | /* Free all resources held by a thread. */ |
134 | extern void release_thread(struct task_struct *); | 152 | extern void release_thread(struct task_struct *); |
135 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 153 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
@@ -140,6 +158,7 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |||
140 | extern unsigned long thread_saved_pc(struct task_struct *t); | 158 | extern unsigned long thread_saved_pc(struct task_struct *t); |
141 | 159 | ||
142 | extern void show_code(struct pt_regs *regs); | 160 | extern void show_code(struct pt_regs *regs); |
161 | extern void print_fn_code(unsigned char *code, unsigned long len); | ||
143 | 162 | ||
144 | unsigned long get_wchan(struct task_struct *p); | 163 | unsigned long get_wchan(struct task_struct *p); |
145 | #define task_pt_regs(tsk) ((struct pt_regs *) \ | 164 | #define task_pt_regs(tsk) ((struct pt_regs *) \ |
@@ -331,23 +350,6 @@ extern void (*s390_base_ext_handler_fn)(void); | |||
331 | 350 | ||
332 | #define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL | 351 | #define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL |
333 | 352 | ||
334 | /* | ||
335 | * Helper macro for exception table entries | ||
336 | */ | ||
337 | #ifndef CONFIG_64BIT | ||
338 | #define EX_TABLE(_fault,_target) \ | ||
339 | ".section __ex_table,\"a\"\n" \ | ||
340 | " .align 4\n" \ | ||
341 | " .long " #_fault "," #_target "\n" \ | ||
342 | ".previous\n" | ||
343 | #else | ||
344 | #define EX_TABLE(_fault,_target) \ | ||
345 | ".section __ex_table,\"a\"\n" \ | ||
346 | " .align 8\n" \ | ||
347 | " .quad " #_fault "," #_target "\n" \ | ||
348 | ".previous\n" | ||
349 | #endif | ||
350 | |||
351 | extern int memcpy_real(void *, void *, size_t); | 353 | extern int memcpy_real(void *, void *, size_t); |
352 | extern void memcpy_absolute(void *, void *, size_t); | 354 | extern void memcpy_absolute(void *, void *, size_t); |
353 | 355 | ||
@@ -358,4 +360,25 @@ extern void memcpy_absolute(void *, void *, size_t); | |||
358 | memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ | 360 | memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ |
359 | } | 361 | } |
360 | 362 | ||
361 | #endif /* __ASM_S390_PROCESSOR_H */ | 363 | /* |
364 | * Helper macro for exception table entries | ||
365 | */ | ||
366 | #define EX_TABLE(_fault, _target) \ | ||
367 | ".section __ex_table,\"a\"\n" \ | ||
368 | ".align 4\n" \ | ||
369 | ".long (" #_fault ") - .\n" \ | ||
370 | ".long (" #_target ") - .\n" \ | ||
371 | ".previous\n" | ||
372 | |||
373 | #else /* __ASSEMBLY__ */ | ||
374 | |||
375 | #define EX_TABLE(_fault, _target) \ | ||
376 | .section __ex_table,"a" ; \ | ||
377 | .align 4 ; \ | ||
378 | .long (_fault) - . ; \ | ||
379 | .long (_target) - . ; \ | ||
380 | .previous | ||
381 | |||
382 | #endif /* __ASSEMBLY__ */ | ||
383 | |||
384 | #endif /* __ASM_S390_PROCESSOR_H */ | ||
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index d5f08ea566ed..ce20a53afe91 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h | |||
@@ -235,6 +235,7 @@ typedef struct | |||
235 | #define PSW_MASK_ASC 0x0000C000UL | 235 | #define PSW_MASK_ASC 0x0000C000UL |
236 | #define PSW_MASK_CC 0x00003000UL | 236 | #define PSW_MASK_CC 0x00003000UL |
237 | #define PSW_MASK_PM 0x00000F00UL | 237 | #define PSW_MASK_PM 0x00000F00UL |
238 | #define PSW_MASK_RI 0x00000000UL | ||
238 | #define PSW_MASK_EA 0x00000000UL | 239 | #define PSW_MASK_EA 0x00000000UL |
239 | #define PSW_MASK_BA 0x00000000UL | 240 | #define PSW_MASK_BA 0x00000000UL |
240 | 241 | ||
@@ -264,10 +265,11 @@ typedef struct | |||
264 | #define PSW_MASK_ASC 0x0000C00000000000UL | 265 | #define PSW_MASK_ASC 0x0000C00000000000UL |
265 | #define PSW_MASK_CC 0x0000300000000000UL | 266 | #define PSW_MASK_CC 0x0000300000000000UL |
266 | #define PSW_MASK_PM 0x00000F0000000000UL | 267 | #define PSW_MASK_PM 0x00000F0000000000UL |
268 | #define PSW_MASK_RI 0x0000008000000000UL | ||
267 | #define PSW_MASK_EA 0x0000000100000000UL | 269 | #define PSW_MASK_EA 0x0000000100000000UL |
268 | #define PSW_MASK_BA 0x0000000080000000UL | 270 | #define PSW_MASK_BA 0x0000000080000000UL |
269 | 271 | ||
270 | #define PSW_MASK_USER 0x00003F0180000000UL | 272 | #define PSW_MASK_USER 0x00003F8180000000UL |
271 | 273 | ||
272 | #define PSW_ADDR_AMODE 0x0000000000000000UL | 274 | #define PSW_ADDR_AMODE 0x0000000000000000UL |
273 | #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL | 275 | #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL |
@@ -359,17 +361,19 @@ struct per_struct_kernel { | |||
359 | unsigned char access_id; /* PER trap access identification */ | 361 | unsigned char access_id; /* PER trap access identification */ |
360 | }; | 362 | }; |
361 | 363 | ||
362 | #define PER_EVENT_MASK 0xE9000000UL | 364 | #define PER_EVENT_MASK 0xEB000000UL |
363 | 365 | ||
364 | #define PER_EVENT_BRANCH 0x80000000UL | 366 | #define PER_EVENT_BRANCH 0x80000000UL |
365 | #define PER_EVENT_IFETCH 0x40000000UL | 367 | #define PER_EVENT_IFETCH 0x40000000UL |
366 | #define PER_EVENT_STORE 0x20000000UL | 368 | #define PER_EVENT_STORE 0x20000000UL |
367 | #define PER_EVENT_STORE_REAL 0x08000000UL | 369 | #define PER_EVENT_STORE_REAL 0x08000000UL |
370 | #define PER_EVENT_TRANSACTION_END 0x02000000UL | ||
368 | #define PER_EVENT_NULLIFICATION 0x01000000UL | 371 | #define PER_EVENT_NULLIFICATION 0x01000000UL |
369 | 372 | ||
370 | #define PER_CONTROL_MASK 0x00a00000UL | 373 | #define PER_CONTROL_MASK 0x00e00000UL |
371 | 374 | ||
372 | #define PER_CONTROL_BRANCH_ADDRESS 0x00800000UL | 375 | #define PER_CONTROL_BRANCH_ADDRESS 0x00800000UL |
376 | #define PER_CONTROL_SUSPENSION 0x00400000UL | ||
373 | #define PER_CONTROL_ALTERATION 0x00200000UL | 377 | #define PER_CONTROL_ALTERATION 0x00200000UL |
374 | 378 | ||
375 | #endif | 379 | #endif |
@@ -483,6 +487,8 @@ typedef struct | |||
483 | #define PTRACE_GET_LAST_BREAK 0x5006 | 487 | #define PTRACE_GET_LAST_BREAK 0x5006 |
484 | #define PTRACE_PEEK_SYSTEM_CALL 0x5007 | 488 | #define PTRACE_PEEK_SYSTEM_CALL 0x5007 |
485 | #define PTRACE_POKE_SYSTEM_CALL 0x5008 | 489 | #define PTRACE_POKE_SYSTEM_CALL 0x5008 |
490 | #define PTRACE_ENABLE_TE 0x5009 | ||
491 | #define PTRACE_DISABLE_TE 0x5010 | ||
486 | 492 | ||
487 | /* | 493 | /* |
488 | * PT_PROT definition is loosely based on hppa bsd definition in | 494 | * PT_PROT definition is loosely based on hppa bsd definition in |
diff --git a/arch/s390/include/asm/runtime_instr.h b/arch/s390/include/asm/runtime_instr.h new file mode 100644 index 000000000000..830da737ff85 --- /dev/null +++ b/arch/s390/include/asm/runtime_instr.h | |||
@@ -0,0 +1,98 @@ | |||
1 | #ifndef _RUNTIME_INSTR_H | ||
2 | #define _RUNTIME_INSTR_H | ||
3 | |||
4 | #define S390_RUNTIME_INSTR_START 0x1 | ||
5 | #define S390_RUNTIME_INSTR_STOP 0x2 | ||
6 | |||
7 | struct runtime_instr_cb { | ||
8 | __u64 buf_current; | ||
9 | __u64 buf_origin; | ||
10 | __u64 buf_limit; | ||
11 | |||
12 | __u32 valid : 1; | ||
13 | __u32 pstate : 1; | ||
14 | __u32 pstate_set_buf : 1; | ||
15 | __u32 home_space : 1; | ||
16 | __u32 altered : 1; | ||
17 | __u32 : 3; | ||
18 | __u32 pstate_sample : 1; | ||
19 | __u32 sstate_sample : 1; | ||
20 | __u32 pstate_collect : 1; | ||
21 | __u32 sstate_collect : 1; | ||
22 | __u32 : 1; | ||
23 | __u32 halted_int : 1; | ||
24 | __u32 int_requested : 1; | ||
25 | __u32 buffer_full_int : 1; | ||
26 | __u32 key : 4; | ||
27 | __u32 : 9; | ||
28 | __u32 rgs : 3; | ||
29 | |||
30 | __u32 mode : 4; | ||
31 | __u32 next : 1; | ||
32 | __u32 mae : 1; | ||
33 | __u32 : 2; | ||
34 | __u32 call_type_br : 1; | ||
35 | __u32 return_type_br : 1; | ||
36 | __u32 other_type_br : 1; | ||
37 | __u32 bc_other_type : 1; | ||
38 | __u32 emit : 1; | ||
39 | __u32 tx_abort : 1; | ||
40 | __u32 : 2; | ||
41 | __u32 bp_xn : 1; | ||
42 | __u32 bp_xt : 1; | ||
43 | __u32 bp_ti : 1; | ||
44 | __u32 bp_ni : 1; | ||
45 | __u32 suppr_y : 1; | ||
46 | __u32 suppr_z : 1; | ||
47 | |||
48 | __u32 dc_miss_extra : 1; | ||
49 | __u32 lat_lev_ignore : 1; | ||
50 | __u32 ic_lat_lev : 4; | ||
51 | __u32 dc_lat_lev : 4; | ||
52 | |||
53 | __u64 reserved1; | ||
54 | __u64 scaling_factor; | ||
55 | __u64 rsic; | ||
56 | __u64 reserved2; | ||
57 | } __packed __aligned(8); | ||
58 | |||
59 | extern struct runtime_instr_cb runtime_instr_empty_cb; | ||
60 | |||
61 | static inline void load_runtime_instr_cb(struct runtime_instr_cb *cb) | ||
62 | { | ||
63 | asm volatile(".insn rsy,0xeb0000000060,0,0,%0" /* LRIC */ | ||
64 | : : "Q" (*cb)); | ||
65 | } | ||
66 | |||
67 | static inline void store_runtime_instr_cb(struct runtime_instr_cb *cb) | ||
68 | { | ||
69 | asm volatile(".insn rsy,0xeb0000000061,0,0,%0" /* STRIC */ | ||
70 | : "=Q" (*cb) : : "cc"); | ||
71 | } | ||
72 | |||
73 | static inline void save_ri_cb(struct runtime_instr_cb *cb_prev) | ||
74 | { | ||
75 | #ifdef CONFIG_64BIT | ||
76 | if (cb_prev) | ||
77 | store_runtime_instr_cb(cb_prev); | ||
78 | #endif | ||
79 | } | ||
80 | |||
81 | static inline void restore_ri_cb(struct runtime_instr_cb *cb_next, | ||
82 | struct runtime_instr_cb *cb_prev) | ||
83 | { | ||
84 | #ifdef CONFIG_64BIT | ||
85 | if (cb_next) | ||
86 | load_runtime_instr_cb(cb_next); | ||
87 | else if (cb_prev) | ||
88 | load_runtime_instr_cb(&runtime_instr_empty_cb); | ||
89 | #endif | ||
90 | } | ||
91 | |||
92 | #ifdef CONFIG_64BIT | ||
93 | extern void exit_thread_runtime_instr(void); | ||
94 | #else | ||
95 | static inline void exit_thread_runtime_instr(void) { } | ||
96 | #endif | ||
97 | |||
98 | #endif /* _RUNTIME_INSTR_H */ | ||
diff --git a/arch/s390/include/asm/scsw.h b/arch/s390/include/asm/scsw.h index 4071d00978cb..4af99cdaddf5 100644 --- a/arch/s390/include/asm/scsw.h +++ b/arch/s390/include/asm/scsw.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Helper functions for scsw access. | 2 | * Helper functions for scsw access. |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2008, 2009 | 4 | * Copyright IBM Corp. 2008, 2012 |
5 | * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | 5 | * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> |
6 | */ | 6 | */ |
7 | 7 | ||
@@ -9,7 +9,7 @@ | |||
9 | #define _ASM_S390_SCSW_H_ | 9 | #define _ASM_S390_SCSW_H_ |
10 | 10 | ||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <asm/chsc.h> | 12 | #include <asm/css_chars.h> |
13 | #include <asm/cio.h> | 13 | #include <asm/cio.h> |
14 | 14 | ||
15 | /** | 15 | /** |
@@ -100,14 +100,46 @@ struct tm_scsw { | |||
100 | } __attribute__ ((packed)); | 100 | } __attribute__ ((packed)); |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * struct eadm_scsw - subchannel status word for eadm subchannels | ||
104 | * @key: subchannel key | ||
105 | * @eswf: esw format | ||
106 | * @cc: deferred condition code | ||
107 | * @ectl: extended control | ||
108 | * @fctl: function control | ||
109 | * @actl: activity control | ||
110 | * @stctl: status control | ||
111 | * @aob: AOB address | ||
112 | * @dstat: device status | ||
113 | * @cstat: subchannel status | ||
114 | */ | ||
115 | struct eadm_scsw { | ||
116 | u32 key:4; | ||
117 | u32:1; | ||
118 | u32 eswf:1; | ||
119 | u32 cc:2; | ||
120 | u32:6; | ||
121 | u32 ectl:1; | ||
122 | u32:2; | ||
123 | u32 fctl:3; | ||
124 | u32 actl:7; | ||
125 | u32 stctl:5; | ||
126 | u32 aob; | ||
127 | u32 dstat:8; | ||
128 | u32 cstat:8; | ||
129 | u32:16; | ||
130 | } __packed; | ||
131 | |||
132 | /** | ||
103 | * union scsw - subchannel status word | 133 | * union scsw - subchannel status word |
104 | * @cmd: command-mode SCSW | 134 | * @cmd: command-mode SCSW |
105 | * @tm: transport-mode SCSW | 135 | * @tm: transport-mode SCSW |
136 | * @eadm: eadm SCSW | ||
106 | */ | 137 | */ |
107 | union scsw { | 138 | union scsw { |
108 | struct cmd_scsw cmd; | 139 | struct cmd_scsw cmd; |
109 | struct tm_scsw tm; | 140 | struct tm_scsw tm; |
110 | } __attribute__ ((packed)); | 141 | struct eadm_scsw eadm; |
142 | } __packed; | ||
111 | 143 | ||
112 | #define SCSW_FCTL_CLEAR_FUNC 0x1 | 144 | #define SCSW_FCTL_CLEAR_FUNC 0x1 |
113 | #define SCSW_FCTL_HALT_FUNC 0x2 | 145 | #define SCSW_FCTL_HALT_FUNC 0x2 |
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index e6859d16ee2d..87b47ca954f1 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h | |||
@@ -60,7 +60,7 @@ void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr, | |||
60 | #define SECONDARY_SPACE_MODE 2 | 60 | #define SECONDARY_SPACE_MODE 2 |
61 | #define HOME_SPACE_MODE 3 | 61 | #define HOME_SPACE_MODE 3 |
62 | 62 | ||
63 | extern unsigned int addressing_mode; | 63 | extern unsigned int s390_user_mode; |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * Machine features detected in head.S | 66 | * Machine features detected in head.S |
@@ -80,6 +80,7 @@ extern unsigned int addressing_mode; | |||
80 | #define MACHINE_FLAG_LPAR (1UL << 12) | 80 | #define MACHINE_FLAG_LPAR (1UL << 12) |
81 | #define MACHINE_FLAG_SPP (1UL << 13) | 81 | #define MACHINE_FLAG_SPP (1UL << 13) |
82 | #define MACHINE_FLAG_TOPOLOGY (1UL << 14) | 82 | #define MACHINE_FLAG_TOPOLOGY (1UL << 14) |
83 | #define MACHINE_FLAG_TE (1UL << 15) | ||
83 | 84 | ||
84 | #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) | 85 | #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) |
85 | #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) | 86 | #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) |
@@ -98,6 +99,7 @@ extern unsigned int addressing_mode; | |||
98 | #define MACHINE_HAS_PFMF (0) | 99 | #define MACHINE_HAS_PFMF (0) |
99 | #define MACHINE_HAS_SPP (0) | 100 | #define MACHINE_HAS_SPP (0) |
100 | #define MACHINE_HAS_TOPOLOGY (0) | 101 | #define MACHINE_HAS_TOPOLOGY (0) |
102 | #define MACHINE_HAS_TE (0) | ||
101 | #else /* CONFIG_64BIT */ | 103 | #else /* CONFIG_64BIT */ |
102 | #define MACHINE_HAS_IEEE (1) | 104 | #define MACHINE_HAS_IEEE (1) |
103 | #define MACHINE_HAS_CSP (1) | 105 | #define MACHINE_HAS_CSP (1) |
@@ -109,6 +111,7 @@ extern unsigned int addressing_mode; | |||
109 | #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) | 111 | #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) |
110 | #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) | 112 | #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) |
111 | #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) | 113 | #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) |
114 | #define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE) | ||
112 | #endif /* CONFIG_64BIT */ | 115 | #endif /* CONFIG_64BIT */ |
113 | 116 | ||
114 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) | 117 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) |
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index ce26ac3cb162..b64f15c3b4cc 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h | |||
@@ -30,6 +30,8 @@ extern int smp_vcpu_scheduled(int cpu); | |||
30 | extern void smp_yield_cpu(int cpu); | 30 | extern void smp_yield_cpu(int cpu); |
31 | extern void smp_yield(void); | 31 | extern void smp_yield(void); |
32 | extern void smp_stop_cpu(void); | 32 | extern void smp_stop_cpu(void); |
33 | extern void smp_cpu_set_polarization(int cpu, int val); | ||
34 | extern int smp_cpu_get_polarization(int cpu); | ||
33 | 35 | ||
34 | #else /* CONFIG_SMP */ | 36 | #else /* CONFIG_SMP */ |
35 | 37 | ||
@@ -43,7 +45,7 @@ static inline void smp_call_online_cpu(void (*func)(void *), void *data) | |||
43 | func(data); | 45 | func(data); |
44 | } | 46 | } |
45 | 47 | ||
46 | static inline int smp_find_processor_id(int address) { return 0; } | 48 | static inline int smp_find_processor_id(u16 address) { return 0; } |
47 | static inline int smp_store_status(int cpu) { return 0; } | 49 | static inline int smp_store_status(int cpu) { return 0; } |
48 | static inline int smp_vcpu_scheduled(int cpu) { return 1; } | 50 | static inline int smp_vcpu_scheduled(int cpu) { return 1; } |
49 | static inline void smp_yield_cpu(int cpu) { } | 51 | static inline void smp_yield_cpu(int cpu) { } |
diff --git a/arch/s390/include/asm/string.h b/arch/s390/include/asm/string.h index 1bd1352fa3b5..7e2dcd7c57ef 100644 --- a/arch/s390/include/asm/string.h +++ b/arch/s390/include/asm/string.h | |||
@@ -96,7 +96,6 @@ static inline char *strcat(char *dst, const char *src) | |||
96 | 96 | ||
97 | static inline char *strcpy(char *dst, const char *src) | 97 | static inline char *strcpy(char *dst, const char *src) |
98 | { | 98 | { |
99 | #if __GNUC__ < 4 | ||
100 | register int r0 asm("0") = 0; | 99 | register int r0 asm("0") = 0; |
101 | char *ret = dst; | 100 | char *ret = dst; |
102 | 101 | ||
@@ -106,14 +105,10 @@ static inline char *strcpy(char *dst, const char *src) | |||
106 | : "+&a" (dst), "+&a" (src) : "d" (r0) | 105 | : "+&a" (dst), "+&a" (src) : "d" (r0) |
107 | : "cc", "memory"); | 106 | : "cc", "memory"); |
108 | return ret; | 107 | return ret; |
109 | #else | ||
110 | return __builtin_strcpy(dst, src); | ||
111 | #endif | ||
112 | } | 108 | } |
113 | 109 | ||
114 | static inline size_t strlen(const char *s) | 110 | static inline size_t strlen(const char *s) |
115 | { | 111 | { |
116 | #if __GNUC__ < 4 | ||
117 | register unsigned long r0 asm("0") = 0; | 112 | register unsigned long r0 asm("0") = 0; |
118 | const char *tmp = s; | 113 | const char *tmp = s; |
119 | 114 | ||
@@ -122,9 +117,6 @@ static inline size_t strlen(const char *s) | |||
122 | " jo 0b" | 117 | " jo 0b" |
123 | : "+d" (r0), "+a" (tmp) : : "cc"); | 118 | : "+d" (r0), "+a" (tmp) : : "cc"); |
124 | return r0 - (unsigned long) s; | 119 | return r0 - (unsigned long) s; |
125 | #else | ||
126 | return __builtin_strlen(s); | ||
127 | #endif | ||
128 | } | 120 | } |
129 | 121 | ||
130 | static inline size_t strnlen(const char * s, size_t n) | 122 | static inline size_t strnlen(const char * s, size_t n) |
diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h index f223068b7822..f3a9e0f92704 100644 --- a/arch/s390/include/asm/switch_to.h +++ b/arch/s390/include/asm/switch_to.h | |||
@@ -80,21 +80,19 @@ static inline void restore_access_regs(unsigned int *acrs) | |||
80 | if (prev->mm) { \ | 80 | if (prev->mm) { \ |
81 | save_fp_regs(&prev->thread.fp_regs); \ | 81 | save_fp_regs(&prev->thread.fp_regs); \ |
82 | save_access_regs(&prev->thread.acrs[0]); \ | 82 | save_access_regs(&prev->thread.acrs[0]); \ |
83 | save_ri_cb(prev->thread.ri_cb); \ | ||
83 | } \ | 84 | } \ |
84 | if (next->mm) { \ | 85 | if (next->mm) { \ |
85 | restore_fp_regs(&next->thread.fp_regs); \ | 86 | restore_fp_regs(&next->thread.fp_regs); \ |
86 | restore_access_regs(&next->thread.acrs[0]); \ | 87 | restore_access_regs(&next->thread.acrs[0]); \ |
88 | restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \ | ||
87 | update_per_regs(next); \ | 89 | update_per_regs(next); \ |
88 | } \ | 90 | } \ |
89 | prev = __switch_to(prev,next); \ | 91 | prev = __switch_to(prev,next); \ |
90 | } while (0) | 92 | } while (0) |
91 | 93 | ||
92 | extern void account_vtime(struct task_struct *, struct task_struct *); | ||
93 | extern void account_tick_vtime(struct task_struct *); | ||
94 | |||
95 | #define finish_arch_switch(prev) do { \ | 94 | #define finish_arch_switch(prev) do { \ |
96 | set_fs(current->thread.mm_segment); \ | 95 | set_fs(current->thread.mm_segment); \ |
97 | account_vtime(prev, current); \ | ||
98 | } while (0) | 96 | } while (0) |
99 | 97 | ||
100 | #endif /* __ASM_SWITCH_TO_H */ | 98 | #endif /* __ASM_SWITCH_TO_H */ |
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index 282ee36f6162..f92428e459f8 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h | |||
@@ -17,7 +17,10 @@ | |||
17 | #include <asm/bitsperlong.h> | 17 | #include <asm/bitsperlong.h> |
18 | 18 | ||
19 | struct sysinfo_1_1_1 { | 19 | struct sysinfo_1_1_1 { |
20 | unsigned short :16; | 20 | unsigned char p:1; |
21 | unsigned char :6; | ||
22 | unsigned char t:1; | ||
23 | unsigned char :8; | ||
21 | unsigned char ccr; | 24 | unsigned char ccr; |
22 | unsigned char cai; | 25 | unsigned char cai; |
23 | char reserved_0[28]; | 26 | char reserved_0[28]; |
@@ -30,9 +33,14 @@ struct sysinfo_1_1_1 { | |||
30 | char model[16]; | 33 | char model[16]; |
31 | char model_perm_cap[16]; | 34 | char model_perm_cap[16]; |
32 | char model_temp_cap[16]; | 35 | char model_temp_cap[16]; |
33 | char model_cap_rating[4]; | 36 | unsigned int model_cap_rating; |
34 | char model_perm_cap_rating[4]; | 37 | unsigned int model_perm_cap_rating; |
35 | char model_temp_cap_rating[4]; | 38 | unsigned int model_temp_cap_rating; |
39 | unsigned char typepct[5]; | ||
40 | unsigned char reserved_2[3]; | ||
41 | unsigned int ncr; | ||
42 | unsigned int npr; | ||
43 | unsigned int ntr; | ||
36 | }; | 44 | }; |
37 | 45 | ||
38 | struct sysinfo_1_2_1 { | 46 | struct sysinfo_1_2_1 { |
@@ -47,8 +55,9 @@ struct sysinfo_1_2_2 { | |||
47 | char format; | 55 | char format; |
48 | char reserved_0[1]; | 56 | char reserved_0[1]; |
49 | unsigned short acc_offset; | 57 | unsigned short acc_offset; |
50 | char reserved_1[24]; | 58 | char reserved_1[20]; |
51 | unsigned int secondary_capability; | 59 | unsigned int nominal_cap; |
60 | unsigned int secondary_cap; | ||
52 | unsigned int capability; | 61 | unsigned int capability; |
53 | unsigned short cpus_total; | 62 | unsigned short cpus_total; |
54 | unsigned short cpus_configured; | 63 | unsigned short cpus_configured; |
@@ -109,6 +118,8 @@ struct sysinfo_3_2_2 { | |||
109 | char reserved_544[3552]; | 118 | char reserved_544[3552]; |
110 | }; | 119 | }; |
111 | 120 | ||
121 | extern int topology_max_mnest; | ||
122 | |||
112 | #define TOPOLOGY_CPU_BITS 64 | 123 | #define TOPOLOGY_CPU_BITS 64 |
113 | #define TOPOLOGY_NR_MAG 6 | 124 | #define TOPOLOGY_NR_MAG 6 |
114 | 125 | ||
@@ -142,21 +153,7 @@ struct sysinfo_15_1_x { | |||
142 | union topology_entry tle[0]; | 153 | union topology_entry tle[0]; |
143 | }; | 154 | }; |
144 | 155 | ||
145 | static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) | 156 | int stsi(void *sysinfo, int fc, int sel1, int sel2); |
146 | { | ||
147 | register int r0 asm("0") = (fc << 28) | sel1; | ||
148 | register int r1 asm("1") = sel2; | ||
149 | |||
150 | asm volatile( | ||
151 | " stsi 0(%2)\n" | ||
152 | "0: jz 2f\n" | ||
153 | "1: lhi %0,%3\n" | ||
154 | "2:\n" | ||
155 | EX_TABLE(0b, 1b) | ||
156 | : "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS) | ||
157 | : "cc", "memory"); | ||
158 | return r0; | ||
159 | } | ||
160 | 157 | ||
161 | /* | 158 | /* |
162 | * Service level reporting interface. | 159 | * Service level reporting interface. |
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index 9fde315f3a7c..1d8fe2b17ef6 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h | |||
@@ -90,12 +90,10 @@ static inline void __tlb_flush_mm(struct mm_struct * mm) | |||
90 | 90 | ||
91 | static inline void __tlb_flush_mm_cond(struct mm_struct * mm) | 91 | static inline void __tlb_flush_mm_cond(struct mm_struct * mm) |
92 | { | 92 | { |
93 | spin_lock(&mm->page_table_lock); | ||
94 | if (mm->context.flush_mm) { | 93 | if (mm->context.flush_mm) { |
95 | __tlb_flush_mm(mm); | 94 | __tlb_flush_mm(mm); |
96 | mm->context.flush_mm = 0; | 95 | mm->context.flush_mm = 0; |
97 | } | 96 | } |
98 | spin_unlock(&mm->page_table_lock); | ||
99 | } | 97 | } |
100 | 98 | ||
101 | /* | 99 | /* |
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index 0837de80c351..9ca305383760 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h | |||
@@ -2,8 +2,8 @@ | |||
2 | #define _ASM_S390_TOPOLOGY_H | 2 | #define _ASM_S390_TOPOLOGY_H |
3 | 3 | ||
4 | #include <linux/cpumask.h> | 4 | #include <linux/cpumask.h> |
5 | #include <asm/sysinfo.h> | ||
6 | 5 | ||
6 | struct sysinfo_15_1_x; | ||
7 | struct cpu; | 7 | struct cpu; |
8 | 8 | ||
9 | #ifdef CONFIG_SCHED_BOOK | 9 | #ifdef CONFIG_SCHED_BOOK |
@@ -51,24 +51,6 @@ static inline void topology_expect_change(void) { } | |||
51 | #define POLARIZATION_VM (2) | 51 | #define POLARIZATION_VM (2) |
52 | #define POLARIZATION_VH (3) | 52 | #define POLARIZATION_VH (3) |
53 | 53 | ||
54 | extern int cpu_polarization[]; | ||
55 | |||
56 | static inline void cpu_set_polarization(int cpu, int val) | ||
57 | { | ||
58 | #ifdef CONFIG_SCHED_BOOK | ||
59 | cpu_polarization[cpu] = val; | ||
60 | #endif | ||
61 | } | ||
62 | |||
63 | static inline int cpu_read_polarization(int cpu) | ||
64 | { | ||
65 | #ifdef CONFIG_SCHED_BOOK | ||
66 | return cpu_polarization[cpu]; | ||
67 | #else | ||
68 | return POLARIZATION_HRZ; | ||
69 | #endif | ||
70 | } | ||
71 | |||
72 | #ifdef CONFIG_SCHED_BOOK | 54 | #ifdef CONFIG_SCHED_BOOK |
73 | void s390_init_cpu_topology(void); | 55 | void s390_init_cpu_topology(void); |
74 | #else | 56 | #else |
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index a8ab18b18b54..34268df959a3 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h | |||
@@ -76,9 +76,22 @@ static inline int __range_ok(unsigned long addr, unsigned long size) | |||
76 | 76 | ||
77 | struct exception_table_entry | 77 | struct exception_table_entry |
78 | { | 78 | { |
79 | unsigned long insn, fixup; | 79 | int insn, fixup; |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static inline unsigned long extable_insn(const struct exception_table_entry *x) | ||
83 | { | ||
84 | return (unsigned long)&x->insn + x->insn; | ||
85 | } | ||
86 | |||
87 | static inline unsigned long extable_fixup(const struct exception_table_entry *x) | ||
88 | { | ||
89 | return (unsigned long)&x->fixup + x->fixup; | ||
90 | } | ||
91 | |||
92 | #define ARCH_HAS_SORT_EXTABLE | ||
93 | #define ARCH_HAS_SEARCH_EXTABLE | ||
94 | |||
82 | struct uaccess_ops { | 95 | struct uaccess_ops { |
83 | size_t (*copy_from_user)(size_t, const void __user *, void *); | 96 | size_t (*copy_from_user)(size_t, const void __user *, void *); |
84 | size_t (*copy_from_user_small)(size_t, const void __user *, void *); | 97 | size_t (*copy_from_user_small)(size_t, const void __user *, void *); |
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 6756e78f4808..4e64b5cd1558 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h | |||
@@ -277,7 +277,9 @@ | |||
277 | #define __NR_setns 339 | 277 | #define __NR_setns 339 |
278 | #define __NR_process_vm_readv 340 | 278 | #define __NR_process_vm_readv 340 |
279 | #define __NR_process_vm_writev 341 | 279 | #define __NR_process_vm_writev 341 |
280 | #define NR_syscalls 342 | 280 | #define __NR_s390_runtime_instr 342 |
281 | #define __NR_kcmp 343 | ||
282 | #define NR_syscalls 344 | ||
281 | 283 | ||
282 | /* | 284 | /* |
283 | * There are some system calls that are not present on 64 bit, some | 285 | * There are some system calls that are not present on 64 bit, some |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 9733b3f0eb6d..4da52fe31743 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -23,10 +23,11 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w | |||
23 | obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \ | 23 | obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \ |
24 | processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \ | 24 | processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \ |
25 | debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \ | 25 | debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \ |
26 | sysinfo.o jump_label.o lgr.o os_info.o | 26 | sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o |
27 | 27 | ||
28 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) | 28 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) |
29 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) | 29 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) |
30 | obj-y += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) | ||
30 | 31 | ||
31 | extra-y += head.o vmlinux.lds | 32 | extra-y += head.o vmlinux.lds |
32 | extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o) | 33 | extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o) |
@@ -48,12 +49,11 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | |||
48 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | 49 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
49 | obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o | 50 | obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o |
50 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 51 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
51 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o | ||
52 | 52 | ||
53 | # Kexec part | 53 | ifdef CONFIG_64BIT |
54 | S390_KEXEC_OBJS := machine_kexec.o crash.o | 54 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o |
55 | S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) | 55 | obj-y += runtime_instr.o cache.o |
56 | obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS) | 56 | endif |
57 | 57 | ||
58 | # vdso | 58 | # vdso |
59 | obj-$(CONFIG_64BIT) += vdso64/ | 59 | obj-$(CONFIG_64BIT) += vdso64/ |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 45ef1a7b08f9..fface87056eb 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
@@ -157,6 +157,8 @@ int main(void) | |||
157 | DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr)); | 157 | DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr)); |
158 | DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); | 158 | DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); |
159 | DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap)); | 159 | DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap)); |
160 | DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb)); | ||
161 | DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb)); | ||
160 | DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); | 162 | DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); |
161 | #endif /* CONFIG_32BIT */ | 163 | #endif /* CONFIG_32BIT */ |
162 | return 0; | 164 | return 0; |
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c new file mode 100644 index 000000000000..8df8d8a19c98 --- /dev/null +++ b/arch/s390/kernel/cache.c | |||
@@ -0,0 +1,385 @@ | |||
1 | /* | ||
2 | * Extract CPU cache information and expose them via sysfs. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2012 | ||
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/notifier.h> | ||
9 | #include <linux/seq_file.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/list.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/cpu.h> | ||
14 | #include <asm/facility.h> | ||
15 | |||
16 | struct cache { | ||
17 | unsigned long size; | ||
18 | unsigned int line_size; | ||
19 | unsigned int associativity; | ||
20 | unsigned int nr_sets; | ||
21 | unsigned int level : 3; | ||
22 | unsigned int type : 2; | ||
23 | unsigned int private : 1; | ||
24 | struct list_head list; | ||
25 | }; | ||
26 | |||
27 | struct cache_dir { | ||
28 | struct kobject *kobj; | ||
29 | struct cache_index_dir *index; | ||
30 | }; | ||
31 | |||
32 | struct cache_index_dir { | ||
33 | struct kobject kobj; | ||
34 | int cpu; | ||
35 | struct cache *cache; | ||
36 | struct cache_index_dir *next; | ||
37 | }; | ||
38 | |||
39 | enum { | ||
40 | CACHE_SCOPE_NOTEXISTS, | ||
41 | CACHE_SCOPE_PRIVATE, | ||
42 | CACHE_SCOPE_SHARED, | ||
43 | CACHE_SCOPE_RESERVED, | ||
44 | }; | ||
45 | |||
46 | enum { | ||
47 | CACHE_TYPE_SEPARATE, | ||
48 | CACHE_TYPE_DATA, | ||
49 | CACHE_TYPE_INSTRUCTION, | ||
50 | CACHE_TYPE_UNIFIED, | ||
51 | }; | ||
52 | |||
53 | enum { | ||
54 | EXTRACT_TOPOLOGY, | ||
55 | EXTRACT_LINE_SIZE, | ||
56 | EXTRACT_SIZE, | ||
57 | EXTRACT_ASSOCIATIVITY, | ||
58 | }; | ||
59 | |||
60 | enum { | ||
61 | CACHE_TI_UNIFIED = 0, | ||
62 | CACHE_TI_INSTRUCTION = 0, | ||
63 | CACHE_TI_DATA, | ||
64 | }; | ||
65 | |||
66 | struct cache_info { | ||
67 | unsigned char : 4; | ||
68 | unsigned char scope : 2; | ||
69 | unsigned char type : 2; | ||
70 | }; | ||
71 | |||
72 | #define CACHE_MAX_LEVEL 8 | ||
73 | |||
74 | union cache_topology { | ||
75 | struct cache_info ci[CACHE_MAX_LEVEL]; | ||
76 | unsigned long long raw; | ||
77 | }; | ||
78 | |||
79 | static const char * const cache_type_string[] = { | ||
80 | "Data", | ||
81 | "Instruction", | ||
82 | "Unified", | ||
83 | }; | ||
84 | |||
85 | static struct cache_dir *cache_dir_cpu[NR_CPUS]; | ||
86 | static LIST_HEAD(cache_list); | ||
87 | |||
88 | void show_cacheinfo(struct seq_file *m) | ||
89 | { | ||
90 | struct cache *cache; | ||
91 | int index = 0; | ||
92 | |||
93 | list_for_each_entry(cache, &cache_list, list) { | ||
94 | seq_printf(m, "cache%-11d: ", index); | ||
95 | seq_printf(m, "level=%d ", cache->level); | ||
96 | seq_printf(m, "type=%s ", cache_type_string[cache->type]); | ||
97 | seq_printf(m, "scope=%s ", cache->private ? "Private" : "Shared"); | ||
98 | seq_printf(m, "size=%luK ", cache->size >> 10); | ||
99 | seq_printf(m, "line_size=%u ", cache->line_size); | ||
100 | seq_printf(m, "associativity=%d", cache->associativity); | ||
101 | seq_puts(m, "\n"); | ||
102 | index++; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | static inline unsigned long ecag(int ai, int li, int ti) | ||
107 | { | ||
108 | unsigned long cmd, val; | ||
109 | |||
110 | cmd = ai << 4 | li << 1 | ti; | ||
111 | asm volatile(".insn rsy,0xeb000000004c,%0,0,0(%1)" /* ecag */ | ||
112 | : "=d" (val) : "a" (cmd)); | ||
113 | return val; | ||
114 | } | ||
115 | |||
116 | static int __init cache_add(int level, int private, int type) | ||
117 | { | ||
118 | struct cache *cache; | ||
119 | int ti; | ||
120 | |||
121 | cache = kzalloc(sizeof(*cache), GFP_KERNEL); | ||
122 | if (!cache) | ||
123 | return -ENOMEM; | ||
124 | ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED; | ||
125 | cache->size = ecag(EXTRACT_SIZE, level, ti); | ||
126 | cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti); | ||
127 | cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti); | ||
128 | cache->nr_sets = cache->size / cache->associativity; | ||
129 | cache->nr_sets /= cache->line_size; | ||
130 | cache->private = private; | ||
131 | cache->level = level + 1; | ||
132 | cache->type = type - 1; | ||
133 | list_add_tail(&cache->list, &cache_list); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static void __init cache_build_info(void) | ||
138 | { | ||
139 | struct cache *cache, *next; | ||
140 | union cache_topology ct; | ||
141 | int level, private, rc; | ||
142 | |||
143 | ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); | ||
144 | for (level = 0; level < CACHE_MAX_LEVEL; level++) { | ||
145 | switch (ct.ci[level].scope) { | ||
146 | case CACHE_SCOPE_NOTEXISTS: | ||
147 | case CACHE_SCOPE_RESERVED: | ||
148 | return; | ||
149 | case CACHE_SCOPE_SHARED: | ||
150 | private = 0; | ||
151 | break; | ||
152 | case CACHE_SCOPE_PRIVATE: | ||
153 | private = 1; | ||
154 | break; | ||
155 | } | ||
156 | if (ct.ci[level].type == CACHE_TYPE_SEPARATE) { | ||
157 | rc = cache_add(level, private, CACHE_TYPE_DATA); | ||
158 | rc |= cache_add(level, private, CACHE_TYPE_INSTRUCTION); | ||
159 | } else { | ||
160 | rc = cache_add(level, private, ct.ci[level].type); | ||
161 | } | ||
162 | if (rc) | ||
163 | goto error; | ||
164 | } | ||
165 | return; | ||
166 | error: | ||
167 | list_for_each_entry_safe(cache, next, &cache_list, list) { | ||
168 | list_del(&cache->list); | ||
169 | kfree(cache); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static struct cache_dir *__cpuinit cache_create_cache_dir(int cpu) | ||
174 | { | ||
175 | struct cache_dir *cache_dir; | ||
176 | struct kobject *kobj = NULL; | ||
177 | struct device *dev; | ||
178 | |||
179 | dev = get_cpu_device(cpu); | ||
180 | if (!dev) | ||
181 | goto out; | ||
182 | kobj = kobject_create_and_add("cache", &dev->kobj); | ||
183 | if (!kobj) | ||
184 | goto out; | ||
185 | cache_dir = kzalloc(sizeof(*cache_dir), GFP_KERNEL); | ||
186 | if (!cache_dir) | ||
187 | goto out; | ||
188 | cache_dir->kobj = kobj; | ||
189 | cache_dir_cpu[cpu] = cache_dir; | ||
190 | return cache_dir; | ||
191 | out: | ||
192 | kobject_put(kobj); | ||
193 | return NULL; | ||
194 | } | ||
195 | |||
196 | static struct cache_index_dir *kobj_to_cache_index_dir(struct kobject *kobj) | ||
197 | { | ||
198 | return container_of(kobj, struct cache_index_dir, kobj); | ||
199 | } | ||
200 | |||
201 | static void cache_index_release(struct kobject *kobj) | ||
202 | { | ||
203 | struct cache_index_dir *index; | ||
204 | |||
205 | index = kobj_to_cache_index_dir(kobj); | ||
206 | kfree(index); | ||
207 | } | ||
208 | |||
209 | static ssize_t cache_index_show(struct kobject *kobj, | ||
210 | struct attribute *attr, char *buf) | ||
211 | { | ||
212 | struct kobj_attribute *kobj_attr; | ||
213 | |||
214 | kobj_attr = container_of(attr, struct kobj_attribute, attr); | ||
215 | return kobj_attr->show(kobj, kobj_attr, buf); | ||
216 | } | ||
217 | |||
218 | #define DEFINE_CACHE_ATTR(_name, _format, _value) \ | ||
219 | static ssize_t cache_##_name##_show(struct kobject *kobj, \ | ||
220 | struct kobj_attribute *attr, \ | ||
221 | char *buf) \ | ||
222 | { \ | ||
223 | struct cache_index_dir *index; \ | ||
224 | \ | ||
225 | index = kobj_to_cache_index_dir(kobj); \ | ||
226 | return sprintf(buf, _format, _value); \ | ||
227 | } \ | ||
228 | static struct kobj_attribute cache_##_name##_attr = \ | ||
229 | __ATTR(_name, 0444, cache_##_name##_show, NULL); | ||
230 | |||
231 | DEFINE_CACHE_ATTR(size, "%luK\n", index->cache->size >> 10); | ||
232 | DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size); | ||
233 | DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets); | ||
234 | DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity); | ||
235 | DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type]); | ||
236 | DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level); | ||
237 | |||
238 | static ssize_t shared_cpu_map_func(struct kobject *kobj, int type, char *buf) | ||
239 | { | ||
240 | struct cache_index_dir *index; | ||
241 | int len; | ||
242 | |||
243 | index = kobj_to_cache_index_dir(kobj); | ||
244 | len = type ? | ||
245 | cpulist_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)) : | ||
246 | cpumask_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)); | ||
247 | len += sprintf(&buf[len], "\n"); | ||
248 | return len; | ||
249 | } | ||
250 | |||
251 | static ssize_t shared_cpu_map_show(struct kobject *kobj, | ||
252 | struct kobj_attribute *attr, char *buf) | ||
253 | { | ||
254 | return shared_cpu_map_func(kobj, 0, buf); | ||
255 | } | ||
256 | static struct kobj_attribute cache_shared_cpu_map_attr = | ||
257 | __ATTR(shared_cpu_map, 0444, shared_cpu_map_show, NULL); | ||
258 | |||
259 | static ssize_t shared_cpu_list_show(struct kobject *kobj, | ||
260 | struct kobj_attribute *attr, char *buf) | ||
261 | { | ||
262 | return shared_cpu_map_func(kobj, 1, buf); | ||
263 | } | ||
264 | static struct kobj_attribute cache_shared_cpu_list_attr = | ||
265 | __ATTR(shared_cpu_list, 0444, shared_cpu_list_show, NULL); | ||
266 | |||
267 | static struct attribute *cache_index_default_attrs[] = { | ||
268 | &cache_type_attr.attr, | ||
269 | &cache_size_attr.attr, | ||
270 | &cache_number_of_sets_attr.attr, | ||
271 | &cache_ways_of_associativity_attr.attr, | ||
272 | &cache_level_attr.attr, | ||
273 | &cache_coherency_line_size_attr.attr, | ||
274 | &cache_shared_cpu_map_attr.attr, | ||
275 | &cache_shared_cpu_list_attr.attr, | ||
276 | NULL, | ||
277 | }; | ||
278 | |||
279 | static const struct sysfs_ops cache_index_ops = { | ||
280 | .show = cache_index_show, | ||
281 | }; | ||
282 | |||
283 | static struct kobj_type cache_index_type = { | ||
284 | .sysfs_ops = &cache_index_ops, | ||
285 | .release = cache_index_release, | ||
286 | .default_attrs = cache_index_default_attrs, | ||
287 | }; | ||
288 | |||
289 | static int __cpuinit cache_create_index_dir(struct cache_dir *cache_dir, | ||
290 | struct cache *cache, int index, | ||
291 | int cpu) | ||
292 | { | ||
293 | struct cache_index_dir *index_dir; | ||
294 | int rc; | ||
295 | |||
296 | index_dir = kzalloc(sizeof(*index_dir), GFP_KERNEL); | ||
297 | if (!index_dir) | ||
298 | return -ENOMEM; | ||
299 | index_dir->cache = cache; | ||
300 | index_dir->cpu = cpu; | ||
301 | rc = kobject_init_and_add(&index_dir->kobj, &cache_index_type, | ||
302 | cache_dir->kobj, "index%d", index); | ||
303 | if (rc) | ||
304 | goto out; | ||
305 | index_dir->next = cache_dir->index; | ||
306 | cache_dir->index = index_dir; | ||
307 | return 0; | ||
308 | out: | ||
309 | kfree(index_dir); | ||
310 | return rc; | ||
311 | } | ||
312 | |||
313 | static int __cpuinit cache_add_cpu(int cpu) | ||
314 | { | ||
315 | struct cache_dir *cache_dir; | ||
316 | struct cache *cache; | ||
317 | int rc, index = 0; | ||
318 | |||
319 | if (list_empty(&cache_list)) | ||
320 | return 0; | ||
321 | cache_dir = cache_create_cache_dir(cpu); | ||
322 | if (!cache_dir) | ||
323 | return -ENOMEM; | ||
324 | list_for_each_entry(cache, &cache_list, list) { | ||
325 | if (!cache->private) | ||
326 | break; | ||
327 | rc = cache_create_index_dir(cache_dir, cache, index, cpu); | ||
328 | if (rc) | ||
329 | return rc; | ||
330 | index++; | ||
331 | } | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static void __cpuinit cache_remove_cpu(int cpu) | ||
336 | { | ||
337 | struct cache_index_dir *index, *next; | ||
338 | struct cache_dir *cache_dir; | ||
339 | |||
340 | cache_dir = cache_dir_cpu[cpu]; | ||
341 | if (!cache_dir) | ||
342 | return; | ||
343 | index = cache_dir->index; | ||
344 | while (index) { | ||
345 | next = index->next; | ||
346 | kobject_put(&index->kobj); | ||
347 | index = next; | ||
348 | } | ||
349 | kobject_put(cache_dir->kobj); | ||
350 | kfree(cache_dir); | ||
351 | cache_dir_cpu[cpu] = NULL; | ||
352 | } | ||
353 | |||
354 | static int __cpuinit cache_hotplug(struct notifier_block *nfb, | ||
355 | unsigned long action, void *hcpu) | ||
356 | { | ||
357 | int cpu = (long)hcpu; | ||
358 | int rc = 0; | ||
359 | |||
360 | switch (action & ~CPU_TASKS_FROZEN) { | ||
361 | case CPU_ONLINE: | ||
362 | rc = cache_add_cpu(cpu); | ||
363 | if (rc) | ||
364 | cache_remove_cpu(cpu); | ||
365 | break; | ||
366 | case CPU_DEAD: | ||
367 | cache_remove_cpu(cpu); | ||
368 | break; | ||
369 | } | ||
370 | return rc ? NOTIFY_BAD : NOTIFY_OK; | ||
371 | } | ||
372 | |||
373 | static int __init cache_init(void) | ||
374 | { | ||
375 | int cpu; | ||
376 | |||
377 | if (!test_facility(34)) | ||
378 | return 0; | ||
379 | cache_build_info(); | ||
380 | for_each_online_cpu(cpu) | ||
381 | cache_add_cpu(cpu); | ||
382 | hotcpu_notifier(cache_hotplug, 0); | ||
383 | return 0; | ||
384 | } | ||
385 | device_initcall(cache_init); | ||
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 2d82cfcbce5b..3afba804fe97 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
@@ -1646,3 +1646,16 @@ ENTRY(compat_sys_process_vm_writev_wrapper) | |||
1646 | llgf %r0,164(%r15) # unsigned long | 1646 | llgf %r0,164(%r15) # unsigned long |
1647 | stg %r0,160(%r15) | 1647 | stg %r0,160(%r15) |
1648 | jg compat_sys_process_vm_writev | 1648 | jg compat_sys_process_vm_writev |
1649 | |||
1650 | ENTRY(sys_s390_runtime_instr_wrapper) | ||
1651 | lgfr %r2,%r2 # int | ||
1652 | lgfr %r3,%r3 # int | ||
1653 | jg sys_s390_runtime_instr | ||
1654 | |||
1655 | ENTRY(sys_kcmp_wrapper) | ||
1656 | lgfr %r2,%r2 # pid_t | ||
1657 | lgfr %r3,%r3 # pid_t | ||
1658 | lgfr %r4,%r4 # int | ||
1659 | llgfr %r5,%r5 # unsigned long | ||
1660 | llgfr %r6,%r6 # unsigned long | ||
1661 | jg sys_kcmp | ||
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c deleted file mode 100644 index 3819153de8bd..000000000000 --- a/arch/s390/kernel/crash.c +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2005 | ||
3 | * | ||
4 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/threads.h> | ||
9 | #include <linux/kexec.h> | ||
10 | #include <linux/reboot.h> | ||
11 | |||
12 | void machine_crash_shutdown(struct pt_regs *regs) | ||
13 | { | ||
14 | } | ||
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index cc1172b26873..fb8d8781a011 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c | |||
@@ -13,8 +13,9 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/bootmem.h> | 14 | #include <linux/bootmem.h> |
15 | #include <linux/elf.h> | 15 | #include <linux/elf.h> |
16 | #include <asm/ipl.h> | ||
17 | #include <asm/os_info.h> | 16 | #include <asm/os_info.h> |
17 | #include <asm/elf.h> | ||
18 | #include <asm/ipl.h> | ||
18 | 19 | ||
19 | #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) | 20 | #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) |
20 | #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) | 21 | #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) |
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index 619c5d350726..cc84a24c023f 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c | |||
@@ -315,6 +315,11 @@ enum { | |||
315 | LONG_INSN_POPCNT, | 315 | LONG_INSN_POPCNT, |
316 | LONG_INSN_RISBHG, | 316 | LONG_INSN_RISBHG, |
317 | LONG_INSN_RISBLG, | 317 | LONG_INSN_RISBLG, |
318 | LONG_INSN_RINEXT, | ||
319 | LONG_INSN_RIEMIT, | ||
320 | LONG_INSN_TABORT, | ||
321 | LONG_INSN_TBEGIN, | ||
322 | LONG_INSN_TBEGINC, | ||
318 | }; | 323 | }; |
319 | 324 | ||
320 | static char *long_insn_name[] = { | 325 | static char *long_insn_name[] = { |
@@ -329,7 +334,12 @@ static char *long_insn_name[] = { | |||
329 | [LONG_INSN_LLGHRL] = "llghrl", | 334 | [LONG_INSN_LLGHRL] = "llghrl", |
330 | [LONG_INSN_POPCNT] = "popcnt", | 335 | [LONG_INSN_POPCNT] = "popcnt", |
331 | [LONG_INSN_RISBHG] = "risbhg", | 336 | [LONG_INSN_RISBHG] = "risbhg", |
332 | [LONG_INSN_RISBLG] = "risblk", | 337 | [LONG_INSN_RISBLG] = "risblg", |
338 | [LONG_INSN_RINEXT] = "rinext", | ||
339 | [LONG_INSN_RIEMIT] = "riemit", | ||
340 | [LONG_INSN_TABORT] = "tabort", | ||
341 | [LONG_INSN_TBEGIN] = "tbegin", | ||
342 | [LONG_INSN_TBEGINC] = "tbeginc", | ||
333 | }; | 343 | }; |
334 | 344 | ||
335 | static struct insn opcode[] = { | 345 | static struct insn opcode[] = { |
@@ -582,6 +592,17 @@ static struct insn opcode_a7[] = { | |||
582 | { "", 0, INSTR_INVALID } | 592 | { "", 0, INSTR_INVALID } |
583 | }; | 593 | }; |
584 | 594 | ||
595 | static struct insn opcode_aa[] = { | ||
596 | #ifdef CONFIG_64BIT | ||
597 | { { 0, LONG_INSN_RINEXT }, 0x00, INSTR_RI_RI }, | ||
598 | { "rion", 0x01, INSTR_RI_RI }, | ||
599 | { "tric", 0x02, INSTR_RI_RI }, | ||
600 | { "rioff", 0x03, INSTR_RI_RI }, | ||
601 | { { 0, LONG_INSN_RIEMIT }, 0x04, INSTR_RI_RI }, | ||
602 | #endif | ||
603 | { "", 0, INSTR_INVALID } | ||
604 | }; | ||
605 | |||
585 | static struct insn opcode_b2[] = { | 606 | static struct insn opcode_b2[] = { |
586 | #ifdef CONFIG_64BIT | 607 | #ifdef CONFIG_64BIT |
587 | { "sske", 0x2b, INSTR_RRF_M0RR }, | 608 | { "sske", 0x2b, INSTR_RRF_M0RR }, |
@@ -594,6 +615,9 @@ static struct insn opcode_b2[] = { | |||
594 | { "lpswe", 0xb2, INSTR_S_RD }, | 615 | { "lpswe", 0xb2, INSTR_S_RD }, |
595 | { "srnmt", 0xb9, INSTR_S_RD }, | 616 | { "srnmt", 0xb9, INSTR_S_RD }, |
596 | { "lfas", 0xbd, INSTR_S_RD }, | 617 | { "lfas", 0xbd, INSTR_S_RD }, |
618 | { "etndg", 0xec, INSTR_RRE_R0 }, | ||
619 | { { 0, LONG_INSN_TABORT }, 0xfc, INSTR_S_RD }, | ||
620 | { "tend", 0xf8, INSTR_S_RD }, | ||
597 | #endif | 621 | #endif |
598 | { "stidp", 0x02, INSTR_S_RD }, | 622 | { "stidp", 0x02, INSTR_S_RD }, |
599 | { "sck", 0x04, INSTR_S_RD }, | 623 | { "sck", 0x04, INSTR_S_RD }, |
@@ -1150,6 +1174,7 @@ static struct insn opcode_e3[] = { | |||
1150 | { "stfh", 0xcb, INSTR_RXY_RRRD }, | 1174 | { "stfh", 0xcb, INSTR_RXY_RRRD }, |
1151 | { "chf", 0xcd, INSTR_RXY_RRRD }, | 1175 | { "chf", 0xcd, INSTR_RXY_RRRD }, |
1152 | { "clhf", 0xcf, INSTR_RXY_RRRD }, | 1176 | { "clhf", 0xcf, INSTR_RXY_RRRD }, |
1177 | { "ntstg", 0x25, INSTR_RXY_RRRD }, | ||
1153 | #endif | 1178 | #endif |
1154 | { "lrv", 0x1e, INSTR_RXY_RRRD }, | 1179 | { "lrv", 0x1e, INSTR_RXY_RRRD }, |
1155 | { "lrvh", 0x1f, INSTR_RXY_RRRD }, | 1180 | { "lrvh", 0x1f, INSTR_RXY_RRRD }, |
@@ -1173,6 +1198,8 @@ static struct insn opcode_e5[] = { | |||
1173 | { "mvhhi", 0x44, INSTR_SIL_RDI }, | 1198 | { "mvhhi", 0x44, INSTR_SIL_RDI }, |
1174 | { "mvhi", 0x4c, INSTR_SIL_RDI }, | 1199 | { "mvhi", 0x4c, INSTR_SIL_RDI }, |
1175 | { "mvghi", 0x48, INSTR_SIL_RDI }, | 1200 | { "mvghi", 0x48, INSTR_SIL_RDI }, |
1201 | { { 0, LONG_INSN_TBEGIN }, 0x60, INSTR_SIL_RDU }, | ||
1202 | { { 0, LONG_INSN_TBEGINC }, 0x61, INSTR_SIL_RDU }, | ||
1176 | #endif | 1203 | #endif |
1177 | { "lasp", 0x00, INSTR_SSE_RDRD }, | 1204 | { "lasp", 0x00, INSTR_SSE_RDRD }, |
1178 | { "tprot", 0x01, INSTR_SSE_RDRD }, | 1205 | { "tprot", 0x01, INSTR_SSE_RDRD }, |
@@ -1210,6 +1237,9 @@ static struct insn opcode_eb[] = { | |||
1210 | { "cliy", 0x55, INSTR_SIY_URD }, | 1237 | { "cliy", 0x55, INSTR_SIY_URD }, |
1211 | { "oiy", 0x56, INSTR_SIY_URD }, | 1238 | { "oiy", 0x56, INSTR_SIY_URD }, |
1212 | { "xiy", 0x57, INSTR_SIY_URD }, | 1239 | { "xiy", 0x57, INSTR_SIY_URD }, |
1240 | { "lric", 0x60, INSTR_RSY_RDRM }, | ||
1241 | { "stric", 0x61, INSTR_RSY_RDRM }, | ||
1242 | { "mric", 0x62, INSTR_RSY_RDRM }, | ||
1213 | { "icmh", 0x80, INSTR_RSE_RURD }, | 1243 | { "icmh", 0x80, INSTR_RSE_RURD }, |
1214 | { "icmh", 0x80, INSTR_RSY_RURD }, | 1244 | { "icmh", 0x80, INSTR_RSY_RURD }, |
1215 | { "icmy", 0x81, INSTR_RSY_RURD }, | 1245 | { "icmy", 0x81, INSTR_RSY_RURD }, |
@@ -1408,6 +1438,9 @@ static struct insn *find_insn(unsigned char *code) | |||
1408 | case 0xa7: | 1438 | case 0xa7: |
1409 | table = opcode_a7; | 1439 | table = opcode_a7; |
1410 | break; | 1440 | break; |
1441 | case 0xaa: | ||
1442 | table = opcode_aa; | ||
1443 | break; | ||
1411 | case 0xb2: | 1444 | case 0xb2: |
1412 | table = opcode_b2; | 1445 | table = opcode_b2; |
1413 | break; | 1446 | break; |
@@ -1601,3 +1634,26 @@ void show_code(struct pt_regs *regs) | |||
1601 | } | 1634 | } |
1602 | printk("\n"); | 1635 | printk("\n"); |
1603 | } | 1636 | } |
1637 | |||
1638 | void print_fn_code(unsigned char *code, unsigned long len) | ||
1639 | { | ||
1640 | char buffer[64], *ptr; | ||
1641 | int opsize, i; | ||
1642 | |||
1643 | while (len) { | ||
1644 | ptr = buffer; | ||
1645 | opsize = insn_length(*code); | ||
1646 | ptr += sprintf(ptr, "%p: ", code); | ||
1647 | for (i = 0; i < opsize; i++) | ||
1648 | ptr += sprintf(ptr, "%02x", code[i]); | ||
1649 | *ptr++ = '\t'; | ||
1650 | if (i < 4) | ||
1651 | *ptr++ = '\t'; | ||
1652 | ptr += print_insn(ptr, code, (unsigned long) code); | ||
1653 | *ptr++ = '\n'; | ||
1654 | *ptr++ = 0; | ||
1655 | printk(buffer); | ||
1656 | code += opsize; | ||
1657 | len -= opsize; | ||
1658 | } | ||
1659 | } | ||
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 83c3271c442b..7f4717675c19 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -215,36 +215,54 @@ static noinline __init void init_kernel_storage_key(void) | |||
215 | PAGE_DEFAULT_KEY, 0); | 215 | PAGE_DEFAULT_KEY, 0); |
216 | } | 216 | } |
217 | 217 | ||
218 | static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); | 218 | static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE); |
219 | 219 | ||
220 | static noinline __init void detect_machine_type(void) | 220 | static noinline __init void detect_machine_type(void) |
221 | { | 221 | { |
222 | struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page; | ||
223 | |||
222 | /* Check current-configuration-level */ | 224 | /* Check current-configuration-level */ |
223 | if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) { | 225 | if (stsi(NULL, 0, 0, 0) <= 2) { |
224 | S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR; | 226 | S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR; |
225 | return; | 227 | return; |
226 | } | 228 | } |
227 | /* Get virtual-machine cpu information. */ | 229 | /* Get virtual-machine cpu information. */ |
228 | if (stsi(&vmms, 3, 2, 2) == -ENOSYS || !vmms.count) | 230 | if (stsi(vmms, 3, 2, 2) || !vmms->count) |
229 | return; | 231 | return; |
230 | 232 | ||
231 | /* Running under KVM? If not we assume z/VM */ | 233 | /* Running under KVM? If not we assume z/VM */ |
232 | if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3)) | 234 | if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3)) |
233 | S390_lowcore.machine_flags |= MACHINE_FLAG_KVM; | 235 | S390_lowcore.machine_flags |= MACHINE_FLAG_KVM; |
234 | else | 236 | else |
235 | S390_lowcore.machine_flags |= MACHINE_FLAG_VM; | 237 | S390_lowcore.machine_flags |= MACHINE_FLAG_VM; |
236 | } | 238 | } |
237 | 239 | ||
240 | static __init void setup_topology(void) | ||
241 | { | ||
242 | #ifdef CONFIG_64BIT | ||
243 | int max_mnest; | ||
244 | |||
245 | if (!test_facility(11)) | ||
246 | return; | ||
247 | S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; | ||
248 | for (max_mnest = 6; max_mnest > 1; max_mnest--) { | ||
249 | if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0) | ||
250 | break; | ||
251 | } | ||
252 | topology_max_mnest = max_mnest; | ||
253 | #endif | ||
254 | } | ||
255 | |||
238 | static void early_pgm_check_handler(void) | 256 | static void early_pgm_check_handler(void) |
239 | { | 257 | { |
240 | unsigned long addr; | ||
241 | const struct exception_table_entry *fixup; | 258 | const struct exception_table_entry *fixup; |
259 | unsigned long addr; | ||
242 | 260 | ||
243 | addr = S390_lowcore.program_old_psw.addr; | 261 | addr = S390_lowcore.program_old_psw.addr; |
244 | fixup = search_exception_tables(addr & PSW_ADDR_INSN); | 262 | fixup = search_exception_tables(addr & PSW_ADDR_INSN); |
245 | if (!fixup) | 263 | if (!fixup) |
246 | disabled_wait(0); | 264 | disabled_wait(0); |
247 | S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE; | 265 | S390_lowcore.program_old_psw.addr = extable_fixup(fixup)|PSW_ADDR_AMODE; |
248 | } | 266 | } |
249 | 267 | ||
250 | static noinline __init void setup_lowcore_early(void) | 268 | static noinline __init void setup_lowcore_early(void) |
@@ -267,12 +285,10 @@ static noinline __init void setup_facility_list(void) | |||
267 | 285 | ||
268 | static noinline __init void setup_hpage(void) | 286 | static noinline __init void setup_hpage(void) |
269 | { | 287 | { |
270 | #ifndef CONFIG_DEBUG_PAGEALLOC | ||
271 | if (!test_facility(2) || !test_facility(8)) | 288 | if (!test_facility(2) || !test_facility(8)) |
272 | return; | 289 | return; |
273 | S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; | 290 | S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; |
274 | __ctl_set_bit(0, 23); | 291 | __ctl_set_bit(0, 23); |
275 | #endif | ||
276 | } | 292 | } |
277 | 293 | ||
278 | static __init void detect_mvpg(void) | 294 | static __init void detect_mvpg(void) |
@@ -366,12 +382,12 @@ static __init void detect_machine_facilities(void) | |||
366 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; | 382 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; |
367 | if (test_facility(8)) | 383 | if (test_facility(8)) |
368 | S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; | 384 | S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; |
369 | if (test_facility(11)) | ||
370 | S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; | ||
371 | if (test_facility(27)) | 385 | if (test_facility(27)) |
372 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; | 386 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; |
373 | if (test_facility(40)) | 387 | if (test_facility(40)) |
374 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; | 388 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; |
389 | if (test_facility(50) && test_facility(73)) | ||
390 | S390_lowcore.machine_flags |= MACHINE_FLAG_TE; | ||
375 | #endif | 391 | #endif |
376 | } | 392 | } |
377 | 393 | ||
@@ -441,7 +457,6 @@ static void __init setup_boot_command_line(void) | |||
441 | append_to_cmdline(append_ipl_scpdata); | 457 | append_to_cmdline(append_ipl_scpdata); |
442 | } | 458 | } |
443 | 459 | ||
444 | |||
445 | /* | 460 | /* |
446 | * Save ipl parameters, clear bss memory, initialize storage keys | 461 | * Save ipl parameters, clear bss memory, initialize storage keys |
447 | * and create a kernel NSS at startup if the SAVESYS= parm is defined | 462 | * and create a kernel NSS at startup if the SAVESYS= parm is defined |
@@ -468,6 +483,7 @@ void __init startup_init(void) | |||
468 | detect_diag44(); | 483 | detect_diag44(); |
469 | detect_machine_facilities(); | 484 | detect_machine_facilities(); |
470 | setup_hpage(); | 485 | setup_hpage(); |
486 | setup_topology(); | ||
471 | sclp_facilities_detect(); | 487 | sclp_facilities_detect(); |
472 | detect_memory_layout(memory_chunk); | 488 | detect_memory_layout(memory_chunk); |
473 | #ifdef CONFIG_DYNAMIC_FTRACE | 489 | #ifdef CONFIG_DYNAMIC_FTRACE |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 349b7eeb348a..7549985402f7 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
13 | #include <asm/processor.h> | ||
13 | #include <asm/cache.h> | 14 | #include <asm/cache.h> |
14 | #include <asm/errno.h> | 15 | #include <asm/errno.h> |
15 | #include <asm/ptrace.h> | 16 | #include <asm/ptrace.h> |
@@ -412,6 +413,11 @@ ENTRY(pgm_check_handler) | |||
412 | 1: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER | 413 | 1: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER |
413 | LAST_BREAK %r14 | 414 | LAST_BREAK %r14 |
414 | lg %r15,__LC_KERNEL_STACK | 415 | lg %r15,__LC_KERNEL_STACK |
416 | lg %r14,__TI_task(%r12) | ||
417 | lghi %r13,__LC_PGM_TDB | ||
418 | tm __LC_PGM_ILC+2,0x02 # check for transaction abort | ||
419 | jz 2f | ||
420 | mvc __THREAD_trap_tdb(256,%r14),0(%r13) | ||
415 | 2: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 421 | 2: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
416 | la %r11,STACK_FRAME_OVERHEAD(%r15) | 422 | la %r11,STACK_FRAME_OVERHEAD(%r15) |
417 | stmg %r0,%r7,__PT_R0(%r11) | 423 | stmg %r0,%r7,__PT_R0(%r11) |
@@ -422,13 +428,12 @@ ENTRY(pgm_check_handler) | |||
422 | stg %r10,__PT_ARGS(%r11) | 428 | stg %r10,__PT_ARGS(%r11) |
423 | tm __LC_PGM_ILC+3,0x80 # check for per exception | 429 | tm __LC_PGM_ILC+3,0x80 # check for per exception |
424 | jz 0f | 430 | jz 0f |
425 | lg %r1,__TI_task(%r12) | ||
426 | tmhh %r8,0x0001 # kernel per event ? | 431 | tmhh %r8,0x0001 # kernel per event ? |
427 | jz pgm_kprobe | 432 | jz pgm_kprobe |
428 | oi __TI_flags+7(%r12),_TIF_PER_TRAP | 433 | oi __TI_flags+7(%r12),_TIF_PER_TRAP |
429 | mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS | 434 | mvc __THREAD_per_address(8,%r14),__LC_PER_ADDRESS |
430 | mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE | 435 | mvc __THREAD_per_cause(2,%r14),__LC_PER_CAUSE |
431 | mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID | 436 | mvc __THREAD_per_paid(1,%r14),__LC_PER_PAID |
432 | 0: REENABLE_IRQS | 437 | 0: REENABLE_IRQS |
433 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 438 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
434 | larl %r1,pgm_check_table | 439 | larl %r1,pgm_check_table |
@@ -1004,9 +1009,7 @@ sie_fault: | |||
1004 | .Lhost_id: | 1009 | .Lhost_id: |
1005 | .quad 0 | 1010 | .quad 0 |
1006 | 1011 | ||
1007 | .section __ex_table,"a" | 1012 | EX_TABLE(sie_loop,sie_fault) |
1008 | .quad sie_loop,sie_fault | ||
1009 | .previous | ||
1010 | #endif | 1013 | #endif |
1011 | 1014 | ||
1012 | .section .rodata, "a" | 1015 | .section .rodata, "a" |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index dd7630d8aab7..6cdc55b26d68 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -30,33 +30,35 @@ struct irq_class { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | static const struct irq_class intrclass_names[] = { | 32 | static const struct irq_class intrclass_names[] = { |
33 | {.name = "EXT" }, | 33 | [EXTERNAL_INTERRUPT] = {.name = "EXT"}, |
34 | {.name = "I/O" }, | 34 | [IO_INTERRUPT] = {.name = "I/O"}, |
35 | {.name = "CLK", .desc = "[EXT] Clock Comparator" }, | 35 | [EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, |
36 | {.name = "EXC", .desc = "[EXT] External Call" }, | 36 | [EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, |
37 | {.name = "EMS", .desc = "[EXT] Emergency Signal" }, | 37 | [EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, |
38 | {.name = "TMR", .desc = "[EXT] CPU Timer" }, | 38 | [EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, |
39 | {.name = "TAL", .desc = "[EXT] Timing Alert" }, | 39 | [EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, |
40 | {.name = "PFL", .desc = "[EXT] Pseudo Page Fault" }, | 40 | [EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, |
41 | {.name = "DSD", .desc = "[EXT] DASD Diag" }, | 41 | [EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, |
42 | {.name = "VRT", .desc = "[EXT] Virtio" }, | 42 | [EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, |
43 | {.name = "SCP", .desc = "[EXT] Service Call" }, | 43 | [EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, |
44 | {.name = "IUC", .desc = "[EXT] IUCV" }, | 44 | [EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, |
45 | {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling" }, | 45 | [EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, |
46 | {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter" }, | 46 | [EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, |
47 | {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" }, | 47 | [EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, |
48 | {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" }, | 48 | [IOINT_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, |
49 | {.name = "DAS", .desc = "[I/O] DASD" }, | 49 | [IOINT_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, |
50 | {.name = "C15", .desc = "[I/O] 3215" }, | 50 | [IOINT_DAS] = {.name = "DAS", .desc = "[I/O] DASD"}, |
51 | {.name = "C70", .desc = "[I/O] 3270" }, | 51 | [IOINT_C15] = {.name = "C15", .desc = "[I/O] 3215"}, |
52 | {.name = "TAP", .desc = "[I/O] Tape" }, | 52 | [IOINT_C70] = {.name = "C70", .desc = "[I/O] 3270"}, |
53 | {.name = "VMR", .desc = "[I/O] Unit Record Devices" }, | 53 | [IOINT_TAP] = {.name = "TAP", .desc = "[I/O] Tape"}, |
54 | {.name = "LCS", .desc = "[I/O] LCS" }, | 54 | [IOINT_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, |
55 | {.name = "CLW", .desc = "[I/O] CLAW" }, | 55 | [IOINT_LCS] = {.name = "LCS", .desc = "[I/O] LCS"}, |
56 | {.name = "CTC", .desc = "[I/O] CTC" }, | 56 | [IOINT_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"}, |
57 | {.name = "APB", .desc = "[I/O] AP Bus" }, | 57 | [IOINT_CTC] = {.name = "CTC", .desc = "[I/O] CTC"}, |
58 | {.name = "CSC", .desc = "[I/O] CHSC Subchannel" }, | 58 | [IOINT_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, |
59 | {.name = "NMI", .desc = "[NMI] Machine Check" }, | 59 | [IOINT_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, |
60 | [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, | ||
61 | [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, | ||
60 | }; | 62 | }; |
61 | 63 | ||
62 | /* | 64 | /* |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 8aa634f5944b..d1c7214e157c 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -547,7 +547,7 @@ static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) | |||
547 | */ | 547 | */ |
548 | entry = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 548 | entry = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
549 | if (entry) { | 549 | if (entry) { |
550 | regs->psw.addr = entry->fixup | PSW_ADDR_AMODE; | 550 | regs->psw.addr = extable_fixup(entry) | PSW_ADDR_AMODE; |
551 | return 1; | 551 | return 1; |
552 | } | 552 | } |
553 | 553 | ||
diff --git a/arch/s390/kernel/lgr.c b/arch/s390/kernel/lgr.c index eca94e74d19a..6ea6d69339b5 100644 --- a/arch/s390/kernel/lgr.c +++ b/arch/s390/kernel/lgr.c | |||
@@ -51,16 +51,6 @@ static struct lgr_info lgr_info_cur; | |||
51 | static struct debug_info *lgr_dbf; | 51 | static struct debug_info *lgr_dbf; |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Return number of valid stsi levels | ||
55 | */ | ||
56 | static inline int stsi_0(void) | ||
57 | { | ||
58 | int rc = stsi(NULL, 0, 0, 0); | ||
59 | |||
60 | return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Copy buffer and then convert it to ASCII | 54 | * Copy buffer and then convert it to ASCII |
65 | */ | 55 | */ |
66 | static void cpascii(char *dst, char *src, int size) | 56 | static void cpascii(char *dst, char *src, int size) |
@@ -76,7 +66,7 @@ static void lgr_stsi_1_1_1(struct lgr_info *lgr_info) | |||
76 | { | 66 | { |
77 | struct sysinfo_1_1_1 *si = (void *) lgr_page; | 67 | struct sysinfo_1_1_1 *si = (void *) lgr_page; |
78 | 68 | ||
79 | if (stsi(si, 1, 1, 1) == -ENOSYS) | 69 | if (stsi(si, 1, 1, 1)) |
80 | return; | 70 | return; |
81 | cpascii(lgr_info->manufacturer, si->manufacturer, | 71 | cpascii(lgr_info->manufacturer, si->manufacturer, |
82 | sizeof(si->manufacturer)); | 72 | sizeof(si->manufacturer)); |
@@ -93,7 +83,7 @@ static void lgr_stsi_2_2_2(struct lgr_info *lgr_info) | |||
93 | { | 83 | { |
94 | struct sysinfo_2_2_2 *si = (void *) lgr_page; | 84 | struct sysinfo_2_2_2 *si = (void *) lgr_page; |
95 | 85 | ||
96 | if (stsi(si, 2, 2, 2) == -ENOSYS) | 86 | if (stsi(si, 2, 2, 2)) |
97 | return; | 87 | return; |
98 | cpascii(lgr_info->name, si->name, sizeof(si->name)); | 88 | cpascii(lgr_info->name, si->name, sizeof(si->name)); |
99 | memcpy(&lgr_info->lpar_number, &si->lpar_number, | 89 | memcpy(&lgr_info->lpar_number, &si->lpar_number, |
@@ -108,7 +98,7 @@ static void lgr_stsi_3_2_2(struct lgr_info *lgr_info) | |||
108 | struct sysinfo_3_2_2 *si = (void *) lgr_page; | 98 | struct sysinfo_3_2_2 *si = (void *) lgr_page; |
109 | int i; | 99 | int i; |
110 | 100 | ||
111 | if (stsi(si, 3, 2, 2) == -ENOSYS) | 101 | if (stsi(si, 3, 2, 2)) |
112 | return; | 102 | return; |
113 | for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) { | 103 | for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) { |
114 | cpascii(lgr_info->vm[i].name, si->vm[i].name, | 104 | cpascii(lgr_info->vm[i].name, si->vm[i].name, |
@@ -124,16 +114,17 @@ static void lgr_stsi_3_2_2(struct lgr_info *lgr_info) | |||
124 | */ | 114 | */ |
125 | static void lgr_info_get(struct lgr_info *lgr_info) | 115 | static void lgr_info_get(struct lgr_info *lgr_info) |
126 | { | 116 | { |
117 | int level; | ||
118 | |||
127 | memset(lgr_info, 0, sizeof(*lgr_info)); | 119 | memset(lgr_info, 0, sizeof(*lgr_info)); |
128 | stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list)); | 120 | stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list)); |
129 | lgr_info->level = stsi_0(); | 121 | level = stsi(NULL, 0, 0, 0); |
130 | if (lgr_info->level == -ENOSYS) | 122 | lgr_info->level = level; |
131 | return; | 123 | if (level >= 1) |
132 | if (lgr_info->level >= 1) | ||
133 | lgr_stsi_1_1_1(lgr_info); | 124 | lgr_stsi_1_1_1(lgr_info); |
134 | if (lgr_info->level >= 2) | 125 | if (level >= 2) |
135 | lgr_stsi_2_2_2(lgr_info); | 126 | lgr_stsi_2_2_2(lgr_info); |
136 | if (lgr_info->level >= 3) | 127 | if (level >= 3) |
137 | lgr_stsi_3_2_2(lgr_info); | 128 | lgr_stsi_3_2_2(lgr_info); |
138 | } | 129 | } |
139 | 130 | ||
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 493304bdf1c7..b3de27700016 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/reset.h> | 21 | #include <asm/reset.h> |
22 | #include <asm/ipl.h> | 22 | #include <asm/ipl.h> |
23 | #include <asm/diag.h> | 23 | #include <asm/diag.h> |
24 | #include <asm/elf.h> | ||
24 | #include <asm/asm-offsets.h> | 25 | #include <asm/asm-offsets.h> |
25 | #include <asm/os_info.h> | 26 | #include <asm/os_info.h> |
26 | 27 | ||
@@ -31,8 +32,6 @@ extern const unsigned long long relocate_kernel_len; | |||
31 | 32 | ||
32 | #ifdef CONFIG_CRASH_DUMP | 33 | #ifdef CONFIG_CRASH_DUMP |
33 | 34 | ||
34 | void *fill_cpu_elf_notes(void *ptr, struct save_area *sa); | ||
35 | |||
36 | /* | 35 | /* |
37 | * Create ELF notes for one CPU | 36 | * Create ELF notes for one CPU |
38 | */ | 37 | */ |
@@ -159,7 +158,7 @@ int machine_kexec_prepare(struct kimage *image) | |||
159 | 158 | ||
160 | /* Can't replace kernel image since it is read-only. */ | 159 | /* Can't replace kernel image since it is read-only. */ |
161 | if (ipl_flags & IPL_NSS_VALID) | 160 | if (ipl_flags & IPL_NSS_VALID) |
162 | return -ENOSYS; | 161 | return -EOPNOTSUPP; |
163 | 162 | ||
164 | if (image->type == KEXEC_TYPE_CRASH) | 163 | if (image->type == KEXEC_TYPE_CRASH) |
165 | return machine_kexec_prepare_kdump(); | 164 | return machine_kexec_prepare_kdump(); |
@@ -191,6 +190,10 @@ void machine_shutdown(void) | |||
191 | { | 190 | { |
192 | } | 191 | } |
193 | 192 | ||
193 | void machine_crash_shutdown(struct pt_regs *regs) | ||
194 | { | ||
195 | } | ||
196 | |||
194 | /* | 197 | /* |
195 | * Do normal kexec | 198 | * Do normal kexec |
196 | */ | 199 | */ |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 733175373a4c..5024be27df44 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -26,10 +26,12 @@ | |||
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
28 | #include <asm/vtimer.h> | 28 | #include <asm/vtimer.h> |
29 | #include <asm/exec.h> | ||
29 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
30 | #include <asm/nmi.h> | 31 | #include <asm/nmi.h> |
31 | #include <asm/smp.h> | 32 | #include <asm/smp.h> |
32 | #include <asm/switch_to.h> | 33 | #include <asm/switch_to.h> |
34 | #include <asm/runtime_instr.h> | ||
33 | #include "entry.h" | 35 | #include "entry.h" |
34 | 36 | ||
35 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); | 37 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); |
@@ -132,6 +134,7 @@ EXPORT_SYMBOL(kernel_thread); | |||
132 | */ | 134 | */ |
133 | void exit_thread(void) | 135 | void exit_thread(void) |
134 | { | 136 | { |
137 | exit_thread_runtime_instr(); | ||
135 | } | 138 | } |
136 | 139 | ||
137 | void flush_thread(void) | 140 | void flush_thread(void) |
@@ -170,6 +173,11 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
170 | /* Save access registers to new thread structure. */ | 173 | /* Save access registers to new thread structure. */ |
171 | save_access_regs(&p->thread.acrs[0]); | 174 | save_access_regs(&p->thread.acrs[0]); |
172 | 175 | ||
176 | /* Don't copy runtime instrumentation info */ | ||
177 | p->thread.ri_cb = NULL; | ||
178 | p->thread.ri_signum = 0; | ||
179 | frame->childregs.psw.mask &= ~PSW_MASK_RI; | ||
180 | |||
173 | #ifndef CONFIG_64BIT | 181 | #ifndef CONFIG_64BIT |
174 | /* | 182 | /* |
175 | * save fprs to current->thread.fp_regs to merge them with | 183 | * save fprs to current->thread.fp_regs to merge them with |
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 572d4c9cb33b..753c41d0ffd3 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c | |||
@@ -39,9 +39,9 @@ void __cpuinit cpu_init(void) | |||
39 | */ | 39 | */ |
40 | static int show_cpuinfo(struct seq_file *m, void *v) | 40 | static int show_cpuinfo(struct seq_file *m, void *v) |
41 | { | 41 | { |
42 | static const char *hwcap_str[10] = { | 42 | static const char *hwcap_str[] = { |
43 | "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", | 43 | "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", |
44 | "edat", "etf3eh", "highgprs" | 44 | "edat", "etf3eh", "highgprs", "te" |
45 | }; | 45 | }; |
46 | unsigned long n = (unsigned long) v - 1; | 46 | unsigned long n = (unsigned long) v - 1; |
47 | int i; | 47 | int i; |
@@ -54,10 +54,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
54 | num_online_cpus(), loops_per_jiffy/(500000/HZ), | 54 | num_online_cpus(), loops_per_jiffy/(500000/HZ), |
55 | (loops_per_jiffy/(5000/HZ))%100); | 55 | (loops_per_jiffy/(5000/HZ))%100); |
56 | seq_puts(m, "features\t: "); | 56 | seq_puts(m, "features\t: "); |
57 | for (i = 0; i < 10; i++) | 57 | for (i = 0; i < ARRAY_SIZE(hwcap_str); i++) |
58 | if (hwcap_str[i] && (elf_hwcap & (1UL << i))) | 58 | if (hwcap_str[i] && (elf_hwcap & (1UL << i))) |
59 | seq_printf(m, "%s ", hwcap_str[i]); | 59 | seq_printf(m, "%s ", hwcap_str[i]); |
60 | seq_puts(m, "\n"); | 60 | seq_puts(m, "\n"); |
61 | show_cacheinfo(m); | ||
61 | } | 62 | } |
62 | get_online_cpus(); | 63 | get_online_cpus(); |
63 | if (cpu_online(n)) { | 64 | if (cpu_online(n)) { |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index e4be113fbac6..a314c57f4e94 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -42,6 +42,7 @@ enum s390_regset { | |||
42 | REGSET_GENERAL, | 42 | REGSET_GENERAL, |
43 | REGSET_FP, | 43 | REGSET_FP, |
44 | REGSET_LAST_BREAK, | 44 | REGSET_LAST_BREAK, |
45 | REGSET_TDB, | ||
45 | REGSET_SYSTEM_CALL, | 46 | REGSET_SYSTEM_CALL, |
46 | REGSET_GENERAL_EXTENDED, | 47 | REGSET_GENERAL_EXTENDED, |
47 | }; | 48 | }; |
@@ -52,6 +53,22 @@ void update_per_regs(struct task_struct *task) | |||
52 | struct thread_struct *thread = &task->thread; | 53 | struct thread_struct *thread = &task->thread; |
53 | struct per_regs old, new; | 54 | struct per_regs old, new; |
54 | 55 | ||
56 | #ifdef CONFIG_64BIT | ||
57 | /* Take care of the enable/disable of transactional execution. */ | ||
58 | if (MACHINE_HAS_TE) { | ||
59 | unsigned long cr0, cr0_new; | ||
60 | |||
61 | __ctl_store(cr0, 0, 0); | ||
62 | /* set or clear transaction execution bits 8 and 9. */ | ||
63 | if (task->thread.per_flags & PER_FLAG_NO_TE) | ||
64 | cr0_new = cr0 & ~(3UL << 54); | ||
65 | else | ||
66 | cr0_new = cr0 | (3UL << 54); | ||
67 | /* Only load control register 0 if necessary. */ | ||
68 | if (cr0 != cr0_new) | ||
69 | __ctl_load(cr0_new, 0, 0); | ||
70 | } | ||
71 | #endif | ||
55 | /* Copy user specified PER registers */ | 72 | /* Copy user specified PER registers */ |
56 | new.control = thread->per_user.control; | 73 | new.control = thread->per_user.control; |
57 | new.start = thread->per_user.start; | 74 | new.start = thread->per_user.start; |
@@ -60,6 +77,10 @@ void update_per_regs(struct task_struct *task) | |||
60 | /* merge TIF_SINGLE_STEP into user specified PER registers. */ | 77 | /* merge TIF_SINGLE_STEP into user specified PER registers. */ |
61 | if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) { | 78 | if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) { |
62 | new.control |= PER_EVENT_IFETCH; | 79 | new.control |= PER_EVENT_IFETCH; |
80 | #ifdef CONFIG_64BIT | ||
81 | new.control |= PER_CONTROL_SUSPENSION; | ||
82 | new.control |= PER_EVENT_TRANSACTION_END; | ||
83 | #endif | ||
63 | new.start = 0; | 84 | new.start = 0; |
64 | new.end = PSW_ADDR_INSN; | 85 | new.end = PSW_ADDR_INSN; |
65 | } | 86 | } |
@@ -100,6 +121,7 @@ void ptrace_disable(struct task_struct *task) | |||
100 | memset(&task->thread.per_event, 0, sizeof(task->thread.per_event)); | 121 | memset(&task->thread.per_event, 0, sizeof(task->thread.per_event)); |
101 | clear_tsk_thread_flag(task, TIF_SINGLE_STEP); | 122 | clear_tsk_thread_flag(task, TIF_SINGLE_STEP); |
102 | clear_tsk_thread_flag(task, TIF_PER_TRAP); | 123 | clear_tsk_thread_flag(task, TIF_PER_TRAP); |
124 | task->thread.per_flags = 0; | ||
103 | } | 125 | } |
104 | 126 | ||
105 | #ifndef CONFIG_64BIT | 127 | #ifndef CONFIG_64BIT |
@@ -416,6 +438,16 @@ long arch_ptrace(struct task_struct *child, long request, | |||
416 | put_user(task_thread_info(child)->last_break, | 438 | put_user(task_thread_info(child)->last_break, |
417 | (unsigned long __user *) data); | 439 | (unsigned long __user *) data); |
418 | return 0; | 440 | return 0; |
441 | case PTRACE_ENABLE_TE: | ||
442 | if (!MACHINE_HAS_TE) | ||
443 | return -EIO; | ||
444 | child->thread.per_flags &= ~PER_FLAG_NO_TE; | ||
445 | return 0; | ||
446 | case PTRACE_DISABLE_TE: | ||
447 | if (!MACHINE_HAS_TE) | ||
448 | return -EIO; | ||
449 | child->thread.per_flags |= PER_FLAG_NO_TE; | ||
450 | return 0; | ||
419 | default: | 451 | default: |
420 | /* Removing high order bit from addr (only for 31 bit). */ | 452 | /* Removing high order bit from addr (only for 31 bit). */ |
421 | addr &= PSW_ADDR_INSN; | 453 | addr &= PSW_ADDR_INSN; |
@@ -903,6 +935,28 @@ static int s390_last_break_set(struct task_struct *target, | |||
903 | return 0; | 935 | return 0; |
904 | } | 936 | } |
905 | 937 | ||
938 | static int s390_tdb_get(struct task_struct *target, | ||
939 | const struct user_regset *regset, | ||
940 | unsigned int pos, unsigned int count, | ||
941 | void *kbuf, void __user *ubuf) | ||
942 | { | ||
943 | struct pt_regs *regs = task_pt_regs(target); | ||
944 | unsigned char *data; | ||
945 | |||
946 | if (!(regs->int_code & 0x200)) | ||
947 | return -ENODATA; | ||
948 | data = target->thread.trap_tdb; | ||
949 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, data, 0, 256); | ||
950 | } | ||
951 | |||
952 | static int s390_tdb_set(struct task_struct *target, | ||
953 | const struct user_regset *regset, | ||
954 | unsigned int pos, unsigned int count, | ||
955 | const void *kbuf, const void __user *ubuf) | ||
956 | { | ||
957 | return 0; | ||
958 | } | ||
959 | |||
906 | #endif | 960 | #endif |
907 | 961 | ||
908 | static int s390_system_call_get(struct task_struct *target, | 962 | static int s390_system_call_get(struct task_struct *target, |
@@ -951,6 +1005,14 @@ static const struct user_regset s390_regsets[] = { | |||
951 | .get = s390_last_break_get, | 1005 | .get = s390_last_break_get, |
952 | .set = s390_last_break_set, | 1006 | .set = s390_last_break_set, |
953 | }, | 1007 | }, |
1008 | [REGSET_TDB] = { | ||
1009 | .core_note_type = NT_S390_TDB, | ||
1010 | .n = 1, | ||
1011 | .size = 256, | ||
1012 | .align = 1, | ||
1013 | .get = s390_tdb_get, | ||
1014 | .set = s390_tdb_set, | ||
1015 | }, | ||
954 | #endif | 1016 | #endif |
955 | [REGSET_SYSTEM_CALL] = { | 1017 | [REGSET_SYSTEM_CALL] = { |
956 | .core_note_type = NT_S390_SYSTEM_CALL, | 1018 | .core_note_type = NT_S390_SYSTEM_CALL, |
@@ -1148,6 +1210,14 @@ static const struct user_regset s390_compat_regsets[] = { | |||
1148 | .get = s390_compat_last_break_get, | 1210 | .get = s390_compat_last_break_get, |
1149 | .set = s390_compat_last_break_set, | 1211 | .set = s390_compat_last_break_set, |
1150 | }, | 1212 | }, |
1213 | [REGSET_TDB] = { | ||
1214 | .core_note_type = NT_S390_TDB, | ||
1215 | .n = 1, | ||
1216 | .size = 256, | ||
1217 | .align = 1, | ||
1218 | .get = s390_tdb_get, | ||
1219 | .set = s390_tdb_set, | ||
1220 | }, | ||
1151 | [REGSET_SYSTEM_CALL] = { | 1221 | [REGSET_SYSTEM_CALL] = { |
1152 | .core_note_type = NT_S390_SYSTEM_CALL, | 1222 | .core_note_type = NT_S390_SYSTEM_CALL, |
1153 | .n = 1, | 1223 | .n = 1, |
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c new file mode 100644 index 000000000000..61066f6f71a5 --- /dev/null +++ b/arch/s390/kernel/runtime_instr.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2012 | ||
3 | * Author(s): Jan Glauber <jang@linux.vnet.ibm.com> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/syscalls.h> | ||
8 | #include <linux/signal.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/kernel_stat.h> | ||
14 | #include <asm/runtime_instr.h> | ||
15 | #include <asm/cpu_mf.h> | ||
16 | #include <asm/irq.h> | ||
17 | |||
18 | /* empty control block to disable RI by loading it */ | ||
19 | struct runtime_instr_cb runtime_instr_empty_cb; | ||
20 | |||
21 | static int runtime_instr_avail(void) | ||
22 | { | ||
23 | return test_facility(64); | ||
24 | } | ||
25 | |||
26 | static void disable_runtime_instr(void) | ||
27 | { | ||
28 | struct pt_regs *regs = task_pt_regs(current); | ||
29 | |||
30 | load_runtime_instr_cb(&runtime_instr_empty_cb); | ||
31 | |||
32 | /* | ||
33 | * Make sure the RI bit is deleted from the PSW. If the user did not | ||
34 | * switch off RI before the system call the process will get a | ||
35 | * specification exception otherwise. | ||
36 | */ | ||
37 | regs->psw.mask &= ~PSW_MASK_RI; | ||
38 | } | ||
39 | |||
40 | static void init_runtime_instr_cb(struct runtime_instr_cb *cb) | ||
41 | { | ||
42 | cb->buf_limit = 0xfff; | ||
43 | if (s390_user_mode == HOME_SPACE_MODE) | ||
44 | cb->home_space = 1; | ||
45 | cb->int_requested = 1; | ||
46 | cb->pstate = 1; | ||
47 | cb->pstate_set_buf = 1; | ||
48 | cb->pstate_sample = 1; | ||
49 | cb->pstate_collect = 1; | ||
50 | cb->key = PAGE_DEFAULT_KEY; | ||
51 | cb->valid = 1; | ||
52 | } | ||
53 | |||
54 | void exit_thread_runtime_instr(void) | ||
55 | { | ||
56 | struct task_struct *task = current; | ||
57 | |||
58 | if (!task->thread.ri_cb) | ||
59 | return; | ||
60 | disable_runtime_instr(); | ||
61 | kfree(task->thread.ri_cb); | ||
62 | task->thread.ri_signum = 0; | ||
63 | task->thread.ri_cb = NULL; | ||
64 | } | ||
65 | |||
66 | static void runtime_instr_int_handler(struct ext_code ext_code, | ||
67 | unsigned int param32, unsigned long param64) | ||
68 | { | ||
69 | struct siginfo info; | ||
70 | |||
71 | if (!(param32 & CPU_MF_INT_RI_MASK)) | ||
72 | return; | ||
73 | |||
74 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++; | ||
75 | |||
76 | if (!current->thread.ri_cb) | ||
77 | return; | ||
78 | if (current->thread.ri_signum < SIGRTMIN || | ||
79 | current->thread.ri_signum > SIGRTMAX) { | ||
80 | WARN_ON_ONCE(1); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | memset(&info, 0, sizeof(info)); | ||
85 | info.si_signo = current->thread.ri_signum; | ||
86 | info.si_code = SI_QUEUE; | ||
87 | if (param32 & CPU_MF_INT_RI_BUF_FULL) | ||
88 | info.si_int = ENOBUFS; | ||
89 | else if (param32 & CPU_MF_INT_RI_HALTED) | ||
90 | info.si_int = ECANCELED; | ||
91 | else | ||
92 | return; /* unknown reason */ | ||
93 | |||
94 | send_sig_info(current->thread.ri_signum, &info, current); | ||
95 | } | ||
96 | |||
97 | SYSCALL_DEFINE2(s390_runtime_instr, int, command, int, signum) | ||
98 | { | ||
99 | struct runtime_instr_cb *cb; | ||
100 | |||
101 | if (!runtime_instr_avail()) | ||
102 | return -EOPNOTSUPP; | ||
103 | |||
104 | if (command == S390_RUNTIME_INSTR_STOP) { | ||
105 | preempt_disable(); | ||
106 | exit_thread_runtime_instr(); | ||
107 | preempt_enable(); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | if (command != S390_RUNTIME_INSTR_START || | ||
112 | (signum < SIGRTMIN || signum > SIGRTMAX)) | ||
113 | return -EINVAL; | ||
114 | |||
115 | if (!current->thread.ri_cb) { | ||
116 | cb = kzalloc(sizeof(*cb), GFP_KERNEL); | ||
117 | if (!cb) | ||
118 | return -ENOMEM; | ||
119 | } else { | ||
120 | cb = current->thread.ri_cb; | ||
121 | memset(cb, 0, sizeof(*cb)); | ||
122 | } | ||
123 | |||
124 | init_runtime_instr_cb(cb); | ||
125 | current->thread.ri_signum = signum; | ||
126 | |||
127 | /* now load the control block to make it available */ | ||
128 | preempt_disable(); | ||
129 | current->thread.ri_cb = cb; | ||
130 | load_runtime_instr_cb(cb); | ||
131 | preempt_enable(); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int __init runtime_instr_init(void) | ||
136 | { | ||
137 | int rc; | ||
138 | |||
139 | if (!runtime_instr_avail()) | ||
140 | return 0; | ||
141 | |||
142 | measurement_alert_subclass_register(); | ||
143 | rc = register_external_interrupt(0x1407, runtime_instr_int_handler); | ||
144 | if (rc) | ||
145 | measurement_alert_subclass_unregister(); | ||
146 | else | ||
147 | pr_info("Runtime instrumentation facility initialized\n"); | ||
148 | return rc; | ||
149 | } | ||
150 | device_initcall(runtime_instr_init); | ||
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 57b536649b00..9bdbcef1da9e 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c | |||
@@ -8,3 +8,5 @@ EXPORT_SYMBOL(_mcount); | |||
8 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 8 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) |
9 | EXPORT_SYMBOL(sie64a); | 9 | EXPORT_SYMBOL(sie64a); |
10 | #endif | 10 | #endif |
11 | EXPORT_SYMBOL(memcpy); | ||
12 | EXPORT_SYMBOL(memset); | ||
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index f86c81e13c37..afa9fdba200e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -302,10 +302,10 @@ static int __init parse_vmalloc(char *arg) | |||
302 | } | 302 | } |
303 | early_param("vmalloc", parse_vmalloc); | 303 | early_param("vmalloc", parse_vmalloc); |
304 | 304 | ||
305 | unsigned int addressing_mode = HOME_SPACE_MODE; | 305 | unsigned int s390_user_mode = PRIMARY_SPACE_MODE; |
306 | EXPORT_SYMBOL_GPL(addressing_mode); | 306 | EXPORT_SYMBOL_GPL(s390_user_mode); |
307 | 307 | ||
308 | static int set_amode_primary(void) | 308 | static void __init set_user_mode_primary(void) |
309 | { | 309 | { |
310 | psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME; | 310 | psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME; |
311 | psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY; | 311 | psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY; |
@@ -313,48 +313,30 @@ static int set_amode_primary(void) | |||
313 | psw32_user_bits = | 313 | psw32_user_bits = |
314 | (psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY; | 314 | (psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY; |
315 | #endif | 315 | #endif |
316 | 316 | uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos_switch : uaccess_pt; | |
317 | if (MACHINE_HAS_MVCOS) { | ||
318 | memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess)); | ||
319 | return 1; | ||
320 | } else { | ||
321 | memcpy(&uaccess, &uaccess_pt, sizeof(uaccess)); | ||
322 | return 0; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * Switch kernel/user addressing modes? | ||
328 | */ | ||
329 | static int __init early_parse_switch_amode(char *p) | ||
330 | { | ||
331 | addressing_mode = PRIMARY_SPACE_MODE; | ||
332 | return 0; | ||
333 | } | 317 | } |
334 | early_param("switch_amode", early_parse_switch_amode); | ||
335 | 318 | ||
336 | static int __init early_parse_user_mode(char *p) | 319 | static int __init early_parse_user_mode(char *p) |
337 | { | 320 | { |
338 | if (p && strcmp(p, "primary") == 0) | 321 | if (p && strcmp(p, "primary") == 0) |
339 | addressing_mode = PRIMARY_SPACE_MODE; | 322 | s390_user_mode = PRIMARY_SPACE_MODE; |
340 | else if (!p || strcmp(p, "home") == 0) | 323 | else if (!p || strcmp(p, "home") == 0) |
341 | addressing_mode = HOME_SPACE_MODE; | 324 | s390_user_mode = HOME_SPACE_MODE; |
342 | else | 325 | else |
343 | return 1; | 326 | return 1; |
344 | return 0; | 327 | return 0; |
345 | } | 328 | } |
346 | early_param("user_mode", early_parse_user_mode); | 329 | early_param("user_mode", early_parse_user_mode); |
347 | 330 | ||
348 | static void setup_addressing_mode(void) | 331 | static void __init setup_addressing_mode(void) |
349 | { | 332 | { |
350 | if (addressing_mode == PRIMARY_SPACE_MODE) { | 333 | if (s390_user_mode != PRIMARY_SPACE_MODE) |
351 | if (set_amode_primary()) | 334 | return; |
352 | pr_info("Address spaces switched, " | 335 | set_user_mode_primary(); |
353 | "mvcos available\n"); | 336 | if (MACHINE_HAS_MVCOS) |
354 | else | 337 | pr_info("Address spaces switched, mvcos available\n"); |
355 | pr_info("Address spaces switched, " | 338 | else |
356 | "mvcos not available\n"); | 339 | pr_info("Address spaces switched, mvcos not available\n"); |
357 | } | ||
358 | } | 340 | } |
359 | 341 | ||
360 | void *restart_stack __attribute__((__section__(".data"))); | 342 | void *restart_stack __attribute__((__section__(".data"))); |
@@ -602,9 +584,7 @@ static void __init setup_memory_end(void) | |||
602 | 584 | ||
603 | static void __init setup_vmcoreinfo(void) | 585 | static void __init setup_vmcoreinfo(void) |
604 | { | 586 | { |
605 | #ifdef CONFIG_KEXEC | ||
606 | mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); | 587 | mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); |
607 | #endif | ||
608 | } | 588 | } |
609 | 589 | ||
610 | #ifdef CONFIG_CRASH_DUMP | 590 | #ifdef CONFIG_CRASH_DUMP |
@@ -974,12 +954,20 @@ static void __init setup_hwcaps(void) | |||
974 | if (MACHINE_HAS_HPAGE) | 954 | if (MACHINE_HAS_HPAGE) |
975 | elf_hwcap |= HWCAP_S390_HPAGE; | 955 | elf_hwcap |= HWCAP_S390_HPAGE; |
976 | 956 | ||
957 | #if defined(CONFIG_64BIT) | ||
977 | /* | 958 | /* |
978 | * 64-bit register support for 31-bit processes | 959 | * 64-bit register support for 31-bit processes |
979 | * HWCAP_S390_HIGH_GPRS is bit 9. | 960 | * HWCAP_S390_HIGH_GPRS is bit 9. |
980 | */ | 961 | */ |
981 | elf_hwcap |= HWCAP_S390_HIGH_GPRS; | 962 | elf_hwcap |= HWCAP_S390_HIGH_GPRS; |
982 | 963 | ||
964 | /* | ||
965 | * Transactional execution support HWCAP_S390_TE is bit 10. | ||
966 | */ | ||
967 | if (test_facility(50) && test_facility(73)) | ||
968 | elf_hwcap |= HWCAP_S390_TE; | ||
969 | #endif | ||
970 | |||
983 | get_cpu_id(&cpu_id); | 971 | get_cpu_id(&cpu_id); |
984 | switch (cpu_id.machine) { | 972 | switch (cpu_id.machine) { |
985 | case 0x9672: | 973 | case 0x9672: |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 720fda1620f2..ea431e551c6b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -66,7 +66,7 @@ struct pcpu { | |||
66 | unsigned long panic_stack; /* panic stack for the cpu */ | 66 | unsigned long panic_stack; /* panic stack for the cpu */ |
67 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ | 67 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ |
68 | int state; /* physical cpu state */ | 68 | int state; /* physical cpu state */ |
69 | u32 status; /* last status received via sigp */ | 69 | int polarization; /* physical polarization */ |
70 | u16 address; /* physical cpu address */ | 70 | u16 address; /* physical cpu address */ |
71 | }; | 71 | }; |
72 | 72 | ||
@@ -74,6 +74,10 @@ static u8 boot_cpu_type; | |||
74 | static u16 boot_cpu_address; | 74 | static u16 boot_cpu_address; |
75 | static struct pcpu pcpu_devices[NR_CPUS]; | 75 | static struct pcpu pcpu_devices[NR_CPUS]; |
76 | 76 | ||
77 | /* | ||
78 | * The smp_cpu_state_mutex must be held when changing the state or polarization | ||
79 | * member of a pcpu data structure within the pcpu_devices arreay. | ||
80 | */ | ||
77 | DEFINE_MUTEX(smp_cpu_state_mutex); | 81 | DEFINE_MUTEX(smp_cpu_state_mutex); |
78 | 82 | ||
79 | /* | 83 | /* |
@@ -99,7 +103,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status) | |||
99 | int cc; | 103 | int cc; |
100 | 104 | ||
101 | while (1) { | 105 | while (1) { |
102 | cc = __pcpu_sigp(addr, order, parm, status); | 106 | cc = __pcpu_sigp(addr, order, parm, NULL); |
103 | if (cc != SIGP_CC_BUSY) | 107 | if (cc != SIGP_CC_BUSY) |
104 | return cc; | 108 | return cc; |
105 | cpu_relax(); | 109 | cpu_relax(); |
@@ -111,7 +115,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) | |||
111 | int cc, retry; | 115 | int cc, retry; |
112 | 116 | ||
113 | for (retry = 0; ; retry++) { | 117 | for (retry = 0; ; retry++) { |
114 | cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status); | 118 | cc = __pcpu_sigp(pcpu->address, order, parm, NULL); |
115 | if (cc != SIGP_CC_BUSY) | 119 | if (cc != SIGP_CC_BUSY) |
116 | break; | 120 | break; |
117 | if (retry >= 3) | 121 | if (retry >= 3) |
@@ -122,16 +126,18 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) | |||
122 | 126 | ||
123 | static inline int pcpu_stopped(struct pcpu *pcpu) | 127 | static inline int pcpu_stopped(struct pcpu *pcpu) |
124 | { | 128 | { |
129 | u32 uninitialized_var(status); | ||
130 | |||
125 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE, | 131 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE, |
126 | 0, &pcpu->status) != SIGP_CC_STATUS_STORED) | 132 | 0, &status) != SIGP_CC_STATUS_STORED) |
127 | return 0; | 133 | return 0; |
128 | return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); | 134 | return !!(status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); |
129 | } | 135 | } |
130 | 136 | ||
131 | static inline int pcpu_running(struct pcpu *pcpu) | 137 | static inline int pcpu_running(struct pcpu *pcpu) |
132 | { | 138 | { |
133 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, | 139 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, |
134 | 0, &pcpu->status) != SIGP_CC_STATUS_STORED) | 140 | 0, NULL) != SIGP_CC_STATUS_STORED) |
135 | return 1; | 141 | return 1; |
136 | /* Status stored condition code is equivalent to cpu not running. */ | 142 | /* Status stored condition code is equivalent to cpu not running. */ |
137 | return 0; | 143 | return 0; |
@@ -586,6 +592,16 @@ static inline void smp_get_save_area(int cpu, u16 address) { } | |||
586 | 592 | ||
587 | #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ | 593 | #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ |
588 | 594 | ||
595 | void smp_cpu_set_polarization(int cpu, int val) | ||
596 | { | ||
597 | pcpu_devices[cpu].polarization = val; | ||
598 | } | ||
599 | |||
600 | int smp_cpu_get_polarization(int cpu) | ||
601 | { | ||
602 | return pcpu_devices[cpu].polarization; | ||
603 | } | ||
604 | |||
589 | static struct sclp_cpu_info *smp_get_cpu_info(void) | 605 | static struct sclp_cpu_info *smp_get_cpu_info(void) |
590 | { | 606 | { |
591 | static int use_sigp_detection; | 607 | static int use_sigp_detection; |
@@ -628,7 +644,7 @@ static int __devinit __smp_rescan_cpus(struct sclp_cpu_info *info, | |||
628 | pcpu->address = info->cpu[i].address; | 644 | pcpu->address = info->cpu[i].address; |
629 | pcpu->state = (cpu >= info->configured) ? | 645 | pcpu->state = (cpu >= info->configured) ? |
630 | CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; | 646 | CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; |
631 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 647 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
632 | set_cpu_present(cpu, true); | 648 | set_cpu_present(cpu, true); |
633 | if (sysfs_add && smp_add_present_cpu(cpu) != 0) | 649 | if (sysfs_add && smp_add_present_cpu(cpu) != 0) |
634 | set_cpu_present(cpu, false); | 650 | set_cpu_present(cpu, false); |
@@ -796,7 +812,7 @@ void __init smp_prepare_boot_cpu(void) | |||
796 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE; | 812 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE; |
797 | pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE; | 813 | pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE; |
798 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; | 814 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; |
799 | cpu_set_polarization(0, POLARIZATION_UNKNOWN); | 815 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); |
800 | set_cpu_present(0, true); | 816 | set_cpu_present(0, true); |
801 | set_cpu_online(0, true); | 817 | set_cpu_online(0, true); |
802 | } | 818 | } |
@@ -862,7 +878,7 @@ static ssize_t cpu_configure_store(struct device *dev, | |||
862 | if (rc) | 878 | if (rc) |
863 | break; | 879 | break; |
864 | pcpu->state = CPU_STATE_STANDBY; | 880 | pcpu->state = CPU_STATE_STANDBY; |
865 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 881 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
866 | topology_expect_change(); | 882 | topology_expect_change(); |
867 | break; | 883 | break; |
868 | case 1: | 884 | case 1: |
@@ -872,7 +888,7 @@ static ssize_t cpu_configure_store(struct device *dev, | |||
872 | if (rc) | 888 | if (rc) |
873 | break; | 889 | break; |
874 | pcpu->state = CPU_STATE_CONFIGURED; | 890 | pcpu->state = CPU_STATE_CONFIGURED; |
875 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 891 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
876 | topology_expect_change(); | 892 | topology_expect_change(); |
877 | break; | 893 | break; |
878 | default: | 894 | default: |
@@ -959,23 +975,17 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, | |||
959 | struct device *s = &c->dev; | 975 | struct device *s = &c->dev; |
960 | int err = 0; | 976 | int err = 0; |
961 | 977 | ||
962 | switch (action) { | 978 | switch (action & ~CPU_TASKS_FROZEN) { |
963 | case CPU_ONLINE: | 979 | case CPU_ONLINE: |
964 | case CPU_ONLINE_FROZEN: | ||
965 | err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); | 980 | err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); |
966 | break; | 981 | break; |
967 | case CPU_DEAD: | 982 | case CPU_DEAD: |
968 | case CPU_DEAD_FROZEN: | ||
969 | sysfs_remove_group(&s->kobj, &cpu_online_attr_group); | 983 | sysfs_remove_group(&s->kobj, &cpu_online_attr_group); |
970 | break; | 984 | break; |
971 | } | 985 | } |
972 | return notifier_from_errno(err); | 986 | return notifier_from_errno(err); |
973 | } | 987 | } |
974 | 988 | ||
975 | static struct notifier_block __cpuinitdata smp_cpu_nb = { | ||
976 | .notifier_call = smp_cpu_notify, | ||
977 | }; | ||
978 | |||
979 | static int __devinit smp_add_present_cpu(int cpu) | 989 | static int __devinit smp_add_present_cpu(int cpu) |
980 | { | 990 | { |
981 | struct cpu *c = &pcpu_devices[cpu].cpu; | 991 | struct cpu *c = &pcpu_devices[cpu].cpu; |
@@ -1050,7 +1060,7 @@ static int __init s390_smp_init(void) | |||
1050 | { | 1060 | { |
1051 | int cpu, rc; | 1061 | int cpu, rc; |
1052 | 1062 | ||
1053 | register_cpu_notifier(&smp_cpu_nb); | 1063 | hotcpu_notifier(smp_cpu_notify, 0); |
1054 | #ifdef CONFIG_HOTPLUG_CPU | 1064 | #ifdef CONFIG_HOTPLUG_CPU |
1055 | rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); | 1065 | rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); |
1056 | if (rc) | 1066 | if (rc) |
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index bcab2f04ba58..48174850f3b0 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
@@ -350,3 +350,5 @@ SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper) | |||
350 | SYSCALL(sys_setns,sys_setns,sys_setns_wrapper) | 350 | SYSCALL(sys_setns,sys_setns,sys_setns_wrapper) |
351 | SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */ | 351 | SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */ |
352 | SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) | 352 | SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) |
353 | SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) | ||
354 | SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) | ||
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index fa0eb238dac7..62f89d98e880 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c | |||
@@ -22,17 +22,41 @@ | |||
22 | #include <math-emu/soft-fp.h> | 22 | #include <math-emu/soft-fp.h> |
23 | #include <math-emu/single.h> | 23 | #include <math-emu/single.h> |
24 | 24 | ||
25 | static inline int stsi_0(void) | 25 | int topology_max_mnest; |
26 | |||
27 | /* | ||
28 | * stsi - store system information | ||
29 | * | ||
30 | * Returns the current configuration level if function code 0 was specified. | ||
31 | * Otherwise returns 0 on success or a negative value on error. | ||
32 | */ | ||
33 | int stsi(void *sysinfo, int fc, int sel1, int sel2) | ||
26 | { | 34 | { |
27 | int rc = stsi(NULL, 0, 0, 0); | 35 | register int r0 asm("0") = (fc << 28) | sel1; |
28 | return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); | 36 | register int r1 asm("1") = sel2; |
37 | int rc = 0; | ||
38 | |||
39 | asm volatile( | ||
40 | " stsi 0(%3)\n" | ||
41 | "0: jz 2f\n" | ||
42 | "1: lhi %1,%4\n" | ||
43 | "2:\n" | ||
44 | EX_TABLE(0b, 1b) | ||
45 | : "+d" (r0), "+d" (rc) | ||
46 | : "d" (r1), "a" (sysinfo), "K" (-EOPNOTSUPP) | ||
47 | : "cc", "memory"); | ||
48 | if (rc) | ||
49 | return rc; | ||
50 | return fc ? 0 : ((unsigned int) r0) >> 28; | ||
29 | } | 51 | } |
52 | EXPORT_SYMBOL(stsi); | ||
30 | 53 | ||
31 | static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) | 54 | static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info) |
32 | { | 55 | { |
33 | if (stsi(info, 1, 1, 1) == -ENOSYS) | 56 | int i; |
34 | return len; | ||
35 | 57 | ||
58 | if (stsi(info, 1, 1, 1)) | ||
59 | return; | ||
36 | EBCASC(info->manufacturer, sizeof(info->manufacturer)); | 60 | EBCASC(info->manufacturer, sizeof(info->manufacturer)); |
37 | EBCASC(info->type, sizeof(info->type)); | 61 | EBCASC(info->type, sizeof(info->type)); |
38 | EBCASC(info->model, sizeof(info->model)); | 62 | EBCASC(info->model, sizeof(info->model)); |
@@ -41,242 +65,197 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) | |||
41 | EBCASC(info->model_capacity, sizeof(info->model_capacity)); | 65 | EBCASC(info->model_capacity, sizeof(info->model_capacity)); |
42 | EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap)); | 66 | EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap)); |
43 | EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap)); | 67 | EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap)); |
44 | len += sprintf(page + len, "Manufacturer: %-16.16s\n", | 68 | seq_printf(m, "Manufacturer: %-16.16s\n", info->manufacturer); |
45 | info->manufacturer); | 69 | seq_printf(m, "Type: %-4.4s\n", info->type); |
46 | len += sprintf(page + len, "Type: %-4.4s\n", | 70 | /* |
47 | info->type); | 71 | * Sigh: the model field has been renamed with System z9 |
72 | * to model_capacity and a new model field has been added | ||
73 | * after the plant field. To avoid confusing older programs | ||
74 | * the "Model:" prints "model_capacity model" or just | ||
75 | * "model_capacity" if the model string is empty . | ||
76 | */ | ||
77 | seq_printf(m, "Model: %-16.16s", info->model_capacity); | ||
48 | if (info->model[0] != '\0') | 78 | if (info->model[0] != '\0') |
49 | /* | 79 | seq_printf(m, " %-16.16s", info->model); |
50 | * Sigh: the model field has been renamed with System z9 | 80 | seq_putc(m, '\n'); |
51 | * to model_capacity and a new model field has been added | 81 | seq_printf(m, "Sequence Code: %-16.16s\n", info->sequence); |
52 | * after the plant field. To avoid confusing older programs | 82 | seq_printf(m, "Plant: %-4.4s\n", info->plant); |
53 | * the "Model:" prints "model_capacity model" or just | 83 | seq_printf(m, "Model Capacity: %-16.16s %08u\n", |
54 | * "model_capacity" if the model string is empty . | 84 | info->model_capacity, info->model_cap_rating); |
55 | */ | 85 | if (info->model_perm_cap_rating) |
56 | len += sprintf(page + len, | 86 | seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n", |
57 | "Model: %-16.16s %-16.16s\n", | 87 | info->model_perm_cap, |
58 | info->model_capacity, info->model); | 88 | info->model_perm_cap_rating); |
59 | else | 89 | if (info->model_temp_cap_rating) |
60 | len += sprintf(page + len, "Model: %-16.16s\n", | 90 | seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n", |
61 | info->model_capacity); | 91 | info->model_temp_cap, |
62 | len += sprintf(page + len, "Sequence Code: %-16.16s\n", | 92 | info->model_temp_cap_rating); |
63 | info->sequence); | 93 | if (info->ncr) |
64 | len += sprintf(page + len, "Plant: %-4.4s\n", | 94 | seq_printf(m, "Nominal Cap. Rating: %08u\n", info->ncr); |
65 | info->plant); | 95 | if (info->npr) |
66 | len += sprintf(page + len, "Model Capacity: %-16.16s %08u\n", | 96 | seq_printf(m, "Nominal Perm. Rating: %08u\n", info->npr); |
67 | info->model_capacity, *(u32 *) info->model_cap_rating); | 97 | if (info->ntr) |
68 | if (info->model_perm_cap[0] != '\0') | 98 | seq_printf(m, "Nominal Temp. Rating: %08u\n", info->ntr); |
69 | len += sprintf(page + len, | ||
70 | "Model Perm. Capacity: %-16.16s %08u\n", | ||
71 | info->model_perm_cap, | ||
72 | *(u32 *) info->model_perm_cap_rating); | ||
73 | if (info->model_temp_cap[0] != '\0') | ||
74 | len += sprintf(page + len, | ||
75 | "Model Temp. Capacity: %-16.16s %08u\n", | ||
76 | info->model_temp_cap, | ||
77 | *(u32 *) info->model_temp_cap_rating); | ||
78 | if (info->cai) { | 99 | if (info->cai) { |
79 | len += sprintf(page + len, | 100 | seq_printf(m, "Capacity Adj. Ind.: %d\n", info->cai); |
80 | "Capacity Adj. Ind.: %d\n", | 101 | seq_printf(m, "Capacity Ch. Reason: %d\n", info->ccr); |
81 | info->cai); | 102 | seq_printf(m, "Capacity Transient: %d\n", info->t); |
82 | len += sprintf(page + len, "Capacity Ch. Reason: %d\n", | 103 | } |
83 | info->ccr); | 104 | if (info->p) { |
105 | for (i = 1; i <= ARRAY_SIZE(info->typepct); i++) { | ||
106 | seq_printf(m, "Type %d Percentage: %d\n", | ||
107 | i, info->typepct[i - 1]); | ||
108 | } | ||
84 | } | 109 | } |
85 | return len; | ||
86 | } | 110 | } |
87 | 111 | ||
88 | static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len) | 112 | static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info) |
89 | { | 113 | { |
90 | static int max_mnest; | 114 | static int max_mnest; |
91 | int i, rc; | 115 | int i, rc; |
92 | 116 | ||
93 | len += sprintf(page + len, "\n"); | 117 | seq_putc(m, '\n'); |
94 | if (!MACHINE_HAS_TOPOLOGY) | 118 | if (!MACHINE_HAS_TOPOLOGY) |
95 | return len; | 119 | return; |
96 | if (max_mnest) { | 120 | if (stsi(info, 15, 1, topology_max_mnest)) |
97 | stsi(info, 15, 1, max_mnest); | 121 | return; |
98 | } else { | 122 | seq_printf(m, "CPU Topology HW: "); |
99 | for (max_mnest = 6; max_mnest > 1; max_mnest--) { | ||
100 | rc = stsi(info, 15, 1, max_mnest); | ||
101 | if (rc != -ENOSYS) | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | len += sprintf(page + len, "CPU Topology HW: "); | ||
106 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | 123 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) |
107 | len += sprintf(page + len, " %d", info->mag[i]); | 124 | seq_printf(m, " %d", info->mag[i]); |
108 | len += sprintf(page + len, "\n"); | 125 | seq_putc(m, '\n'); |
109 | #ifdef CONFIG_SCHED_MC | 126 | #ifdef CONFIG_SCHED_MC |
110 | store_topology(info); | 127 | store_topology(info); |
111 | len += sprintf(page + len, "CPU Topology SW: "); | 128 | seq_printf(m, "CPU Topology SW: "); |
112 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | 129 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) |
113 | len += sprintf(page + len, " %d", info->mag[i]); | 130 | seq_printf(m, " %d", info->mag[i]); |
114 | len += sprintf(page + len, "\n"); | 131 | seq_putc(m, '\n'); |
115 | #endif | 132 | #endif |
116 | return len; | ||
117 | } | 133 | } |
118 | 134 | ||
119 | static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) | 135 | static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info) |
120 | { | 136 | { |
121 | struct sysinfo_1_2_2_extension *ext; | 137 | struct sysinfo_1_2_2_extension *ext; |
122 | int i; | 138 | int i; |
123 | 139 | ||
124 | if (stsi(info, 1, 2, 2) == -ENOSYS) | 140 | if (stsi(info, 1, 2, 2)) |
125 | return len; | 141 | return; |
126 | ext = (struct sysinfo_1_2_2_extension *) | 142 | ext = (struct sysinfo_1_2_2_extension *) |
127 | ((unsigned long) info + info->acc_offset); | 143 | ((unsigned long) info + info->acc_offset); |
128 | 144 | seq_printf(m, "CPUs Total: %d\n", info->cpus_total); | |
129 | len += sprintf(page + len, "CPUs Total: %d\n", | 145 | seq_printf(m, "CPUs Configured: %d\n", info->cpus_configured); |
130 | info->cpus_total); | 146 | seq_printf(m, "CPUs Standby: %d\n", info->cpus_standby); |
131 | len += sprintf(page + len, "CPUs Configured: %d\n", | 147 | seq_printf(m, "CPUs Reserved: %d\n", info->cpus_reserved); |
132 | info->cpus_configured); | 148 | /* |
133 | len += sprintf(page + len, "CPUs Standby: %d\n", | 149 | * Sigh 2. According to the specification the alternate |
134 | info->cpus_standby); | 150 | * capability field is a 32 bit floating point number |
135 | len += sprintf(page + len, "CPUs Reserved: %d\n", | 151 | * if the higher order 8 bits are not zero. Printing |
136 | info->cpus_reserved); | 152 | * a floating point number in the kernel is a no-no, |
137 | 153 | * always print the number as 32 bit unsigned integer. | |
138 | if (info->format == 1) { | 154 | * The user-space needs to know about the strange |
139 | /* | 155 | * encoding of the alternate cpu capability. |
140 | * Sigh 2. According to the specification the alternate | 156 | */ |
141 | * capability field is a 32 bit floating point number | 157 | seq_printf(m, "Capability: %u", info->capability); |
142 | * if the higher order 8 bits are not zero. Printing | 158 | if (info->format == 1) |
143 | * a floating point number in the kernel is a no-no, | 159 | seq_printf(m, " %u", ext->alt_capability); |
144 | * always print the number as 32 bit unsigned integer. | 160 | seq_putc(m, '\n'); |
145 | * The user-space needs to know about the strange | 161 | if (info->nominal_cap) |
146 | * encoding of the alternate cpu capability. | 162 | seq_printf(m, "Nominal Capability: %d\n", info->nominal_cap); |
147 | */ | 163 | if (info->secondary_cap) |
148 | len += sprintf(page + len, "Capability: %u %u\n", | 164 | seq_printf(m, "Secondary Capability: %d\n", info->secondary_cap); |
149 | info->capability, ext->alt_capability); | 165 | for (i = 2; i <= info->cpus_total; i++) { |
150 | for (i = 2; i <= info->cpus_total; i++) | 166 | seq_printf(m, "Adjustment %02d-way: %u", |
151 | len += sprintf(page + len, | 167 | i, info->adjustment[i-2]); |
152 | "Adjustment %02d-way: %u %u\n", | 168 | if (info->format == 1) |
153 | i, info->adjustment[i-2], | 169 | seq_printf(m, " %u", ext->alt_adjustment[i-2]); |
154 | ext->alt_adjustment[i-2]); | 170 | seq_putc(m, '\n'); |
155 | |||
156 | } else { | ||
157 | len += sprintf(page + len, "Capability: %u\n", | ||
158 | info->capability); | ||
159 | for (i = 2; i <= info->cpus_total; i++) | ||
160 | len += sprintf(page + len, | ||
161 | "Adjustment %02d-way: %u\n", | ||
162 | i, info->adjustment[i-2]); | ||
163 | } | 171 | } |
164 | |||
165 | if (info->secondary_capability != 0) | ||
166 | len += sprintf(page + len, "Secondary Capability: %d\n", | ||
167 | info->secondary_capability); | ||
168 | return len; | ||
169 | } | 172 | } |
170 | 173 | ||
171 | static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) | 174 | static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info) |
172 | { | 175 | { |
173 | if (stsi(info, 2, 2, 2) == -ENOSYS) | 176 | if (stsi(info, 2, 2, 2)) |
174 | return len; | 177 | return; |
175 | |||
176 | EBCASC(info->name, sizeof(info->name)); | 178 | EBCASC(info->name, sizeof(info->name)); |
177 | 179 | seq_putc(m, '\n'); | |
178 | len += sprintf(page + len, "\n"); | 180 | seq_printf(m, "LPAR Number: %d\n", info->lpar_number); |
179 | len += sprintf(page + len, "LPAR Number: %d\n", | 181 | seq_printf(m, "LPAR Characteristics: "); |
180 | info->lpar_number); | ||
181 | |||
182 | len += sprintf(page + len, "LPAR Characteristics: "); | ||
183 | if (info->characteristics & LPAR_CHAR_DEDICATED) | 182 | if (info->characteristics & LPAR_CHAR_DEDICATED) |
184 | len += sprintf(page + len, "Dedicated "); | 183 | seq_printf(m, "Dedicated "); |
185 | if (info->characteristics & LPAR_CHAR_SHARED) | 184 | if (info->characteristics & LPAR_CHAR_SHARED) |
186 | len += sprintf(page + len, "Shared "); | 185 | seq_printf(m, "Shared "); |
187 | if (info->characteristics & LPAR_CHAR_LIMITED) | 186 | if (info->characteristics & LPAR_CHAR_LIMITED) |
188 | len += sprintf(page + len, "Limited "); | 187 | seq_printf(m, "Limited "); |
189 | len += sprintf(page + len, "\n"); | 188 | seq_putc(m, '\n'); |
190 | 189 | seq_printf(m, "LPAR Name: %-8.8s\n", info->name); | |
191 | len += sprintf(page + len, "LPAR Name: %-8.8s\n", | 190 | seq_printf(m, "LPAR Adjustment: %d\n", info->caf); |
192 | info->name); | 191 | seq_printf(m, "LPAR CPUs Total: %d\n", info->cpus_total); |
193 | 192 | seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured); | |
194 | len += sprintf(page + len, "LPAR Adjustment: %d\n", | 193 | seq_printf(m, "LPAR CPUs Standby: %d\n", info->cpus_standby); |
195 | info->caf); | 194 | seq_printf(m, "LPAR CPUs Reserved: %d\n", info->cpus_reserved); |
196 | 195 | seq_printf(m, "LPAR CPUs Dedicated: %d\n", info->cpus_dedicated); | |
197 | len += sprintf(page + len, "LPAR CPUs Total: %d\n", | 196 | seq_printf(m, "LPAR CPUs Shared: %d\n", info->cpus_shared); |
198 | info->cpus_total); | ||
199 | len += sprintf(page + len, "LPAR CPUs Configured: %d\n", | ||
200 | info->cpus_configured); | ||
201 | len += sprintf(page + len, "LPAR CPUs Standby: %d\n", | ||
202 | info->cpus_standby); | ||
203 | len += sprintf(page + len, "LPAR CPUs Reserved: %d\n", | ||
204 | info->cpus_reserved); | ||
205 | len += sprintf(page + len, "LPAR CPUs Dedicated: %d\n", | ||
206 | info->cpus_dedicated); | ||
207 | len += sprintf(page + len, "LPAR CPUs Shared: %d\n", | ||
208 | info->cpus_shared); | ||
209 | return len; | ||
210 | } | 197 | } |
211 | 198 | ||
212 | static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) | 199 | static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info) |
213 | { | 200 | { |
214 | int i; | 201 | int i; |
215 | 202 | ||
216 | if (stsi(info, 3, 2, 2) == -ENOSYS) | 203 | if (stsi(info, 3, 2, 2)) |
217 | return len; | 204 | return; |
218 | for (i = 0; i < info->count; i++) { | 205 | for (i = 0; i < info->count; i++) { |
219 | EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); | 206 | EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); |
220 | EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); | 207 | EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); |
221 | len += sprintf(page + len, "\n"); | 208 | seq_putc(m, '\n'); |
222 | len += sprintf(page + len, "VM%02d Name: %-8.8s\n", | 209 | seq_printf(m, "VM%02d Name: %-8.8s\n", i, info->vm[i].name); |
223 | i, info->vm[i].name); | 210 | seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi); |
224 | len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n", | 211 | seq_printf(m, "VM%02d Adjustment: %d\n", i, info->vm[i].caf); |
225 | i, info->vm[i].cpi); | 212 | seq_printf(m, "VM%02d CPUs Total: %d\n", i, info->vm[i].cpus_total); |
226 | 213 | seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured); | |
227 | len += sprintf(page + len, "VM%02d Adjustment: %d\n", | 214 | seq_printf(m, "VM%02d CPUs Standby: %d\n", i, info->vm[i].cpus_standby); |
228 | i, info->vm[i].caf); | 215 | seq_printf(m, "VM%02d CPUs Reserved: %d\n", i, info->vm[i].cpus_reserved); |
229 | |||
230 | len += sprintf(page + len, "VM%02d CPUs Total: %d\n", | ||
231 | i, info->vm[i].cpus_total); | ||
232 | len += sprintf(page + len, "VM%02d CPUs Configured: %d\n", | ||
233 | i, info->vm[i].cpus_configured); | ||
234 | len += sprintf(page + len, "VM%02d CPUs Standby: %d\n", | ||
235 | i, info->vm[i].cpus_standby); | ||
236 | len += sprintf(page + len, "VM%02d CPUs Reserved: %d\n", | ||
237 | i, info->vm[i].cpus_reserved); | ||
238 | } | 216 | } |
239 | return len; | ||
240 | } | 217 | } |
241 | 218 | ||
242 | static int proc_read_sysinfo(char *page, char **start, | 219 | static int sysinfo_show(struct seq_file *m, void *v) |
243 | off_t off, int count, | ||
244 | int *eof, void *data) | ||
245 | { | 220 | { |
246 | unsigned long info = get_zeroed_page(GFP_KERNEL); | 221 | void *info = (void *)get_zeroed_page(GFP_KERNEL); |
247 | int level, len; | 222 | int level; |
248 | 223 | ||
249 | if (!info) | 224 | if (!info) |
250 | return 0; | 225 | return 0; |
251 | 226 | level = stsi(NULL, 0, 0, 0); | |
252 | len = 0; | ||
253 | level = stsi_0(); | ||
254 | if (level >= 1) | 227 | if (level >= 1) |
255 | len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len); | 228 | stsi_1_1_1(m, info); |
256 | |||
257 | if (level >= 1) | 229 | if (level >= 1) |
258 | len = stsi_15_1_x((struct sysinfo_15_1_x *) info, page, len); | 230 | stsi_15_1_x(m, info); |
259 | |||
260 | if (level >= 1) | 231 | if (level >= 1) |
261 | len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len); | 232 | stsi_1_2_2(m, info); |
262 | |||
263 | if (level >= 2) | 233 | if (level >= 2) |
264 | len = stsi_2_2_2((struct sysinfo_2_2_2 *) info, page, len); | 234 | stsi_2_2_2(m, info); |
265 | |||
266 | if (level >= 3) | 235 | if (level >= 3) |
267 | len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); | 236 | stsi_3_2_2(m, info); |
237 | free_page((unsigned long)info); | ||
238 | return 0; | ||
239 | } | ||
268 | 240 | ||
269 | free_page(info); | 241 | static int sysinfo_open(struct inode *inode, struct file *file) |
270 | return len; | 242 | { |
243 | return single_open(file, sysinfo_show, NULL); | ||
271 | } | 244 | } |
272 | 245 | ||
273 | static __init int create_proc_sysinfo(void) | 246 | static const struct file_operations sysinfo_fops = { |
247 | .open = sysinfo_open, | ||
248 | .read = seq_read, | ||
249 | .llseek = seq_lseek, | ||
250 | .release = single_release, | ||
251 | }; | ||
252 | |||
253 | static int __init sysinfo_create_proc(void) | ||
274 | { | 254 | { |
275 | create_proc_read_entry("sysinfo", 0444, NULL, | 255 | proc_create("sysinfo", 0444, NULL, &sysinfo_fops); |
276 | proc_read_sysinfo, NULL); | ||
277 | return 0; | 256 | return 0; |
278 | } | 257 | } |
279 | device_initcall(create_proc_sysinfo); | 258 | device_initcall(sysinfo_create_proc); |
280 | 259 | ||
281 | /* | 260 | /* |
282 | * Service levels interface. | 261 | * Service levels interface. |
@@ -407,7 +386,7 @@ void s390_adjust_jiffies(void) | |||
407 | if (!info) | 386 | if (!info) |
408 | return; | 387 | return; |
409 | 388 | ||
410 | if (stsi(info, 1, 2, 2) != -ENOSYS) { | 389 | if (stsi(info, 1, 2, 2) == 0) { |
411 | /* | 390 | /* |
412 | * Major sigh. The cpu capability encoding is "special". | 391 | * Major sigh. The cpu capability encoding is "special". |
413 | * If the first 9 bits of info->capability are 0 then it | 392 | * If the first 9 bits of info->capability are 0 then it |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index dcec960fc724..2db1011b8b19 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -329,7 +329,7 @@ static unsigned long clock_sync_flags; | |||
329 | * The synchronous get_clock function. It will write the current clock | 329 | * The synchronous get_clock function. It will write the current clock |
330 | * value to the clock pointer and return 0 if the clock is in sync with | 330 | * value to the clock pointer and return 0 if the clock is in sync with |
331 | * the external time source. If the clock mode is local it will return | 331 | * the external time source. If the clock mode is local it will return |
332 | * -ENOSYS and -EAGAIN if the clock is not in sync with the external | 332 | * -EOPNOTSUPP and -EAGAIN if the clock is not in sync with the external |
333 | * reference. | 333 | * reference. |
334 | */ | 334 | */ |
335 | int get_sync_clock(unsigned long long *clock) | 335 | int get_sync_clock(unsigned long long *clock) |
@@ -347,7 +347,7 @@ int get_sync_clock(unsigned long long *clock) | |||
347 | return 0; | 347 | return 0; |
348 | if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags) && | 348 | if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags) && |
349 | !test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) | 349 | !test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) |
350 | return -ENOSYS; | 350 | return -EOPNOTSUPP; |
351 | if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags) && | 351 | if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags) && |
352 | !test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) | 352 | !test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) |
353 | return -EACCES; | 353 | return -EACCES; |
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 05151e06c388..54d93f4b6818 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/cpu.h> | 17 | #include <linux/cpu.h> |
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
20 | #include <asm/sysinfo.h> | ||
20 | 21 | ||
21 | #define PTF_HORIZONTAL (0UL) | 22 | #define PTF_HORIZONTAL (0UL) |
22 | #define PTF_VERTICAL (1UL) | 23 | #define PTF_VERTICAL (1UL) |
@@ -44,9 +45,6 @@ static struct mask_info book_info; | |||
44 | cpumask_t cpu_book_map[NR_CPUS]; | 45 | cpumask_t cpu_book_map[NR_CPUS]; |
45 | unsigned char cpu_book_id[NR_CPUS]; | 46 | unsigned char cpu_book_id[NR_CPUS]; |
46 | 47 | ||
47 | /* smp_cpu_state_mutex must be held when accessing this array */ | ||
48 | int cpu_polarization[NR_CPUS]; | ||
49 | |||
50 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) | 48 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) |
51 | { | 49 | { |
52 | cpumask_t mask; | 50 | cpumask_t mask; |
@@ -75,10 +73,7 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu, | |||
75 | { | 73 | { |
76 | unsigned int cpu; | 74 | unsigned int cpu; |
77 | 75 | ||
78 | for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS); | 76 | for_each_set_bit(cpu, &tl_cpu->mask[0], TOPOLOGY_CPU_BITS) { |
79 | cpu < TOPOLOGY_CPU_BITS; | ||
80 | cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1)) | ||
81 | { | ||
82 | unsigned int rcpu; | 77 | unsigned int rcpu; |
83 | int lcpu; | 78 | int lcpu; |
84 | 79 | ||
@@ -94,7 +89,7 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu, | |||
94 | } else { | 89 | } else { |
95 | cpu_core_id[lcpu] = core->id; | 90 | cpu_core_id[lcpu] = core->id; |
96 | } | 91 | } |
97 | cpu_set_polarization(lcpu, tl_cpu->pp); | 92 | smp_cpu_set_polarization(lcpu, tl_cpu->pp); |
98 | } | 93 | } |
99 | } | 94 | } |
100 | return core; | 95 | return core; |
@@ -201,7 +196,7 @@ static void topology_update_polarization_simple(void) | |||
201 | 196 | ||
202 | mutex_lock(&smp_cpu_state_mutex); | 197 | mutex_lock(&smp_cpu_state_mutex); |
203 | for_each_possible_cpu(cpu) | 198 | for_each_possible_cpu(cpu) |
204 | cpu_set_polarization(cpu, POLARIZATION_HRZ); | 199 | smp_cpu_set_polarization(cpu, POLARIZATION_HRZ); |
205 | mutex_unlock(&smp_cpu_state_mutex); | 200 | mutex_unlock(&smp_cpu_state_mutex); |
206 | } | 201 | } |
207 | 202 | ||
@@ -231,7 +226,7 @@ int topology_set_cpu_management(int fc) | |||
231 | if (rc) | 226 | if (rc) |
232 | return -EBUSY; | 227 | return -EBUSY; |
233 | for_each_possible_cpu(cpu) | 228 | for_each_possible_cpu(cpu) |
234 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 229 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
235 | return rc; | 230 | return rc; |
236 | } | 231 | } |
237 | 232 | ||
@@ -250,12 +245,10 @@ static void update_cpu_core_map(void) | |||
250 | 245 | ||
251 | void store_topology(struct sysinfo_15_1_x *info) | 246 | void store_topology(struct sysinfo_15_1_x *info) |
252 | { | 247 | { |
253 | int rc; | 248 | if (topology_max_mnest >= 3) |
254 | 249 | stsi(info, 15, 1, 3); | |
255 | rc = stsi(info, 15, 1, 3); | 250 | else |
256 | if (rc != -ENOSYS) | 251 | stsi(info, 15, 1, 2); |
257 | return; | ||
258 | stsi(info, 15, 1, 2); | ||
259 | } | 252 | } |
260 | 253 | ||
261 | int arch_update_cpu_topology(void) | 254 | int arch_update_cpu_topology(void) |
@@ -415,7 +408,7 @@ static ssize_t cpu_polarization_show(struct device *dev, | |||
415 | ssize_t count; | 408 | ssize_t count; |
416 | 409 | ||
417 | mutex_lock(&smp_cpu_state_mutex); | 410 | mutex_lock(&smp_cpu_state_mutex); |
418 | switch (cpu_read_polarization(cpu)) { | 411 | switch (smp_cpu_get_polarization(cpu)) { |
419 | case POLARIZATION_HRZ: | 412 | case POLARIZATION_HRZ: |
420 | count = sprintf(buf, "horizontal\n"); | 413 | count = sprintf(buf, "horizontal\n"); |
421 | break; | 414 | break; |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 01775c04a90e..3d2b0fa37db0 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -57,6 +57,23 @@ static int kstack_depth_to_print = 12; | |||
57 | static int kstack_depth_to_print = 20; | 57 | static int kstack_depth_to_print = 20; |
58 | #endif /* CONFIG_64BIT */ | 58 | #endif /* CONFIG_64BIT */ |
59 | 59 | ||
60 | static inline void __user *get_trap_ip(struct pt_regs *regs) | ||
61 | { | ||
62 | #ifdef CONFIG_64BIT | ||
63 | unsigned long address; | ||
64 | |||
65 | if (regs->int_code & 0x200) | ||
66 | address = *(unsigned long *)(current->thread.trap_tdb + 24); | ||
67 | else | ||
68 | address = regs->psw.addr; | ||
69 | return (void __user *) | ||
70 | ((address - (regs->int_code >> 16)) & PSW_ADDR_INSN); | ||
71 | #else | ||
72 | return (void __user *) | ||
73 | ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN); | ||
74 | #endif | ||
75 | } | ||
76 | |||
60 | /* | 77 | /* |
61 | * For show_trace we have tree different stack to consider: | 78 | * For show_trace we have tree different stack to consider: |
62 | * - the panic stack which is used if the kernel stack has overflown | 79 | * - the panic stack which is used if the kernel stack has overflown |
@@ -214,7 +231,6 @@ void show_registers(struct pt_regs *regs) | |||
214 | 231 | ||
215 | void show_regs(struct pt_regs *regs) | 232 | void show_regs(struct pt_regs *regs) |
216 | { | 233 | { |
217 | print_modules(); | ||
218 | printk("CPU: %d %s %s %.*s\n", | 234 | printk("CPU: %d %s %s %.*s\n", |
219 | task_thread_info(current)->cpu, print_tainted(), | 235 | task_thread_info(current)->cpu, print_tainted(), |
220 | init_utsname()->release, | 236 | init_utsname()->release, |
@@ -254,6 +270,7 @@ void die(struct pt_regs *regs, const char *str) | |||
254 | #endif | 270 | #endif |
255 | printk("\n"); | 271 | printk("\n"); |
256 | notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV); | 272 | notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV); |
273 | print_modules(); | ||
257 | show_regs(regs); | 274 | show_regs(regs); |
258 | bust_spinlocks(0); | 275 | bust_spinlocks(0); |
259 | add_taint(TAINT_DIE); | 276 | add_taint(TAINT_DIE); |
@@ -285,12 +302,6 @@ int is_valid_bugaddr(unsigned long addr) | |||
285 | return 1; | 302 | return 1; |
286 | } | 303 | } |
287 | 304 | ||
288 | static inline void __user *get_psw_address(struct pt_regs *regs) | ||
289 | { | ||
290 | return (void __user *) | ||
291 | ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN); | ||
292 | } | ||
293 | |||
294 | static void __kprobes do_trap(struct pt_regs *regs, | 305 | static void __kprobes do_trap(struct pt_regs *regs, |
295 | int si_signo, int si_code, char *str) | 306 | int si_signo, int si_code, char *str) |
296 | { | 307 | { |
@@ -304,14 +315,14 @@ static void __kprobes do_trap(struct pt_regs *regs, | |||
304 | info.si_signo = si_signo; | 315 | info.si_signo = si_signo; |
305 | info.si_errno = 0; | 316 | info.si_errno = 0; |
306 | info.si_code = si_code; | 317 | info.si_code = si_code; |
307 | info.si_addr = get_psw_address(regs); | 318 | info.si_addr = get_trap_ip(regs); |
308 | force_sig_info(si_signo, &info, current); | 319 | force_sig_info(si_signo, &info, current); |
309 | report_user_fault(regs, si_signo); | 320 | report_user_fault(regs, si_signo); |
310 | } else { | 321 | } else { |
311 | const struct exception_table_entry *fixup; | 322 | const struct exception_table_entry *fixup; |
312 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 323 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
313 | if (fixup) | 324 | if (fixup) |
314 | regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; | 325 | regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE; |
315 | else { | 326 | else { |
316 | enum bug_trap_type btt; | 327 | enum bug_trap_type btt; |
317 | 328 | ||
@@ -381,6 +392,11 @@ DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, | |||
381 | DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, | 392 | DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, |
382 | "translation exception") | 393 | "translation exception") |
383 | 394 | ||
395 | #ifdef CONFIG_64BIT | ||
396 | DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN, | ||
397 | "transaction constraint exception") | ||
398 | #endif | ||
399 | |||
384 | static inline void do_fp_trap(struct pt_regs *regs, int fpc) | 400 | static inline void do_fp_trap(struct pt_regs *regs, int fpc) |
385 | { | 401 | { |
386 | int si_code = 0; | 402 | int si_code = 0; |
@@ -408,7 +424,7 @@ static void __kprobes illegal_op(struct pt_regs *regs) | |||
408 | __u16 __user *location; | 424 | __u16 __user *location; |
409 | int signal = 0; | 425 | int signal = 0; |
410 | 426 | ||
411 | location = get_psw_address(regs); | 427 | location = get_trap_ip(regs); |
412 | 428 | ||
413 | if (user_mode(regs)) { | 429 | if (user_mode(regs)) { |
414 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) | 430 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) |
@@ -476,7 +492,7 @@ void specification_exception(struct pt_regs *regs) | |||
476 | __u16 __user *location = NULL; | 492 | __u16 __user *location = NULL; |
477 | int signal = 0; | 493 | int signal = 0; |
478 | 494 | ||
479 | location = (__u16 __user *) get_psw_address(regs); | 495 | location = (__u16 __user *) get_trap_ip(regs); |
480 | 496 | ||
481 | if (user_mode(regs)) { | 497 | if (user_mode(regs)) { |
482 | get_user(*((__u16 *) opcode), location); | 498 | get_user(*((__u16 *) opcode), location); |
@@ -525,7 +541,7 @@ static void data_exception(struct pt_regs *regs) | |||
525 | __u16 __user *location; | 541 | __u16 __user *location; |
526 | int signal = 0; | 542 | int signal = 0; |
527 | 543 | ||
528 | location = get_psw_address(regs); | 544 | location = get_trap_ip(regs); |
529 | 545 | ||
530 | if (MACHINE_HAS_IEEE) | 546 | if (MACHINE_HAS_IEEE) |
531 | asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); | 547 | asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); |
@@ -641,6 +657,7 @@ void __init trap_init(void) | |||
641 | pgm_check_table[0x12] = &translation_exception; | 657 | pgm_check_table[0x12] = &translation_exception; |
642 | pgm_check_table[0x13] = &special_op_exception; | 658 | pgm_check_table[0x13] = &special_op_exception; |
643 | #ifdef CONFIG_64BIT | 659 | #ifdef CONFIG_64BIT |
660 | pgm_check_table[0x18] = &transaction_exception; | ||
644 | pgm_check_table[0x38] = &do_asce_exception; | 661 | pgm_check_table[0x38] = &do_asce_exception; |
645 | pgm_check_table[0x39] = &do_dat_exception; | 662 | pgm_check_table[0x39] = &do_dat_exception; |
646 | pgm_check_table[0x3A] = &do_dat_exception; | 663 | pgm_check_table[0x3A] = &do_dat_exception; |
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 9a19ca367c17..d7776281cb60 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c | |||
@@ -85,7 +85,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data; | |||
85 | static void vdso_init_data(struct vdso_data *vd) | 85 | static void vdso_init_data(struct vdso_data *vd) |
86 | { | 86 | { |
87 | vd->ectg_available = | 87 | vd->ectg_available = |
88 | addressing_mode != HOME_SPACE_MODE && test_facility(31); | 88 | s390_user_mode != HOME_SPACE_MODE && test_facility(31); |
89 | } | 89 | } |
90 | 90 | ||
91 | #ifdef CONFIG_64BIT | 91 | #ifdef CONFIG_64BIT |
@@ -102,7 +102,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore) | |||
102 | 102 | ||
103 | lowcore->vdso_per_cpu_data = __LC_PASTE; | 103 | lowcore->vdso_per_cpu_data = __LC_PASTE; |
104 | 104 | ||
105 | if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) | 105 | if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) |
106 | return 0; | 106 | return 0; |
107 | 107 | ||
108 | segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER); | 108 | segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER); |
@@ -147,7 +147,7 @@ void vdso_free_per_cpu(struct _lowcore *lowcore) | |||
147 | unsigned long segment_table, page_table, page_frame; | 147 | unsigned long segment_table, page_table, page_frame; |
148 | u32 *psal, *aste; | 148 | u32 *psal, *aste; |
149 | 149 | ||
150 | if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) | 150 | if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) |
151 | return; | 151 | return; |
152 | 152 | ||
153 | psal = (u32 *)(addr_t) lowcore->paste[4]; | 153 | psal = (u32 *)(addr_t) lowcore->paste[4]; |
@@ -165,7 +165,7 @@ static void vdso_init_cr5(void) | |||
165 | { | 165 | { |
166 | unsigned long cr5; | 166 | unsigned long cr5; |
167 | 167 | ||
168 | if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) | 168 | if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) |
169 | return; | 169 | return; |
170 | cr5 = offsetof(struct _lowcore, paste); | 170 | cr5 = offsetof(struct _lowcore, paste); |
171 | __ctl_load(cr5, 5, 5); | 171 | __ctl_load(cr5, 5, 5); |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 4fc97b40a6e1..790334427895 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -99,7 +99,7 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset) | |||
99 | return virt_timer_forward(user + system); | 99 | return virt_timer_forward(user + system); |
100 | } | 100 | } |
101 | 101 | ||
102 | void account_vtime(struct task_struct *prev, struct task_struct *next) | 102 | void vtime_task_switch(struct task_struct *prev) |
103 | { | 103 | { |
104 | struct thread_info *ti; | 104 | struct thread_info *ti; |
105 | 105 | ||
@@ -107,7 +107,7 @@ void account_vtime(struct task_struct *prev, struct task_struct *next) | |||
107 | ti = task_thread_info(prev); | 107 | ti = task_thread_info(prev); |
108 | ti->user_timer = S390_lowcore.user_timer; | 108 | ti->user_timer = S390_lowcore.user_timer; |
109 | ti->system_timer = S390_lowcore.system_timer; | 109 | ti->system_timer = S390_lowcore.system_timer; |
110 | ti = task_thread_info(next); | 110 | ti = task_thread_info(current); |
111 | S390_lowcore.user_timer = ti->user_timer; | 111 | S390_lowcore.user_timer = ti->user_timer; |
112 | S390_lowcore.system_timer = ti->system_timer; | 112 | S390_lowcore.system_timer = ti->system_timer; |
113 | } | 113 | } |
@@ -122,7 +122,7 @@ void account_process_tick(struct task_struct *tsk, int user_tick) | |||
122 | * Update process times based on virtual cpu times stored by entry.S | 122 | * Update process times based on virtual cpu times stored by entry.S |
123 | * to the lowcore fields user_timer, system_timer & steal_clock. | 123 | * to the lowcore fields user_timer, system_timer & steal_clock. |
124 | */ | 124 | */ |
125 | void account_system_vtime(struct task_struct *tsk) | 125 | void vtime_account(struct task_struct *tsk) |
126 | { | 126 | { |
127 | struct thread_info *ti = task_thread_info(tsk); | 127 | struct thread_info *ti = task_thread_info(tsk); |
128 | u64 timer, system; | 128 | u64 timer, system; |
@@ -138,7 +138,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
138 | 138 | ||
139 | virt_timer_forward(system); | 139 | virt_timer_forward(system); |
140 | } | 140 | } |
141 | EXPORT_SYMBOL_GPL(account_system_vtime); | 141 | EXPORT_SYMBOL_GPL(vtime_account); |
142 | 142 | ||
143 | void __kprobes vtime_stop_cpu(void) | 143 | void __kprobes vtime_stop_cpu(void) |
144 | { | 144 | { |
@@ -378,9 +378,8 @@ static int __cpuinit s390_nohz_notify(struct notifier_block *self, | |||
378 | long cpu = (long) hcpu; | 378 | long cpu = (long) hcpu; |
379 | 379 | ||
380 | idle = &per_cpu(s390_idle, cpu); | 380 | idle = &per_cpu(s390_idle, cpu); |
381 | switch (action) { | 381 | switch (action & ~CPU_TASKS_FROZEN) { |
382 | case CPU_DYING: | 382 | case CPU_DYING: |
383 | case CPU_DYING_FROZEN: | ||
384 | idle->nohz_delay = 0; | 383 | idle->nohz_delay = 0; |
385 | default: | 384 | default: |
386 | break; | 385 | break; |
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index 78eb9847008f..9b04a32e5695 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig | |||
@@ -5,7 +5,7 @@ source "virt/kvm/Kconfig" | |||
5 | 5 | ||
6 | menuconfig VIRTUALIZATION | 6 | menuconfig VIRTUALIZATION |
7 | def_bool y | 7 | def_bool y |
8 | prompt "Virtualization" | 8 | prompt "KVM" |
9 | ---help--- | 9 | ---help--- |
10 | Say Y here to get to see options for using your Linux host to run other | 10 | Say Y here to get to see options for using your Linux host to run other |
11 | operating systems inside virtual machines (guests). | 11 | operating systems inside virtual machines (guests). |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 60da903d6f3e..310be61bead7 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -211,7 +211,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem) | |||
211 | spin_unlock(&fi->lock); | 211 | spin_unlock(&fi->lock); |
212 | 212 | ||
213 | /* deal with other level 3 hypervisors */ | 213 | /* deal with other level 3 hypervisors */ |
214 | if (stsi(mem, 3, 2, 2) == -ENOSYS) | 214 | if (stsi(mem, 3, 2, 2)) |
215 | mem->count = 0; | 215 | mem->count = 0; |
216 | if (mem->count < 8) | 216 | if (mem->count < 8) |
217 | mem->count++; | 217 | mem->count++; |
@@ -259,7 +259,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu) | |||
259 | mem = get_zeroed_page(GFP_KERNEL); | 259 | mem = get_zeroed_page(GFP_KERNEL); |
260 | if (!mem) | 260 | if (!mem) |
261 | goto out_fail; | 261 | goto out_fail; |
262 | if (stsi((void *) mem, fc, sel1, sel2) == -ENOSYS) | 262 | if (stsi((void *) mem, fc, sel1, sel2)) |
263 | goto out_mem; | 263 | goto out_mem; |
264 | break; | 264 | break; |
265 | case 3: | 265 | case 3: |
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile index 761ab8b56afc..6ab0d0b5cec8 100644 --- a/arch/s390/lib/Makefile +++ b/arch/s390/lib/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o | 5 | lib-y += delay.o string.o uaccess_std.o uaccess_pt.o |
6 | obj-y += usercopy.o | 6 | obj-y += usercopy.o |
7 | obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o | 7 | obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o |
8 | obj-$(CONFIG_64BIT) += mem64.o | ||
8 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o | 9 | lib-$(CONFIG_64BIT) += uaccess_mvcos.o |
9 | lib-$(CONFIG_SMP) += spinlock.o | 10 | lib-$(CONFIG_SMP) += spinlock.o |
diff --git a/arch/s390/lib/mem32.S b/arch/s390/lib/mem32.S new file mode 100644 index 000000000000..14ca9244b615 --- /dev/null +++ b/arch/s390/lib/mem32.S | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * String handling functions. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2012 | ||
5 | */ | ||
6 | |||
7 | #include <linux/linkage.h> | ||
8 | |||
9 | /* | ||
10 | * memset implementation | ||
11 | * | ||
12 | * This code corresponds to the C construct below. We do distinguish | ||
13 | * between clearing (c == 0) and setting a memory array (c != 0) simply | ||
14 | * because nearly all memset invocations in the kernel clear memory and | ||
15 | * the xc instruction is preferred in such cases. | ||
16 | * | ||
17 | * void *memset(void *s, int c, size_t n) | ||
18 | * { | ||
19 | * if (likely(c == 0)) | ||
20 | * return __builtin_memset(s, 0, n); | ||
21 | * return __builtin_memset(s, c, n); | ||
22 | * } | ||
23 | */ | ||
24 | ENTRY(memset) | ||
25 | basr %r5,%r0 | ||
26 | .Lmemset_base: | ||
27 | ltr %r4,%r4 | ||
28 | bzr %r14 | ||
29 | ltr %r3,%r3 | ||
30 | jnz .Lmemset_fill | ||
31 | ahi %r4,-1 | ||
32 | lr %r3,%r4 | ||
33 | srl %r3,8 | ||
34 | ltr %r3,%r3 | ||
35 | lr %r1,%r2 | ||
36 | je .Lmemset_clear_rest | ||
37 | .Lmemset_clear_loop: | ||
38 | xc 0(256,%r1),0(%r1) | ||
39 | la %r1,256(%r1) | ||
40 | brct %r3,.Lmemset_clear_loop | ||
41 | .Lmemset_clear_rest: | ||
42 | ex %r4,.Lmemset_xc-.Lmemset_base(%r5) | ||
43 | br %r14 | ||
44 | .Lmemset_fill: | ||
45 | stc %r3,0(%r2) | ||
46 | chi %r4,1 | ||
47 | lr %r1,%r2 | ||
48 | ber %r14 | ||
49 | ahi %r4,-2 | ||
50 | lr %r3,%r4 | ||
51 | srl %r3,8 | ||
52 | ltr %r3,%r3 | ||
53 | je .Lmemset_fill_rest | ||
54 | .Lmemset_fill_loop: | ||
55 | mvc 1(256,%r1),0(%r1) | ||
56 | la %r1,256(%r1) | ||
57 | brct %r3,.Lmemset_fill_loop | ||
58 | .Lmemset_fill_rest: | ||
59 | ex %r4,.Lmemset_mvc-.Lmemset_base(%r5) | ||
60 | br %r14 | ||
61 | .Lmemset_xc: | ||
62 | xc 0(1,%r1),0(%r1) | ||
63 | .Lmemset_mvc: | ||
64 | mvc 1(1,%r1),0(%r1) | ||
65 | |||
66 | /* | ||
67 | * memcpy implementation | ||
68 | * | ||
69 | * void *memcpy(void *dest, const void *src, size_t n) | ||
70 | */ | ||
71 | ENTRY(memcpy) | ||
72 | basr %r5,%r0 | ||
73 | .Lmemcpy_base: | ||
74 | ltr %r4,%r4 | ||
75 | bzr %r14 | ||
76 | ahi %r4,-1 | ||
77 | lr %r0,%r4 | ||
78 | srl %r0,8 | ||
79 | ltr %r0,%r0 | ||
80 | lr %r1,%r2 | ||
81 | jnz .Lmemcpy_loop | ||
82 | .Lmemcpy_rest: | ||
83 | ex %r4,.Lmemcpy_mvc-.Lmemcpy_base(%r5) | ||
84 | br %r14 | ||
85 | .Lmemcpy_loop: | ||
86 | mvc 0(256,%r1),0(%r3) | ||
87 | la %r1,256(%r1) | ||
88 | la %r3,256(%r3) | ||
89 | brct %r0,.Lmemcpy_loop | ||
90 | j .Lmemcpy_rest | ||
91 | .Lmemcpy_mvc: | ||
92 | mvc 0(1,%r1),0(%r3) | ||
diff --git a/arch/s390/lib/mem64.S b/arch/s390/lib/mem64.S new file mode 100644 index 000000000000..c6d553e85ab1 --- /dev/null +++ b/arch/s390/lib/mem64.S | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * String handling functions. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2012 | ||
5 | */ | ||
6 | |||
7 | #include <linux/linkage.h> | ||
8 | |||
9 | /* | ||
10 | * memset implementation | ||
11 | * | ||
12 | * This code corresponds to the C construct below. We do distinguish | ||
13 | * between clearing (c == 0) and setting a memory array (c != 0) simply | ||
14 | * because nearly all memset invocations in the kernel clear memory and | ||
15 | * the xc instruction is preferred in such cases. | ||
16 | * | ||
17 | * void *memset(void *s, int c, size_t n) | ||
18 | * { | ||
19 | * if (likely(c == 0)) | ||
20 | * return __builtin_memset(s, 0, n); | ||
21 | * return __builtin_memset(s, c, n); | ||
22 | * } | ||
23 | */ | ||
24 | ENTRY(memset) | ||
25 | ltgr %r4,%r4 | ||
26 | bzr %r14 | ||
27 | ltgr %r3,%r3 | ||
28 | jnz .Lmemset_fill | ||
29 | aghi %r4,-1 | ||
30 | srlg %r3,%r4,8 | ||
31 | ltgr %r3,%r3 | ||
32 | lgr %r1,%r2 | ||
33 | jz .Lmemset_clear_rest | ||
34 | .Lmemset_clear_loop: | ||
35 | xc 0(256,%r1),0(%r1) | ||
36 | la %r1,256(%r1) | ||
37 | brctg %r3,.Lmemset_clear_loop | ||
38 | .Lmemset_clear_rest: | ||
39 | larl %r3,.Lmemset_xc | ||
40 | ex %r4,0(%r3) | ||
41 | br %r14 | ||
42 | .Lmemset_fill: | ||
43 | stc %r3,0(%r2) | ||
44 | cghi %r4,1 | ||
45 | lgr %r1,%r2 | ||
46 | ber %r14 | ||
47 | aghi %r4,-2 | ||
48 | srlg %r3,%r4,8 | ||
49 | ltgr %r3,%r3 | ||
50 | jz .Lmemset_fill_rest | ||
51 | .Lmemset_fill_loop: | ||
52 | mvc 1(256,%r1),0(%r1) | ||
53 | la %r1,256(%r1) | ||
54 | brctg %r3,.Lmemset_fill_loop | ||
55 | .Lmemset_fill_rest: | ||
56 | larl %r3,.Lmemset_mvc | ||
57 | ex %r4,0(%r3) | ||
58 | br %r14 | ||
59 | .Lmemset_xc: | ||
60 | xc 0(1,%r1),0(%r1) | ||
61 | .Lmemset_mvc: | ||
62 | mvc 1(1,%r1),0(%r1) | ||
63 | |||
64 | /* | ||
65 | * memcpy implementation | ||
66 | * | ||
67 | * void *memcpy(void *dest, const void *src, size_t n) | ||
68 | */ | ||
69 | ENTRY(memcpy) | ||
70 | ltgr %r4,%r4 | ||
71 | bzr %r14 | ||
72 | aghi %r4,-1 | ||
73 | srlg %r5,%r4,8 | ||
74 | ltgr %r5,%r5 | ||
75 | lgr %r1,%r2 | ||
76 | jnz .Lmemcpy_loop | ||
77 | .Lmemcpy_rest: | ||
78 | larl %r5,.Lmemcpy_mvc | ||
79 | ex %r4,0(%r5) | ||
80 | br %r14 | ||
81 | .Lmemcpy_loop: | ||
82 | mvc 0(256,%r1),0(%r3) | ||
83 | la %r1,256(%r1) | ||
84 | la %r3,256(%r3) | ||
85 | brctg %r5,.Lmemcpy_loop | ||
86 | j .Lmemcpy_rest | ||
87 | .Lmemcpy_mvc: | ||
88 | mvc 0(1,%r1),0(%r3) | ||
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index 846ec64ab2c9..b647d5ff0ad9 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c | |||
@@ -43,11 +43,7 @@ static inline char *__strnend(const char *s, size_t n) | |||
43 | */ | 43 | */ |
44 | size_t strlen(const char *s) | 44 | size_t strlen(const char *s) |
45 | { | 45 | { |
46 | #if __GNUC__ < 4 | ||
47 | return __strend(s) - s; | 46 | return __strend(s) - s; |
48 | #else | ||
49 | return __builtin_strlen(s); | ||
50 | #endif | ||
51 | } | 47 | } |
52 | EXPORT_SYMBOL(strlen); | 48 | EXPORT_SYMBOL(strlen); |
53 | 49 | ||
@@ -73,7 +69,6 @@ EXPORT_SYMBOL(strnlen); | |||
73 | */ | 69 | */ |
74 | char *strcpy(char *dest, const char *src) | 70 | char *strcpy(char *dest, const char *src) |
75 | { | 71 | { |
76 | #if __GNUC__ < 4 | ||
77 | register int r0 asm("0") = 0; | 72 | register int r0 asm("0") = 0; |
78 | char *ret = dest; | 73 | char *ret = dest; |
79 | 74 | ||
@@ -82,9 +77,6 @@ char *strcpy(char *dest, const char *src) | |||
82 | : "+&a" (dest), "+&a" (src) : "d" (r0) | 77 | : "+&a" (dest), "+&a" (src) : "d" (r0) |
83 | : "cc", "memory" ); | 78 | : "cc", "memory" ); |
84 | return ret; | 79 | return ret; |
85 | #else | ||
86 | return __builtin_strcpy(dest, src); | ||
87 | #endif | ||
88 | } | 80 | } |
89 | EXPORT_SYMBOL(strcpy); | 81 | EXPORT_SYMBOL(strcpy); |
90 | 82 | ||
@@ -106,7 +98,7 @@ size_t strlcpy(char *dest, const char *src, size_t size) | |||
106 | if (size) { | 98 | if (size) { |
107 | size_t len = (ret >= size) ? size-1 : ret; | 99 | size_t len = (ret >= size) ? size-1 : ret; |
108 | dest[len] = '\0'; | 100 | dest[len] = '\0'; |
109 | __builtin_memcpy(dest, src, len); | 101 | memcpy(dest, src, len); |
110 | } | 102 | } |
111 | return ret; | 103 | return ret; |
112 | } | 104 | } |
@@ -124,8 +116,8 @@ EXPORT_SYMBOL(strlcpy); | |||
124 | char *strncpy(char *dest, const char *src, size_t n) | 116 | char *strncpy(char *dest, const char *src, size_t n) |
125 | { | 117 | { |
126 | size_t len = __strnend(src, n) - src; | 118 | size_t len = __strnend(src, n) - src; |
127 | __builtin_memset(dest + len, 0, n - len); | 119 | memset(dest + len, 0, n - len); |
128 | __builtin_memcpy(dest, src, len); | 120 | memcpy(dest, src, len); |
129 | return dest; | 121 | return dest; |
130 | } | 122 | } |
131 | EXPORT_SYMBOL(strncpy); | 123 | EXPORT_SYMBOL(strncpy); |
@@ -171,7 +163,7 @@ size_t strlcat(char *dest, const char *src, size_t n) | |||
171 | if (len >= n) | 163 | if (len >= n) |
172 | len = n - 1; | 164 | len = n - 1; |
173 | dest[len] = '\0'; | 165 | dest[len] = '\0'; |
174 | __builtin_memcpy(dest, src, len); | 166 | memcpy(dest, src, len); |
175 | } | 167 | } |
176 | return res; | 168 | return res; |
177 | } | 169 | } |
@@ -194,7 +186,7 @@ char *strncat(char *dest, const char *src, size_t n) | |||
194 | char *p = __strend(dest); | 186 | char *p = __strend(dest); |
195 | 187 | ||
196 | p[len] = '\0'; | 188 | p[len] = '\0'; |
197 | __builtin_memcpy(p, src, len); | 189 | memcpy(p, src, len); |
198 | return dest; | 190 | return dest; |
199 | } | 191 | } |
200 | EXPORT_SYMBOL(strncat); | 192 | EXPORT_SYMBOL(strncat); |
@@ -348,41 +340,3 @@ void *memscan(void *s, int c, size_t n) | |||
348 | return (void *) ret; | 340 | return (void *) ret; |
349 | } | 341 | } |
350 | EXPORT_SYMBOL(memscan); | 342 | EXPORT_SYMBOL(memscan); |
351 | |||
352 | /** | ||
353 | * memcpy - Copy one area of memory to another | ||
354 | * @dest: Where to copy to | ||
355 | * @src: Where to copy from | ||
356 | * @n: The size of the area. | ||
357 | * | ||
358 | * returns a pointer to @dest | ||
359 | */ | ||
360 | void *memcpy(void *dest, const void *src, size_t n) | ||
361 | { | ||
362 | return __builtin_memcpy(dest, src, n); | ||
363 | } | ||
364 | EXPORT_SYMBOL(memcpy); | ||
365 | |||
366 | /** | ||
367 | * memset - Fill a region of memory with the given value | ||
368 | * @s: Pointer to the start of the area. | ||
369 | * @c: The byte to fill the area with | ||
370 | * @n: The size of the area. | ||
371 | * | ||
372 | * returns a pointer to @s | ||
373 | */ | ||
374 | void *memset(void *s, int c, size_t n) | ||
375 | { | ||
376 | char *xs; | ||
377 | |||
378 | if (c == 0) | ||
379 | return __builtin_memset(s, 0, n); | ||
380 | |||
381 | xs = (char *) s; | ||
382 | if (n > 0) | ||
383 | do { | ||
384 | *xs++ = c; | ||
385 | } while (--n > 0); | ||
386 | return s; | ||
387 | } | ||
388 | EXPORT_SYMBOL(memset); | ||
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index 60ee2b883797..2d37bb861faf 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c | |||
@@ -2,69 +2,82 @@ | |||
2 | * User access functions based on page table walks for enhanced | 2 | * User access functions based on page table walks for enhanced |
3 | * system layout without hardware support. | 3 | * system layout without hardware support. |
4 | * | 4 | * |
5 | * Copyright IBM Corp. 2006 | 5 | * Copyright IBM Corp. 2006, 2012 |
6 | * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com) | 6 | * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/hardirq.h> | 10 | #include <linux/hardirq.h> |
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/hugetlb.h> | ||
12 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
13 | #include <asm/futex.h> | 14 | #include <asm/futex.h> |
14 | #include "uaccess.h" | 15 | #include "uaccess.h" |
15 | 16 | ||
16 | static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr) | 17 | |
18 | /* | ||
19 | * Returns kernel address for user virtual address. If the returned address is | ||
20 | * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address | ||
21 | * contains the (negative) exception code. | ||
22 | */ | ||
23 | static __always_inline unsigned long follow_table(struct mm_struct *mm, | ||
24 | unsigned long addr, int write) | ||
17 | { | 25 | { |
18 | pgd_t *pgd; | 26 | pgd_t *pgd; |
19 | pud_t *pud; | 27 | pud_t *pud; |
20 | pmd_t *pmd; | 28 | pmd_t *pmd; |
29 | pte_t *ptep; | ||
21 | 30 | ||
22 | pgd = pgd_offset(mm, addr); | 31 | pgd = pgd_offset(mm, addr); |
23 | if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) | 32 | if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) |
24 | return (pte_t *) 0x3a; | 33 | return -0x3aUL; |
25 | 34 | ||
26 | pud = pud_offset(pgd, addr); | 35 | pud = pud_offset(pgd, addr); |
27 | if (pud_none(*pud) || unlikely(pud_bad(*pud))) | 36 | if (pud_none(*pud) || unlikely(pud_bad(*pud))) |
28 | return (pte_t *) 0x3b; | 37 | return -0x3bUL; |
29 | 38 | ||
30 | pmd = pmd_offset(pud, addr); | 39 | pmd = pmd_offset(pud, addr); |
31 | if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) | 40 | if (pmd_none(*pmd)) |
32 | return (pte_t *) 0x10; | 41 | return -0x10UL; |
42 | if (pmd_huge(*pmd)) { | ||
43 | if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO)) | ||
44 | return -0x04UL; | ||
45 | return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK); | ||
46 | } | ||
47 | if (unlikely(pmd_bad(*pmd))) | ||
48 | return -0x10UL; | ||
49 | |||
50 | ptep = pte_offset_map(pmd, addr); | ||
51 | if (!pte_present(*ptep)) | ||
52 | return -0x11UL; | ||
53 | if (write && !pte_write(*ptep)) | ||
54 | return -0x04UL; | ||
33 | 55 | ||
34 | return pte_offset_map(pmd, addr); | 56 | return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK); |
35 | } | 57 | } |
36 | 58 | ||
37 | static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, | 59 | static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr, |
38 | size_t n, int write_user) | 60 | size_t n, int write_user) |
39 | { | 61 | { |
40 | struct mm_struct *mm = current->mm; | 62 | struct mm_struct *mm = current->mm; |
41 | unsigned long offset, pfn, done, size; | 63 | unsigned long offset, done, size, kaddr; |
42 | pte_t *pte; | ||
43 | void *from, *to; | 64 | void *from, *to; |
44 | 65 | ||
45 | done = 0; | 66 | done = 0; |
46 | retry: | 67 | retry: |
47 | spin_lock(&mm->page_table_lock); | 68 | spin_lock(&mm->page_table_lock); |
48 | do { | 69 | do { |
49 | pte = follow_table(mm, uaddr); | 70 | kaddr = follow_table(mm, uaddr, write_user); |
50 | if ((unsigned long) pte < 0x1000) | 71 | if (IS_ERR_VALUE(kaddr)) |
51 | goto fault; | 72 | goto fault; |
52 | if (!pte_present(*pte)) { | ||
53 | pte = (pte_t *) 0x11; | ||
54 | goto fault; | ||
55 | } else if (write_user && !pte_write(*pte)) { | ||
56 | pte = (pte_t *) 0x04; | ||
57 | goto fault; | ||
58 | } | ||
59 | 73 | ||
60 | pfn = pte_pfn(*pte); | 74 | offset = uaddr & ~PAGE_MASK; |
61 | offset = uaddr & (PAGE_SIZE - 1); | ||
62 | size = min(n - done, PAGE_SIZE - offset); | 75 | size = min(n - done, PAGE_SIZE - offset); |
63 | if (write_user) { | 76 | if (write_user) { |
64 | to = (void *)((pfn << PAGE_SHIFT) + offset); | 77 | to = (void *) kaddr; |
65 | from = kptr + done; | 78 | from = kptr + done; |
66 | } else { | 79 | } else { |
67 | from = (void *)((pfn << PAGE_SHIFT) + offset); | 80 | from = (void *) kaddr; |
68 | to = kptr + done; | 81 | to = kptr + done; |
69 | } | 82 | } |
70 | memcpy(to, from, size); | 83 | memcpy(to, from, size); |
@@ -75,7 +88,7 @@ retry: | |||
75 | return n - done; | 88 | return n - done; |
76 | fault: | 89 | fault: |
77 | spin_unlock(&mm->page_table_lock); | 90 | spin_unlock(&mm->page_table_lock); |
78 | if (__handle_fault(uaddr, (unsigned long) pte, write_user)) | 91 | if (__handle_fault(uaddr, -kaddr, write_user)) |
79 | return n - done; | 92 | return n - done; |
80 | goto retry; | 93 | goto retry; |
81 | } | 94 | } |
@@ -84,27 +97,22 @@ fault: | |||
84 | * Do DAT for user address by page table walk, return kernel address. | 97 | * Do DAT for user address by page table walk, return kernel address. |
85 | * This function needs to be called with current->mm->page_table_lock held. | 98 | * This function needs to be called with current->mm->page_table_lock held. |
86 | */ | 99 | */ |
87 | static __always_inline unsigned long __dat_user_addr(unsigned long uaddr) | 100 | static __always_inline unsigned long __dat_user_addr(unsigned long uaddr, |
101 | int write) | ||
88 | { | 102 | { |
89 | struct mm_struct *mm = current->mm; | 103 | struct mm_struct *mm = current->mm; |
90 | unsigned long pfn; | 104 | unsigned long kaddr; |
91 | pte_t *pte; | ||
92 | int rc; | 105 | int rc; |
93 | 106 | ||
94 | retry: | 107 | retry: |
95 | pte = follow_table(mm, uaddr); | 108 | kaddr = follow_table(mm, uaddr, write); |
96 | if ((unsigned long) pte < 0x1000) | 109 | if (IS_ERR_VALUE(kaddr)) |
97 | goto fault; | ||
98 | if (!pte_present(*pte)) { | ||
99 | pte = (pte_t *) 0x11; | ||
100 | goto fault; | 110 | goto fault; |
101 | } | ||
102 | 111 | ||
103 | pfn = pte_pfn(*pte); | 112 | return kaddr; |
104 | return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1)); | ||
105 | fault: | 113 | fault: |
106 | spin_unlock(&mm->page_table_lock); | 114 | spin_unlock(&mm->page_table_lock); |
107 | rc = __handle_fault(uaddr, (unsigned long) pte, 0); | 115 | rc = __handle_fault(uaddr, -kaddr, write); |
108 | spin_lock(&mm->page_table_lock); | 116 | spin_lock(&mm->page_table_lock); |
109 | if (!rc) | 117 | if (!rc) |
110 | goto retry; | 118 | goto retry; |
@@ -159,11 +167,9 @@ static size_t clear_user_pt(size_t n, void __user *to) | |||
159 | 167 | ||
160 | static size_t strnlen_user_pt(size_t count, const char __user *src) | 168 | static size_t strnlen_user_pt(size_t count, const char __user *src) |
161 | { | 169 | { |
162 | char *addr; | ||
163 | unsigned long uaddr = (unsigned long) src; | 170 | unsigned long uaddr = (unsigned long) src; |
164 | struct mm_struct *mm = current->mm; | 171 | struct mm_struct *mm = current->mm; |
165 | unsigned long offset, pfn, done, len; | 172 | unsigned long offset, done, len, kaddr; |
166 | pte_t *pte; | ||
167 | size_t len_str; | 173 | size_t len_str; |
168 | 174 | ||
169 | if (segment_eq(get_fs(), KERNEL_DS)) | 175 | if (segment_eq(get_fs(), KERNEL_DS)) |
@@ -172,19 +178,13 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) | |||
172 | retry: | 178 | retry: |
173 | spin_lock(&mm->page_table_lock); | 179 | spin_lock(&mm->page_table_lock); |
174 | do { | 180 | do { |
175 | pte = follow_table(mm, uaddr); | 181 | kaddr = follow_table(mm, uaddr, 0); |
176 | if ((unsigned long) pte < 0x1000) | 182 | if (IS_ERR_VALUE(kaddr)) |
177 | goto fault; | ||
178 | if (!pte_present(*pte)) { | ||
179 | pte = (pte_t *) 0x11; | ||
180 | goto fault; | 183 | goto fault; |
181 | } | ||
182 | 184 | ||
183 | pfn = pte_pfn(*pte); | 185 | offset = uaddr & ~PAGE_MASK; |
184 | offset = uaddr & (PAGE_SIZE-1); | ||
185 | addr = (char *)(pfn << PAGE_SHIFT) + offset; | ||
186 | len = min(count - done, PAGE_SIZE - offset); | 186 | len = min(count - done, PAGE_SIZE - offset); |
187 | len_str = strnlen(addr, len); | 187 | len_str = strnlen((char *) kaddr, len); |
188 | done += len_str; | 188 | done += len_str; |
189 | uaddr += len_str; | 189 | uaddr += len_str; |
190 | } while ((len_str == len) && (done < count)); | 190 | } while ((len_str == len) && (done < count)); |
@@ -192,7 +192,7 @@ retry: | |||
192 | return done + 1; | 192 | return done + 1; |
193 | fault: | 193 | fault: |
194 | spin_unlock(&mm->page_table_lock); | 194 | spin_unlock(&mm->page_table_lock); |
195 | if (__handle_fault(uaddr, (unsigned long) pte, 0)) | 195 | if (__handle_fault(uaddr, -kaddr, 0)) |
196 | return 0; | 196 | return 0; |
197 | goto retry; | 197 | goto retry; |
198 | } | 198 | } |
@@ -225,11 +225,10 @@ static size_t copy_in_user_pt(size_t n, void __user *to, | |||
225 | const void __user *from) | 225 | const void __user *from) |
226 | { | 226 | { |
227 | struct mm_struct *mm = current->mm; | 227 | struct mm_struct *mm = current->mm; |
228 | unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to, | 228 | unsigned long offset_max, uaddr, done, size, error_code; |
229 | uaddr, done, size, error_code; | ||
230 | unsigned long uaddr_from = (unsigned long) from; | 229 | unsigned long uaddr_from = (unsigned long) from; |
231 | unsigned long uaddr_to = (unsigned long) to; | 230 | unsigned long uaddr_to = (unsigned long) to; |
232 | pte_t *pte_from, *pte_to; | 231 | unsigned long kaddr_to, kaddr_from; |
233 | int write_user; | 232 | int write_user; |
234 | 233 | ||
235 | if (segment_eq(get_fs(), KERNEL_DS)) { | 234 | if (segment_eq(get_fs(), KERNEL_DS)) { |
@@ -242,38 +241,23 @@ retry: | |||
242 | do { | 241 | do { |
243 | write_user = 0; | 242 | write_user = 0; |
244 | uaddr = uaddr_from; | 243 | uaddr = uaddr_from; |
245 | pte_from = follow_table(mm, uaddr_from); | 244 | kaddr_from = follow_table(mm, uaddr_from, 0); |
246 | error_code = (unsigned long) pte_from; | 245 | error_code = kaddr_from; |
247 | if (error_code < 0x1000) | 246 | if (IS_ERR_VALUE(error_code)) |
248 | goto fault; | ||
249 | if (!pte_present(*pte_from)) { | ||
250 | error_code = 0x11; | ||
251 | goto fault; | 247 | goto fault; |
252 | } | ||
253 | 248 | ||
254 | write_user = 1; | 249 | write_user = 1; |
255 | uaddr = uaddr_to; | 250 | uaddr = uaddr_to; |
256 | pte_to = follow_table(mm, uaddr_to); | 251 | kaddr_to = follow_table(mm, uaddr_to, 1); |
257 | error_code = (unsigned long) pte_to; | 252 | error_code = (unsigned long) kaddr_to; |
258 | if (error_code < 0x1000) | 253 | if (IS_ERR_VALUE(error_code)) |
259 | goto fault; | ||
260 | if (!pte_present(*pte_to)) { | ||
261 | error_code = 0x11; | ||
262 | goto fault; | 254 | goto fault; |
263 | } else if (!pte_write(*pte_to)) { | ||
264 | error_code = 0x04; | ||
265 | goto fault; | ||
266 | } | ||
267 | 255 | ||
268 | pfn_from = pte_pfn(*pte_from); | 256 | offset_max = max(uaddr_from & ~PAGE_MASK, |
269 | pfn_to = pte_pfn(*pte_to); | 257 | uaddr_to & ~PAGE_MASK); |
270 | offset_from = uaddr_from & (PAGE_SIZE-1); | ||
271 | offset_to = uaddr_from & (PAGE_SIZE-1); | ||
272 | offset_max = max(offset_from, offset_to); | ||
273 | size = min(n - done, PAGE_SIZE - offset_max); | 258 | size = min(n - done, PAGE_SIZE - offset_max); |
274 | 259 | ||
275 | memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to, | 260 | memcpy((void *) kaddr_to, (void *) kaddr_from, size); |
276 | (void *)(pfn_from << PAGE_SHIFT) + offset_from, size); | ||
277 | done += size; | 261 | done += size; |
278 | uaddr_from += size; | 262 | uaddr_from += size; |
279 | uaddr_to += size; | 263 | uaddr_to += size; |
@@ -282,7 +266,7 @@ retry: | |||
282 | return n - done; | 266 | return n - done; |
283 | fault: | 267 | fault: |
284 | spin_unlock(&mm->page_table_lock); | 268 | spin_unlock(&mm->page_table_lock); |
285 | if (__handle_fault(uaddr, error_code, write_user)) | 269 | if (__handle_fault(uaddr, -error_code, write_user)) |
286 | return n - done; | 270 | return n - done; |
287 | goto retry; | 271 | goto retry; |
288 | } | 272 | } |
@@ -341,7 +325,7 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old) | |||
341 | return __futex_atomic_op_pt(op, uaddr, oparg, old); | 325 | return __futex_atomic_op_pt(op, uaddr, oparg, old); |
342 | spin_lock(¤t->mm->page_table_lock); | 326 | spin_lock(¤t->mm->page_table_lock); |
343 | uaddr = (u32 __force __user *) | 327 | uaddr = (u32 __force __user *) |
344 | __dat_user_addr((__force unsigned long) uaddr); | 328 | __dat_user_addr((__force unsigned long) uaddr, 1); |
345 | if (!uaddr) { | 329 | if (!uaddr) { |
346 | spin_unlock(¤t->mm->page_table_lock); | 330 | spin_unlock(¤t->mm->page_table_lock); |
347 | return -EFAULT; | 331 | return -EFAULT; |
@@ -378,7 +362,7 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr, | |||
378 | return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); | 362 | return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval); |
379 | spin_lock(¤t->mm->page_table_lock); | 363 | spin_lock(¤t->mm->page_table_lock); |
380 | uaddr = (u32 __force __user *) | 364 | uaddr = (u32 __force __user *) |
381 | __dat_user_addr((__force unsigned long) uaddr); | 365 | __dat_user_addr((__force unsigned long) uaddr, 1); |
382 | if (!uaddr) { | 366 | if (!uaddr) { |
383 | spin_unlock(¤t->mm->page_table_lock); | 367 | spin_unlock(¤t->mm->page_table_lock); |
384 | return -EFAULT; | 368 | return -EFAULT; |
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile index d98fe9004a52..0f5536b0c1a1 100644 --- a/arch/s390/mm/Makefile +++ b/arch/s390/mm/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \ | 5 | obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \ |
6 | page-states.o gup.o | 6 | page-states.o gup.o extable.o |
7 | obj-$(CONFIG_CMM) += cmm.o | 7 | obj-$(CONFIG_CMM) += cmm.o |
8 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 8 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
9 | obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o | 9 | obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o |
diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c new file mode 100644 index 000000000000..4d1ee88864e8 --- /dev/null +++ b/arch/s390/mm/extable.c | |||
@@ -0,0 +1,81 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/sort.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | /* | ||
6 | * Search one exception table for an entry corresponding to the | ||
7 | * given instruction address, and return the address of the entry, | ||
8 | * or NULL if none is found. | ||
9 | * We use a binary search, and thus we assume that the table is | ||
10 | * already sorted. | ||
11 | */ | ||
12 | const struct exception_table_entry * | ||
13 | search_extable(const struct exception_table_entry *first, | ||
14 | const struct exception_table_entry *last, | ||
15 | unsigned long value) | ||
16 | { | ||
17 | const struct exception_table_entry *mid; | ||
18 | unsigned long addr; | ||
19 | |||
20 | while (first <= last) { | ||
21 | mid = ((last - first) >> 1) + first; | ||
22 | addr = extable_insn(mid); | ||
23 | if (addr < value) | ||
24 | first = mid + 1; | ||
25 | else if (addr > value) | ||
26 | last = mid - 1; | ||
27 | else | ||
28 | return mid; | ||
29 | } | ||
30 | return NULL; | ||
31 | } | ||
32 | |||
33 | /* | ||
34 | * The exception table needs to be sorted so that the binary | ||
35 | * search that we use to find entries in it works properly. | ||
36 | * This is used both for the kernel exception table and for | ||
37 | * the exception tables of modules that get loaded. | ||
38 | * | ||
39 | */ | ||
40 | static int cmp_ex(const void *a, const void *b) | ||
41 | { | ||
42 | const struct exception_table_entry *x = a, *y = b; | ||
43 | |||
44 | /* This compare is only valid after normalization. */ | ||
45 | return x->insn - y->insn; | ||
46 | } | ||
47 | |||
48 | void sort_extable(struct exception_table_entry *start, | ||
49 | struct exception_table_entry *finish) | ||
50 | { | ||
51 | struct exception_table_entry *p; | ||
52 | int i; | ||
53 | |||
54 | /* Normalize entries to being relative to the start of the section */ | ||
55 | for (p = start, i = 0; p < finish; p++, i += 8) | ||
56 | p->insn += i; | ||
57 | sort(start, finish - start, sizeof(*start), cmp_ex, NULL); | ||
58 | /* Denormalize all entries */ | ||
59 | for (p = start, i = 0; p < finish; p++, i += 8) | ||
60 | p->insn -= i; | ||
61 | } | ||
62 | |||
63 | #ifdef CONFIG_MODULES | ||
64 | /* | ||
65 | * If the exception table is sorted, any referring to the module init | ||
66 | * will be at the beginning or the end. | ||
67 | */ | ||
68 | void trim_init_extable(struct module *m) | ||
69 | { | ||
70 | /* Trim the beginning */ | ||
71 | while (m->num_exentries && | ||
72 | within_module_init(extable_insn(&m->extable[0]), m)) { | ||
73 | m->extable++; | ||
74 | m->num_exentries--; | ||
75 | } | ||
76 | /* Trim the end */ | ||
77 | while (m->num_exentries && | ||
78 | within_module_init(extable_insn(&m->extable[m->num_exentries-1]), m)) | ||
79 | m->num_exentries--; | ||
80 | } | ||
81 | #endif /* CONFIG_MODULES */ | ||
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 6c013f544146..ac9122ca1152 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -111,7 +111,7 @@ static inline int user_space_fault(unsigned long trans_exc_code) | |||
111 | if (trans_exc_code == 2) | 111 | if (trans_exc_code == 2) |
112 | /* Access via secondary space, set_fs setting decides */ | 112 | /* Access via secondary space, set_fs setting decides */ |
113 | return current->thread.mm_segment.ar4; | 113 | return current->thread.mm_segment.ar4; |
114 | if (addressing_mode == HOME_SPACE_MODE) | 114 | if (s390_user_mode == HOME_SPACE_MODE) |
115 | /* User space if the access has been done via home space. */ | 115 | /* User space if the access has been done via home space. */ |
116 | return trans_exc_code == 3; | 116 | return trans_exc_code == 3; |
117 | /* | 117 | /* |
@@ -163,7 +163,7 @@ static noinline void do_no_context(struct pt_regs *regs) | |||
163 | /* Are we prepared to handle this kernel fault? */ | 163 | /* Are we prepared to handle this kernel fault? */ |
164 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 164 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
165 | if (fixup) { | 165 | if (fixup) { |
166 | regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; | 166 | regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE; |
167 | return; | 167 | return; |
168 | } | 168 | } |
169 | 169 | ||
@@ -628,9 +628,8 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self, | |||
628 | struct thread_struct *thread, *next; | 628 | struct thread_struct *thread, *next; |
629 | struct task_struct *tsk; | 629 | struct task_struct *tsk; |
630 | 630 | ||
631 | switch (action) { | 631 | switch (action & ~CPU_TASKS_FROZEN) { |
632 | case CPU_DEAD: | 632 | case CPU_DEAD: |
633 | case CPU_DEAD_FROZEN: | ||
634 | spin_lock_irq(&pfault_lock); | 633 | spin_lock_irq(&pfault_lock); |
635 | list_for_each_entry_safe(thread, next, &pfault_list, list) { | 634 | list_for_each_entry_safe(thread, next, &pfault_list, list) { |
636 | thread->pfault_wait = 0; | 635 | thread->pfault_wait = 0; |
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 65cb06e2af4e..eeaf8023851f 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c | |||
@@ -154,6 +154,43 @@ static inline int gup_pud_range(pgd_t *pgdp, pgd_t pgd, unsigned long addr, | |||
154 | return 1; | 154 | return 1; |
155 | } | 155 | } |
156 | 156 | ||
157 | /* | ||
158 | * Like get_user_pages_fast() except its IRQ-safe in that it won't fall | ||
159 | * back to the regular GUP. | ||
160 | */ | ||
161 | int __get_user_pages_fast(unsigned long start, int nr_pages, int write, | ||
162 | struct page **pages) | ||
163 | { | ||
164 | struct mm_struct *mm = current->mm; | ||
165 | unsigned long addr, len, end; | ||
166 | unsigned long next, flags; | ||
167 | pgd_t *pgdp, pgd; | ||
168 | int nr = 0; | ||
169 | |||
170 | start &= PAGE_MASK; | ||
171 | addr = start; | ||
172 | len = (unsigned long) nr_pages << PAGE_SHIFT; | ||
173 | end = start + len; | ||
174 | if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ, | ||
175 | (void __user *)start, len))) | ||
176 | return 0; | ||
177 | |||
178 | local_irq_save(flags); | ||
179 | pgdp = pgd_offset(mm, addr); | ||
180 | do { | ||
181 | pgd = *pgdp; | ||
182 | barrier(); | ||
183 | next = pgd_addr_end(addr, end); | ||
184 | if (pgd_none(pgd)) | ||
185 | break; | ||
186 | if (!gup_pud_range(pgdp, pgd, addr, next, write, pages, &nr)) | ||
187 | break; | ||
188 | } while (pgdp++, addr = next, addr != end); | ||
189 | local_irq_restore(flags); | ||
190 | |||
191 | return nr; | ||
192 | } | ||
193 | |||
157 | /** | 194 | /** |
158 | * get_user_pages_fast() - pin user pages in memory | 195 | * get_user_pages_fast() - pin user pages in memory |
159 | * @start: starting user address | 196 | * @start: starting user address |
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 6adbc082618a..81e596c65dee 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
@@ -42,7 +42,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); | |||
42 | unsigned long empty_zero_page, zero_page_mask; | 42 | unsigned long empty_zero_page, zero_page_mask; |
43 | EXPORT_SYMBOL(empty_zero_page); | 43 | EXPORT_SYMBOL(empty_zero_page); |
44 | 44 | ||
45 | static unsigned long setup_zero_pages(void) | 45 | static unsigned long __init setup_zero_pages(void) |
46 | { | 46 | { |
47 | struct cpuid cpu_id; | 47 | struct cpuid cpu_id; |
48 | unsigned int order; | 48 | unsigned int order; |
@@ -212,7 +212,7 @@ void free_initmem(void) | |||
212 | } | 212 | } |
213 | 213 | ||
214 | #ifdef CONFIG_BLK_DEV_INITRD | 214 | #ifdef CONFIG_BLK_DEV_INITRD |
215 | void free_initrd_mem(unsigned long start, unsigned long end) | 215 | void __init free_initrd_mem(unsigned long start, unsigned long end) |
216 | { | 216 | { |
217 | free_init_pages("initrd memory", start, end); | 217 | free_init_pages("initrd memory", start, end); |
218 | } | 218 | } |
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 18df31d1f2c9..b402991e43d7 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
@@ -609,8 +609,8 @@ static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits) | |||
609 | */ | 609 | */ |
610 | unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr) | 610 | unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr) |
611 | { | 611 | { |
612 | struct page *page; | 612 | unsigned long *uninitialized_var(table); |
613 | unsigned long *table; | 613 | struct page *uninitialized_var(page); |
614 | unsigned int mask, bit; | 614 | unsigned int mask, bit; |
615 | 615 | ||
616 | if (mm_has_pgste(mm)) | 616 | if (mm_has_pgste(mm)) |
@@ -796,7 +796,7 @@ int s390_enable_sie(void) | |||
796 | struct mm_struct *mm, *old_mm; | 796 | struct mm_struct *mm, *old_mm; |
797 | 797 | ||
798 | /* Do we have switched amode? If no, we cannot do sie */ | 798 | /* Do we have switched amode? If no, we cannot do sie */ |
799 | if (addressing_mode == HOME_SPACE_MODE) | 799 | if (s390_user_mode == HOME_SPACE_MODE) |
800 | return -EINVAL; | 800 | return -EINVAL; |
801 | 801 | ||
802 | /* Do we have pgstes? if yes, we are done */ | 802 | /* Do we have pgstes? if yes, we are done */ |
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 6f896e75ab49..c22abf900c9e 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c | |||
@@ -107,7 +107,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) | |||
107 | pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0)); | 107 | pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0)); |
108 | pm_dir = pmd_offset(pu_dir, address); | 108 | pm_dir = pmd_offset(pu_dir, address); |
109 | 109 | ||
110 | #ifdef CONFIG_64BIT | 110 | #if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC) |
111 | if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) && | 111 | if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) && |
112 | (address + HPAGE_SIZE <= start + size) && | 112 | (address + HPAGE_SIZE <= start + size) && |
113 | (address >= HPAGE_SIZE)) { | 113 | (address >= HPAGE_SIZE)) { |
diff --git a/arch/s390/net/Makefile b/arch/s390/net/Makefile new file mode 100644 index 000000000000..90568c33ddb0 --- /dev/null +++ b/arch/s390/net/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # | ||
2 | # Arch-specific network modules | ||
3 | # | ||
4 | obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o | ||
diff --git a/arch/s390/net/bpf_jit.S b/arch/s390/net/bpf_jit.S new file mode 100644 index 000000000000..7e45d13816c1 --- /dev/null +++ b/arch/s390/net/bpf_jit.S | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * BPF Jit compiler for s390, help functions. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2012 | ||
5 | * | ||
6 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
7 | */ | ||
8 | #include <linux/linkage.h> | ||
9 | |||
10 | /* | ||
11 | * Calling convention: | ||
12 | * registers %r2, %r6-%r8, %r10-%r11, %r13, %r15 are call saved | ||
13 | * %r2: skb pointer | ||
14 | * %r3: offset parameter | ||
15 | * %r5: BPF A accumulator | ||
16 | * %r8: return address | ||
17 | * %r9: save register for skb pointer | ||
18 | * %r10: skb->data | ||
19 | * %r11: skb->len - skb->data_len (headlen) | ||
20 | * %r12: BPF X accumulator | ||
21 | * | ||
22 | * skb_copy_bits takes 4 parameters: | ||
23 | * %r2 = skb pointer | ||
24 | * %r3 = offset into skb data | ||
25 | * %r4 = length to copy | ||
26 | * %r5 = pointer to temp buffer | ||
27 | */ | ||
28 | #define SKBDATA %r8 | ||
29 | |||
30 | /* A = *(u32 *) (skb->data+K+X) */ | ||
31 | ENTRY(sk_load_word_ind) | ||
32 | ar %r3,%r12 # offset += X | ||
33 | bmr %r8 # < 0 -> return with cc | ||
34 | |||
35 | /* A = *(u32 *) (skb->data+K) */ | ||
36 | ENTRY(sk_load_word) | ||
37 | llgfr %r1,%r3 # extend offset | ||
38 | ahi %r3,4 # offset + 4 | ||
39 | clr %r11,%r3 # hlen <= offset + 4 ? | ||
40 | jl sk_load_word_slow | ||
41 | l %r5,0(%r1,%r10) # get word from skb | ||
42 | xr %r1,%r1 # set cc to zero | ||
43 | br %r8 | ||
44 | |||
45 | sk_load_word_slow: | ||
46 | lgr %r9,%r2 # save %r2 | ||
47 | lhi %r4,4 # 4 bytes | ||
48 | la %r5,160(%r15) # pointer to temp buffer | ||
49 | brasl %r14,skb_copy_bits # get data from skb | ||
50 | l %r5,160(%r15) # load result from temp buffer | ||
51 | ltgr %r2,%r2 # set cc to (%r2 != 0) | ||
52 | lgr %r2,%r9 # restore %r2 | ||
53 | br %r8 | ||
54 | |||
55 | /* A = *(u16 *) (skb->data+K+X) */ | ||
56 | ENTRY(sk_load_half_ind) | ||
57 | ar %r3,%r12 # offset += X | ||
58 | bmr %r8 # < 0 -> return with cc | ||
59 | |||
60 | /* A = *(u16 *) (skb->data+K) */ | ||
61 | ENTRY(sk_load_half) | ||
62 | llgfr %r1,%r3 # extend offset | ||
63 | ahi %r3,2 # offset + 2 | ||
64 | clr %r11,%r3 # hlen <= offset + 2 ? | ||
65 | jl sk_load_half_slow | ||
66 | llgh %r5,0(%r1,%r10) # get half from skb | ||
67 | xr %r1,%r1 # set cc to zero | ||
68 | br %r8 | ||
69 | |||
70 | sk_load_half_slow: | ||
71 | lgr %r9,%r2 # save %r2 | ||
72 | lhi %r4,2 # 2 bytes | ||
73 | la %r5,162(%r15) # pointer to temp buffer | ||
74 | brasl %r14,skb_copy_bits # get data from skb | ||
75 | xc 160(2,%r15),160(%r15) | ||
76 | l %r5,160(%r15) # load result from temp buffer | ||
77 | ltgr %r2,%r2 # set cc to (%r2 != 0) | ||
78 | lgr %r2,%r9 # restore %r2 | ||
79 | br %r8 | ||
80 | |||
81 | /* A = *(u8 *) (skb->data+K+X) */ | ||
82 | ENTRY(sk_load_byte_ind) | ||
83 | ar %r3,%r12 # offset += X | ||
84 | bmr %r8 # < 0 -> return with cc | ||
85 | |||
86 | /* A = *(u8 *) (skb->data+K) */ | ||
87 | ENTRY(sk_load_byte) | ||
88 | llgfr %r1,%r3 # extend offset | ||
89 | clr %r11,%r3 # hlen < offset ? | ||
90 | jle sk_load_byte_slow | ||
91 | lhi %r5,0 | ||
92 | ic %r5,0(%r1,%r10) # get byte from skb | ||
93 | xr %r1,%r1 # set cc to zero | ||
94 | br %r8 | ||
95 | |||
96 | sk_load_byte_slow: | ||
97 | lgr %r9,%r2 # save %r2 | ||
98 | lhi %r4,1 # 1 bytes | ||
99 | la %r5,163(%r15) # pointer to temp buffer | ||
100 | brasl %r14,skb_copy_bits # get data from skb | ||
101 | xc 160(3,%r15),160(%r15) | ||
102 | l %r5,160(%r15) # load result from temp buffer | ||
103 | ltgr %r2,%r2 # set cc to (%r2 != 0) | ||
104 | lgr %r2,%r9 # restore %r2 | ||
105 | br %r8 | ||
106 | |||
107 | /* A = (*(u8 *)(skb->data+K) & 0xf) << 2 */ | ||
108 | ENTRY(sk_load_byte_msh) | ||
109 | llgfr %r1,%r3 # extend offset | ||
110 | clr %r11,%r3 # hlen < offset ? | ||
111 | jle sk_load_byte_slow | ||
112 | lhi %r12,0 | ||
113 | ic %r12,0(%r1,%r10) # get byte from skb | ||
114 | nill %r12,0x0f | ||
115 | sll %r12,2 | ||
116 | xr %r1,%r1 # set cc to zero | ||
117 | br %r8 | ||
118 | |||
119 | sk_load_byte_msh_slow: | ||
120 | lgr %r9,%r2 # save %r2 | ||
121 | lhi %r4,2 # 2 bytes | ||
122 | la %r5,162(%r15) # pointer to temp buffer | ||
123 | brasl %r14,skb_copy_bits # get data from skb | ||
124 | xc 160(3,%r15),160(%r15) | ||
125 | l %r12,160(%r15) # load result from temp buffer | ||
126 | nill %r12,0x0f | ||
127 | sll %r12,2 | ||
128 | ltgr %r2,%r2 # set cc to (%r2 != 0) | ||
129 | lgr %r2,%r9 # restore %r2 | ||
130 | br %r8 | ||
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c new file mode 100644 index 000000000000..9b355b406afa --- /dev/null +++ b/arch/s390/net/bpf_jit_comp.c | |||
@@ -0,0 +1,776 @@ | |||
1 | /* | ||
2 | * BPF Jit compiler for s390. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2012 | ||
5 | * | ||
6 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
7 | */ | ||
8 | #include <linux/moduleloader.h> | ||
9 | #include <linux/netdevice.h> | ||
10 | #include <linux/filter.h> | ||
11 | #include <asm/cacheflush.h> | ||
12 | #include <asm/processor.h> | ||
13 | #include <asm/facility.h> | ||
14 | |||
15 | /* | ||
16 | * Conventions: | ||
17 | * %r2 = skb pointer | ||
18 | * %r3 = offset parameter | ||
19 | * %r4 = scratch register / length parameter | ||
20 | * %r5 = BPF A accumulator | ||
21 | * %r8 = return address | ||
22 | * %r9 = save register for skb pointer | ||
23 | * %r10 = skb->data | ||
24 | * %r11 = skb->len - skb->data_len (headlen) | ||
25 | * %r12 = BPF X accumulator | ||
26 | * %r13 = literal pool pointer | ||
27 | * 0(%r15) - 63(%r15) scratch memory array with BPF_MEMWORDS | ||
28 | */ | ||
29 | int bpf_jit_enable __read_mostly; | ||
30 | |||
31 | /* | ||
32 | * assembly code in arch/x86/net/bpf_jit.S | ||
33 | */ | ||
34 | extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[]; | ||
35 | extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[]; | ||
36 | |||
37 | struct bpf_jit { | ||
38 | unsigned int seen; | ||
39 | u8 *start; | ||
40 | u8 *prg; | ||
41 | u8 *mid; | ||
42 | u8 *lit; | ||
43 | u8 *end; | ||
44 | u8 *base_ip; | ||
45 | u8 *ret0_ip; | ||
46 | u8 *exit_ip; | ||
47 | unsigned int off_load_word; | ||
48 | unsigned int off_load_half; | ||
49 | unsigned int off_load_byte; | ||
50 | unsigned int off_load_bmsh; | ||
51 | unsigned int off_load_iword; | ||
52 | unsigned int off_load_ihalf; | ||
53 | unsigned int off_load_ibyte; | ||
54 | }; | ||
55 | |||
56 | #define BPF_SIZE_MAX 4096 /* Max size for program */ | ||
57 | |||
58 | #define SEEN_DATAREF 1 /* might call external helpers */ | ||
59 | #define SEEN_XREG 2 /* ebx is used */ | ||
60 | #define SEEN_MEM 4 /* use mem[] for temporary storage */ | ||
61 | #define SEEN_RET0 8 /* pc_ret0 points to a valid return 0 */ | ||
62 | #define SEEN_LITERAL 16 /* code uses literals */ | ||
63 | #define SEEN_LOAD_WORD 32 /* code uses sk_load_word */ | ||
64 | #define SEEN_LOAD_HALF 64 /* code uses sk_load_half */ | ||
65 | #define SEEN_LOAD_BYTE 128 /* code uses sk_load_byte */ | ||
66 | #define SEEN_LOAD_BMSH 256 /* code uses sk_load_byte_msh */ | ||
67 | #define SEEN_LOAD_IWORD 512 /* code uses sk_load_word_ind */ | ||
68 | #define SEEN_LOAD_IHALF 1024 /* code uses sk_load_half_ind */ | ||
69 | #define SEEN_LOAD_IBYTE 2048 /* code uses sk_load_byte_ind */ | ||
70 | |||
71 | #define EMIT2(op) \ | ||
72 | ({ \ | ||
73 | if (jit->prg + 2 <= jit->mid) \ | ||
74 | *(u16 *) jit->prg = op; \ | ||
75 | jit->prg += 2; \ | ||
76 | }) | ||
77 | |||
78 | #define EMIT4(op) \ | ||
79 | ({ \ | ||
80 | if (jit->prg + 4 <= jit->mid) \ | ||
81 | *(u32 *) jit->prg = op; \ | ||
82 | jit->prg += 4; \ | ||
83 | }) | ||
84 | |||
85 | #define EMIT4_DISP(op, disp) \ | ||
86 | ({ \ | ||
87 | unsigned int __disp = (disp) & 0xfff; \ | ||
88 | EMIT4(op | __disp); \ | ||
89 | }) | ||
90 | |||
91 | #define EMIT4_IMM(op, imm) \ | ||
92 | ({ \ | ||
93 | unsigned int __imm = (imm) & 0xffff; \ | ||
94 | EMIT4(op | __imm); \ | ||
95 | }) | ||
96 | |||
97 | #define EMIT4_PCREL(op, pcrel) \ | ||
98 | ({ \ | ||
99 | long __pcrel = ((pcrel) >> 1) & 0xffff; \ | ||
100 | EMIT4(op | __pcrel); \ | ||
101 | }) | ||
102 | |||
103 | #define EMIT6(op1, op2) \ | ||
104 | ({ \ | ||
105 | if (jit->prg + 6 <= jit->mid) { \ | ||
106 | *(u32 *) jit->prg = op1; \ | ||
107 | *(u16 *) (jit->prg + 4) = op2; \ | ||
108 | } \ | ||
109 | jit->prg += 6; \ | ||
110 | }) | ||
111 | |||
112 | #define EMIT6_DISP(op1, op2, disp) \ | ||
113 | ({ \ | ||
114 | unsigned int __disp = (disp) & 0xfff; \ | ||
115 | EMIT6(op1 | __disp, op2); \ | ||
116 | }) | ||
117 | |||
118 | #define EMIT6_IMM(op, imm) \ | ||
119 | ({ \ | ||
120 | unsigned int __imm = (imm); \ | ||
121 | EMIT6(op | (__imm >> 16), __imm & 0xffff); \ | ||
122 | }) | ||
123 | |||
124 | #define EMIT_CONST(val) \ | ||
125 | ({ \ | ||
126 | unsigned int ret; \ | ||
127 | ret = (unsigned int) (jit->lit - jit->base_ip); \ | ||
128 | jit->seen |= SEEN_LITERAL; \ | ||
129 | if (jit->lit + 4 <= jit->end) \ | ||
130 | *(u32 *) jit->lit = val; \ | ||
131 | jit->lit += 4; \ | ||
132 | ret; \ | ||
133 | }) | ||
134 | |||
135 | #define EMIT_FN_CONST(bit, fn) \ | ||
136 | ({ \ | ||
137 | unsigned int ret; \ | ||
138 | ret = (unsigned int) (jit->lit - jit->base_ip); \ | ||
139 | if (jit->seen & bit) { \ | ||
140 | jit->seen |= SEEN_LITERAL; \ | ||
141 | if (jit->lit + 8 <= jit->end) \ | ||
142 | *(void **) jit->lit = fn; \ | ||
143 | jit->lit += 8; \ | ||
144 | } \ | ||
145 | ret; \ | ||
146 | }) | ||
147 | |||
148 | static void bpf_jit_prologue(struct bpf_jit *jit) | ||
149 | { | ||
150 | /* Save registers and create stack frame if necessary */ | ||
151 | if (jit->seen & SEEN_DATAREF) { | ||
152 | /* stmg %r8,%r15,88(%r15) */ | ||
153 | EMIT6(0xeb8ff058, 0x0024); | ||
154 | /* lgr %r14,%r15 */ | ||
155 | EMIT4(0xb90400ef); | ||
156 | /* ahi %r15,<offset> */ | ||
157 | EMIT4_IMM(0xa7fa0000, (jit->seen & SEEN_MEM) ? -112 : -80); | ||
158 | /* stg %r14,152(%r15) */ | ||
159 | EMIT6(0xe3e0f098, 0x0024); | ||
160 | } else if ((jit->seen & SEEN_XREG) && (jit->seen & SEEN_LITERAL)) | ||
161 | /* stmg %r12,%r13,120(%r15) */ | ||
162 | EMIT6(0xebcdf078, 0x0024); | ||
163 | else if (jit->seen & SEEN_XREG) | ||
164 | /* stg %r12,120(%r15) */ | ||
165 | EMIT6(0xe3c0f078, 0x0024); | ||
166 | else if (jit->seen & SEEN_LITERAL) | ||
167 | /* stg %r13,128(%r15) */ | ||
168 | EMIT6(0xe3d0f080, 0x0024); | ||
169 | |||
170 | /* Setup literal pool */ | ||
171 | if (jit->seen & SEEN_LITERAL) { | ||
172 | /* basr %r13,0 */ | ||
173 | EMIT2(0x0dd0); | ||
174 | jit->base_ip = jit->prg; | ||
175 | } | ||
176 | jit->off_load_word = EMIT_FN_CONST(SEEN_LOAD_WORD, sk_load_word); | ||
177 | jit->off_load_half = EMIT_FN_CONST(SEEN_LOAD_HALF, sk_load_half); | ||
178 | jit->off_load_byte = EMIT_FN_CONST(SEEN_LOAD_BYTE, sk_load_byte); | ||
179 | jit->off_load_bmsh = EMIT_FN_CONST(SEEN_LOAD_BMSH, sk_load_byte_msh); | ||
180 | jit->off_load_iword = EMIT_FN_CONST(SEEN_LOAD_IWORD, sk_load_word_ind); | ||
181 | jit->off_load_ihalf = EMIT_FN_CONST(SEEN_LOAD_IHALF, sk_load_half_ind); | ||
182 | jit->off_load_ibyte = EMIT_FN_CONST(SEEN_LOAD_IBYTE, sk_load_byte_ind); | ||
183 | |||
184 | /* Filter needs to access skb data */ | ||
185 | if (jit->seen & SEEN_DATAREF) { | ||
186 | /* l %r11,<len>(%r2) */ | ||
187 | EMIT4_DISP(0x58b02000, offsetof(struct sk_buff, len)); | ||
188 | /* s %r11,<data_len>(%r2) */ | ||
189 | EMIT4_DISP(0x5bb02000, offsetof(struct sk_buff, data_len)); | ||
190 | /* lg %r10,<data>(%r2) */ | ||
191 | EMIT6_DISP(0xe3a02000, 0x0004, | ||
192 | offsetof(struct sk_buff, data)); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static void bpf_jit_epilogue(struct bpf_jit *jit) | ||
197 | { | ||
198 | /* Return 0 */ | ||
199 | if (jit->seen & SEEN_RET0) { | ||
200 | jit->ret0_ip = jit->prg; | ||
201 | /* lghi %r2,0 */ | ||
202 | EMIT4(0xa7290000); | ||
203 | } | ||
204 | jit->exit_ip = jit->prg; | ||
205 | /* Restore registers */ | ||
206 | if (jit->seen & SEEN_DATAREF) | ||
207 | /* lmg %r8,%r15,<offset>(%r15) */ | ||
208 | EMIT6_DISP(0xeb8ff000, 0x0004, | ||
209 | (jit->seen & SEEN_MEM) ? 200 : 168); | ||
210 | else if ((jit->seen & SEEN_XREG) && (jit->seen & SEEN_LITERAL)) | ||
211 | /* lmg %r12,%r13,120(%r15) */ | ||
212 | EMIT6(0xebcdf078, 0x0004); | ||
213 | else if (jit->seen & SEEN_XREG) | ||
214 | /* lg %r12,120(%r15) */ | ||
215 | EMIT6(0xe3c0f078, 0x0004); | ||
216 | else if (jit->seen & SEEN_LITERAL) | ||
217 | /* lg %r13,128(%r15) */ | ||
218 | EMIT6(0xe3d0f080, 0x0004); | ||
219 | /* br %r14 */ | ||
220 | EMIT2(0x07fe); | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * make sure we dont leak kernel information to user | ||
225 | */ | ||
226 | static void bpf_jit_noleaks(struct bpf_jit *jit, struct sock_filter *filter) | ||
227 | { | ||
228 | /* Clear temporary memory if (seen & SEEN_MEM) */ | ||
229 | if (jit->seen & SEEN_MEM) | ||
230 | /* xc 0(64,%r15),0(%r15) */ | ||
231 | EMIT6(0xd73ff000, 0xf000); | ||
232 | /* Clear X if (seen & SEEN_XREG) */ | ||
233 | if (jit->seen & SEEN_XREG) | ||
234 | /* lhi %r12,0 */ | ||
235 | EMIT4(0xa7c80000); | ||
236 | /* Clear A if the first register does not set it. */ | ||
237 | switch (filter[0].code) { | ||
238 | case BPF_S_LD_W_ABS: | ||
239 | case BPF_S_LD_H_ABS: | ||
240 | case BPF_S_LD_B_ABS: | ||
241 | case BPF_S_LD_W_LEN: | ||
242 | case BPF_S_LD_W_IND: | ||
243 | case BPF_S_LD_H_IND: | ||
244 | case BPF_S_LD_B_IND: | ||
245 | case BPF_S_LDX_B_MSH: | ||
246 | case BPF_S_LD_IMM: | ||
247 | case BPF_S_LD_MEM: | ||
248 | case BPF_S_MISC_TXA: | ||
249 | case BPF_S_ANC_PROTOCOL: | ||
250 | case BPF_S_ANC_PKTTYPE: | ||
251 | case BPF_S_ANC_IFINDEX: | ||
252 | case BPF_S_ANC_MARK: | ||
253 | case BPF_S_ANC_QUEUE: | ||
254 | case BPF_S_ANC_HATYPE: | ||
255 | case BPF_S_ANC_RXHASH: | ||
256 | case BPF_S_ANC_CPU: | ||
257 | case BPF_S_RET_K: | ||
258 | /* first instruction sets A register */ | ||
259 | break; | ||
260 | default: /* A = 0 */ | ||
261 | /* lhi %r5,0 */ | ||
262 | EMIT4(0xa7580000); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter, | ||
267 | unsigned int *addrs, int i, int last) | ||
268 | { | ||
269 | unsigned int K; | ||
270 | int offset; | ||
271 | unsigned int mask; | ||
272 | |||
273 | K = filter->k; | ||
274 | switch (filter->code) { | ||
275 | case BPF_S_ALU_ADD_X: /* A += X */ | ||
276 | jit->seen |= SEEN_XREG; | ||
277 | /* ar %r5,%r12 */ | ||
278 | EMIT2(0x1a5c); | ||
279 | break; | ||
280 | case BPF_S_ALU_ADD_K: /* A += K */ | ||
281 | if (!K) | ||
282 | break; | ||
283 | if (K <= 16383) | ||
284 | /* ahi %r5,<K> */ | ||
285 | EMIT4_IMM(0xa75a0000, K); | ||
286 | else if (test_facility(21)) | ||
287 | /* alfi %r5,<K> */ | ||
288 | EMIT6_IMM(0xc25b0000, K); | ||
289 | else | ||
290 | /* a %r5,<d(K)>(%r13) */ | ||
291 | EMIT4_DISP(0x5a50d000, EMIT_CONST(K)); | ||
292 | break; | ||
293 | case BPF_S_ALU_SUB_X: /* A -= X */ | ||
294 | jit->seen |= SEEN_XREG; | ||
295 | /* sr %r5,%r12 */ | ||
296 | EMIT2(0x1b5c); | ||
297 | break; | ||
298 | case BPF_S_ALU_SUB_K: /* A -= K */ | ||
299 | if (!K) | ||
300 | break; | ||
301 | if (K <= 16384) | ||
302 | /* ahi %r5,-K */ | ||
303 | EMIT4_IMM(0xa75a0000, -K); | ||
304 | else if (test_facility(21)) | ||
305 | /* alfi %r5,-K */ | ||
306 | EMIT6_IMM(0xc25b0000, -K); | ||
307 | else | ||
308 | /* s %r5,<d(K)>(%r13) */ | ||
309 | EMIT4_DISP(0x5b50d000, EMIT_CONST(K)); | ||
310 | break; | ||
311 | case BPF_S_ALU_MUL_X: /* A *= X */ | ||
312 | jit->seen |= SEEN_XREG; | ||
313 | /* msr %r5,%r12 */ | ||
314 | EMIT4(0xb252005c); | ||
315 | break; | ||
316 | case BPF_S_ALU_MUL_K: /* A *= K */ | ||
317 | if (K <= 16383) | ||
318 | /* mhi %r5,K */ | ||
319 | EMIT4_IMM(0xa75c0000, K); | ||
320 | else if (test_facility(34)) | ||
321 | /* msfi %r5,<K> */ | ||
322 | EMIT6_IMM(0xc2510000, K); | ||
323 | else | ||
324 | /* ms %r5,<d(K)>(%r13) */ | ||
325 | EMIT4_DISP(0x7150d000, EMIT_CONST(K)); | ||
326 | break; | ||
327 | case BPF_S_ALU_DIV_X: /* A /= X */ | ||
328 | jit->seen |= SEEN_XREG | SEEN_RET0; | ||
329 | /* ltr %r12,%r12 */ | ||
330 | EMIT2(0x12cc); | ||
331 | /* jz <ret0> */ | ||
332 | EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg)); | ||
333 | /* lhi %r4,0 */ | ||
334 | EMIT4(0xa7480000); | ||
335 | /* dr %r4,%r12 */ | ||
336 | EMIT2(0x1d4c); | ||
337 | break; | ||
338 | case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */ | ||
339 | /* m %r4,<d(K)>(%r13) */ | ||
340 | EMIT4_DISP(0x5c40d000, EMIT_CONST(K)); | ||
341 | /* lr %r5,%r4 */ | ||
342 | EMIT2(0x1854); | ||
343 | break; | ||
344 | case BPF_S_ALU_AND_X: /* A &= X */ | ||
345 | jit->seen |= SEEN_XREG; | ||
346 | /* nr %r5,%r12 */ | ||
347 | EMIT2(0x145c); | ||
348 | break; | ||
349 | case BPF_S_ALU_AND_K: /* A &= K */ | ||
350 | if (test_facility(21)) | ||
351 | /* nilf %r5,<K> */ | ||
352 | EMIT6_IMM(0xc05b0000, K); | ||
353 | else | ||
354 | /* n %r5,<d(K)>(%r13) */ | ||
355 | EMIT4_DISP(0x5450d000, EMIT_CONST(K)); | ||
356 | break; | ||
357 | case BPF_S_ALU_OR_X: /* A |= X */ | ||
358 | jit->seen |= SEEN_XREG; | ||
359 | /* or %r5,%r12 */ | ||
360 | EMIT2(0x165c); | ||
361 | break; | ||
362 | case BPF_S_ALU_OR_K: /* A |= K */ | ||
363 | if (test_facility(21)) | ||
364 | /* oilf %r5,<K> */ | ||
365 | EMIT6_IMM(0xc05d0000, K); | ||
366 | else | ||
367 | /* o %r5,<d(K)>(%r13) */ | ||
368 | EMIT4_DISP(0x5650d000, EMIT_CONST(K)); | ||
369 | break; | ||
370 | case BPF_S_ANC_ALU_XOR_X: /* A ^= X; */ | ||
371 | jit->seen |= SEEN_XREG; | ||
372 | /* xr %r5,%r12 */ | ||
373 | EMIT2(0x175c); | ||
374 | break; | ||
375 | case BPF_S_ALU_LSH_X: /* A <<= X; */ | ||
376 | jit->seen |= SEEN_XREG; | ||
377 | /* sll %r5,0(%r12) */ | ||
378 | EMIT4(0x8950c000); | ||
379 | break; | ||
380 | case BPF_S_ALU_LSH_K: /* A <<= K */ | ||
381 | if (K == 0) | ||
382 | break; | ||
383 | /* sll %r5,K */ | ||
384 | EMIT4_DISP(0x89500000, K); | ||
385 | break; | ||
386 | case BPF_S_ALU_RSH_X: /* A >>= X; */ | ||
387 | jit->seen |= SEEN_XREG; | ||
388 | /* srl %r5,0(%r12) */ | ||
389 | EMIT4(0x8850c000); | ||
390 | break; | ||
391 | case BPF_S_ALU_RSH_K: /* A >>= K; */ | ||
392 | if (K == 0) | ||
393 | break; | ||
394 | /* srl %r5,K */ | ||
395 | EMIT4_DISP(0x88500000, K); | ||
396 | break; | ||
397 | case BPF_S_ALU_NEG: /* A = -A */ | ||
398 | /* lnr %r5,%r5 */ | ||
399 | EMIT2(0x1155); | ||
400 | break; | ||
401 | case BPF_S_JMP_JA: /* ip += K */ | ||
402 | offset = addrs[i + K] + jit->start - jit->prg; | ||
403 | EMIT4_PCREL(0xa7f40000, offset); | ||
404 | break; | ||
405 | case BPF_S_JMP_JGT_K: /* ip += (A > K) ? jt : jf */ | ||
406 | mask = 0x200000; /* jh */ | ||
407 | goto kbranch; | ||
408 | case BPF_S_JMP_JGE_K: /* ip += (A >= K) ? jt : jf */ | ||
409 | mask = 0xa00000; /* jhe */ | ||
410 | goto kbranch; | ||
411 | case BPF_S_JMP_JEQ_K: /* ip += (A == K) ? jt : jf */ | ||
412 | mask = 0x800000; /* je */ | ||
413 | kbranch: /* Emit compare if the branch targets are different */ | ||
414 | if (filter->jt != filter->jf) { | ||
415 | if (K <= 16383) | ||
416 | /* chi %r5,<K> */ | ||
417 | EMIT4_IMM(0xa75e0000, K); | ||
418 | else if (test_facility(21)) | ||
419 | /* clfi %r5,<K> */ | ||
420 | EMIT6_IMM(0xc25f0000, K); | ||
421 | else | ||
422 | /* c %r5,<d(K)>(%r13) */ | ||
423 | EMIT4_DISP(0x5950d000, EMIT_CONST(K)); | ||
424 | } | ||
425 | branch: if (filter->jt == filter->jf) { | ||
426 | if (filter->jt == 0) | ||
427 | break; | ||
428 | /* j <jt> */ | ||
429 | offset = addrs[i + filter->jt] + jit->start - jit->prg; | ||
430 | EMIT4_PCREL(0xa7f40000, offset); | ||
431 | break; | ||
432 | } | ||
433 | if (filter->jt != 0) { | ||
434 | /* brc <mask>,<jt> */ | ||
435 | offset = addrs[i + filter->jt] + jit->start - jit->prg; | ||
436 | EMIT4_PCREL(0xa7040000 | mask, offset); | ||
437 | } | ||
438 | if (filter->jf != 0) { | ||
439 | /* brc <mask^15>,<jf> */ | ||
440 | offset = addrs[i + filter->jf] + jit->start - jit->prg; | ||
441 | EMIT4_PCREL(0xa7040000 | (mask ^ 0xf00000), offset); | ||
442 | } | ||
443 | break; | ||
444 | case BPF_S_JMP_JSET_K: /* ip += (A & K) ? jt : jf */ | ||
445 | mask = 0x700000; /* jnz */ | ||
446 | /* Emit test if the branch targets are different */ | ||
447 | if (filter->jt != filter->jf) { | ||
448 | if (K > 65535) { | ||
449 | /* lr %r4,%r5 */ | ||
450 | EMIT2(0x1845); | ||
451 | /* n %r4,<d(K)>(%r13) */ | ||
452 | EMIT4_DISP(0x5440d000, EMIT_CONST(K)); | ||
453 | } else | ||
454 | /* tmll %r5,K */ | ||
455 | EMIT4_IMM(0xa7510000, K); | ||
456 | } | ||
457 | goto branch; | ||
458 | case BPF_S_JMP_JGT_X: /* ip += (A > X) ? jt : jf */ | ||
459 | mask = 0x200000; /* jh */ | ||
460 | goto xbranch; | ||
461 | case BPF_S_JMP_JGE_X: /* ip += (A >= X) ? jt : jf */ | ||
462 | mask = 0xa00000; /* jhe */ | ||
463 | goto xbranch; | ||
464 | case BPF_S_JMP_JEQ_X: /* ip += (A == X) ? jt : jf */ | ||
465 | mask = 0x800000; /* je */ | ||
466 | xbranch: /* Emit compare if the branch targets are different */ | ||
467 | if (filter->jt != filter->jf) { | ||
468 | jit->seen |= SEEN_XREG; | ||
469 | /* cr %r5,%r12 */ | ||
470 | EMIT2(0x195c); | ||
471 | } | ||
472 | goto branch; | ||
473 | case BPF_S_JMP_JSET_X: /* ip += (A & X) ? jt : jf */ | ||
474 | mask = 0x700000; /* jnz */ | ||
475 | /* Emit test if the branch targets are different */ | ||
476 | if (filter->jt != filter->jf) { | ||
477 | jit->seen |= SEEN_XREG; | ||
478 | /* lr %r4,%r5 */ | ||
479 | EMIT2(0x1845); | ||
480 | /* nr %r4,%r12 */ | ||
481 | EMIT2(0x144c); | ||
482 | } | ||
483 | goto branch; | ||
484 | case BPF_S_LD_W_ABS: /* A = *(u32 *) (skb->data+K) */ | ||
485 | jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_WORD; | ||
486 | offset = jit->off_load_word; | ||
487 | goto load_abs; | ||
488 | case BPF_S_LD_H_ABS: /* A = *(u16 *) (skb->data+K) */ | ||
489 | jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_HALF; | ||
490 | offset = jit->off_load_half; | ||
491 | goto load_abs; | ||
492 | case BPF_S_LD_B_ABS: /* A = *(u8 *) (skb->data+K) */ | ||
493 | jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_BYTE; | ||
494 | offset = jit->off_load_byte; | ||
495 | load_abs: if ((int) K < 0) | ||
496 | goto out; | ||
497 | call_fn: /* lg %r1,<d(function)>(%r13) */ | ||
498 | EMIT6_DISP(0xe310d000, 0x0004, offset); | ||
499 | /* l %r3,<d(K)>(%r13) */ | ||
500 | EMIT4_DISP(0x5830d000, EMIT_CONST(K)); | ||
501 | /* basr %r8,%r1 */ | ||
502 | EMIT2(0x0d81); | ||
503 | /* jnz <ret0> */ | ||
504 | EMIT4_PCREL(0xa7740000, (jit->ret0_ip - jit->prg)); | ||
505 | break; | ||
506 | case BPF_S_LD_W_IND: /* A = *(u32 *) (skb->data+K+X) */ | ||
507 | jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IWORD; | ||
508 | offset = jit->off_load_iword; | ||
509 | goto call_fn; | ||
510 | case BPF_S_LD_H_IND: /* A = *(u16 *) (skb->data+K+X) */ | ||
511 | jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IHALF; | ||
512 | offset = jit->off_load_ihalf; | ||
513 | goto call_fn; | ||
514 | case BPF_S_LD_B_IND: /* A = *(u8 *) (skb->data+K+X) */ | ||
515 | jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IBYTE; | ||
516 | offset = jit->off_load_ibyte; | ||
517 | goto call_fn; | ||
518 | case BPF_S_LDX_B_MSH: | ||
519 | /* X = (*(u8 *)(skb->data+K) & 0xf) << 2 */ | ||
520 | jit->seen |= SEEN_RET0; | ||
521 | if ((int) K < 0) { | ||
522 | /* j <ret0> */ | ||
523 | EMIT4_PCREL(0xa7f40000, (jit->ret0_ip - jit->prg)); | ||
524 | break; | ||
525 | } | ||
526 | jit->seen |= SEEN_DATAREF | SEEN_LOAD_BMSH; | ||
527 | offset = jit->off_load_bmsh; | ||
528 | goto call_fn; | ||
529 | case BPF_S_LD_W_LEN: /* A = skb->len; */ | ||
530 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4); | ||
531 | /* l %r5,<d(len)>(%r2) */ | ||
532 | EMIT4_DISP(0x58502000, offsetof(struct sk_buff, len)); | ||
533 | break; | ||
534 | case BPF_S_LDX_W_LEN: /* X = skb->len; */ | ||
535 | jit->seen |= SEEN_XREG; | ||
536 | /* l %r12,<d(len)>(%r2) */ | ||
537 | EMIT4_DISP(0x58c02000, offsetof(struct sk_buff, len)); | ||
538 | break; | ||
539 | case BPF_S_LD_IMM: /* A = K */ | ||
540 | if (K <= 16383) | ||
541 | /* lhi %r5,K */ | ||
542 | EMIT4_IMM(0xa7580000, K); | ||
543 | else if (test_facility(21)) | ||
544 | /* llilf %r5,<K> */ | ||
545 | EMIT6_IMM(0xc05f0000, K); | ||
546 | else | ||
547 | /* l %r5,<d(K)>(%r13) */ | ||
548 | EMIT4_DISP(0x5850d000, EMIT_CONST(K)); | ||
549 | break; | ||
550 | case BPF_S_LDX_IMM: /* X = K */ | ||
551 | jit->seen |= SEEN_XREG; | ||
552 | if (K <= 16383) | ||
553 | /* lhi %r12,<K> */ | ||
554 | EMIT4_IMM(0xa7c80000, K); | ||
555 | else if (test_facility(21)) | ||
556 | /* llilf %r12,<K> */ | ||
557 | EMIT6_IMM(0xc0cf0000, K); | ||
558 | else | ||
559 | /* l %r12,<d(K)>(%r13) */ | ||
560 | EMIT4_DISP(0x58c0d000, EMIT_CONST(K)); | ||
561 | break; | ||
562 | case BPF_S_LD_MEM: /* A = mem[K] */ | ||
563 | jit->seen |= SEEN_MEM; | ||
564 | /* l %r5,<K>(%r15) */ | ||
565 | EMIT4_DISP(0x5850f000, | ||
566 | (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4); | ||
567 | break; | ||
568 | case BPF_S_LDX_MEM: /* X = mem[K] */ | ||
569 | jit->seen |= SEEN_XREG | SEEN_MEM; | ||
570 | /* l %r12,<K>(%r15) */ | ||
571 | EMIT4_DISP(0x58c0f000, | ||
572 | (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4); | ||
573 | break; | ||
574 | case BPF_S_MISC_TAX: /* X = A */ | ||
575 | jit->seen |= SEEN_XREG; | ||
576 | /* lr %r12,%r5 */ | ||
577 | EMIT2(0x18c5); | ||
578 | break; | ||
579 | case BPF_S_MISC_TXA: /* A = X */ | ||
580 | jit->seen |= SEEN_XREG; | ||
581 | /* lr %r5,%r12 */ | ||
582 | EMIT2(0x185c); | ||
583 | break; | ||
584 | case BPF_S_RET_K: | ||
585 | if (K == 0) { | ||
586 | jit->seen |= SEEN_RET0; | ||
587 | if (last) | ||
588 | break; | ||
589 | /* j <ret0> */ | ||
590 | EMIT4_PCREL(0xa7f40000, jit->ret0_ip - jit->prg); | ||
591 | } else { | ||
592 | if (K <= 16383) | ||
593 | /* lghi %r2,K */ | ||
594 | EMIT4_IMM(0xa7290000, K); | ||
595 | else | ||
596 | /* llgf %r2,<K>(%r13) */ | ||
597 | EMIT6_DISP(0xe320d000, 0x0016, EMIT_CONST(K)); | ||
598 | /* j <exit> */ | ||
599 | if (last && !(jit->seen & SEEN_RET0)) | ||
600 | break; | ||
601 | EMIT4_PCREL(0xa7f40000, jit->exit_ip - jit->prg); | ||
602 | } | ||
603 | break; | ||
604 | case BPF_S_RET_A: | ||
605 | /* llgfr %r2,%r5 */ | ||
606 | EMIT4(0xb9160025); | ||
607 | /* j <exit> */ | ||
608 | EMIT4_PCREL(0xa7f40000, jit->exit_ip - jit->prg); | ||
609 | break; | ||
610 | case BPF_S_ST: /* mem[K] = A */ | ||
611 | jit->seen |= SEEN_MEM; | ||
612 | /* st %r5,<K>(%r15) */ | ||
613 | EMIT4_DISP(0x5050f000, | ||
614 | (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4); | ||
615 | break; | ||
616 | case BPF_S_STX: /* mem[K] = X : mov %ebx,off8(%rbp) */ | ||
617 | jit->seen |= SEEN_XREG | SEEN_MEM; | ||
618 | /* st %r12,<K>(%r15) */ | ||
619 | EMIT4_DISP(0x50c0f000, | ||
620 | (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4); | ||
621 | break; | ||
622 | case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */ | ||
623 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2); | ||
624 | /* lhi %r5,0 */ | ||
625 | EMIT4(0xa7580000); | ||
626 | /* icm %r5,3,<d(protocol)>(%r2) */ | ||
627 | EMIT4_DISP(0xbf532000, offsetof(struct sk_buff, protocol)); | ||
628 | break; | ||
629 | case BPF_S_ANC_IFINDEX: /* if (!skb->dev) return 0; | ||
630 | * A = skb->dev->ifindex */ | ||
631 | BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4); | ||
632 | jit->seen |= SEEN_RET0; | ||
633 | /* lg %r1,<d(dev)>(%r2) */ | ||
634 | EMIT6_DISP(0xe3102000, 0x0004, offsetof(struct sk_buff, dev)); | ||
635 | /* ltgr %r1,%r1 */ | ||
636 | EMIT4(0xb9020011); | ||
637 | /* jz <ret0> */ | ||
638 | EMIT4_PCREL(0xa7840000, jit->ret0_ip - jit->prg); | ||
639 | /* l %r5,<d(ifindex)>(%r1) */ | ||
640 | EMIT4_DISP(0x58501000, offsetof(struct net_device, ifindex)); | ||
641 | break; | ||
642 | case BPF_S_ANC_MARK: /* A = skb->mark */ | ||
643 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); | ||
644 | /* l %r5,<d(mark)>(%r2) */ | ||
645 | EMIT4_DISP(0x58502000, offsetof(struct sk_buff, mark)); | ||
646 | break; | ||
647 | case BPF_S_ANC_QUEUE: /* A = skb->queue_mapping */ | ||
648 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2); | ||
649 | /* lhi %r5,0 */ | ||
650 | EMIT4(0xa7580000); | ||
651 | /* icm %r5,3,<d(queue_mapping)>(%r2) */ | ||
652 | EMIT4_DISP(0xbf532000, offsetof(struct sk_buff, queue_mapping)); | ||
653 | break; | ||
654 | case BPF_S_ANC_HATYPE: /* if (!skb->dev) return 0; | ||
655 | * A = skb->dev->type */ | ||
656 | BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2); | ||
657 | jit->seen |= SEEN_RET0; | ||
658 | /* lg %r1,<d(dev)>(%r2) */ | ||
659 | EMIT6_DISP(0xe3102000, 0x0004, offsetof(struct sk_buff, dev)); | ||
660 | /* ltgr %r1,%r1 */ | ||
661 | EMIT4(0xb9020011); | ||
662 | /* jz <ret0> */ | ||
663 | EMIT4_PCREL(0xa7840000, jit->ret0_ip - jit->prg); | ||
664 | /* lhi %r5,0 */ | ||
665 | EMIT4(0xa7580000); | ||
666 | /* icm %r5,3,<d(type)>(%r1) */ | ||
667 | EMIT4_DISP(0xbf531000, offsetof(struct net_device, type)); | ||
668 | break; | ||
669 | case BPF_S_ANC_RXHASH: /* A = skb->rxhash */ | ||
670 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4); | ||
671 | /* l %r5,<d(rxhash)>(%r2) */ | ||
672 | EMIT4_DISP(0x58502000, offsetof(struct sk_buff, rxhash)); | ||
673 | break; | ||
674 | case BPF_S_ANC_CPU: /* A = smp_processor_id() */ | ||
675 | #ifdef CONFIG_SMP | ||
676 | /* l %r5,<d(cpu_nr)> */ | ||
677 | EMIT4_DISP(0x58500000, offsetof(struct _lowcore, cpu_nr)); | ||
678 | #else | ||
679 | /* lhi %r5,0 */ | ||
680 | EMIT4(0xa7580000); | ||
681 | #endif | ||
682 | break; | ||
683 | default: /* too complex, give up */ | ||
684 | goto out; | ||
685 | } | ||
686 | addrs[i] = jit->prg - jit->start; | ||
687 | return 0; | ||
688 | out: | ||
689 | return -1; | ||
690 | } | ||
691 | |||
692 | void bpf_jit_compile(struct sk_filter *fp) | ||
693 | { | ||
694 | unsigned long size, prg_len, lit_len; | ||
695 | struct bpf_jit jit, cjit; | ||
696 | unsigned int *addrs; | ||
697 | int pass, i; | ||
698 | |||
699 | if (!bpf_jit_enable) | ||
700 | return; | ||
701 | addrs = kmalloc(fp->len * sizeof(*addrs), GFP_KERNEL); | ||
702 | if (addrs == NULL) | ||
703 | return; | ||
704 | memset(addrs, 0, fp->len * sizeof(*addrs)); | ||
705 | memset(&jit, 0, sizeof(cjit)); | ||
706 | memset(&cjit, 0, sizeof(cjit)); | ||
707 | |||
708 | for (pass = 0; pass < 10; pass++) { | ||
709 | jit.prg = jit.start; | ||
710 | jit.lit = jit.mid; | ||
711 | |||
712 | bpf_jit_prologue(&jit); | ||
713 | bpf_jit_noleaks(&jit, fp->insns); | ||
714 | for (i = 0; i < fp->len; i++) { | ||
715 | if (bpf_jit_insn(&jit, fp->insns + i, addrs, i, | ||
716 | i == fp->len - 1)) | ||
717 | goto out; | ||
718 | } | ||
719 | bpf_jit_epilogue(&jit); | ||
720 | if (jit.start) { | ||
721 | WARN_ON(jit.prg > cjit.prg || jit.lit > cjit.lit); | ||
722 | if (memcmp(&jit, &cjit, sizeof(jit)) == 0) | ||
723 | break; | ||
724 | } else if (jit.prg == cjit.prg && jit.lit == cjit.lit) { | ||
725 | prg_len = jit.prg - jit.start; | ||
726 | lit_len = jit.lit - jit.mid; | ||
727 | size = max_t(unsigned long, prg_len + lit_len, | ||
728 | sizeof(struct work_struct)); | ||
729 | if (size >= BPF_SIZE_MAX) | ||
730 | goto out; | ||
731 | jit.start = module_alloc(size); | ||
732 | if (!jit.start) | ||
733 | goto out; | ||
734 | jit.prg = jit.mid = jit.start + prg_len; | ||
735 | jit.lit = jit.end = jit.start + prg_len + lit_len; | ||
736 | jit.base_ip += (unsigned long) jit.start; | ||
737 | jit.exit_ip += (unsigned long) jit.start; | ||
738 | jit.ret0_ip += (unsigned long) jit.start; | ||
739 | } | ||
740 | cjit = jit; | ||
741 | } | ||
742 | if (bpf_jit_enable > 1) { | ||
743 | pr_err("flen=%d proglen=%lu pass=%d image=%p\n", | ||
744 | fp->len, jit.end - jit.start, pass, jit.start); | ||
745 | if (jit.start) { | ||
746 | printk(KERN_ERR "JIT code:\n"); | ||
747 | print_fn_code(jit.start, jit.mid - jit.start); | ||
748 | print_hex_dump(KERN_ERR, "JIT literals:\n", | ||
749 | DUMP_PREFIX_ADDRESS, 16, 1, | ||
750 | jit.mid, jit.end - jit.mid, false); | ||
751 | } | ||
752 | } | ||
753 | if (jit.start) | ||
754 | fp->bpf_func = (void *) jit.start; | ||
755 | out: | ||
756 | kfree(addrs); | ||
757 | } | ||
758 | |||
759 | static void jit_free_defer(struct work_struct *arg) | ||
760 | { | ||
761 | module_free(NULL, arg); | ||
762 | } | ||
763 | |||
764 | /* run from softirq, we must use a work_struct to call | ||
765 | * module_free() from process context | ||
766 | */ | ||
767 | void bpf_jit_free(struct sk_filter *fp) | ||
768 | { | ||
769 | struct work_struct *work; | ||
770 | |||
771 | if (fp->bpf_func == sk_run_filter) | ||
772 | return; | ||
773 | work = (struct work_struct *)fp->bpf_func; | ||
774 | INIT_WORK(work, jit_free_defer); | ||
775 | schedule_work(work); | ||
776 | } | ||
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index a1e9d69a9c90..584b93674ea4 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c | |||
@@ -169,7 +169,7 @@ static ssize_t hw_interval_write(struct file *file, char const __user *buf, | |||
169 | if (*offset) | 169 | if (*offset) |
170 | return -EINVAL; | 170 | return -EINVAL; |
171 | retval = oprofilefs_ulong_from_user(&val, buf, count); | 171 | retval = oprofilefs_ulong_from_user(&val, buf, count); |
172 | if (retval) | 172 | if (retval <= 0) |
173 | return retval; | 173 | return retval; |
174 | if (val < oprofile_min_interval) | 174 | if (val < oprofile_min_interval) |
175 | oprofile_hw_interval = oprofile_min_interval; | 175 | oprofile_hw_interval = oprofile_min_interval; |
@@ -212,7 +212,7 @@ static ssize_t hwsampler_zero_write(struct file *file, char const __user *buf, | |||
212 | return -EINVAL; | 212 | return -EINVAL; |
213 | 213 | ||
214 | retval = oprofilefs_ulong_from_user(&val, buf, count); | 214 | retval = oprofilefs_ulong_from_user(&val, buf, count); |
215 | if (retval) | 215 | if (retval <= 0) |
216 | return retval; | 216 | return retval; |
217 | if (val != 0) | 217 | if (val != 0) |
218 | return -EINVAL; | 218 | return -EINVAL; |
@@ -243,7 +243,7 @@ static ssize_t hwsampler_kernel_write(struct file *file, char const __user *buf, | |||
243 | return -EINVAL; | 243 | return -EINVAL; |
244 | 244 | ||
245 | retval = oprofilefs_ulong_from_user(&val, buf, count); | 245 | retval = oprofilefs_ulong_from_user(&val, buf, count); |
246 | if (retval) | 246 | if (retval <= 0) |
247 | return retval; | 247 | return retval; |
248 | 248 | ||
249 | if (val != 0 && val != 1) | 249 | if (val != 0 && val != 1) |
@@ -278,7 +278,7 @@ static ssize_t hwsampler_user_write(struct file *file, char const __user *buf, | |||
278 | return -EINVAL; | 278 | return -EINVAL; |
279 | 279 | ||
280 | retval = oprofilefs_ulong_from_user(&val, buf, count); | 280 | retval = oprofilefs_ulong_from_user(&val, buf, count); |
281 | if (retval) | 281 | if (retval <= 0) |
282 | return retval; | 282 | return retval; |
283 | 283 | ||
284 | if (val != 0 && val != 1) | 284 | if (val != 0 && val != 1) |
@@ -317,7 +317,7 @@ static ssize_t timer_enabled_write(struct file *file, char const __user *buf, | |||
317 | return -EINVAL; | 317 | return -EINVAL; |
318 | 318 | ||
319 | retval = oprofilefs_ulong_from_user(&val, buf, count); | 319 | retval = oprofilefs_ulong_from_user(&val, buf, count); |
320 | if (retval) | 320 | if (retval <= 0) |
321 | return retval; | 321 | return retval; |
322 | 322 | ||
323 | if (val != 0 && val != 1) | 323 | if (val != 0 && val != 1) |
diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c index 2707023c7563..637970cfd3f4 100644 --- a/arch/score/kernel/process.c +++ b/arch/score/kernel/process.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/reboot.h> | 27 | #include <linux/reboot.h> |
28 | #include <linux/elfcore.h> | 28 | #include <linux/elfcore.h> |
29 | #include <linux/pm.h> | 29 | #include <linux/pm.h> |
30 | #include <linux/rcupdate.h> | ||
30 | 31 | ||
31 | void (*pm_power_off)(void); | 32 | void (*pm_power_off)(void); |
32 | EXPORT_SYMBOL(pm_power_off); | 33 | EXPORT_SYMBOL(pm_power_off); |
@@ -50,9 +51,10 @@ void __noreturn cpu_idle(void) | |||
50 | { | 51 | { |
51 | /* endless idle loop with no priority at all */ | 52 | /* endless idle loop with no priority at all */ |
52 | while (1) { | 53 | while (1) { |
54 | rcu_idle_enter(); | ||
53 | while (!need_resched()) | 55 | while (!need_resched()) |
54 | barrier(); | 56 | barrier(); |
55 | 57 | rcu_idle_exit(); | |
56 | schedule_preempt_disabled(); | 58 | schedule_preempt_disabled(); |
57 | } | 59 | } |
58 | } | 60 | } |
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index b7cf6a547f11..7e605b95592a 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S | |||
@@ -933,7 +933,7 @@ ret_with_reschedule: | |||
933 | 933 | ||
934 | pta restore_all, tr1 | 934 | pta restore_all, tr1 |
935 | 935 | ||
936 | movi _TIF_SIGPENDING, r8 | 936 | movi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8 |
937 | and r8, r7, r8 | 937 | and r8, r7, r8 |
938 | pta work_notifysig, tr0 | 938 | pta work_notifysig, tr0 |
939 | bne r8, ZERO, tr0 | 939 | bne r8, ZERO, tr0 |
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index f67601cb3f1f..b96489d8b27d 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
@@ -139,7 +139,7 @@ work_pending: | |||
139 | ! r8: current_thread_info | 139 | ! r8: current_thread_info |
140 | ! t: result of "tst #_TIF_NEED_RESCHED, r0" | 140 | ! t: result of "tst #_TIF_NEED_RESCHED, r0" |
141 | bf/s work_resched | 141 | bf/s work_resched |
142 | tst #_TIF_SIGPENDING, r0 | 142 | tst #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0 |
143 | work_notifysig: | 143 | work_notifysig: |
144 | bt/s __restore_all | 144 | bt/s __restore_all |
145 | mov r15, r4 | 145 | mov r15, r4 |
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index 15e0a1693976..f1ddc0d23679 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c | |||
@@ -48,9 +48,7 @@ void *module_alloc(unsigned long size) | |||
48 | return NULL; | 48 | return NULL; |
49 | 49 | ||
50 | ret = module_map(size); | 50 | ret = module_map(size); |
51 | if (!ret) | 51 | if (ret) |
52 | ret = ERR_PTR(-ENOMEM); | ||
53 | else | ||
54 | memset(ret, 0, size); | 52 | memset(ret, 0, size); |
55 | 53 | ||
56 | return ret; | 54 | return ret; |
@@ -116,6 +114,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, | |||
116 | v = sym->st_value + rel[i].r_addend; | 114 | v = sym->st_value + rel[i].r_addend; |
117 | 115 | ||
118 | switch (ELF_R_TYPE(rel[i].r_info) & 0xff) { | 116 | switch (ELF_R_TYPE(rel[i].r_info) & 0xff) { |
117 | case R_SPARC_DISP32: | ||
118 | v -= (Elf_Addr) location; | ||
119 | *loc32 = v; | ||
120 | break; | ||
119 | #ifdef CONFIG_SPARC64 | 121 | #ifdef CONFIG_SPARC64 |
120 | case R_SPARC_64: | 122 | case R_SPARC_64: |
121 | location[0] = v >> 56; | 123 | location[0] = v >> 56; |
@@ -128,11 +130,6 @@ int apply_relocate_add(Elf_Shdr *sechdrs, | |||
128 | location[7] = v >> 0; | 130 | location[7] = v >> 0; |
129 | break; | 131 | break; |
130 | 132 | ||
131 | case R_SPARC_DISP32: | ||
132 | v -= (Elf_Addr) location; | ||
133 | *loc32 = v; | ||
134 | break; | ||
135 | |||
136 | case R_SPARC_WDISP19: | 133 | case R_SPARC_WDISP19: |
137 | v -= (Elf_Addr) location; | 134 | v -= (Elf_Addr) location; |
138 | *loc32 = (*loc32 & ~0x7ffff) | | 135 | *loc32 = (*loc32 & ~0x7ffff) | |
diff --git a/arch/tile/include/asm/topology.h b/arch/tile/include/asm/topology.h index 7a7ce390534f..d5e86c9f74fd 100644 --- a/arch/tile/include/asm/topology.h +++ b/arch/tile/include/asm/topology.h | |||
@@ -69,7 +69,6 @@ static inline const struct cpumask *cpumask_of_node(int node) | |||
69 | | 1*SD_BALANCE_FORK \ | 69 | | 1*SD_BALANCE_FORK \ |
70 | | 0*SD_BALANCE_WAKE \ | 70 | | 0*SD_BALANCE_WAKE \ |
71 | | 0*SD_WAKE_AFFINE \ | 71 | | 0*SD_WAKE_AFFINE \ |
72 | | 0*SD_PREFER_LOCAL \ | ||
73 | | 0*SD_SHARE_CPUPOWER \ | 72 | | 0*SD_SHARE_CPUPOWER \ |
74 | | 0*SD_SHARE_PKG_RESOURCES \ | 73 | | 0*SD_SHARE_PKG_RESOURCES \ |
75 | | 0*SD_SERIALIZE \ | 74 | | 0*SD_SERIALIZE \ |
diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h index 15fb77992083..58105c31228b 100644 --- a/arch/tile/include/gxio/iorpc_trio.h +++ b/arch/tile/include/gxio/iorpc_trio.h | |||
@@ -25,21 +25,23 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
27 | 27 | ||
28 | #define GXIO_TRIO_OP_ALLOC_ASIDS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400) | 28 | #define GXIO_TRIO_OP_DEALLOC_ASID IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400) |
29 | #define GXIO_TRIO_OP_ALLOC_ASIDS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1401) | ||
29 | 30 | ||
30 | #define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402) | 31 | #define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404) |
31 | 32 | ||
32 | #define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e) | 33 | #define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412) |
33 | #define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f) | ||
34 | 34 | ||
35 | #define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417) | 35 | #define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414) |
36 | #define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418) | ||
37 | #define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1419) | ||
38 | #define GXIO_TRIO_OP_CONFIG_MSI_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a) | ||
39 | 36 | ||
40 | #define GXIO_TRIO_OP_SET_MPS_MRS IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141c) | 37 | #define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e) |
41 | #define GXIO_TRIO_OP_FORCE_RC_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d) | 38 | #define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141f) |
42 | #define GXIO_TRIO_OP_FORCE_EP_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e) | 39 | #define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1420) |
40 | #define GXIO_TRIO_OP_CONFIG_MSI_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1421) | ||
41 | |||
42 | #define GXIO_TRIO_OP_SET_MPS_MRS IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1423) | ||
43 | #define GXIO_TRIO_OP_FORCE_RC_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1424) | ||
44 | #define GXIO_TRIO_OP_FORCE_EP_LINK_UP IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1425) | ||
43 | #define GXIO_TRIO_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000) | 45 | #define GXIO_TRIO_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000) |
44 | #define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001) | 46 | #define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001) |
45 | 47 | ||
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 664a60e8dfb4..c17de0db6736 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -705,6 +705,7 @@ static void stack_proc(void *arg) | |||
705 | struct task_struct *from = current, *to = arg; | 705 | struct task_struct *from = current, *to = arg; |
706 | 706 | ||
707 | to->thread.saved_task = from; | 707 | to->thread.saved_task = from; |
708 | rcu_switch(from, to); | ||
708 | switch_to(from, to, from); | 709 | switch_to(from, to, from); |
709 | } | 710 | } |
710 | 711 | ||
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index 69f1c57a8d0d..33a6a2423bd2 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h | |||
@@ -20,14 +20,6 @@ struct mm_struct; | |||
20 | 20 | ||
21 | struct thread_struct { | 21 | struct thread_struct { |
22 | struct task_struct *saved_task; | 22 | struct task_struct *saved_task; |
23 | /* | ||
24 | * This flag is set to 1 before calling do_fork (and analyzed in | ||
25 | * copy_thread) to mark that we are begin called from userspace (fork / | ||
26 | * vfork / clone), and reset to 0 after. It is left to 0 when called | ||
27 | * from kernelspace (i.e. kernel_thread() or fork_idle(), | ||
28 | * as of 2.6.11). | ||
29 | */ | ||
30 | int forking; | ||
31 | struct pt_regs regs; | 23 | struct pt_regs regs; |
32 | int singlestep_syscall; | 24 | int singlestep_syscall; |
33 | void *fault_addr; | 25 | void *fault_addr; |
@@ -58,7 +50,6 @@ struct thread_struct { | |||
58 | 50 | ||
59 | #define INIT_THREAD \ | 51 | #define INIT_THREAD \ |
60 | { \ | 52 | { \ |
61 | .forking = 0, \ | ||
62 | .regs = EMPTY_REGS, \ | 53 | .regs = EMPTY_REGS, \ |
63 | .fault_addr = NULL, \ | 54 | .fault_addr = NULL, \ |
64 | .prev_sched = NULL, \ | 55 | .prev_sched = NULL, \ |
diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h index 40db8f71deae..2df313b6a586 100644 --- a/arch/um/include/shared/common-offsets.h +++ b/arch/um/include/shared/common-offsets.h | |||
@@ -7,16 +7,6 @@ DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); | |||
7 | DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); | 7 | DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); |
8 | DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); | 8 | DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); |
9 | 9 | ||
10 | DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); | ||
11 | DEFINE_STR(UM_KERN_ALERT, KERN_ALERT); | ||
12 | DEFINE_STR(UM_KERN_CRIT, KERN_CRIT); | ||
13 | DEFINE_STR(UM_KERN_ERR, KERN_ERR); | ||
14 | DEFINE_STR(UM_KERN_WARNING, KERN_WARNING); | ||
15 | DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); | ||
16 | DEFINE_STR(UM_KERN_INFO, KERN_INFO); | ||
17 | DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); | ||
18 | DEFINE_STR(UM_KERN_CONT, KERN_CONT); | ||
19 | |||
20 | DEFINE(UM_ELF_CLASS, ELF_CLASS); | 10 | DEFINE(UM_ELF_CLASS, ELF_CLASS); |
21 | DEFINE(UM_ELFCLASS32, ELFCLASS32); | 11 | DEFINE(UM_ELFCLASS32, ELFCLASS32); |
22 | DEFINE(UM_ELFCLASS64, ELFCLASS64); | 12 | DEFINE(UM_ELFCLASS64, ELFCLASS64); |
diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h index 4fa82c055aab..cef068563336 100644 --- a/arch/um/include/shared/user.h +++ b/arch/um/include/shared/user.h | |||
@@ -26,6 +26,17 @@ | |||
26 | extern void panic(const char *fmt, ...) | 26 | extern void panic(const char *fmt, ...) |
27 | __attribute__ ((format (printf, 1, 2))); | 27 | __attribute__ ((format (printf, 1, 2))); |
28 | 28 | ||
29 | /* Requires preincluding include/linux/kern_levels.h */ | ||
30 | #define UM_KERN_EMERG KERN_EMERG | ||
31 | #define UM_KERN_ALERT KERN_ALERT | ||
32 | #define UM_KERN_CRIT KERN_CRIT | ||
33 | #define UM_KERN_ERR KERN_ERR | ||
34 | #define UM_KERN_WARNING KERN_WARNING | ||
35 | #define UM_KERN_NOTICE KERN_NOTICE | ||
36 | #define UM_KERN_INFO KERN_INFO | ||
37 | #define UM_KERN_DEBUG KERN_DEBUG | ||
38 | #define UM_KERN_CONT KERN_CONT | ||
39 | |||
29 | #ifdef UML_CONFIG_PRINTK | 40 | #ifdef UML_CONFIG_PRINTK |
30 | extern int printk(const char *fmt, ...) | 41 | extern int printk(const char *fmt, ...) |
31 | __attribute__ ((format (printf, 1, 2))); | 42 | __attribute__ ((format (printf, 1, 2))); |
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 6cade9366364..8c82786da823 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
@@ -39,34 +39,21 @@ void flush_thread(void) | |||
39 | 39 | ||
40 | void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | 40 | void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) |
41 | { | 41 | { |
42 | get_safe_registers(regs->regs.gp, regs->regs.fp); | ||
42 | PT_REGS_IP(regs) = eip; | 43 | PT_REGS_IP(regs) = eip; |
43 | PT_REGS_SP(regs) = esp; | 44 | PT_REGS_SP(regs) = esp; |
44 | } | 45 | current->ptrace &= ~PT_DTRACE; |
45 | EXPORT_SYMBOL(start_thread); | ||
46 | |||
47 | static long execve1(const char *file, | ||
48 | const char __user *const __user *argv, | ||
49 | const char __user *const __user *env) | ||
50 | { | ||
51 | long error; | ||
52 | |||
53 | error = do_execve(file, argv, env, ¤t->thread.regs); | ||
54 | if (error == 0) { | ||
55 | task_lock(current); | ||
56 | current->ptrace &= ~PT_DTRACE; | ||
57 | #ifdef SUBARCH_EXECVE1 | 46 | #ifdef SUBARCH_EXECVE1 |
58 | SUBARCH_EXECVE1(¤t->thread.regs.regs); | 47 | SUBARCH_EXECVE1(regs->regs); |
59 | #endif | 48 | #endif |
60 | task_unlock(current); | ||
61 | } | ||
62 | return error; | ||
63 | } | 49 | } |
50 | EXPORT_SYMBOL(start_thread); | ||
64 | 51 | ||
65 | long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) | 52 | long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) |
66 | { | 53 | { |
67 | long err; | 54 | long err; |
68 | 55 | ||
69 | err = execve1(file, argv, env); | 56 | err = do_execve(file, argv, env, ¤t->thread.regs); |
70 | if (!err) | 57 | if (!err) |
71 | UML_LONGJMP(current->thread.exec_buf, 1); | 58 | UML_LONGJMP(current->thread.exec_buf, 1); |
72 | return err; | 59 | return err; |
@@ -81,7 +68,7 @@ long sys_execve(const char __user *file, const char __user *const __user *argv, | |||
81 | filename = getname(file); | 68 | filename = getname(file); |
82 | error = PTR_ERR(filename); | 69 | error = PTR_ERR(filename); |
83 | if (IS_ERR(filename)) goto out; | 70 | if (IS_ERR(filename)) goto out; |
84 | error = execve1(filename, argv, env); | 71 | error = do_execve(filename, argv, env, ¤t->thread.regs); |
85 | putname(filename); | 72 | putname(filename); |
86 | out: | 73 | out: |
87 | return error; | 74 | return error; |
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 57fc7028714a..c5f5afa50745 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
@@ -181,11 +181,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
181 | struct pt_regs *regs) | 181 | struct pt_regs *regs) |
182 | { | 182 | { |
183 | void (*handler)(void); | 183 | void (*handler)(void); |
184 | int kthread = current->flags & PF_KTHREAD; | ||
184 | int ret = 0; | 185 | int ret = 0; |
185 | 186 | ||
186 | p->thread = (struct thread_struct) INIT_THREAD; | 187 | p->thread = (struct thread_struct) INIT_THREAD; |
187 | 188 | ||
188 | if (current->thread.forking) { | 189 | if (!kthread) { |
189 | memcpy(&p->thread.regs.regs, ®s->regs, | 190 | memcpy(&p->thread.regs.regs, ®s->regs, |
190 | sizeof(p->thread.regs.regs)); | 191 | sizeof(p->thread.regs.regs)); |
191 | PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); | 192 | PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); |
@@ -195,8 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
195 | handler = fork_handler; | 196 | handler = fork_handler; |
196 | 197 | ||
197 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | 198 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); |
198 | } | 199 | } else { |
199 | else { | ||
200 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); | 200 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); |
201 | p->thread.request.u.thread = current->thread.request.u.thread; | 201 | p->thread.request.u.thread = current->thread.request.u.thread; |
202 | handler = new_thread_handler; | 202 | handler = new_thread_handler; |
@@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
204 | 204 | ||
205 | new_thread(task_stack_page(p), &p->thread.switch_buf, handler); | 205 | new_thread(task_stack_page(p), &p->thread.switch_buf, handler); |
206 | 206 | ||
207 | if (current->thread.forking) { | 207 | if (!kthread) { |
208 | clear_flushed_tls(p); | 208 | clear_flushed_tls(p); |
209 | 209 | ||
210 | /* | 210 | /* |
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index 7362d58efc29..cc9c2350e417 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c | |||
@@ -22,9 +22,13 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, | |||
22 | struct k_sigaction *ka, siginfo_t *info) | 22 | struct k_sigaction *ka, siginfo_t *info) |
23 | { | 23 | { |
24 | sigset_t *oldset = sigmask_to_save(); | 24 | sigset_t *oldset = sigmask_to_save(); |
25 | int singlestep = 0; | ||
25 | unsigned long sp; | 26 | unsigned long sp; |
26 | int err; | 27 | int err; |
27 | 28 | ||
29 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) | ||
30 | singlestep = 1; | ||
31 | |||
28 | /* Did we come from a system call? */ | 32 | /* Did we come from a system call? */ |
29 | if (PT_REGS_SYSCALL_NR(regs) >= 0) { | 33 | if (PT_REGS_SYSCALL_NR(regs) >= 0) { |
30 | /* If so, check system call restarting.. */ | 34 | /* If so, check system call restarting.. */ |
@@ -61,7 +65,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, | |||
61 | if (err) | 65 | if (err) |
62 | force_sigsegv(signr, current); | 66 | force_sigsegv(signr, current); |
63 | else | 67 | else |
64 | signal_delivered(signr, info, ka, regs, 0); | 68 | signal_delivered(signr, info, ka, regs, singlestep); |
65 | } | 69 | } |
66 | 70 | ||
67 | static int kern_do_signal(struct pt_regs *regs) | 71 | static int kern_do_signal(struct pt_regs *regs) |
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index f958cb876ee3..a4c6d8eee74c 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c | |||
@@ -17,25 +17,25 @@ | |||
17 | 17 | ||
18 | long sys_fork(void) | 18 | long sys_fork(void) |
19 | { | 19 | { |
20 | long ret; | 20 | return do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), |
21 | |||
22 | current->thread.forking = 1; | ||
23 | ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), | ||
24 | ¤t->thread.regs, 0, NULL, NULL); | 21 | ¤t->thread.regs, 0, NULL, NULL); |
25 | current->thread.forking = 0; | ||
26 | return ret; | ||
27 | } | 22 | } |
28 | 23 | ||
29 | long sys_vfork(void) | 24 | long sys_vfork(void) |
30 | { | 25 | { |
31 | long ret; | 26 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, |
32 | |||
33 | current->thread.forking = 1; | ||
34 | ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | ||
35 | UPT_SP(¤t->thread.regs.regs), | 27 | UPT_SP(¤t->thread.regs.regs), |
36 | ¤t->thread.regs, 0, NULL, NULL); | 28 | ¤t->thread.regs, 0, NULL, NULL); |
37 | current->thread.forking = 0; | 29 | } |
38 | return ret; | 30 | |
31 | long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
32 | void __user *parent_tid, void __user *child_tid) | ||
33 | { | ||
34 | if (!newsp) | ||
35 | newsp = UPT_SP(¤t->thread.regs.regs); | ||
36 | |||
37 | return do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, | ||
38 | child_tid); | ||
39 | } | 39 | } |
40 | 40 | ||
41 | long old_mmap(unsigned long addr, unsigned long len, | 41 | long old_mmap(unsigned long addr, unsigned long len, |
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index d50270d26b42..15889df9b466 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules | |||
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) | |||
8 | USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) | 8 | USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) |
9 | 9 | ||
10 | $(USER_OBJS:.o=.%): \ | 10 | $(USER_OBJS:.o=.%): \ |
11 | c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o) | 11 | c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o) |
12 | 12 | ||
13 | # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of | 13 | # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of |
14 | # using it directly. | 14 | # using it directly. |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 8ec3a1aa4abd..943667050dae 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -7,11 +7,13 @@ config 64BIT | |||
7 | Say no to build a 32-bit kernel - formerly known as i386 | 7 | Say no to build a 32-bit kernel - formerly known as i386 |
8 | 8 | ||
9 | config X86_32 | 9 | config X86_32 |
10 | def_bool !64BIT | 10 | def_bool y |
11 | depends on !64BIT | ||
11 | select CLKSRC_I8253 | 12 | select CLKSRC_I8253 |
12 | 13 | ||
13 | config X86_64 | 14 | config X86_64 |
14 | def_bool 64BIT | 15 | def_bool y |
16 | depends on 64BIT | ||
15 | select X86_DEV_DMA_OPS | 17 | select X86_DEV_DMA_OPS |
16 | 18 | ||
17 | ### Arch settings | 19 | ### Arch settings |
@@ -36,6 +38,7 @@ config X86 | |||
36 | select HAVE_KRETPROBES | 38 | select HAVE_KRETPROBES |
37 | select HAVE_OPTPROBES | 39 | select HAVE_OPTPROBES |
38 | select HAVE_FTRACE_MCOUNT_RECORD | 40 | select HAVE_FTRACE_MCOUNT_RECORD |
41 | select HAVE_FENTRY if X86_64 | ||
39 | select HAVE_C_RECORDMCOUNT | 42 | select HAVE_C_RECORDMCOUNT |
40 | select HAVE_DYNAMIC_FTRACE | 43 | select HAVE_DYNAMIC_FTRACE |
41 | select HAVE_FUNCTION_TRACER | 44 | select HAVE_FUNCTION_TRACER |
@@ -60,6 +63,8 @@ config X86 | |||
60 | select HAVE_MIXED_BREAKPOINTS_REGS | 63 | select HAVE_MIXED_BREAKPOINTS_REGS |
61 | select PERF_EVENTS | 64 | select PERF_EVENTS |
62 | select HAVE_PERF_EVENTS_NMI | 65 | select HAVE_PERF_EVENTS_NMI |
66 | select HAVE_PERF_REGS | ||
67 | select HAVE_PERF_USER_STACK_DUMP | ||
63 | select ANON_INODES | 68 | select ANON_INODES |
64 | select HAVE_ALIGNED_STRUCT_PAGE if SLUB && !M386 | 69 | select HAVE_ALIGNED_STRUCT_PAGE if SLUB && !M386 |
65 | select HAVE_CMPXCHG_LOCAL if !M386 | 70 | select HAVE_CMPXCHG_LOCAL if !M386 |
@@ -97,9 +102,12 @@ config X86 | |||
97 | select KTIME_SCALAR if X86_32 | 102 | select KTIME_SCALAR if X86_32 |
98 | select GENERIC_STRNCPY_FROM_USER | 103 | select GENERIC_STRNCPY_FROM_USER |
99 | select GENERIC_STRNLEN_USER | 104 | select GENERIC_STRNLEN_USER |
105 | select HAVE_RCU_USER_QS if X86_64 | ||
106 | select HAVE_IRQ_TIME_ACCOUNTING | ||
100 | 107 | ||
101 | config INSTRUCTION_DECODER | 108 | config INSTRUCTION_DECODER |
102 | def_bool (KPROBES || PERF_EVENTS || UPROBES) | 109 | def_bool y |
110 | depends on KPROBES || PERF_EVENTS || UPROBES | ||
103 | 111 | ||
104 | config OUTPUT_FORMAT | 112 | config OUTPUT_FORMAT |
105 | string | 113 | string |
@@ -127,13 +135,15 @@ config SBUS | |||
127 | bool | 135 | bool |
128 | 136 | ||
129 | config NEED_DMA_MAP_STATE | 137 | config NEED_DMA_MAP_STATE |
130 | def_bool (X86_64 || INTEL_IOMMU || DMA_API_DEBUG) | 138 | def_bool y |
139 | depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG | ||
131 | 140 | ||
132 | config NEED_SG_DMA_LENGTH | 141 | config NEED_SG_DMA_LENGTH |
133 | def_bool y | 142 | def_bool y |
134 | 143 | ||
135 | config GENERIC_ISA_DMA | 144 | config GENERIC_ISA_DMA |
136 | def_bool ISA_DMA_API | 145 | def_bool y |
146 | depends on ISA_DMA_API | ||
137 | 147 | ||
138 | config GENERIC_BUG | 148 | config GENERIC_BUG |
139 | def_bool y | 149 | def_bool y |
@@ -150,13 +160,16 @@ config GENERIC_GPIO | |||
150 | bool | 160 | bool |
151 | 161 | ||
152 | config ARCH_MAY_HAVE_PC_FDC | 162 | config ARCH_MAY_HAVE_PC_FDC |
153 | def_bool ISA_DMA_API | 163 | def_bool y |
164 | depends on ISA_DMA_API | ||
154 | 165 | ||
155 | config RWSEM_GENERIC_SPINLOCK | 166 | config RWSEM_GENERIC_SPINLOCK |
156 | def_bool !X86_XADD | 167 | def_bool y |
168 | depends on !X86_XADD | ||
157 | 169 | ||
158 | config RWSEM_XCHGADD_ALGORITHM | 170 | config RWSEM_XCHGADD_ALGORITHM |
159 | def_bool X86_XADD | 171 | def_bool y |
172 | depends on X86_XADD | ||
160 | 173 | ||
161 | config GENERIC_CALIBRATE_DELAY | 174 | config GENERIC_CALIBRATE_DELAY |
162 | def_bool y | 175 | def_bool y |
@@ -746,13 +759,14 @@ config SWIOTLB | |||
746 | def_bool y if X86_64 | 759 | def_bool y if X86_64 |
747 | ---help--- | 760 | ---help--- |
748 | Support for software bounce buffers used on x86-64 systems | 761 | Support for software bounce buffers used on x86-64 systems |
749 | which don't have a hardware IOMMU (e.g. the current generation | 762 | which don't have a hardware IOMMU. Using this PCI devices |
750 | of Intel's x86-64 CPUs). Using this PCI devices which can only | 763 | which can only access 32-bits of memory can be used on systems |
751 | access 32-bits of memory can be used on systems with more than | 764 | with more than 3 GB of memory. |
752 | 3 GB of memory. If unsure, say Y. | 765 | If unsure, say Y. |
753 | 766 | ||
754 | config IOMMU_HELPER | 767 | config IOMMU_HELPER |
755 | def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU) | 768 | def_bool y |
769 | depends on CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU | ||
756 | 770 | ||
757 | config MAXSMP | 771 | config MAXSMP |
758 | bool "Enable Maximum number of SMP Processors and NUMA Nodes" | 772 | bool "Enable Maximum number of SMP Processors and NUMA Nodes" |
@@ -796,17 +810,6 @@ config SCHED_MC | |||
796 | making when dealing with multi-core CPU chips at a cost of slightly | 810 | making when dealing with multi-core CPU chips at a cost of slightly |
797 | increased overhead in some places. If unsure say N here. | 811 | increased overhead in some places. If unsure say N here. |
798 | 812 | ||
799 | config IRQ_TIME_ACCOUNTING | ||
800 | bool "Fine granularity task level IRQ time accounting" | ||
801 | default n | ||
802 | ---help--- | ||
803 | Select this option to enable fine granularity task irq time | ||
804 | accounting. This is done by reading a timestamp on each | ||
805 | transitions between softirq and hardirq state, so there can be a | ||
806 | small performance impact. | ||
807 | |||
808 | If in doubt, say N here. | ||
809 | |||
810 | source "kernel/Kconfig.preempt" | 813 | source "kernel/Kconfig.preempt" |
811 | 814 | ||
812 | config X86_UP_APIC | 815 | config X86_UP_APIC |
@@ -871,6 +874,7 @@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS | |||
871 | 874 | ||
872 | config X86_MCE | 875 | config X86_MCE |
873 | bool "Machine Check / overheating reporting" | 876 | bool "Machine Check / overheating reporting" |
877 | default y | ||
874 | ---help--- | 878 | ---help--- |
875 | Machine Check support allows the processor to notify the | 879 | Machine Check support allows the processor to notify the |
876 | kernel if it detects a problem (e.g. overheating, data corruption). | 880 | kernel if it detects a problem (e.g. overheating, data corruption). |
@@ -982,25 +986,25 @@ config X86_REBOOTFIXUPS | |||
982 | Say N otherwise. | 986 | Say N otherwise. |
983 | 987 | ||
984 | config MICROCODE | 988 | config MICROCODE |
985 | tristate "/dev/cpu/microcode - microcode support" | 989 | tristate "CPU microcode loading support" |
986 | select FW_LOADER | 990 | select FW_LOADER |
987 | ---help--- | 991 | ---help--- |
992 | |||
988 | If you say Y here, you will be able to update the microcode on | 993 | If you say Y here, you will be able to update the microcode on |
989 | certain Intel and AMD processors. The Intel support is for the | 994 | certain Intel and AMD processors. The Intel support is for the |
990 | IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, | 995 | IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, |
991 | Pentium 4, Xeon etc. The AMD support is for family 0x10 and | 996 | Xeon etc. The AMD support is for families 0x10 and later. You will |
992 | 0x11 processors, e.g. Opteron, Phenom and Turion 64 Ultra. | 997 | obviously need the actual microcode binary data itself which is not |
993 | You will obviously need the actual microcode binary data itself | 998 | shipped with the Linux kernel. |
994 | which is not shipped with the Linux kernel. | ||
995 | 999 | ||
996 | This option selects the general module only, you need to select | 1000 | This option selects the general module only, you need to select |
997 | at least one vendor specific module as well. | 1001 | at least one vendor specific module as well. |
998 | 1002 | ||
999 | To compile this driver as a module, choose M here: the | 1003 | To compile this driver as a module, choose M here: the module |
1000 | module will be called microcode. | 1004 | will be called microcode. |
1001 | 1005 | ||
1002 | config MICROCODE_INTEL | 1006 | config MICROCODE_INTEL |
1003 | bool "Intel microcode patch loading support" | 1007 | bool "Intel microcode loading support" |
1004 | depends on MICROCODE | 1008 | depends on MICROCODE |
1005 | default MICROCODE | 1009 | default MICROCODE |
1006 | select FW_LOADER | 1010 | select FW_LOADER |
@@ -1013,7 +1017,7 @@ config MICROCODE_INTEL | |||
1013 | <http://www.urbanmyth.org/microcode/>. | 1017 | <http://www.urbanmyth.org/microcode/>. |
1014 | 1018 | ||
1015 | config MICROCODE_AMD | 1019 | config MICROCODE_AMD |
1016 | bool "AMD microcode patch loading support" | 1020 | bool "AMD microcode loading support" |
1017 | depends on MICROCODE | 1021 | depends on MICROCODE |
1018 | select FW_LOADER | 1022 | select FW_LOADER |
1019 | ---help--- | 1023 | ---help--- |
@@ -1159,10 +1163,12 @@ config X86_PAE | |||
1159 | consumes more pagetable space per process. | 1163 | consumes more pagetable space per process. |
1160 | 1164 | ||
1161 | config ARCH_PHYS_ADDR_T_64BIT | 1165 | config ARCH_PHYS_ADDR_T_64BIT |
1162 | def_bool X86_64 || X86_PAE | 1166 | def_bool y |
1167 | depends on X86_64 || X86_PAE | ||
1163 | 1168 | ||
1164 | config ARCH_DMA_ADDR_T_64BIT | 1169 | config ARCH_DMA_ADDR_T_64BIT |
1165 | def_bool X86_64 || HIGHMEM64G | 1170 | def_bool y |
1171 | depends on X86_64 || HIGHMEM64G | ||
1166 | 1172 | ||
1167 | config DIRECT_GBPAGES | 1173 | config DIRECT_GBPAGES |
1168 | bool "Enable 1GB pages for kernel pagetables" if EXPERT | 1174 | bool "Enable 1GB pages for kernel pagetables" if EXPERT |
@@ -1285,8 +1291,8 @@ config ARCH_SELECT_MEMORY_MODEL | |||
1285 | depends on ARCH_SPARSEMEM_ENABLE | 1291 | depends on ARCH_SPARSEMEM_ENABLE |
1286 | 1292 | ||
1287 | config ARCH_MEMORY_PROBE | 1293 | config ARCH_MEMORY_PROBE |
1288 | def_bool X86_64 | 1294 | def_bool y |
1289 | depends on MEMORY_HOTPLUG | 1295 | depends on X86_64 && MEMORY_HOTPLUG |
1290 | 1296 | ||
1291 | config ARCH_PROC_KCORE_TEXT | 1297 | config ARCH_PROC_KCORE_TEXT |
1292 | def_bool y | 1298 | def_bool y |
@@ -1975,7 +1981,6 @@ config PCI_MMCONFIG | |||
1975 | 1981 | ||
1976 | config PCI_CNB20LE_QUIRK | 1982 | config PCI_CNB20LE_QUIRK |
1977 | bool "Read CNB20LE Host Bridge Windows" if EXPERT | 1983 | bool "Read CNB20LE Host Bridge Windows" if EXPERT |
1978 | default n | ||
1979 | depends on PCI && EXPERIMENTAL | 1984 | depends on PCI && EXPERIMENTAL |
1980 | help | 1985 | help |
1981 | Read the PCI windows out of the CNB20LE host bridge. This allows | 1986 | Read the PCI windows out of the CNB20LE host bridge. This allows |
@@ -2186,18 +2191,18 @@ config COMPAT | |||
2186 | depends on IA32_EMULATION || X86_X32 | 2191 | depends on IA32_EMULATION || X86_X32 |
2187 | select ARCH_WANT_OLD_COMPAT_IPC | 2192 | select ARCH_WANT_OLD_COMPAT_IPC |
2188 | 2193 | ||
2194 | if COMPAT | ||
2189 | config COMPAT_FOR_U64_ALIGNMENT | 2195 | config COMPAT_FOR_U64_ALIGNMENT |
2190 | def_bool COMPAT | 2196 | def_bool y |
2191 | depends on X86_64 | ||
2192 | 2197 | ||
2193 | config SYSVIPC_COMPAT | 2198 | config SYSVIPC_COMPAT |
2194 | def_bool y | 2199 | def_bool y |
2195 | depends on COMPAT && SYSVIPC | 2200 | depends on SYSVIPC |
2196 | 2201 | ||
2197 | config KEYS_COMPAT | 2202 | config KEYS_COMPAT |
2198 | bool | 2203 | def_bool y |
2199 | depends on COMPAT && KEYS | 2204 | depends on KEYS |
2200 | default y | 2205 | endif |
2201 | 2206 | ||
2202 | endmenu | 2207 | endmenu |
2203 | 2208 | ||
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 706e12e9984b..f3b86d0df44e 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu | |||
@@ -306,7 +306,8 @@ config X86_INTERNODE_CACHE_SHIFT | |||
306 | default X86_L1_CACHE_SHIFT | 306 | default X86_L1_CACHE_SHIFT |
307 | 307 | ||
308 | config X86_CMPXCHG | 308 | config X86_CMPXCHG |
309 | def_bool X86_64 || (X86_32 && !M386) | 309 | def_bool y |
310 | depends on X86_64 || (X86_32 && !M386) | ||
310 | 311 | ||
311 | config X86_L1_CACHE_SHIFT | 312 | config X86_L1_CACHE_SHIFT |
312 | int | 313 | int |
@@ -317,7 +318,7 @@ config X86_L1_CACHE_SHIFT | |||
317 | 318 | ||
318 | config X86_XADD | 319 | config X86_XADD |
319 | def_bool y | 320 | def_bool y |
320 | depends on X86_64 || !M386 | 321 | depends on !M386 |
321 | 322 | ||
322 | config X86_PPRO_FENCE | 323 | config X86_PPRO_FENCE |
323 | bool "PentiumPro memory ordering errata workaround" | 324 | bool "PentiumPro memory ordering errata workaround" |
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 682e9c210baa..474ca35b1bce 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile | |||
@@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) | |||
142 | KBUILD_CFLAGS += $(mflags-y) | 142 | KBUILD_CFLAGS += $(mflags-y) |
143 | KBUILD_AFLAGS += $(mflags-y) | 143 | KBUILD_AFLAGS += $(mflags-y) |
144 | 144 | ||
145 | archscripts: | 145 | archscripts: scripts_basic |
146 | $(Q)$(MAKE) $(build)=arch/x86/tools relocs | 146 | $(Q)$(MAKE) $(build)=arch/x86/tools relocs |
147 | 147 | ||
148 | ### | 148 | ### |
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index e398bb5d63bb..8a84501acb1b 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -28,6 +28,9 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ | |||
28 | $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ | 28 | $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ |
29 | $(obj)/piggy.o | 29 | $(obj)/piggy.o |
30 | 30 | ||
31 | $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone | ||
32 | $(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone | ||
33 | |||
31 | ifeq ($(CONFIG_EFI_STUB), y) | 34 | ifeq ($(CONFIG_EFI_STUB), y) |
32 | VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o | 35 | VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o |
33 | endif | 36 | endif |
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b3e0227df2c9..c760e073963e 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -276,8 +276,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, | |||
276 | nr_gops = size / sizeof(void *); | 276 | nr_gops = size / sizeof(void *); |
277 | for (i = 0; i < nr_gops; i++) { | 277 | for (i = 0; i < nr_gops; i++) { |
278 | struct efi_graphics_output_mode_info *info; | 278 | struct efi_graphics_output_mode_info *info; |
279 | efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; | 279 | efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; |
280 | void *pciio; | 280 | bool conout_found = false; |
281 | void *dummy; | ||
281 | void *h = gop_handle[i]; | 282 | void *h = gop_handle[i]; |
282 | 283 | ||
283 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | 284 | status = efi_call_phys3(sys_table->boottime->handle_protocol, |
@@ -285,19 +286,21 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, | |||
285 | if (status != EFI_SUCCESS) | 286 | if (status != EFI_SUCCESS) |
286 | continue; | 287 | continue; |
287 | 288 | ||
288 | efi_call_phys3(sys_table->boottime->handle_protocol, | 289 | status = efi_call_phys3(sys_table->boottime->handle_protocol, |
289 | h, &pciio_proto, &pciio); | 290 | h, &conout_proto, &dummy); |
291 | |||
292 | if (status == EFI_SUCCESS) | ||
293 | conout_found = true; | ||
290 | 294 | ||
291 | status = efi_call_phys4(gop->query_mode, gop, | 295 | status = efi_call_phys4(gop->query_mode, gop, |
292 | gop->mode->mode, &size, &info); | 296 | gop->mode->mode, &size, &info); |
293 | if (status == EFI_SUCCESS && (!first_gop || pciio)) { | 297 | if (status == EFI_SUCCESS && (!first_gop || conout_found)) { |
294 | /* | 298 | /* |
295 | * Apple provide GOPs that are not backed by | 299 | * Systems that use the UEFI Console Splitter may |
296 | * real hardware (they're used to handle | 300 | * provide multiple GOP devices, not all of which are |
297 | * multiple displays). The workaround is to | 301 | * backed by real hardware. The workaround is to search |
298 | * search for a GOP implementing the PCIIO | 302 | * for a GOP implementing the ConOut protocol, and if |
299 | * protocol, and if one isn't found, to just | 303 | * one isn't found, to just fall back to the first GOP. |
300 | * fallback to the first GOP. | ||
301 | */ | 304 | */ |
302 | width = info->horizontal_resolution; | 305 | width = info->horizontal_resolution; |
303 | height = info->vertical_resolution; | 306 | height = info->vertical_resolution; |
@@ -308,10 +311,10 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, | |||
308 | pixels_per_scan_line = info->pixels_per_scan_line; | 311 | pixels_per_scan_line = info->pixels_per_scan_line; |
309 | 312 | ||
310 | /* | 313 | /* |
311 | * Once we've found a GOP supporting PCIIO, | 314 | * Once we've found a GOP supporting ConOut, |
312 | * don't bother looking any further. | 315 | * don't bother looking any further. |
313 | */ | 316 | */ |
314 | if (pciio) | 317 | if (conout_found) |
315 | break; | 318 | break; |
316 | 319 | ||
317 | first_gop = gop; | 320 | first_gop = gop; |
@@ -328,7 +331,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, | |||
328 | si->lfb_width = width; | 331 | si->lfb_width = width; |
329 | si->lfb_height = height; | 332 | si->lfb_height = height; |
330 | si->lfb_base = fb_base; | 333 | si->lfb_base = fb_base; |
331 | si->lfb_size = fb_size; | ||
332 | si->pages = 1; | 334 | si->pages = 1; |
333 | 335 | ||
334 | if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { | 336 | if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { |
@@ -376,6 +378,10 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, | |||
376 | si->rsvd_pos = 0; | 378 | si->rsvd_pos = 0; |
377 | } | 379 | } |
378 | 380 | ||
381 | si->lfb_size = si->lfb_linelength * si->lfb_height; | ||
382 | |||
383 | si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; | ||
384 | |||
379 | free_handle: | 385 | free_handle: |
380 | efi_call_phys1(sys_table->boottime->free_pool, gop_handle); | 386 | efi_call_phys1(sys_table->boottime->free_pool, gop_handle); |
381 | return status; | 387 | return status; |
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index 3b6e15627c55..e5b0a8f91c5f 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h | |||
@@ -14,6 +14,10 @@ | |||
14 | #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) | 14 | #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) |
15 | #define EFI_READ_CHUNK_SIZE (1024 * 1024) | 15 | #define EFI_READ_CHUNK_SIZE (1024 * 1024) |
16 | 16 | ||
17 | #define EFI_CONSOLE_OUT_DEVICE_GUID \ | ||
18 | EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \ | ||
19 | 0x3f, 0xc1, 0x4d) | ||
20 | |||
17 | #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 | 21 | #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 |
18 | #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 | 22 | #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 |
19 | #define PIXEL_BIT_MASK 2 | 23 | #define PIXEL_BIT_MASK 2 |
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index b4e15dd6786a..2a017441b8b2 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -32,10 +32,6 @@ SYSSEG = 0x1000 /* historical load address >> 4 */ | |||
32 | #define SVGA_MODE ASK_VGA | 32 | #define SVGA_MODE ASK_VGA |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #ifndef RAMDISK | ||
36 | #define RAMDISK 0 | ||
37 | #endif | ||
38 | |||
39 | #ifndef ROOT_RDONLY | 35 | #ifndef ROOT_RDONLY |
40 | #define ROOT_RDONLY 1 | 36 | #define ROOT_RDONLY 1 |
41 | #endif | 37 | #endif |
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 119db67dcb03..5598547281a7 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig | |||
@@ -8,6 +8,8 @@ CONFIG_TASK_DELAY_ACCT=y | |||
8 | CONFIG_TASK_XACCT=y | 8 | CONFIG_TASK_XACCT=y |
9 | CONFIG_TASK_IO_ACCOUNTING=y | 9 | CONFIG_TASK_IO_ACCOUNTING=y |
10 | CONFIG_AUDIT=y | 10 | CONFIG_AUDIT=y |
11 | CONFIG_NO_HZ=y | ||
12 | CONFIG_HIGH_RES_TIMERS=y | ||
11 | CONFIG_LOG_BUF_SHIFT=18 | 13 | CONFIG_LOG_BUF_SHIFT=18 |
12 | CONFIG_CGROUPS=y | 14 | CONFIG_CGROUPS=y |
13 | CONFIG_CGROUP_FREEZER=y | 15 | CONFIG_CGROUP_FREEZER=y |
@@ -34,8 +36,6 @@ CONFIG_SGI_PARTITION=y | |||
34 | CONFIG_SUN_PARTITION=y | 36 | CONFIG_SUN_PARTITION=y |
35 | CONFIG_KARMA_PARTITION=y | 37 | CONFIG_KARMA_PARTITION=y |
36 | CONFIG_EFI_PARTITION=y | 38 | CONFIG_EFI_PARTITION=y |
37 | CONFIG_NO_HZ=y | ||
38 | CONFIG_HIGH_RES_TIMERS=y | ||
39 | CONFIG_SMP=y | 39 | CONFIG_SMP=y |
40 | CONFIG_X86_GENERIC=y | 40 | CONFIG_X86_GENERIC=y |
41 | CONFIG_HPET_TIMER=y | 41 | CONFIG_HPET_TIMER=y |
@@ -144,8 +144,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | |||
144 | CONFIG_DEBUG_DEVRES=y | 144 | CONFIG_DEBUG_DEVRES=y |
145 | CONFIG_CONNECTOR=y | 145 | CONFIG_CONNECTOR=y |
146 | CONFIG_BLK_DEV_LOOP=y | 146 | CONFIG_BLK_DEV_LOOP=y |
147 | CONFIG_BLK_DEV_RAM=y | ||
148 | CONFIG_BLK_DEV_RAM_SIZE=16384 | ||
149 | CONFIG_BLK_DEV_SD=y | 147 | CONFIG_BLK_DEV_SD=y |
150 | CONFIG_BLK_DEV_SR=y | 148 | CONFIG_BLK_DEV_SR=y |
151 | CONFIG_BLK_DEV_SR_VENDOR=y | 149 | CONFIG_BLK_DEV_SR_VENDOR=y |
@@ -231,8 +229,6 @@ CONFIG_SND_HRTIMER=y | |||
231 | CONFIG_SND_HDA_INTEL=y | 229 | CONFIG_SND_HDA_INTEL=y |
232 | CONFIG_SND_HDA_HWDEP=y | 230 | CONFIG_SND_HDA_HWDEP=y |
233 | CONFIG_HIDRAW=y | 231 | CONFIG_HIDRAW=y |
234 | CONFIG_HID_PID=y | ||
235 | CONFIG_USB_HIDDEV=y | ||
236 | CONFIG_HID_GYRATION=y | 232 | CONFIG_HID_GYRATION=y |
237 | CONFIG_LOGITECH_FF=y | 233 | CONFIG_LOGITECH_FF=y |
238 | CONFIG_HID_NTRIG=y | 234 | CONFIG_HID_NTRIG=y |
@@ -243,11 +239,11 @@ CONFIG_HID_SAMSUNG=y | |||
243 | CONFIG_HID_SONY=y | 239 | CONFIG_HID_SONY=y |
244 | CONFIG_HID_SUNPLUS=y | 240 | CONFIG_HID_SUNPLUS=y |
245 | CONFIG_HID_TOPSEED=y | 241 | CONFIG_HID_TOPSEED=y |
242 | CONFIG_HID_PID=y | ||
243 | CONFIG_USB_HIDDEV=y | ||
246 | CONFIG_USB=y | 244 | CONFIG_USB=y |
247 | CONFIG_USB_DEBUG=y | 245 | CONFIG_USB_DEBUG=y |
248 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y | 246 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y |
249 | CONFIG_USB_DEVICEFS=y | ||
250 | # CONFIG_USB_DEVICE_CLASS is not set | ||
251 | CONFIG_USB_MON=y | 247 | CONFIG_USB_MON=y |
252 | CONFIG_USB_EHCI_HCD=y | 248 | CONFIG_USB_EHCI_HCD=y |
253 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set | 249 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set |
@@ -262,10 +258,9 @@ CONFIG_RTC_CLASS=y | |||
262 | CONFIG_DMADEVICES=y | 258 | CONFIG_DMADEVICES=y |
263 | CONFIG_EEEPC_LAPTOP=y | 259 | CONFIG_EEEPC_LAPTOP=y |
264 | CONFIG_EFI_VARS=y | 260 | CONFIG_EFI_VARS=y |
265 | CONFIG_EXT3_FS=y | 261 | CONFIG_EXT4_FS=y |
266 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | 262 | CONFIG_EXT4_FS_POSIX_ACL=y |
267 | CONFIG_EXT3_FS_POSIX_ACL=y | 263 | CONFIG_EXT4_FS_SECURITY=y |
268 | CONFIG_EXT3_FS_SECURITY=y | ||
269 | CONFIG_QUOTA=y | 264 | CONFIG_QUOTA=y |
270 | CONFIG_QUOTA_NETLINK_INTERFACE=y | 265 | CONFIG_QUOTA_NETLINK_INTERFACE=y |
271 | # CONFIG_PRINT_QUOTA_WARNING is not set | 266 | # CONFIG_PRINT_QUOTA_WARNING is not set |
@@ -280,7 +275,6 @@ CONFIG_PROC_KCORE=y | |||
280 | CONFIG_TMPFS_POSIX_ACL=y | 275 | CONFIG_TMPFS_POSIX_ACL=y |
281 | CONFIG_HUGETLBFS=y | 276 | CONFIG_HUGETLBFS=y |
282 | CONFIG_NFS_FS=y | 277 | CONFIG_NFS_FS=y |
283 | CONFIG_NFS_V3=y | ||
284 | CONFIG_NFS_V3_ACL=y | 278 | CONFIG_NFS_V3_ACL=y |
285 | CONFIG_NFS_V4=y | 279 | CONFIG_NFS_V4=y |
286 | CONFIG_ROOT_NFS=y | 280 | CONFIG_ROOT_NFS=y |
@@ -299,13 +293,11 @@ CONFIG_DEBUG_KERNEL=y | |||
299 | CONFIG_SCHEDSTATS=y | 293 | CONFIG_SCHEDSTATS=y |
300 | CONFIG_TIMER_STATS=y | 294 | CONFIG_TIMER_STATS=y |
301 | CONFIG_DEBUG_STACK_USAGE=y | 295 | CONFIG_DEBUG_STACK_USAGE=y |
302 | CONFIG_SYSCTL_SYSCALL_CHECK=y | ||
303 | CONFIG_BLK_DEV_IO_TRACE=y | 296 | CONFIG_BLK_DEV_IO_TRACE=y |
304 | CONFIG_PROVIDE_OHCI1394_DMA_INIT=y | 297 | CONFIG_PROVIDE_OHCI1394_DMA_INIT=y |
305 | CONFIG_EARLY_PRINTK_DBGP=y | 298 | CONFIG_EARLY_PRINTK_DBGP=y |
306 | CONFIG_DEBUG_STACKOVERFLOW=y | 299 | CONFIG_DEBUG_STACKOVERFLOW=y |
307 | # CONFIG_DEBUG_RODATA_TEST is not set | 300 | # CONFIG_DEBUG_RODATA_TEST is not set |
308 | CONFIG_DEBUG_NX_TEST=m | ||
309 | CONFIG_DEBUG_BOOT_PARAMS=y | 301 | CONFIG_DEBUG_BOOT_PARAMS=y |
310 | CONFIG_OPTIMIZE_INLINING=y | 302 | CONFIG_OPTIMIZE_INLINING=y |
311 | CONFIG_KEYS_DEBUG_PROC_KEYS=y | 303 | CONFIG_KEYS_DEBUG_PROC_KEYS=y |
@@ -316,4 +308,3 @@ CONFIG_SECURITY_SELINUX_BOOTPARAM=y | |||
316 | CONFIG_SECURITY_SELINUX_DISABLE=y | 308 | CONFIG_SECURITY_SELINUX_DISABLE=y |
317 | CONFIG_CRYPTO_AES_586=y | 309 | CONFIG_CRYPTO_AES_586=y |
318 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 310 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
319 | CONFIG_CRC_T10DIF=y | ||
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 76eb2903809f..671524d0f6c0 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig | |||
@@ -8,6 +8,8 @@ CONFIG_TASK_DELAY_ACCT=y | |||
8 | CONFIG_TASK_XACCT=y | 8 | CONFIG_TASK_XACCT=y |
9 | CONFIG_TASK_IO_ACCOUNTING=y | 9 | CONFIG_TASK_IO_ACCOUNTING=y |
10 | CONFIG_AUDIT=y | 10 | CONFIG_AUDIT=y |
11 | CONFIG_NO_HZ=y | ||
12 | CONFIG_HIGH_RES_TIMERS=y | ||
11 | CONFIG_LOG_BUF_SHIFT=18 | 13 | CONFIG_LOG_BUF_SHIFT=18 |
12 | CONFIG_CGROUPS=y | 14 | CONFIG_CGROUPS=y |
13 | CONFIG_CGROUP_FREEZER=y | 15 | CONFIG_CGROUP_FREEZER=y |
@@ -34,8 +36,6 @@ CONFIG_SGI_PARTITION=y | |||
34 | CONFIG_SUN_PARTITION=y | 36 | CONFIG_SUN_PARTITION=y |
35 | CONFIG_KARMA_PARTITION=y | 37 | CONFIG_KARMA_PARTITION=y |
36 | CONFIG_EFI_PARTITION=y | 38 | CONFIG_EFI_PARTITION=y |
37 | CONFIG_NO_HZ=y | ||
38 | CONFIG_HIGH_RES_TIMERS=y | ||
39 | CONFIG_SMP=y | 39 | CONFIG_SMP=y |
40 | CONFIG_CALGARY_IOMMU=y | 40 | CONFIG_CALGARY_IOMMU=y |
41 | CONFIG_NR_CPUS=64 | 41 | CONFIG_NR_CPUS=64 |
@@ -144,8 +144,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | |||
144 | CONFIG_DEBUG_DEVRES=y | 144 | CONFIG_DEBUG_DEVRES=y |
145 | CONFIG_CONNECTOR=y | 145 | CONFIG_CONNECTOR=y |
146 | CONFIG_BLK_DEV_LOOP=y | 146 | CONFIG_BLK_DEV_LOOP=y |
147 | CONFIG_BLK_DEV_RAM=y | ||
148 | CONFIG_BLK_DEV_RAM_SIZE=16384 | ||
149 | CONFIG_BLK_DEV_SD=y | 147 | CONFIG_BLK_DEV_SD=y |
150 | CONFIG_BLK_DEV_SR=y | 148 | CONFIG_BLK_DEV_SR=y |
151 | CONFIG_BLK_DEV_SR_VENDOR=y | 149 | CONFIG_BLK_DEV_SR_VENDOR=y |
@@ -227,8 +225,6 @@ CONFIG_SND_HRTIMER=y | |||
227 | CONFIG_SND_HDA_INTEL=y | 225 | CONFIG_SND_HDA_INTEL=y |
228 | CONFIG_SND_HDA_HWDEP=y | 226 | CONFIG_SND_HDA_HWDEP=y |
229 | CONFIG_HIDRAW=y | 227 | CONFIG_HIDRAW=y |
230 | CONFIG_HID_PID=y | ||
231 | CONFIG_USB_HIDDEV=y | ||
232 | CONFIG_HID_GYRATION=y | 228 | CONFIG_HID_GYRATION=y |
233 | CONFIG_LOGITECH_FF=y | 229 | CONFIG_LOGITECH_FF=y |
234 | CONFIG_HID_NTRIG=y | 230 | CONFIG_HID_NTRIG=y |
@@ -239,11 +235,11 @@ CONFIG_HID_SAMSUNG=y | |||
239 | CONFIG_HID_SONY=y | 235 | CONFIG_HID_SONY=y |
240 | CONFIG_HID_SUNPLUS=y | 236 | CONFIG_HID_SUNPLUS=y |
241 | CONFIG_HID_TOPSEED=y | 237 | CONFIG_HID_TOPSEED=y |
238 | CONFIG_HID_PID=y | ||
239 | CONFIG_USB_HIDDEV=y | ||
242 | CONFIG_USB=y | 240 | CONFIG_USB=y |
243 | CONFIG_USB_DEBUG=y | 241 | CONFIG_USB_DEBUG=y |
244 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y | 242 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y |
245 | CONFIG_USB_DEVICEFS=y | ||
246 | # CONFIG_USB_DEVICE_CLASS is not set | ||
247 | CONFIG_USB_MON=y | 243 | CONFIG_USB_MON=y |
248 | CONFIG_USB_EHCI_HCD=y | 244 | CONFIG_USB_EHCI_HCD=y |
249 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set | 245 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set |
@@ -262,10 +258,9 @@ CONFIG_AMD_IOMMU_STATS=y | |||
262 | CONFIG_INTEL_IOMMU=y | 258 | CONFIG_INTEL_IOMMU=y |
263 | # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set | 259 | # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set |
264 | CONFIG_EFI_VARS=y | 260 | CONFIG_EFI_VARS=y |
265 | CONFIG_EXT3_FS=y | 261 | CONFIG_EXT4_FS=y |
266 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | 262 | CONFIG_EXT4_FS_POSIX_ACL=y |
267 | CONFIG_EXT3_FS_POSIX_ACL=y | 263 | CONFIG_EXT4_FS_SECURITY=y |
268 | CONFIG_EXT3_FS_SECURITY=y | ||
269 | CONFIG_QUOTA=y | 264 | CONFIG_QUOTA=y |
270 | CONFIG_QUOTA_NETLINK_INTERFACE=y | 265 | CONFIG_QUOTA_NETLINK_INTERFACE=y |
271 | # CONFIG_PRINT_QUOTA_WARNING is not set | 266 | # CONFIG_PRINT_QUOTA_WARNING is not set |
@@ -280,7 +275,6 @@ CONFIG_PROC_KCORE=y | |||
280 | CONFIG_TMPFS_POSIX_ACL=y | 275 | CONFIG_TMPFS_POSIX_ACL=y |
281 | CONFIG_HUGETLBFS=y | 276 | CONFIG_HUGETLBFS=y |
282 | CONFIG_NFS_FS=y | 277 | CONFIG_NFS_FS=y |
283 | CONFIG_NFS_V3=y | ||
284 | CONFIG_NFS_V3_ACL=y | 278 | CONFIG_NFS_V3_ACL=y |
285 | CONFIG_NFS_V4=y | 279 | CONFIG_NFS_V4=y |
286 | CONFIG_ROOT_NFS=y | 280 | CONFIG_ROOT_NFS=y |
@@ -298,13 +292,11 @@ CONFIG_DEBUG_KERNEL=y | |||
298 | CONFIG_SCHEDSTATS=y | 292 | CONFIG_SCHEDSTATS=y |
299 | CONFIG_TIMER_STATS=y | 293 | CONFIG_TIMER_STATS=y |
300 | CONFIG_DEBUG_STACK_USAGE=y | 294 | CONFIG_DEBUG_STACK_USAGE=y |
301 | CONFIG_SYSCTL_SYSCALL_CHECK=y | ||
302 | CONFIG_BLK_DEV_IO_TRACE=y | 295 | CONFIG_BLK_DEV_IO_TRACE=y |
303 | CONFIG_PROVIDE_OHCI1394_DMA_INIT=y | 296 | CONFIG_PROVIDE_OHCI1394_DMA_INIT=y |
304 | CONFIG_EARLY_PRINTK_DBGP=y | 297 | CONFIG_EARLY_PRINTK_DBGP=y |
305 | CONFIG_DEBUG_STACKOVERFLOW=y | 298 | CONFIG_DEBUG_STACKOVERFLOW=y |
306 | # CONFIG_DEBUG_RODATA_TEST is not set | 299 | # CONFIG_DEBUG_RODATA_TEST is not set |
307 | CONFIG_DEBUG_NX_TEST=m | ||
308 | CONFIG_DEBUG_BOOT_PARAMS=y | 300 | CONFIG_DEBUG_BOOT_PARAMS=y |
309 | CONFIG_OPTIMIZE_INLINING=y | 301 | CONFIG_OPTIMIZE_INLINING=y |
310 | CONFIG_KEYS_DEBUG_PROC_KEYS=y | 302 | CONFIG_KEYS_DEBUG_PROC_KEYS=y |
@@ -314,4 +306,3 @@ CONFIG_SECURITY_SELINUX=y | |||
314 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y | 306 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y |
315 | CONFIG_SECURITY_SELINUX_DISABLE=y | 307 | CONFIG_SECURITY_SELINUX_DISABLE=y |
316 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 308 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
317 | CONFIG_CRC_T10DIF=y | ||
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 673ac9b63d6b..8c77c64fbd27 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -162,7 +162,8 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, | |||
162 | } | 162 | } |
163 | seg = get_fs(); | 163 | seg = get_fs(); |
164 | set_fs(KERNEL_DS); | 164 | set_fs(KERNEL_DS); |
165 | ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp); | 165 | ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), |
166 | (stack_t __force __user *) &uoss, regs->sp); | ||
166 | set_fs(seg); | 167 | set_fs(seg); |
167 | if (ret >= 0 && uoss_ptr) { | 168 | if (ret >= 0 && uoss_ptr) { |
168 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t))) | 169 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t))) |
@@ -250,7 +251,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, | |||
250 | 251 | ||
251 | get_user_ex(tmp, &sc->fpstate); | 252 | get_user_ex(tmp, &sc->fpstate); |
252 | buf = compat_ptr(tmp); | 253 | buf = compat_ptr(tmp); |
253 | err |= restore_i387_xstate_ia32(buf); | 254 | err |= restore_xstate_sig(buf, 1); |
254 | 255 | ||
255 | get_user_ex(*pax, &sc->ax); | 256 | get_user_ex(*pax, &sc->ax); |
256 | } get_user_catch(err); | 257 | } get_user_catch(err); |
@@ -361,7 +362,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, | |||
361 | */ | 362 | */ |
362 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 363 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
363 | size_t frame_size, | 364 | size_t frame_size, |
364 | void **fpstate) | 365 | void __user **fpstate) |
365 | { | 366 | { |
366 | unsigned long sp; | 367 | unsigned long sp; |
367 | 368 | ||
@@ -381,9 +382,12 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
381 | sp = (unsigned long) ka->sa.sa_restorer; | 382 | sp = (unsigned long) ka->sa.sa_restorer; |
382 | 383 | ||
383 | if (used_math()) { | 384 | if (used_math()) { |
384 | sp = sp - sig_xstate_ia32_size; | 385 | unsigned long fx_aligned, math_size; |
385 | *fpstate = (struct _fpstate_ia32 *) sp; | 386 | |
386 | if (save_i387_xstate_ia32(*fpstate) < 0) | 387 | sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size); |
388 | *fpstate = (struct _fpstate_ia32 __user *) sp; | ||
389 | if (save_xstate_sig(*fpstate, (void __user *)fx_aligned, | ||
390 | math_size) < 0) | ||
387 | return (void __user *) -1L; | 391 | return (void __user *) -1L; |
388 | } | 392 | } |
389 | 393 | ||
@@ -448,7 +452,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
448 | * These are actually not used anymore, but left because some | 452 | * These are actually not used anymore, but left because some |
449 | * gdb versions depend on them as a marker. | 453 | * gdb versions depend on them as a marker. |
450 | */ | 454 | */ |
451 | put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); | 455 | put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); |
452 | } put_user_catch(err); | 456 | } put_user_catch(err); |
453 | 457 | ||
454 | if (err) | 458 | if (err) |
@@ -529,7 +533,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
529 | * Not actually used anymore, but left because some gdb | 533 | * Not actually used anymore, but left because some gdb |
530 | * versions need it. | 534 | * versions need it. |
531 | */ | 535 | */ |
532 | put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); | 536 | put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); |
533 | } put_user_catch(err); | 537 | } put_user_catch(err); |
534 | 538 | ||
535 | if (err) | 539 | if (err) |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index 4540bece0946..c5b938d92eab 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c | |||
@@ -287,7 +287,7 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 __user *act, | |||
287 | return ret; | 287 | return ret; |
288 | } | 288 | } |
289 | 289 | ||
290 | asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, | 290 | asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int __user *stat_addr, |
291 | int options) | 291 | int options) |
292 | { | 292 | { |
293 | return compat_sys_wait4(pid, stat_addr, options, NULL); | 293 | return compat_sys_wait4(pid, stat_addr, options, NULL); |
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 70780689599a..444704c8e186 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h | |||
@@ -60,7 +60,7 @@ extern void alternatives_smp_module_add(struct module *mod, char *name, | |||
60 | void *locks, void *locks_end, | 60 | void *locks, void *locks_end, |
61 | void *text, void *text_end); | 61 | void *text, void *text_end); |
62 | extern void alternatives_smp_module_del(struct module *mod); | 62 | extern void alternatives_smp_module_del(struct module *mod); |
63 | extern void alternatives_smp_switch(int smp); | 63 | extern void alternatives_enable_smp(void); |
64 | extern int alternatives_text_reserved(void *start, void *end); | 64 | extern int alternatives_text_reserved(void *start, void *end); |
65 | extern bool skip_smp_alternatives; | 65 | extern bool skip_smp_alternatives; |
66 | #else | 66 | #else |
@@ -68,7 +68,7 @@ static inline void alternatives_smp_module_add(struct module *mod, char *name, | |||
68 | void *locks, void *locks_end, | 68 | void *locks, void *locks_end, |
69 | void *text, void *text_end) {} | 69 | void *text, void *text_end) {} |
70 | static inline void alternatives_smp_module_del(struct module *mod) {} | 70 | static inline void alternatives_smp_module_del(struct module *mod) {} |
71 | static inline void alternatives_smp_switch(int smp) {} | 71 | static inline void alternatives_enable_smp(void) {} |
72 | static inline int alternatives_text_reserved(void *start, void *end) | 72 | static inline int alternatives_text_reserved(void *start, void *end) |
73 | { | 73 | { |
74 | return 0; | 74 | return 0; |
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index 72f5009deb5a..6dfd0195bb55 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h | |||
@@ -355,7 +355,7 @@ static int test_bit(int nr, const volatile unsigned long *addr); | |||
355 | */ | 355 | */ |
356 | static inline unsigned long __ffs(unsigned long word) | 356 | static inline unsigned long __ffs(unsigned long word) |
357 | { | 357 | { |
358 | asm("bsf %1,%0" | 358 | asm("rep; bsf %1,%0" |
359 | : "=r" (word) | 359 | : "=r" (word) |
360 | : "rm" (word)); | 360 | : "rm" (word)); |
361 | return word; | 361 | return word; |
@@ -369,7 +369,7 @@ static inline unsigned long __ffs(unsigned long word) | |||
369 | */ | 369 | */ |
370 | static inline unsigned long ffz(unsigned long word) | 370 | static inline unsigned long ffz(unsigned long word) |
371 | { | 371 | { |
372 | asm("bsf %1,%0" | 372 | asm("rep; bsf %1,%0" |
373 | : "=r" (word) | 373 | : "=r" (word) |
374 | : "r" (~word)); | 374 | : "r" (~word)); |
375 | return word; | 375 | return word; |
@@ -417,10 +417,9 @@ static inline int ffs(int x) | |||
417 | * We cannot do this on 32 bits because at the very least some | 417 | * We cannot do this on 32 bits because at the very least some |
418 | * 486 CPUs did not behave this way. | 418 | * 486 CPUs did not behave this way. |
419 | */ | 419 | */ |
420 | long tmp = -1; | ||
421 | asm("bsfl %1,%0" | 420 | asm("bsfl %1,%0" |
422 | : "=r" (r) | 421 | : "=r" (r) |
423 | : "rm" (x), "0" (tmp)); | 422 | : "rm" (x), "0" (-1)); |
424 | #elif defined(CONFIG_X86_CMOV) | 423 | #elif defined(CONFIG_X86_CMOV) |
425 | asm("bsfl %1,%0\n\t" | 424 | asm("bsfl %1,%0\n\t" |
426 | "cmovzl %2,%0" | 425 | "cmovzl %2,%0" |
@@ -459,10 +458,9 @@ static inline int fls(int x) | |||
459 | * We cannot do this on 32 bits because at the very least some | 458 | * We cannot do this on 32 bits because at the very least some |
460 | * 486 CPUs did not behave this way. | 459 | * 486 CPUs did not behave this way. |
461 | */ | 460 | */ |
462 | long tmp = -1; | ||
463 | asm("bsrl %1,%0" | 461 | asm("bsrl %1,%0" |
464 | : "=r" (r) | 462 | : "=r" (r) |
465 | : "rm" (x), "0" (tmp)); | 463 | : "rm" (x), "0" (-1)); |
466 | #elif defined(CONFIG_X86_CMOV) | 464 | #elif defined(CONFIG_X86_CMOV) |
467 | asm("bsrl %1,%0\n\t" | 465 | asm("bsrl %1,%0\n\t" |
468 | "cmovzl %2,%0" | 466 | "cmovzl %2,%0" |
@@ -490,13 +488,13 @@ static inline int fls(int x) | |||
490 | #ifdef CONFIG_X86_64 | 488 | #ifdef CONFIG_X86_64 |
491 | static __always_inline int fls64(__u64 x) | 489 | static __always_inline int fls64(__u64 x) |
492 | { | 490 | { |
493 | long bitpos = -1; | 491 | int bitpos = -1; |
494 | /* | 492 | /* |
495 | * AMD64 says BSRQ won't clobber the dest reg if x==0; Intel64 says the | 493 | * AMD64 says BSRQ won't clobber the dest reg if x==0; Intel64 says the |
496 | * dest reg is undefined if x==0, but their CPU architect says its | 494 | * dest reg is undefined if x==0, but their CPU architect says its |
497 | * value is written to set it to the same as before. | 495 | * value is written to set it to the same as before. |
498 | */ | 496 | */ |
499 | asm("bsrq %1,%0" | 497 | asm("bsrq %1,%q0" |
500 | : "+r" (bitpos) | 498 | : "+r" (bitpos) |
501 | : "rm" (x)); | 499 | : "rm" (x)); |
502 | return bitpos + 1; | 500 | return bitpos + 1; |
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h index a9e3a740f697..7f8422a28a46 100644 --- a/arch/x86/include/asm/calling.h +++ b/arch/x86/include/asm/calling.h | |||
@@ -49,38 +49,36 @@ For 32-bit we have the following conventions - kernel is built with | |||
49 | #include "dwarf2.h" | 49 | #include "dwarf2.h" |
50 | 50 | ||
51 | /* | 51 | /* |
52 | * 64-bit system call stack frame layout defines and helpers, for | 52 | * 64-bit system call stack frame layout defines and helpers, |
53 | * assembly code (note that the seemingly unnecessary parentheses | 53 | * for assembly code: |
54 | * are to prevent cpp from inserting spaces in expressions that get | ||
55 | * passed to macros): | ||
56 | */ | 54 | */ |
57 | 55 | ||
58 | #define R15 (0) | 56 | #define R15 0 |
59 | #define R14 (8) | 57 | #define R14 8 |
60 | #define R13 (16) | 58 | #define R13 16 |
61 | #define R12 (24) | 59 | #define R12 24 |
62 | #define RBP (32) | 60 | #define RBP 32 |
63 | #define RBX (40) | 61 | #define RBX 40 |
64 | 62 | ||
65 | /* arguments: interrupts/non tracing syscalls only save up to here: */ | 63 | /* arguments: interrupts/non tracing syscalls only save up to here: */ |
66 | #define R11 (48) | 64 | #define R11 48 |
67 | #define R10 (56) | 65 | #define R10 56 |
68 | #define R9 (64) | 66 | #define R9 64 |
69 | #define R8 (72) | 67 | #define R8 72 |
70 | #define RAX (80) | 68 | #define RAX 80 |
71 | #define RCX (88) | 69 | #define RCX 88 |
72 | #define RDX (96) | 70 | #define RDX 96 |
73 | #define RSI (104) | 71 | #define RSI 104 |
74 | #define RDI (112) | 72 | #define RDI 112 |
75 | #define ORIG_RAX (120) /* + error_code */ | 73 | #define ORIG_RAX 120 /* + error_code */ |
76 | /* end of arguments */ | 74 | /* end of arguments */ |
77 | 75 | ||
78 | /* cpu exception frame or undefined in case of fast syscall: */ | 76 | /* cpu exception frame or undefined in case of fast syscall: */ |
79 | #define RIP (128) | 77 | #define RIP 128 |
80 | #define CS (136) | 78 | #define CS 136 |
81 | #define EFLAGS (144) | 79 | #define EFLAGS 144 |
82 | #define RSP (152) | 80 | #define RSP 152 |
83 | #define SS (160) | 81 | #define SS 160 |
84 | 82 | ||
85 | #define ARGOFFSET R11 | 83 | #define ARGOFFSET R11 |
86 | #define SWFRAME ORIG_RAX | 84 | #define SWFRAME ORIG_RAX |
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 6b7ee5ff6820..16cae425d1f8 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
@@ -97,6 +97,7 @@ | |||
97 | #define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */ | 97 | #define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */ |
98 | #define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */ | 98 | #define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */ |
99 | #define X86_FEATURE_APERFMPERF (3*32+28) /* APERFMPERF */ | 99 | #define X86_FEATURE_APERFMPERF (3*32+28) /* APERFMPERF */ |
100 | #define X86_FEATURE_EAGER_FPU (3*32+29) /* "eagerfpu" Non lazy FPU restore */ | ||
100 | 101 | ||
101 | /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ | 102 | /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ |
102 | #define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */ | 103 | #define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */ |
@@ -209,6 +210,7 @@ | |||
209 | #define X86_FEATURE_RTM (9*32+11) /* Restricted Transactional Memory */ | 210 | #define X86_FEATURE_RTM (9*32+11) /* Restricted Transactional Memory */ |
210 | #define X86_FEATURE_RDSEED (9*32+18) /* The RDSEED instruction */ | 211 | #define X86_FEATURE_RDSEED (9*32+18) /* The RDSEED instruction */ |
211 | #define X86_FEATURE_ADX (9*32+19) /* The ADCX and ADOX instructions */ | 212 | #define X86_FEATURE_ADX (9*32+19) /* The ADCX and ADOX instructions */ |
213 | #define X86_FEATURE_SMAP (9*32+20) /* Supervisor Mode Access Prevention */ | ||
212 | 214 | ||
213 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) | 215 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) |
214 | 216 | ||
@@ -299,12 +301,14 @@ extern const char * const x86_power_flags[32]; | |||
299 | #define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2) | 301 | #define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2) |
300 | #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) | 302 | #define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) |
301 | #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) | 303 | #define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) |
304 | #define cpu_has_xsaveopt boot_cpu_has(X86_FEATURE_XSAVEOPT) | ||
302 | #define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE) | 305 | #define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE) |
303 | #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) | 306 | #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) |
304 | #define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ) | 307 | #define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ) |
305 | #define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE) | 308 | #define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE) |
306 | #define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8) | 309 | #define cpu_has_cx8 boot_cpu_has(X86_FEATURE_CX8) |
307 | #define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) | 310 | #define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) |
311 | #define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU) | ||
308 | 312 | ||
309 | #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) | 313 | #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64) |
310 | # define cpu_has_invlpg 1 | 314 | # define cpu_has_invlpg 1 |
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h index 75f4c6d6a331..92f3c6ed817f 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/kernel_stat.h> | 13 | #include <linux/kernel_stat.h> |
14 | #include <linux/regset.h> | 14 | #include <linux/regset.h> |
15 | #include <linux/compat.h> | ||
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
16 | #include <asm/asm.h> | 17 | #include <asm/asm.h> |
17 | #include <asm/cpufeature.h> | 18 | #include <asm/cpufeature.h> |
@@ -21,42 +22,74 @@ | |||
21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
22 | #include <asm/xsave.h> | 23 | #include <asm/xsave.h> |
23 | 24 | ||
24 | extern unsigned int sig_xstate_size; | 25 | #ifdef CONFIG_X86_64 |
26 | # include <asm/sigcontext32.h> | ||
27 | # include <asm/user32.h> | ||
28 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
29 | compat_sigset_t *set, struct pt_regs *regs); | ||
30 | int ia32_setup_frame(int sig, struct k_sigaction *ka, | ||
31 | compat_sigset_t *set, struct pt_regs *regs); | ||
32 | #else | ||
33 | # define user_i387_ia32_struct user_i387_struct | ||
34 | # define user32_fxsr_struct user_fxsr_struct | ||
35 | # define ia32_setup_frame __setup_frame | ||
36 | # define ia32_setup_rt_frame __setup_rt_frame | ||
37 | #endif | ||
38 | |||
39 | extern unsigned int mxcsr_feature_mask; | ||
25 | extern void fpu_init(void); | 40 | extern void fpu_init(void); |
41 | extern void eager_fpu_init(void); | ||
26 | 42 | ||
27 | DECLARE_PER_CPU(struct task_struct *, fpu_owner_task); | 43 | DECLARE_PER_CPU(struct task_struct *, fpu_owner_task); |
28 | 44 | ||
45 | extern void convert_from_fxsr(struct user_i387_ia32_struct *env, | ||
46 | struct task_struct *tsk); | ||
47 | extern void convert_to_fxsr(struct task_struct *tsk, | ||
48 | const struct user_i387_ia32_struct *env); | ||
49 | |||
29 | extern user_regset_active_fn fpregs_active, xfpregs_active; | 50 | extern user_regset_active_fn fpregs_active, xfpregs_active; |
30 | extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get, | 51 | extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get, |
31 | xstateregs_get; | 52 | xstateregs_get; |
32 | extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set, | 53 | extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set, |
33 | xstateregs_set; | 54 | xstateregs_set; |
34 | 55 | ||
35 | |||
36 | /* | 56 | /* |
37 | * xstateregs_active == fpregs_active. Please refer to the comment | 57 | * xstateregs_active == fpregs_active. Please refer to the comment |
38 | * at the definition of fpregs_active. | 58 | * at the definition of fpregs_active. |
39 | */ | 59 | */ |
40 | #define xstateregs_active fpregs_active | 60 | #define xstateregs_active fpregs_active |
41 | 61 | ||
42 | extern struct _fpx_sw_bytes fx_sw_reserved; | ||
43 | #ifdef CONFIG_IA32_EMULATION | ||
44 | extern unsigned int sig_xstate_ia32_size; | ||
45 | extern struct _fpx_sw_bytes fx_sw_reserved_ia32; | ||
46 | struct _fpstate_ia32; | ||
47 | struct _xstate_ia32; | ||
48 | extern int save_i387_xstate_ia32(void __user *buf); | ||
49 | extern int restore_i387_xstate_ia32(void __user *buf); | ||
50 | #endif | ||
51 | |||
52 | #ifdef CONFIG_MATH_EMULATION | 62 | #ifdef CONFIG_MATH_EMULATION |
63 | # define HAVE_HWFP (boot_cpu_data.hard_math) | ||
53 | extern void finit_soft_fpu(struct i387_soft_struct *soft); | 64 | extern void finit_soft_fpu(struct i387_soft_struct *soft); |
54 | #else | 65 | #else |
66 | # define HAVE_HWFP 1 | ||
55 | static inline void finit_soft_fpu(struct i387_soft_struct *soft) {} | 67 | static inline void finit_soft_fpu(struct i387_soft_struct *soft) {} |
56 | #endif | 68 | #endif |
57 | 69 | ||
70 | static inline int is_ia32_compat_frame(void) | ||
71 | { | ||
72 | return config_enabled(CONFIG_IA32_EMULATION) && | ||
73 | test_thread_flag(TIF_IA32); | ||
74 | } | ||
75 | |||
76 | static inline int is_ia32_frame(void) | ||
77 | { | ||
78 | return config_enabled(CONFIG_X86_32) || is_ia32_compat_frame(); | ||
79 | } | ||
80 | |||
81 | static inline int is_x32_frame(void) | ||
82 | { | ||
83 | return config_enabled(CONFIG_X86_X32_ABI) && test_thread_flag(TIF_X32); | ||
84 | } | ||
85 | |||
58 | #define X87_FSW_ES (1 << 7) /* Exception Summary */ | 86 | #define X87_FSW_ES (1 << 7) /* Exception Summary */ |
59 | 87 | ||
88 | static __always_inline __pure bool use_eager_fpu(void) | ||
89 | { | ||
90 | return static_cpu_has(X86_FEATURE_EAGER_FPU); | ||
91 | } | ||
92 | |||
60 | static __always_inline __pure bool use_xsaveopt(void) | 93 | static __always_inline __pure bool use_xsaveopt(void) |
61 | { | 94 | { |
62 | return static_cpu_has(X86_FEATURE_XSAVEOPT); | 95 | return static_cpu_has(X86_FEATURE_XSAVEOPT); |
@@ -72,6 +105,13 @@ static __always_inline __pure bool use_fxsr(void) | |||
72 | return static_cpu_has(X86_FEATURE_FXSR); | 105 | return static_cpu_has(X86_FEATURE_FXSR); |
73 | } | 106 | } |
74 | 107 | ||
108 | static inline void fx_finit(struct i387_fxsave_struct *fx) | ||
109 | { | ||
110 | memset(fx, 0, xstate_size); | ||
111 | fx->cwd = 0x37f; | ||
112 | fx->mxcsr = MXCSR_DEFAULT; | ||
113 | } | ||
114 | |||
75 | extern void __sanitize_i387_state(struct task_struct *); | 115 | extern void __sanitize_i387_state(struct task_struct *); |
76 | 116 | ||
77 | static inline void sanitize_i387_state(struct task_struct *tsk) | 117 | static inline void sanitize_i387_state(struct task_struct *tsk) |
@@ -81,131 +121,88 @@ static inline void sanitize_i387_state(struct task_struct *tsk) | |||
81 | __sanitize_i387_state(tsk); | 121 | __sanitize_i387_state(tsk); |
82 | } | 122 | } |
83 | 123 | ||
84 | #ifdef CONFIG_X86_64 | 124 | #define check_insn(insn, output, input...) \ |
85 | static inline int fxrstor_checking(struct i387_fxsave_struct *fx) | 125 | ({ \ |
126 | int err; \ | ||
127 | asm volatile("1:" #insn "\n\t" \ | ||
128 | "2:\n" \ | ||
129 | ".section .fixup,\"ax\"\n" \ | ||
130 | "3: movl $-1,%[err]\n" \ | ||
131 | " jmp 2b\n" \ | ||
132 | ".previous\n" \ | ||
133 | _ASM_EXTABLE(1b, 3b) \ | ||
134 | : [err] "=r" (err), output \ | ||
135 | : "0"(0), input); \ | ||
136 | err; \ | ||
137 | }) | ||
138 | |||
139 | static inline int fsave_user(struct i387_fsave_struct __user *fx) | ||
86 | { | 140 | { |
87 | int err; | 141 | return check_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx)); |
88 | |||
89 | /* See comment in fxsave() below. */ | ||
90 | #ifdef CONFIG_AS_FXSAVEQ | ||
91 | asm volatile("1: fxrstorq %[fx]\n\t" | ||
92 | "2:\n" | ||
93 | ".section .fixup,\"ax\"\n" | ||
94 | "3: movl $-1,%[err]\n" | ||
95 | " jmp 2b\n" | ||
96 | ".previous\n" | ||
97 | _ASM_EXTABLE(1b, 3b) | ||
98 | : [err] "=r" (err) | ||
99 | : [fx] "m" (*fx), "0" (0)); | ||
100 | #else | ||
101 | asm volatile("1: rex64/fxrstor (%[fx])\n\t" | ||
102 | "2:\n" | ||
103 | ".section .fixup,\"ax\"\n" | ||
104 | "3: movl $-1,%[err]\n" | ||
105 | " jmp 2b\n" | ||
106 | ".previous\n" | ||
107 | _ASM_EXTABLE(1b, 3b) | ||
108 | : [err] "=r" (err) | ||
109 | : [fx] "R" (fx), "m" (*fx), "0" (0)); | ||
110 | #endif | ||
111 | return err; | ||
112 | } | 142 | } |
113 | 143 | ||
114 | static inline int fxsave_user(struct i387_fxsave_struct __user *fx) | 144 | static inline int fxsave_user(struct i387_fxsave_struct __user *fx) |
115 | { | 145 | { |
116 | int err; | 146 | if (config_enabled(CONFIG_X86_32)) |
147 | return check_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx)); | ||
148 | else if (config_enabled(CONFIG_AS_FXSAVEQ)) | ||
149 | return check_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx)); | ||
117 | 150 | ||
118 | /* | 151 | /* See comment in fpu_fxsave() below. */ |
119 | * Clear the bytes not touched by the fxsave and reserved | 152 | return check_insn(rex64/fxsave (%[fx]), "=m" (*fx), [fx] "R" (fx)); |
120 | * for the SW usage. | ||
121 | */ | ||
122 | err = __clear_user(&fx->sw_reserved, | ||
123 | sizeof(struct _fpx_sw_bytes)); | ||
124 | if (unlikely(err)) | ||
125 | return -EFAULT; | ||
126 | |||
127 | /* See comment in fxsave() below. */ | ||
128 | #ifdef CONFIG_AS_FXSAVEQ | ||
129 | asm volatile("1: fxsaveq %[fx]\n\t" | ||
130 | "2:\n" | ||
131 | ".section .fixup,\"ax\"\n" | ||
132 | "3: movl $-1,%[err]\n" | ||
133 | " jmp 2b\n" | ||
134 | ".previous\n" | ||
135 | _ASM_EXTABLE(1b, 3b) | ||
136 | : [err] "=r" (err), [fx] "=m" (*fx) | ||
137 | : "0" (0)); | ||
138 | #else | ||
139 | asm volatile("1: rex64/fxsave (%[fx])\n\t" | ||
140 | "2:\n" | ||
141 | ".section .fixup,\"ax\"\n" | ||
142 | "3: movl $-1,%[err]\n" | ||
143 | " jmp 2b\n" | ||
144 | ".previous\n" | ||
145 | _ASM_EXTABLE(1b, 3b) | ||
146 | : [err] "=r" (err), "=m" (*fx) | ||
147 | : [fx] "R" (fx), "0" (0)); | ||
148 | #endif | ||
149 | if (unlikely(err) && | ||
150 | __clear_user(fx, sizeof(struct i387_fxsave_struct))) | ||
151 | err = -EFAULT; | ||
152 | /* No need to clear here because the caller clears USED_MATH */ | ||
153 | return err; | ||
154 | } | 153 | } |
155 | 154 | ||
156 | static inline void fpu_fxsave(struct fpu *fpu) | 155 | static inline int fxrstor_checking(struct i387_fxsave_struct *fx) |
157 | { | 156 | { |
158 | /* Using "rex64; fxsave %0" is broken because, if the memory operand | 157 | if (config_enabled(CONFIG_X86_32)) |
159 | uses any extended registers for addressing, a second REX prefix | 158 | return check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx)); |
160 | will be generated (to the assembler, rex64 followed by semicolon | 159 | else if (config_enabled(CONFIG_AS_FXSAVEQ)) |
161 | is a separate instruction), and hence the 64-bitness is lost. */ | 160 | return check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx)); |
162 | 161 | ||
163 | #ifdef CONFIG_AS_FXSAVEQ | 162 | /* See comment in fpu_fxsave() below. */ |
164 | /* Using "fxsaveq %0" would be the ideal choice, but is only supported | 163 | return check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx), |
165 | starting with gas 2.16. */ | 164 | "m" (*fx)); |
166 | __asm__ __volatile__("fxsaveq %0" | ||
167 | : "=m" (fpu->state->fxsave)); | ||
168 | #else | ||
169 | /* Using, as a workaround, the properly prefixed form below isn't | ||
170 | accepted by any binutils version so far released, complaining that | ||
171 | the same type of prefix is used twice if an extended register is | ||
172 | needed for addressing (fix submitted to mainline 2005-11-21). | ||
173 | asm volatile("rex64/fxsave %0" | ||
174 | : "=m" (fpu->state->fxsave)); | ||
175 | This, however, we can work around by forcing the compiler to select | ||
176 | an addressing mode that doesn't require extended registers. */ | ||
177 | asm volatile("rex64/fxsave (%[fx])" | ||
178 | : "=m" (fpu->state->fxsave) | ||
179 | : [fx] "R" (&fpu->state->fxsave)); | ||
180 | #endif | ||
181 | } | 165 | } |
182 | 166 | ||
183 | #else /* CONFIG_X86_32 */ | 167 | static inline int frstor_checking(struct i387_fsave_struct *fx) |
184 | |||
185 | /* perform fxrstor iff the processor has extended states, otherwise frstor */ | ||
186 | static inline int fxrstor_checking(struct i387_fxsave_struct *fx) | ||
187 | { | 168 | { |
188 | /* | 169 | return check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx)); |
189 | * The "nop" is needed to make the instructions the same | ||
190 | * length. | ||
191 | */ | ||
192 | alternative_input( | ||
193 | "nop ; frstor %1", | ||
194 | "fxrstor %1", | ||
195 | X86_FEATURE_FXSR, | ||
196 | "m" (*fx)); | ||
197 | |||
198 | return 0; | ||
199 | } | 170 | } |
200 | 171 | ||
201 | static inline void fpu_fxsave(struct fpu *fpu) | 172 | static inline void fpu_fxsave(struct fpu *fpu) |
202 | { | 173 | { |
203 | asm volatile("fxsave %[fx]" | 174 | if (config_enabled(CONFIG_X86_32)) |
204 | : [fx] "=m" (fpu->state->fxsave)); | 175 | asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state->fxsave)); |
176 | else if (config_enabled(CONFIG_AS_FXSAVEQ)) | ||
177 | asm volatile("fxsaveq %0" : "=m" (fpu->state->fxsave)); | ||
178 | else { | ||
179 | /* Using "rex64; fxsave %0" is broken because, if the memory | ||
180 | * operand uses any extended registers for addressing, a second | ||
181 | * REX prefix will be generated (to the assembler, rex64 | ||
182 | * followed by semicolon is a separate instruction), and hence | ||
183 | * the 64-bitness is lost. | ||
184 | * | ||
185 | * Using "fxsaveq %0" would be the ideal choice, but is only | ||
186 | * supported starting with gas 2.16. | ||
187 | * | ||
188 | * Using, as a workaround, the properly prefixed form below | ||
189 | * isn't accepted by any binutils version so far released, | ||
190 | * complaining that the same type of prefix is used twice if | ||
191 | * an extended register is needed for addressing (fix submitted | ||
192 | * to mainline 2005-11-21). | ||
193 | * | ||
194 | * asm volatile("rex64/fxsave %0" : "=m" (fpu->state->fxsave)); | ||
195 | * | ||
196 | * This, however, we can work around by forcing the compiler to | ||
197 | * select an addressing mode that doesn't require extended | ||
198 | * registers. | ||
199 | */ | ||
200 | asm volatile( "rex64/fxsave (%[fx])" | ||
201 | : "=m" (fpu->state->fxsave) | ||
202 | : [fx] "R" (&fpu->state->fxsave)); | ||
203 | } | ||
205 | } | 204 | } |
206 | 205 | ||
207 | #endif /* CONFIG_X86_64 */ | ||
208 | |||
209 | /* | 206 | /* |
210 | * These must be called with preempt disabled. Returns | 207 | * These must be called with preempt disabled. Returns |
211 | * 'true' if the FPU state is still intact. | 208 | * 'true' if the FPU state is still intact. |
@@ -248,17 +245,14 @@ static inline int __save_init_fpu(struct task_struct *tsk) | |||
248 | return fpu_save_init(&tsk->thread.fpu); | 245 | return fpu_save_init(&tsk->thread.fpu); |
249 | } | 246 | } |
250 | 247 | ||
251 | static inline int fpu_fxrstor_checking(struct fpu *fpu) | ||
252 | { | ||
253 | return fxrstor_checking(&fpu->state->fxsave); | ||
254 | } | ||
255 | |||
256 | static inline int fpu_restore_checking(struct fpu *fpu) | 248 | static inline int fpu_restore_checking(struct fpu *fpu) |
257 | { | 249 | { |
258 | if (use_xsave()) | 250 | if (use_xsave()) |
259 | return fpu_xrstor_checking(fpu); | 251 | return fpu_xrstor_checking(&fpu->state->xsave); |
252 | else if (use_fxsr()) | ||
253 | return fxrstor_checking(&fpu->state->fxsave); | ||
260 | else | 254 | else |
261 | return fpu_fxrstor_checking(fpu); | 255 | return frstor_checking(&fpu->state->fsave); |
262 | } | 256 | } |
263 | 257 | ||
264 | static inline int restore_fpu_checking(struct task_struct *tsk) | 258 | static inline int restore_fpu_checking(struct task_struct *tsk) |
@@ -310,15 +304,52 @@ static inline void __thread_set_has_fpu(struct task_struct *tsk) | |||
310 | static inline void __thread_fpu_end(struct task_struct *tsk) | 304 | static inline void __thread_fpu_end(struct task_struct *tsk) |
311 | { | 305 | { |
312 | __thread_clear_has_fpu(tsk); | 306 | __thread_clear_has_fpu(tsk); |
313 | stts(); | 307 | if (!use_eager_fpu()) |
308 | stts(); | ||
314 | } | 309 | } |
315 | 310 | ||
316 | static inline void __thread_fpu_begin(struct task_struct *tsk) | 311 | static inline void __thread_fpu_begin(struct task_struct *tsk) |
317 | { | 312 | { |
318 | clts(); | 313 | if (!use_eager_fpu()) |
314 | clts(); | ||
319 | __thread_set_has_fpu(tsk); | 315 | __thread_set_has_fpu(tsk); |
320 | } | 316 | } |
321 | 317 | ||
318 | static inline void __drop_fpu(struct task_struct *tsk) | ||
319 | { | ||
320 | if (__thread_has_fpu(tsk)) { | ||
321 | /* Ignore delayed exceptions from user space */ | ||
322 | asm volatile("1: fwait\n" | ||
323 | "2:\n" | ||
324 | _ASM_EXTABLE(1b, 2b)); | ||
325 | __thread_fpu_end(tsk); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | static inline void drop_fpu(struct task_struct *tsk) | ||
330 | { | ||
331 | /* | ||
332 | * Forget coprocessor state.. | ||
333 | */ | ||
334 | preempt_disable(); | ||
335 | tsk->fpu_counter = 0; | ||
336 | __drop_fpu(tsk); | ||
337 | clear_used_math(); | ||
338 | preempt_enable(); | ||
339 | } | ||
340 | |||
341 | static inline void drop_init_fpu(struct task_struct *tsk) | ||
342 | { | ||
343 | if (!use_eager_fpu()) | ||
344 | drop_fpu(tsk); | ||
345 | else { | ||
346 | if (use_xsave()) | ||
347 | xrstor_state(init_xstate_buf, -1); | ||
348 | else | ||
349 | fxrstor_checking(&init_xstate_buf->i387); | ||
350 | } | ||
351 | } | ||
352 | |||
322 | /* | 353 | /* |
323 | * FPU state switching for scheduling. | 354 | * FPU state switching for scheduling. |
324 | * | 355 | * |
@@ -352,7 +383,12 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta | |||
352 | { | 383 | { |
353 | fpu_switch_t fpu; | 384 | fpu_switch_t fpu; |
354 | 385 | ||
355 | fpu.preload = tsk_used_math(new) && new->fpu_counter > 5; | 386 | /* |
387 | * If the task has used the math, pre-load the FPU on xsave processors | ||
388 | * or if the past 5 consecutive context-switches used math. | ||
389 | */ | ||
390 | fpu.preload = tsk_used_math(new) && (use_eager_fpu() || | ||
391 | new->fpu_counter > 5); | ||
356 | if (__thread_has_fpu(old)) { | 392 | if (__thread_has_fpu(old)) { |
357 | if (!__save_init_fpu(old)) | 393 | if (!__save_init_fpu(old)) |
358 | cpu = ~0; | 394 | cpu = ~0; |
@@ -364,14 +400,14 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta | |||
364 | new->fpu_counter++; | 400 | new->fpu_counter++; |
365 | __thread_set_has_fpu(new); | 401 | __thread_set_has_fpu(new); |
366 | prefetch(new->thread.fpu.state); | 402 | prefetch(new->thread.fpu.state); |
367 | } else | 403 | } else if (!use_eager_fpu()) |
368 | stts(); | 404 | stts(); |
369 | } else { | 405 | } else { |
370 | old->fpu_counter = 0; | 406 | old->fpu_counter = 0; |
371 | old->thread.fpu.last_cpu = ~0; | 407 | old->thread.fpu.last_cpu = ~0; |
372 | if (fpu.preload) { | 408 | if (fpu.preload) { |
373 | new->fpu_counter++; | 409 | new->fpu_counter++; |
374 | if (fpu_lazy_restore(new, cpu)) | 410 | if (!use_eager_fpu() && fpu_lazy_restore(new, cpu)) |
375 | fpu.preload = 0; | 411 | fpu.preload = 0; |
376 | else | 412 | else |
377 | prefetch(new->thread.fpu.state); | 413 | prefetch(new->thread.fpu.state); |
@@ -391,44 +427,40 @@ static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu) | |||
391 | { | 427 | { |
392 | if (fpu.preload) { | 428 | if (fpu.preload) { |
393 | if (unlikely(restore_fpu_checking(new))) | 429 | if (unlikely(restore_fpu_checking(new))) |
394 | __thread_fpu_end(new); | 430 | drop_init_fpu(new); |
395 | } | 431 | } |
396 | } | 432 | } |
397 | 433 | ||
398 | /* | 434 | /* |
399 | * Signal frame handlers... | 435 | * Signal frame handlers... |
400 | */ | 436 | */ |
401 | extern int save_i387_xstate(void __user *buf); | 437 | extern int save_xstate_sig(void __user *buf, void __user *fx, int size); |
402 | extern int restore_i387_xstate(void __user *buf); | 438 | extern int __restore_xstate_sig(void __user *buf, void __user *fx, int size); |
403 | 439 | ||
404 | static inline void __clear_fpu(struct task_struct *tsk) | 440 | static inline int xstate_sigframe_size(void) |
405 | { | 441 | { |
406 | if (__thread_has_fpu(tsk)) { | 442 | return use_xsave() ? xstate_size + FP_XSTATE_MAGIC2_SIZE : xstate_size; |
407 | /* Ignore delayed exceptions from user space */ | 443 | } |
408 | asm volatile("1: fwait\n" | 444 | |
409 | "2:\n" | 445 | static inline int restore_xstate_sig(void __user *buf, int ia32_frame) |
410 | _ASM_EXTABLE(1b, 2b)); | 446 | { |
411 | __thread_fpu_end(tsk); | 447 | void __user *buf_fx = buf; |
448 | int size = xstate_sigframe_size(); | ||
449 | |||
450 | if (ia32_frame && use_fxsr()) { | ||
451 | buf_fx = buf + sizeof(struct i387_fsave_struct); | ||
452 | size += sizeof(struct i387_fsave_struct); | ||
412 | } | 453 | } |
454 | |||
455 | return __restore_xstate_sig(buf, buf_fx, size); | ||
413 | } | 456 | } |
414 | 457 | ||
415 | /* | 458 | /* |
416 | * The actual user_fpu_begin/end() functions | 459 | * Need to be preemption-safe. |
417 | * need to be preemption-safe. | ||
418 | * | 460 | * |
419 | * NOTE! user_fpu_end() must be used only after you | 461 | * NOTE! user_fpu_begin() must be used only immediately before restoring |
420 | * have saved the FP state, and user_fpu_begin() must | 462 | * it. This function does not do any save/restore on their own. |
421 | * be used only immediately before restoring it. | ||
422 | * These functions do not do any save/restore on | ||
423 | * their own. | ||
424 | */ | 463 | */ |
425 | static inline void user_fpu_end(void) | ||
426 | { | ||
427 | preempt_disable(); | ||
428 | __thread_fpu_end(current); | ||
429 | preempt_enable(); | ||
430 | } | ||
431 | |||
432 | static inline void user_fpu_begin(void) | 464 | static inline void user_fpu_begin(void) |
433 | { | 465 | { |
434 | preempt_disable(); | 466 | preempt_disable(); |
@@ -437,25 +469,32 @@ static inline void user_fpu_begin(void) | |||
437 | preempt_enable(); | 469 | preempt_enable(); |
438 | } | 470 | } |
439 | 471 | ||
472 | static inline void __save_fpu(struct task_struct *tsk) | ||
473 | { | ||
474 | if (use_xsave()) | ||
475 | xsave_state(&tsk->thread.fpu.state->xsave, -1); | ||
476 | else | ||
477 | fpu_fxsave(&tsk->thread.fpu); | ||
478 | } | ||
479 | |||
440 | /* | 480 | /* |
441 | * These disable preemption on their own and are safe | 481 | * These disable preemption on their own and are safe |
442 | */ | 482 | */ |
443 | static inline void save_init_fpu(struct task_struct *tsk) | 483 | static inline void save_init_fpu(struct task_struct *tsk) |
444 | { | 484 | { |
445 | WARN_ON_ONCE(!__thread_has_fpu(tsk)); | 485 | WARN_ON_ONCE(!__thread_has_fpu(tsk)); |
486 | |||
487 | if (use_eager_fpu()) { | ||
488 | __save_fpu(tsk); | ||
489 | return; | ||
490 | } | ||
491 | |||
446 | preempt_disable(); | 492 | preempt_disable(); |
447 | __save_init_fpu(tsk); | 493 | __save_init_fpu(tsk); |
448 | __thread_fpu_end(tsk); | 494 | __thread_fpu_end(tsk); |
449 | preempt_enable(); | 495 | preempt_enable(); |
450 | } | 496 | } |
451 | 497 | ||
452 | static inline void clear_fpu(struct task_struct *tsk) | ||
453 | { | ||
454 | preempt_disable(); | ||
455 | __clear_fpu(tsk); | ||
456 | preempt_enable(); | ||
457 | } | ||
458 | |||
459 | /* | 498 | /* |
460 | * i387 state interaction | 499 | * i387 state interaction |
461 | */ | 500 | */ |
@@ -510,11 +549,34 @@ static inline void fpu_free(struct fpu *fpu) | |||
510 | } | 549 | } |
511 | } | 550 | } |
512 | 551 | ||
513 | static inline void fpu_copy(struct fpu *dst, struct fpu *src) | 552 | static inline void fpu_copy(struct task_struct *dst, struct task_struct *src) |
514 | { | 553 | { |
515 | memcpy(dst->state, src->state, xstate_size); | 554 | if (use_eager_fpu()) { |
555 | memset(&dst->thread.fpu.state->xsave, 0, xstate_size); | ||
556 | __save_fpu(dst); | ||
557 | } else { | ||
558 | struct fpu *dfpu = &dst->thread.fpu; | ||
559 | struct fpu *sfpu = &src->thread.fpu; | ||
560 | |||
561 | unlazy_fpu(src); | ||
562 | memcpy(dfpu->state, sfpu->state, xstate_size); | ||
563 | } | ||
516 | } | 564 | } |
517 | 565 | ||
518 | extern void fpu_finit(struct fpu *fpu); | 566 | static inline unsigned long |
567 | alloc_mathframe(unsigned long sp, int ia32_frame, unsigned long *buf_fx, | ||
568 | unsigned long *size) | ||
569 | { | ||
570 | unsigned long frame_size = xstate_sigframe_size(); | ||
571 | |||
572 | *buf_fx = sp = round_down(sp - frame_size, 64); | ||
573 | if (ia32_frame && use_fxsr()) { | ||
574 | frame_size += sizeof(struct i387_fsave_struct); | ||
575 | sp -= sizeof(struct i387_fsave_struct); | ||
576 | } | ||
577 | |||
578 | *size = frame_size; | ||
579 | return sp; | ||
580 | } | ||
519 | 581 | ||
520 | #endif | 582 | #endif |
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index b0767bc08740..9a25b522d377 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h | |||
@@ -3,38 +3,54 @@ | |||
3 | 3 | ||
4 | #ifdef __ASSEMBLY__ | 4 | #ifdef __ASSEMBLY__ |
5 | 5 | ||
6 | .macro MCOUNT_SAVE_FRAME | 6 | /* skip is set if the stack was already partially adjusted */ |
7 | /* taken from glibc */ | 7 | .macro MCOUNT_SAVE_FRAME skip=0 |
8 | subq $0x38, %rsp | 8 | /* |
9 | movq %rax, (%rsp) | 9 | * We add enough stack to save all regs. |
10 | movq %rcx, 8(%rsp) | 10 | */ |
11 | movq %rdx, 16(%rsp) | 11 | subq $(SS+8-\skip), %rsp |
12 | movq %rsi, 24(%rsp) | 12 | movq %rax, RAX(%rsp) |
13 | movq %rdi, 32(%rsp) | 13 | movq %rcx, RCX(%rsp) |
14 | movq %r8, 40(%rsp) | 14 | movq %rdx, RDX(%rsp) |
15 | movq %r9, 48(%rsp) | 15 | movq %rsi, RSI(%rsp) |
16 | movq %rdi, RDI(%rsp) | ||
17 | movq %r8, R8(%rsp) | ||
18 | movq %r9, R9(%rsp) | ||
19 | /* Move RIP to its proper location */ | ||
20 | movq SS+8(%rsp), %rdx | ||
21 | movq %rdx, RIP(%rsp) | ||
16 | .endm | 22 | .endm |
17 | 23 | ||
18 | .macro MCOUNT_RESTORE_FRAME | 24 | .macro MCOUNT_RESTORE_FRAME skip=0 |
19 | movq 48(%rsp), %r9 | 25 | movq R9(%rsp), %r9 |
20 | movq 40(%rsp), %r8 | 26 | movq R8(%rsp), %r8 |
21 | movq 32(%rsp), %rdi | 27 | movq RDI(%rsp), %rdi |
22 | movq 24(%rsp), %rsi | 28 | movq RSI(%rsp), %rsi |
23 | movq 16(%rsp), %rdx | 29 | movq RDX(%rsp), %rdx |
24 | movq 8(%rsp), %rcx | 30 | movq RCX(%rsp), %rcx |
25 | movq (%rsp), %rax | 31 | movq RAX(%rsp), %rax |
26 | addq $0x38, %rsp | 32 | addq $(SS+8-\skip), %rsp |
27 | .endm | 33 | .endm |
28 | 34 | ||
29 | #endif | 35 | #endif |
30 | 36 | ||
31 | #ifdef CONFIG_FUNCTION_TRACER | 37 | #ifdef CONFIG_FUNCTION_TRACER |
32 | #define MCOUNT_ADDR ((long)(mcount)) | 38 | #ifdef CC_USING_FENTRY |
39 | # define MCOUNT_ADDR ((long)(__fentry__)) | ||
40 | #else | ||
41 | # define MCOUNT_ADDR ((long)(mcount)) | ||
42 | #endif | ||
33 | #define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ | 43 | #define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ |
34 | 44 | ||
45 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
46 | #define ARCH_SUPPORTS_FTRACE_OPS 1 | ||
47 | #define ARCH_SUPPORTS_FTRACE_SAVE_REGS | ||
48 | #endif | ||
49 | |||
35 | #ifndef __ASSEMBLY__ | 50 | #ifndef __ASSEMBLY__ |
36 | extern void mcount(void); | 51 | extern void mcount(void); |
37 | extern atomic_t modifying_ftrace_code; | 52 | extern atomic_t modifying_ftrace_code; |
53 | extern void __fentry__(void); | ||
38 | 54 | ||
39 | static inline unsigned long ftrace_call_adjust(unsigned long addr) | 55 | static inline unsigned long ftrace_call_adjust(unsigned long addr) |
40 | { | 56 | { |
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index d3895dbf4ddb..81f04cee5f74 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
@@ -18,6 +18,10 @@ typedef struct { | |||
18 | #ifdef CONFIG_SMP | 18 | #ifdef CONFIG_SMP |
19 | unsigned int irq_resched_count; | 19 | unsigned int irq_resched_count; |
20 | unsigned int irq_call_count; | 20 | unsigned int irq_call_count; |
21 | /* | ||
22 | * irq_tlb_count is double-counted in irq_call_count, so it must be | ||
23 | * subtracted from irq_call_count when displaying irq_call_count | ||
24 | */ | ||
21 | unsigned int irq_tlb_count; | 25 | unsigned int irq_tlb_count; |
22 | #endif | 26 | #endif |
23 | #ifdef CONFIG_X86_THERMAL_VECTOR | 27 | #ifdef CONFIG_X86_THERMAL_VECTOR |
diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index 2c392d663dce..434e2106cc87 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h | |||
@@ -35,8 +35,6 @@ | |||
35 | #define HPET_ID_NUMBER_SHIFT 8 | 35 | #define HPET_ID_NUMBER_SHIFT 8 |
36 | #define HPET_ID_VENDOR_SHIFT 16 | 36 | #define HPET_ID_VENDOR_SHIFT 16 |
37 | 37 | ||
38 | #define HPET_ID_VENDOR_8086 0x8086 | ||
39 | |||
40 | #define HPET_CFG_ENABLE 0x001 | 38 | #define HPET_CFG_ENABLE 0x001 |
41 | #define HPET_CFG_LEGACY 0x002 | 39 | #define HPET_CFG_LEGACY 0x002 |
42 | #define HPET_LEGACY_8254 2 | 40 | #define HPET_LEGACY_8254 2 |
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 257d9cca214f..ed8089d69094 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
@@ -19,12 +19,37 @@ struct pt_regs; | |||
19 | struct user_i387_struct; | 19 | struct user_i387_struct; |
20 | 20 | ||
21 | extern int init_fpu(struct task_struct *child); | 21 | extern int init_fpu(struct task_struct *child); |
22 | extern void fpu_finit(struct fpu *fpu); | ||
22 | extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); | 23 | extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); |
23 | extern void math_state_restore(void); | 24 | extern void math_state_restore(void); |
24 | 25 | ||
25 | extern bool irq_fpu_usable(void); | 26 | extern bool irq_fpu_usable(void); |
26 | extern void kernel_fpu_begin(void); | 27 | |
27 | extern void kernel_fpu_end(void); | 28 | /* |
29 | * Careful: __kernel_fpu_begin/end() must be called with preempt disabled | ||
30 | * and they don't touch the preempt state on their own. | ||
31 | * If you enable preemption after __kernel_fpu_begin(), preempt notifier | ||
32 | * should call the __kernel_fpu_end() to prevent the kernel/user FPU | ||
33 | * state from getting corrupted. KVM for example uses this model. | ||
34 | * | ||
35 | * All other cases use kernel_fpu_begin/end() which disable preemption | ||
36 | * during kernel FPU usage. | ||
37 | */ | ||
38 | extern void __kernel_fpu_begin(void); | ||
39 | extern void __kernel_fpu_end(void); | ||
40 | |||
41 | static inline void kernel_fpu_begin(void) | ||
42 | { | ||
43 | WARN_ON_ONCE(!irq_fpu_usable()); | ||
44 | preempt_disable(); | ||
45 | __kernel_fpu_begin(); | ||
46 | } | ||
47 | |||
48 | static inline void kernel_fpu_end(void) | ||
49 | { | ||
50 | __kernel_fpu_end(); | ||
51 | preempt_enable(); | ||
52 | } | ||
28 | 53 | ||
29 | /* | 54 | /* |
30 | * Some instructions like VIA's padlock instructions generate a spurious | 55 | * Some instructions like VIA's padlock instructions generate a spurious |
diff --git a/arch/x86/include/asm/iommu_table.h b/arch/x86/include/asm/iommu_table.h index f229b13a5f30..f42a04735a0a 100644 --- a/arch/x86/include/asm/iommu_table.h +++ b/arch/x86/include/asm/iommu_table.h | |||
@@ -48,7 +48,7 @@ struct iommu_table_entry { | |||
48 | 48 | ||
49 | 49 | ||
50 | #define __IOMMU_INIT(_detect, _depend, _early_init, _late_init, _finish)\ | 50 | #define __IOMMU_INIT(_detect, _depend, _early_init, _late_init, _finish)\ |
51 | static const struct iommu_table_entry const \ | 51 | static const struct iommu_table_entry \ |
52 | __iommu_entry_##_detect __used \ | 52 | __iommu_entry_##_detect __used \ |
53 | __attribute__ ((unused, __section__(".iommu_table"), \ | 53 | __attribute__ ((unused, __section__(".iommu_table"), \ |
54 | aligned((sizeof(void *))))) \ | 54 | aligned((sizeof(void *))))) \ |
@@ -63,10 +63,10 @@ struct iommu_table_entry { | |||
63 | * to stop detecting the other IOMMUs after yours has been detected. | 63 | * to stop detecting the other IOMMUs after yours has been detected. |
64 | */ | 64 | */ |
65 | #define IOMMU_INIT_POST(_detect) \ | 65 | #define IOMMU_INIT_POST(_detect) \ |
66 | __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, 0, 0, 0) | 66 | __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, NULL, NULL, 0) |
67 | 67 | ||
68 | #define IOMMU_INIT_POST_FINISH(detect) \ | 68 | #define IOMMU_INIT_POST_FINISH(detect) \ |
69 | __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, 0, 0, 1) | 69 | __IOMMU_INIT(_detect, pci_swiotlb_detect_4gb, NULL, NULL, 1) |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * A more sophisticated version of IOMMU_INIT. This variant requires: | 72 | * A more sophisticated version of IOMMU_INIT. This variant requires: |
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h index 547882539157..d3ddd17405d0 100644 --- a/arch/x86/include/asm/kprobes.h +++ b/arch/x86/include/asm/kprobes.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/insn.h> | 27 | #include <asm/insn.h> |
28 | 28 | ||
29 | #define __ARCH_WANT_KPROBES_INSN_SLOT | 29 | #define __ARCH_WANT_KPROBES_INSN_SLOT |
30 | #define ARCH_SUPPORTS_KPROBES_ON_FTRACE | ||
30 | 31 | ||
31 | struct pt_regs; | 32 | struct pt_regs; |
32 | struct kprobe; | 33 | struct kprobe; |
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index 246617efd67f..41e08cb6a092 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h | |||
@@ -9,6 +9,22 @@ | |||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/ioctl.h> | 10 | #include <linux/ioctl.h> |
11 | 11 | ||
12 | #define DE_VECTOR 0 | ||
13 | #define DB_VECTOR 1 | ||
14 | #define BP_VECTOR 3 | ||
15 | #define OF_VECTOR 4 | ||
16 | #define BR_VECTOR 5 | ||
17 | #define UD_VECTOR 6 | ||
18 | #define NM_VECTOR 7 | ||
19 | #define DF_VECTOR 8 | ||
20 | #define TS_VECTOR 10 | ||
21 | #define NP_VECTOR 11 | ||
22 | #define SS_VECTOR 12 | ||
23 | #define GP_VECTOR 13 | ||
24 | #define PF_VECTOR 14 | ||
25 | #define MF_VECTOR 16 | ||
26 | #define MC_VECTOR 18 | ||
27 | |||
12 | /* Select x86 specific features in <linux/kvm.h> */ | 28 | /* Select x86 specific features in <linux/kvm.h> */ |
13 | #define __KVM_HAVE_PIT | 29 | #define __KVM_HAVE_PIT |
14 | #define __KVM_HAVE_IOAPIC | 30 | #define __KVM_HAVE_IOAPIC |
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 09155d64cf7e..1eaa6b056670 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -75,22 +75,6 @@ | |||
75 | #define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1)) | 75 | #define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1)) |
76 | #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE) | 76 | #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE) |
77 | 77 | ||
78 | #define DE_VECTOR 0 | ||
79 | #define DB_VECTOR 1 | ||
80 | #define BP_VECTOR 3 | ||
81 | #define OF_VECTOR 4 | ||
82 | #define BR_VECTOR 5 | ||
83 | #define UD_VECTOR 6 | ||
84 | #define NM_VECTOR 7 | ||
85 | #define DF_VECTOR 8 | ||
86 | #define TS_VECTOR 10 | ||
87 | #define NP_VECTOR 11 | ||
88 | #define SS_VECTOR 12 | ||
89 | #define GP_VECTOR 13 | ||
90 | #define PF_VECTOR 14 | ||
91 | #define MF_VECTOR 16 | ||
92 | #define MC_VECTOR 18 | ||
93 | |||
94 | #define SELECTOR_TI_MASK (1 << 2) | 78 | #define SELECTOR_TI_MASK (1 << 2) |
95 | #define SELECTOR_RPL_MASK 0x03 | 79 | #define SELECTOR_RPL_MASK 0x03 |
96 | 80 | ||
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index a3ac52b29cbf..54d73b1f00a0 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
@@ -116,19 +116,9 @@ struct mce_log { | |||
116 | /* Software defined banks */ | 116 | /* Software defined banks */ |
117 | #define MCE_EXTENDED_BANK 128 | 117 | #define MCE_EXTENDED_BANK 128 |
118 | #define MCE_THERMAL_BANK MCE_EXTENDED_BANK + 0 | 118 | #define MCE_THERMAL_BANK MCE_EXTENDED_BANK + 0 |
119 | 119 | #define K8_MCE_THRESHOLD_BASE (MCE_EXTENDED_BANK + 1) | |
120 | #define K8_MCE_THRESHOLD_BASE (MCE_EXTENDED_BANK + 1) /* MCE_AMD */ | ||
121 | #define K8_MCE_THRESHOLD_BANK_0 (MCE_THRESHOLD_BASE + 0 * 9) | ||
122 | #define K8_MCE_THRESHOLD_BANK_1 (MCE_THRESHOLD_BASE + 1 * 9) | ||
123 | #define K8_MCE_THRESHOLD_BANK_2 (MCE_THRESHOLD_BASE + 2 * 9) | ||
124 | #define K8_MCE_THRESHOLD_BANK_3 (MCE_THRESHOLD_BASE + 3 * 9) | ||
125 | #define K8_MCE_THRESHOLD_BANK_4 (MCE_THRESHOLD_BASE + 4 * 9) | ||
126 | #define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) | ||
127 | #define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) | ||
128 | |||
129 | 120 | ||
130 | #ifdef __KERNEL__ | 121 | #ifdef __KERNEL__ |
131 | |||
132 | extern void mce_register_decode_chain(struct notifier_block *nb); | 122 | extern void mce_register_decode_chain(struct notifier_block *nb); |
133 | extern void mce_unregister_decode_chain(struct notifier_block *nb); | 123 | extern void mce_unregister_decode_chain(struct notifier_block *nb); |
134 | 124 | ||
@@ -171,6 +161,7 @@ DECLARE_PER_CPU(struct device *, mce_device); | |||
171 | #ifdef CONFIG_X86_MCE_INTEL | 161 | #ifdef CONFIG_X86_MCE_INTEL |
172 | extern int mce_cmci_disabled; | 162 | extern int mce_cmci_disabled; |
173 | extern int mce_ignore_ce; | 163 | extern int mce_ignore_ce; |
164 | extern int mce_bios_cmci_threshold; | ||
174 | void mce_intel_feature_init(struct cpuinfo_x86 *c); | 165 | void mce_intel_feature_init(struct cpuinfo_x86 *c); |
175 | void cmci_clear(void); | 166 | void cmci_clear(void); |
176 | void cmci_reenable(void); | 167 | void cmci_reenable(void); |
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 4ebe157bf73d..43d921b4752c 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
@@ -15,8 +15,8 @@ struct microcode_ops { | |||
15 | enum ucode_state (*request_microcode_user) (int cpu, | 15 | enum ucode_state (*request_microcode_user) (int cpu, |
16 | const void __user *buf, size_t size); | 16 | const void __user *buf, size_t size); |
17 | 17 | ||
18 | enum ucode_state (*request_microcode_fw) (int cpu, | 18 | enum ucode_state (*request_microcode_fw) (int cpu, struct device *, |
19 | struct device *device); | 19 | bool refresh_fw); |
20 | 20 | ||
21 | void (*microcode_fini_cpu) (int cpu); | 21 | void (*microcode_fini_cpu) (int cpu); |
22 | 22 | ||
@@ -49,12 +49,6 @@ static inline struct microcode_ops * __init init_intel_microcode(void) | |||
49 | #ifdef CONFIG_MICROCODE_AMD | 49 | #ifdef CONFIG_MICROCODE_AMD |
50 | extern struct microcode_ops * __init init_amd_microcode(void); | 50 | extern struct microcode_ops * __init init_amd_microcode(void); |
51 | extern void __exit exit_amd_microcode(void); | 51 | extern void __exit exit_amd_microcode(void); |
52 | |||
53 | static inline void get_ucode_data(void *to, const u8 *from, size_t n) | ||
54 | { | ||
55 | memcpy(to, from, n); | ||
56 | } | ||
57 | |||
58 | #else | 52 | #else |
59 | static inline struct microcode_ops * __init init_amd_microcode(void) | 53 | static inline struct microcode_ops * __init init_amd_microcode(void) |
60 | { | 54 | { |
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index cb4e43bce98a..4fabcdf1cfa7 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h | |||
@@ -262,4 +262,6 @@ static inline void perf_check_microcode(void) { } | |||
262 | static inline void amd_pmu_disable_virt(void) { } | 262 | static inline void amd_pmu_disable_virt(void) { } |
263 | #endif | 263 | #endif |
264 | 264 | ||
265 | #define arch_perf_out_copy_user copy_from_user_nmi | ||
266 | |||
265 | #endif /* _ASM_X86_PERF_EVENT_H */ | 267 | #endif /* _ASM_X86_PERF_EVENT_H */ |
diff --git a/arch/x86/include/asm/perf_regs.h b/arch/x86/include/asm/perf_regs.h new file mode 100644 index 000000000000..3f2207bfd17b --- /dev/null +++ b/arch/x86/include/asm/perf_regs.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef _ASM_X86_PERF_REGS_H | ||
2 | #define _ASM_X86_PERF_REGS_H | ||
3 | |||
4 | enum perf_event_x86_regs { | ||
5 | PERF_REG_X86_AX, | ||
6 | PERF_REG_X86_BX, | ||
7 | PERF_REG_X86_CX, | ||
8 | PERF_REG_X86_DX, | ||
9 | PERF_REG_X86_SI, | ||
10 | PERF_REG_X86_DI, | ||
11 | PERF_REG_X86_BP, | ||
12 | PERF_REG_X86_SP, | ||
13 | PERF_REG_X86_IP, | ||
14 | PERF_REG_X86_FLAGS, | ||
15 | PERF_REG_X86_CS, | ||
16 | PERF_REG_X86_SS, | ||
17 | PERF_REG_X86_DS, | ||
18 | PERF_REG_X86_ES, | ||
19 | PERF_REG_X86_FS, | ||
20 | PERF_REG_X86_GS, | ||
21 | PERF_REG_X86_R8, | ||
22 | PERF_REG_X86_R9, | ||
23 | PERF_REG_X86_R10, | ||
24 | PERF_REG_X86_R11, | ||
25 | PERF_REG_X86_R12, | ||
26 | PERF_REG_X86_R13, | ||
27 | PERF_REG_X86_R14, | ||
28 | PERF_REG_X86_R15, | ||
29 | |||
30 | PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1, | ||
31 | PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1, | ||
32 | }; | ||
33 | #endif /* _ASM_X86_PERF_REGS_H */ | ||
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 013286a10c2c..db8fec6d2953 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h | |||
@@ -303,11 +303,9 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pte); | |||
303 | 303 | ||
304 | extern void native_pagetable_reserve(u64 start, u64 end); | 304 | extern void native_pagetable_reserve(u64 start, u64 end); |
305 | #ifdef CONFIG_X86_32 | 305 | #ifdef CONFIG_X86_32 |
306 | extern void native_pagetable_setup_start(pgd_t *base); | 306 | extern void native_pagetable_init(void); |
307 | extern void native_pagetable_setup_done(pgd_t *base); | ||
308 | #else | 307 | #else |
309 | #define native_pagetable_setup_start x86_init_pgd_noop | 308 | #define native_pagetable_init paging_init |
310 | #define native_pagetable_setup_done x86_init_pgd_noop | ||
311 | #endif | 309 | #endif |
312 | 310 | ||
313 | struct seq_file; | 311 | struct seq_file; |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index d048cad9bcad..b98c0d958ebb 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -423,7 +423,6 @@ DECLARE_INIT_PER_CPU(irq_stack_union); | |||
423 | 423 | ||
424 | DECLARE_PER_CPU(char *, irq_stack_ptr); | 424 | DECLARE_PER_CPU(char *, irq_stack_ptr); |
425 | DECLARE_PER_CPU(unsigned int, irq_count); | 425 | DECLARE_PER_CPU(unsigned int, irq_count); |
426 | extern unsigned long kernel_eflags; | ||
427 | extern asmlinkage void ignore_sysret(void); | 426 | extern asmlinkage void ignore_sysret(void); |
428 | #else /* X86_64 */ | 427 | #else /* X86_64 */ |
429 | #ifdef CONFIG_CC_STACKPROTECTOR | 428 | #ifdef CONFIG_CC_STACKPROTECTOR |
@@ -759,6 +758,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr) | |||
759 | wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); | 758 | wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); |
760 | } | 759 | } |
761 | 760 | ||
761 | extern void set_task_blockstep(struct task_struct *task, bool on); | ||
762 | |||
762 | /* | 763 | /* |
763 | * from system description table in BIOS. Mostly for MCA use, but | 764 | * from system description table in BIOS. Mostly for MCA use, but |
764 | * others may find it useful: | 765 | * others may find it useful: |
diff --git a/arch/x86/include/asm/rcu.h b/arch/x86/include/asm/rcu.h new file mode 100644 index 000000000000..d1ac07a23979 --- /dev/null +++ b/arch/x86/include/asm/rcu.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef _ASM_X86_RCU_H | ||
2 | #define _ASM_X86_RCU_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | |||
6 | #include <linux/rcupdate.h> | ||
7 | #include <asm/ptrace.h> | ||
8 | |||
9 | static inline void exception_enter(struct pt_regs *regs) | ||
10 | { | ||
11 | rcu_user_exit(); | ||
12 | } | ||
13 | |||
14 | static inline void exception_exit(struct pt_regs *regs) | ||
15 | { | ||
16 | #ifdef CONFIG_RCU_USER_QS | ||
17 | if (user_mode(regs)) | ||
18 | rcu_user_enter(); | ||
19 | #endif | ||
20 | } | ||
21 | |||
22 | #else /* __ASSEMBLY__ */ | ||
23 | |||
24 | #ifdef CONFIG_RCU_USER_QS | ||
25 | # define SCHEDULE_USER call schedule_user | ||
26 | #else | ||
27 | # define SCHEDULE_USER call schedule | ||
28 | #endif | ||
29 | |||
30 | #endif /* !__ASSEMBLY__ */ | ||
31 | |||
32 | #endif | ||
diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h index 598457cbd0f8..323973f4abf1 100644 --- a/arch/x86/include/asm/signal.h +++ b/arch/x86/include/asm/signal.h | |||
@@ -31,6 +31,10 @@ typedef struct { | |||
31 | unsigned long sig[_NSIG_WORDS]; | 31 | unsigned long sig[_NSIG_WORDS]; |
32 | } sigset_t; | 32 | } sigset_t; |
33 | 33 | ||
34 | #ifndef CONFIG_COMPAT | ||
35 | typedef sigset_t compat_sigset_t; | ||
36 | #endif | ||
37 | |||
34 | #else | 38 | #else |
35 | /* Here we must cater to libcs that poke about in kernel headers. */ | 39 | /* Here we must cater to libcs that poke about in kernel headers. */ |
36 | 40 | ||
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index f2b83bc7d784..cdf5674dd23a 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h | |||
@@ -1,6 +1,135 @@ | |||
1 | #ifndef __SVM_H | 1 | #ifndef __SVM_H |
2 | #define __SVM_H | 2 | #define __SVM_H |
3 | 3 | ||
4 | #define SVM_EXIT_READ_CR0 0x000 | ||
5 | #define SVM_EXIT_READ_CR3 0x003 | ||
6 | #define SVM_EXIT_READ_CR4 0x004 | ||
7 | #define SVM_EXIT_READ_CR8 0x008 | ||
8 | #define SVM_EXIT_WRITE_CR0 0x010 | ||
9 | #define SVM_EXIT_WRITE_CR3 0x013 | ||
10 | #define SVM_EXIT_WRITE_CR4 0x014 | ||
11 | #define SVM_EXIT_WRITE_CR8 0x018 | ||
12 | #define SVM_EXIT_READ_DR0 0x020 | ||
13 | #define SVM_EXIT_READ_DR1 0x021 | ||
14 | #define SVM_EXIT_READ_DR2 0x022 | ||
15 | #define SVM_EXIT_READ_DR3 0x023 | ||
16 | #define SVM_EXIT_READ_DR4 0x024 | ||
17 | #define SVM_EXIT_READ_DR5 0x025 | ||
18 | #define SVM_EXIT_READ_DR6 0x026 | ||
19 | #define SVM_EXIT_READ_DR7 0x027 | ||
20 | #define SVM_EXIT_WRITE_DR0 0x030 | ||
21 | #define SVM_EXIT_WRITE_DR1 0x031 | ||
22 | #define SVM_EXIT_WRITE_DR2 0x032 | ||
23 | #define SVM_EXIT_WRITE_DR3 0x033 | ||
24 | #define SVM_EXIT_WRITE_DR4 0x034 | ||
25 | #define SVM_EXIT_WRITE_DR5 0x035 | ||
26 | #define SVM_EXIT_WRITE_DR6 0x036 | ||
27 | #define SVM_EXIT_WRITE_DR7 0x037 | ||
28 | #define SVM_EXIT_EXCP_BASE 0x040 | ||
29 | #define SVM_EXIT_INTR 0x060 | ||
30 | #define SVM_EXIT_NMI 0x061 | ||
31 | #define SVM_EXIT_SMI 0x062 | ||
32 | #define SVM_EXIT_INIT 0x063 | ||
33 | #define SVM_EXIT_VINTR 0x064 | ||
34 | #define SVM_EXIT_CR0_SEL_WRITE 0x065 | ||
35 | #define SVM_EXIT_IDTR_READ 0x066 | ||
36 | #define SVM_EXIT_GDTR_READ 0x067 | ||
37 | #define SVM_EXIT_LDTR_READ 0x068 | ||
38 | #define SVM_EXIT_TR_READ 0x069 | ||
39 | #define SVM_EXIT_IDTR_WRITE 0x06a | ||
40 | #define SVM_EXIT_GDTR_WRITE 0x06b | ||
41 | #define SVM_EXIT_LDTR_WRITE 0x06c | ||
42 | #define SVM_EXIT_TR_WRITE 0x06d | ||
43 | #define SVM_EXIT_RDTSC 0x06e | ||
44 | #define SVM_EXIT_RDPMC 0x06f | ||
45 | #define SVM_EXIT_PUSHF 0x070 | ||
46 | #define SVM_EXIT_POPF 0x071 | ||
47 | #define SVM_EXIT_CPUID 0x072 | ||
48 | #define SVM_EXIT_RSM 0x073 | ||
49 | #define SVM_EXIT_IRET 0x074 | ||
50 | #define SVM_EXIT_SWINT 0x075 | ||
51 | #define SVM_EXIT_INVD 0x076 | ||
52 | #define SVM_EXIT_PAUSE 0x077 | ||
53 | #define SVM_EXIT_HLT 0x078 | ||
54 | #define SVM_EXIT_INVLPG 0x079 | ||
55 | #define SVM_EXIT_INVLPGA 0x07a | ||
56 | #define SVM_EXIT_IOIO 0x07b | ||
57 | #define SVM_EXIT_MSR 0x07c | ||
58 | #define SVM_EXIT_TASK_SWITCH 0x07d | ||
59 | #define SVM_EXIT_FERR_FREEZE 0x07e | ||
60 | #define SVM_EXIT_SHUTDOWN 0x07f | ||
61 | #define SVM_EXIT_VMRUN 0x080 | ||
62 | #define SVM_EXIT_VMMCALL 0x081 | ||
63 | #define SVM_EXIT_VMLOAD 0x082 | ||
64 | #define SVM_EXIT_VMSAVE 0x083 | ||
65 | #define SVM_EXIT_STGI 0x084 | ||
66 | #define SVM_EXIT_CLGI 0x085 | ||
67 | #define SVM_EXIT_SKINIT 0x086 | ||
68 | #define SVM_EXIT_RDTSCP 0x087 | ||
69 | #define SVM_EXIT_ICEBP 0x088 | ||
70 | #define SVM_EXIT_WBINVD 0x089 | ||
71 | #define SVM_EXIT_MONITOR 0x08a | ||
72 | #define SVM_EXIT_MWAIT 0x08b | ||
73 | #define SVM_EXIT_MWAIT_COND 0x08c | ||
74 | #define SVM_EXIT_XSETBV 0x08d | ||
75 | #define SVM_EXIT_NPF 0x400 | ||
76 | |||
77 | #define SVM_EXIT_ERR -1 | ||
78 | |||
79 | #define SVM_EXIT_REASONS \ | ||
80 | { SVM_EXIT_READ_CR0, "read_cr0" }, \ | ||
81 | { SVM_EXIT_READ_CR3, "read_cr3" }, \ | ||
82 | { SVM_EXIT_READ_CR4, "read_cr4" }, \ | ||
83 | { SVM_EXIT_READ_CR8, "read_cr8" }, \ | ||
84 | { SVM_EXIT_WRITE_CR0, "write_cr0" }, \ | ||
85 | { SVM_EXIT_WRITE_CR3, "write_cr3" }, \ | ||
86 | { SVM_EXIT_WRITE_CR4, "write_cr4" }, \ | ||
87 | { SVM_EXIT_WRITE_CR8, "write_cr8" }, \ | ||
88 | { SVM_EXIT_READ_DR0, "read_dr0" }, \ | ||
89 | { SVM_EXIT_READ_DR1, "read_dr1" }, \ | ||
90 | { SVM_EXIT_READ_DR2, "read_dr2" }, \ | ||
91 | { SVM_EXIT_READ_DR3, "read_dr3" }, \ | ||
92 | { SVM_EXIT_WRITE_DR0, "write_dr0" }, \ | ||
93 | { SVM_EXIT_WRITE_DR1, "write_dr1" }, \ | ||
94 | { SVM_EXIT_WRITE_DR2, "write_dr2" }, \ | ||
95 | { SVM_EXIT_WRITE_DR3, "write_dr3" }, \ | ||
96 | { SVM_EXIT_WRITE_DR5, "write_dr5" }, \ | ||
97 | { SVM_EXIT_WRITE_DR7, "write_dr7" }, \ | ||
98 | { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \ | ||
99 | { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \ | ||
100 | { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \ | ||
101 | { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \ | ||
102 | { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \ | ||
103 | { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \ | ||
104 | { SVM_EXIT_INTR, "interrupt" }, \ | ||
105 | { SVM_EXIT_NMI, "nmi" }, \ | ||
106 | { SVM_EXIT_SMI, "smi" }, \ | ||
107 | { SVM_EXIT_INIT, "init" }, \ | ||
108 | { SVM_EXIT_VINTR, "vintr" }, \ | ||
109 | { SVM_EXIT_CPUID, "cpuid" }, \ | ||
110 | { SVM_EXIT_INVD, "invd" }, \ | ||
111 | { SVM_EXIT_HLT, "hlt" }, \ | ||
112 | { SVM_EXIT_INVLPG, "invlpg" }, \ | ||
113 | { SVM_EXIT_INVLPGA, "invlpga" }, \ | ||
114 | { SVM_EXIT_IOIO, "io" }, \ | ||
115 | { SVM_EXIT_MSR, "msr" }, \ | ||
116 | { SVM_EXIT_TASK_SWITCH, "task_switch" }, \ | ||
117 | { SVM_EXIT_SHUTDOWN, "shutdown" }, \ | ||
118 | { SVM_EXIT_VMRUN, "vmrun" }, \ | ||
119 | { SVM_EXIT_VMMCALL, "hypercall" }, \ | ||
120 | { SVM_EXIT_VMLOAD, "vmload" }, \ | ||
121 | { SVM_EXIT_VMSAVE, "vmsave" }, \ | ||
122 | { SVM_EXIT_STGI, "stgi" }, \ | ||
123 | { SVM_EXIT_CLGI, "clgi" }, \ | ||
124 | { SVM_EXIT_SKINIT, "skinit" }, \ | ||
125 | { SVM_EXIT_WBINVD, "wbinvd" }, \ | ||
126 | { SVM_EXIT_MONITOR, "monitor" }, \ | ||
127 | { SVM_EXIT_MWAIT, "mwait" }, \ | ||
128 | { SVM_EXIT_XSETBV, "xsetbv" }, \ | ||
129 | { SVM_EXIT_NPF, "npf" } | ||
130 | |||
131 | #ifdef __KERNEL__ | ||
132 | |||
4 | enum { | 133 | enum { |
5 | INTERCEPT_INTR, | 134 | INTERCEPT_INTR, |
6 | INTERCEPT_NMI, | 135 | INTERCEPT_NMI, |
@@ -264,81 +393,6 @@ struct __attribute__ ((__packed__)) vmcb { | |||
264 | 393 | ||
265 | #define SVM_EXITINFO_REG_MASK 0x0F | 394 | #define SVM_EXITINFO_REG_MASK 0x0F |
266 | 395 | ||
267 | #define SVM_EXIT_READ_CR0 0x000 | ||
268 | #define SVM_EXIT_READ_CR3 0x003 | ||
269 | #define SVM_EXIT_READ_CR4 0x004 | ||
270 | #define SVM_EXIT_READ_CR8 0x008 | ||
271 | #define SVM_EXIT_WRITE_CR0 0x010 | ||
272 | #define SVM_EXIT_WRITE_CR3 0x013 | ||
273 | #define SVM_EXIT_WRITE_CR4 0x014 | ||
274 | #define SVM_EXIT_WRITE_CR8 0x018 | ||
275 | #define SVM_EXIT_READ_DR0 0x020 | ||
276 | #define SVM_EXIT_READ_DR1 0x021 | ||
277 | #define SVM_EXIT_READ_DR2 0x022 | ||
278 | #define SVM_EXIT_READ_DR3 0x023 | ||
279 | #define SVM_EXIT_READ_DR4 0x024 | ||
280 | #define SVM_EXIT_READ_DR5 0x025 | ||
281 | #define SVM_EXIT_READ_DR6 0x026 | ||
282 | #define SVM_EXIT_READ_DR7 0x027 | ||
283 | #define SVM_EXIT_WRITE_DR0 0x030 | ||
284 | #define SVM_EXIT_WRITE_DR1 0x031 | ||
285 | #define SVM_EXIT_WRITE_DR2 0x032 | ||
286 | #define SVM_EXIT_WRITE_DR3 0x033 | ||
287 | #define SVM_EXIT_WRITE_DR4 0x034 | ||
288 | #define SVM_EXIT_WRITE_DR5 0x035 | ||
289 | #define SVM_EXIT_WRITE_DR6 0x036 | ||
290 | #define SVM_EXIT_WRITE_DR7 0x037 | ||
291 | #define SVM_EXIT_EXCP_BASE 0x040 | ||
292 | #define SVM_EXIT_INTR 0x060 | ||
293 | #define SVM_EXIT_NMI 0x061 | ||
294 | #define SVM_EXIT_SMI 0x062 | ||
295 | #define SVM_EXIT_INIT 0x063 | ||
296 | #define SVM_EXIT_VINTR 0x064 | ||
297 | #define SVM_EXIT_CR0_SEL_WRITE 0x065 | ||
298 | #define SVM_EXIT_IDTR_READ 0x066 | ||
299 | #define SVM_EXIT_GDTR_READ 0x067 | ||
300 | #define SVM_EXIT_LDTR_READ 0x068 | ||
301 | #define SVM_EXIT_TR_READ 0x069 | ||
302 | #define SVM_EXIT_IDTR_WRITE 0x06a | ||
303 | #define SVM_EXIT_GDTR_WRITE 0x06b | ||
304 | #define SVM_EXIT_LDTR_WRITE 0x06c | ||
305 | #define SVM_EXIT_TR_WRITE 0x06d | ||
306 | #define SVM_EXIT_RDTSC 0x06e | ||
307 | #define SVM_EXIT_RDPMC 0x06f | ||
308 | #define SVM_EXIT_PUSHF 0x070 | ||
309 | #define SVM_EXIT_POPF 0x071 | ||
310 | #define SVM_EXIT_CPUID 0x072 | ||
311 | #define SVM_EXIT_RSM 0x073 | ||
312 | #define SVM_EXIT_IRET 0x074 | ||
313 | #define SVM_EXIT_SWINT 0x075 | ||
314 | #define SVM_EXIT_INVD 0x076 | ||
315 | #define SVM_EXIT_PAUSE 0x077 | ||
316 | #define SVM_EXIT_HLT 0x078 | ||
317 | #define SVM_EXIT_INVLPG 0x079 | ||
318 | #define SVM_EXIT_INVLPGA 0x07a | ||
319 | #define SVM_EXIT_IOIO 0x07b | ||
320 | #define SVM_EXIT_MSR 0x07c | ||
321 | #define SVM_EXIT_TASK_SWITCH 0x07d | ||
322 | #define SVM_EXIT_FERR_FREEZE 0x07e | ||
323 | #define SVM_EXIT_SHUTDOWN 0x07f | ||
324 | #define SVM_EXIT_VMRUN 0x080 | ||
325 | #define SVM_EXIT_VMMCALL 0x081 | ||
326 | #define SVM_EXIT_VMLOAD 0x082 | ||
327 | #define SVM_EXIT_VMSAVE 0x083 | ||
328 | #define SVM_EXIT_STGI 0x084 | ||
329 | #define SVM_EXIT_CLGI 0x085 | ||
330 | #define SVM_EXIT_SKINIT 0x086 | ||
331 | #define SVM_EXIT_RDTSCP 0x087 | ||
332 | #define SVM_EXIT_ICEBP 0x088 | ||
333 | #define SVM_EXIT_WBINVD 0x089 | ||
334 | #define SVM_EXIT_MONITOR 0x08a | ||
335 | #define SVM_EXIT_MWAIT 0x08b | ||
336 | #define SVM_EXIT_MWAIT_COND 0x08c | ||
337 | #define SVM_EXIT_XSETBV 0x08d | ||
338 | #define SVM_EXIT_NPF 0x400 | ||
339 | |||
340 | #define SVM_EXIT_ERR -1 | ||
341 | |||
342 | #define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP) | 396 | #define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP) |
343 | 397 | ||
344 | #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda" | 398 | #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda" |
@@ -350,3 +404,4 @@ struct __attribute__ ((__packed__)) vmcb { | |||
350 | 404 | ||
351 | #endif | 405 | #endif |
352 | 406 | ||
407 | #endif | ||
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index 3fda9db48819..4ca1c611b552 100644 --- a/arch/x86/include/asm/sys_ia32.h +++ b/arch/x86/include/asm/sys_ia32.h | |||
@@ -40,7 +40,7 @@ asmlinkage long sys32_sigaction(int, struct old_sigaction32 __user *, | |||
40 | struct old_sigaction32 __user *); | 40 | struct old_sigaction32 __user *); |
41 | asmlinkage long sys32_alarm(unsigned int); | 41 | asmlinkage long sys32_alarm(unsigned int); |
42 | 42 | ||
43 | asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int); | 43 | asmlinkage long sys32_waitpid(compat_pid_t, unsigned int __user *, int); |
44 | asmlinkage long sys32_sysfs(int, u32, u32); | 44 | asmlinkage long sys32_sysfs(int, u32, u32); |
45 | 45 | ||
46 | asmlinkage long sys32_sched_rr_get_interval(compat_pid_t, | 46 | asmlinkage long sys32_sched_rr_get_interval(compat_pid_t, |
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 89f794f007ec..c535d847e3b5 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
@@ -89,6 +89,7 @@ struct thread_info { | |||
89 | #define TIF_NOTSC 16 /* TSC is not accessible in userland */ | 89 | #define TIF_NOTSC 16 /* TSC is not accessible in userland */ |
90 | #define TIF_IA32 17 /* IA32 compatibility process */ | 90 | #define TIF_IA32 17 /* IA32 compatibility process */ |
91 | #define TIF_FORK 18 /* ret_from_fork */ | 91 | #define TIF_FORK 18 /* ret_from_fork */ |
92 | #define TIF_NOHZ 19 /* in adaptive nohz mode */ | ||
92 | #define TIF_MEMDIE 20 /* is terminating due to OOM killer */ | 93 | #define TIF_MEMDIE 20 /* is terminating due to OOM killer */ |
93 | #define TIF_DEBUG 21 /* uses debug registers */ | 94 | #define TIF_DEBUG 21 /* uses debug registers */ |
94 | #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ | 95 | #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ |
@@ -114,6 +115,7 @@ struct thread_info { | |||
114 | #define _TIF_NOTSC (1 << TIF_NOTSC) | 115 | #define _TIF_NOTSC (1 << TIF_NOTSC) |
115 | #define _TIF_IA32 (1 << TIF_IA32) | 116 | #define _TIF_IA32 (1 << TIF_IA32) |
116 | #define _TIF_FORK (1 << TIF_FORK) | 117 | #define _TIF_FORK (1 << TIF_FORK) |
118 | #define _TIF_NOHZ (1 << TIF_NOHZ) | ||
117 | #define _TIF_DEBUG (1 << TIF_DEBUG) | 119 | #define _TIF_DEBUG (1 << TIF_DEBUG) |
118 | #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) | 120 | #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) |
119 | #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) | 121 | #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) |
@@ -126,12 +128,13 @@ struct thread_info { | |||
126 | /* work to do in syscall_trace_enter() */ | 128 | /* work to do in syscall_trace_enter() */ |
127 | #define _TIF_WORK_SYSCALL_ENTRY \ | 129 | #define _TIF_WORK_SYSCALL_ENTRY \ |
128 | (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | _TIF_SYSCALL_AUDIT | \ | 130 | (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | _TIF_SYSCALL_AUDIT | \ |
129 | _TIF_SECCOMP | _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT) | 131 | _TIF_SECCOMP | _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT | \ |
132 | _TIF_NOHZ) | ||
130 | 133 | ||
131 | /* work to do in syscall_trace_leave() */ | 134 | /* work to do in syscall_trace_leave() */ |
132 | #define _TIF_WORK_SYSCALL_EXIT \ | 135 | #define _TIF_WORK_SYSCALL_EXIT \ |
133 | (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP | \ | 136 | (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP | \ |
134 | _TIF_SYSCALL_TRACEPOINT) | 137 | _TIF_SYSCALL_TRACEPOINT | _TIF_NOHZ) |
135 | 138 | ||
136 | /* work to do on interrupt/exception return */ | 139 | /* work to do on interrupt/exception return */ |
137 | #define _TIF_WORK_MASK \ | 140 | #define _TIF_WORK_MASK \ |
@@ -141,7 +144,8 @@ struct thread_info { | |||
141 | 144 | ||
142 | /* work to do on any return to user space */ | 145 | /* work to do on any return to user space */ |
143 | #define _TIF_ALLWORK_MASK \ | 146 | #define _TIF_ALLWORK_MASK \ |
144 | ((0x0000FFFF & ~_TIF_SECCOMP) | _TIF_SYSCALL_TRACEPOINT) | 147 | ((0x0000FFFF & ~_TIF_SECCOMP) | _TIF_SYSCALL_TRACEPOINT | \ |
148 | _TIF_NOHZ) | ||
145 | 149 | ||
146 | /* Only used for 64 bit */ | 150 | /* Only used for 64 bit */ |
147 | #define _TIF_DO_NOTIFY_MASK \ | 151 | #define _TIF_DO_NOTIFY_MASK \ |
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h index f3971bbcd1de..8ff8be7835ab 100644 --- a/arch/x86/include/asm/uprobes.h +++ b/arch/x86/include/asm/uprobes.h | |||
@@ -42,10 +42,11 @@ struct arch_uprobe { | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | struct arch_uprobe_task { | 44 | struct arch_uprobe_task { |
45 | unsigned long saved_trap_nr; | ||
46 | #ifdef CONFIG_X86_64 | 45 | #ifdef CONFIG_X86_64 |
47 | unsigned long saved_scratch_register; | 46 | unsigned long saved_scratch_register; |
48 | #endif | 47 | #endif |
48 | unsigned int saved_trap_nr; | ||
49 | unsigned int saved_tf; | ||
49 | }; | 50 | }; |
50 | 51 | ||
51 | extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); | 52 | extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); |
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h index bb0522850b74..fddb53d63915 100644 --- a/arch/x86/include/asm/vdso.h +++ b/arch/x86/include/asm/vdso.h | |||
@@ -11,7 +11,8 @@ extern const char VDSO32_PRELINK[]; | |||
11 | #define VDSO32_SYMBOL(base, name) \ | 11 | #define VDSO32_SYMBOL(base, name) \ |
12 | ({ \ | 12 | ({ \ |
13 | extern const char VDSO32_##name[]; \ | 13 | extern const char VDSO32_##name[]; \ |
14 | (void *)(VDSO32_##name - VDSO32_PRELINK + (unsigned long)(base)); \ | 14 | (void __user *)(VDSO32_##name - VDSO32_PRELINK + \ |
15 | (unsigned long)(base)); \ | ||
15 | }) | 16 | }) |
16 | #endif | 17 | #endif |
17 | 18 | ||
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 74fcb963595b..36ec21c36d68 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h | |||
@@ -25,6 +25,88 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 | ||
29 | |||
30 | #define EXIT_REASON_EXCEPTION_NMI 0 | ||
31 | #define EXIT_REASON_EXTERNAL_INTERRUPT 1 | ||
32 | #define EXIT_REASON_TRIPLE_FAULT 2 | ||
33 | |||
34 | #define EXIT_REASON_PENDING_INTERRUPT 7 | ||
35 | #define EXIT_REASON_NMI_WINDOW 8 | ||
36 | #define EXIT_REASON_TASK_SWITCH 9 | ||
37 | #define EXIT_REASON_CPUID 10 | ||
38 | #define EXIT_REASON_HLT 12 | ||
39 | #define EXIT_REASON_INVD 13 | ||
40 | #define EXIT_REASON_INVLPG 14 | ||
41 | #define EXIT_REASON_RDPMC 15 | ||
42 | #define EXIT_REASON_RDTSC 16 | ||
43 | #define EXIT_REASON_VMCALL 18 | ||
44 | #define EXIT_REASON_VMCLEAR 19 | ||
45 | #define EXIT_REASON_VMLAUNCH 20 | ||
46 | #define EXIT_REASON_VMPTRLD 21 | ||
47 | #define EXIT_REASON_VMPTRST 22 | ||
48 | #define EXIT_REASON_VMREAD 23 | ||
49 | #define EXIT_REASON_VMRESUME 24 | ||
50 | #define EXIT_REASON_VMWRITE 25 | ||
51 | #define EXIT_REASON_VMOFF 26 | ||
52 | #define EXIT_REASON_VMON 27 | ||
53 | #define EXIT_REASON_CR_ACCESS 28 | ||
54 | #define EXIT_REASON_DR_ACCESS 29 | ||
55 | #define EXIT_REASON_IO_INSTRUCTION 30 | ||
56 | #define EXIT_REASON_MSR_READ 31 | ||
57 | #define EXIT_REASON_MSR_WRITE 32 | ||
58 | #define EXIT_REASON_INVALID_STATE 33 | ||
59 | #define EXIT_REASON_MWAIT_INSTRUCTION 36 | ||
60 | #define EXIT_REASON_MONITOR_INSTRUCTION 39 | ||
61 | #define EXIT_REASON_PAUSE_INSTRUCTION 40 | ||
62 | #define EXIT_REASON_MCE_DURING_VMENTRY 41 | ||
63 | #define EXIT_REASON_TPR_BELOW_THRESHOLD 43 | ||
64 | #define EXIT_REASON_APIC_ACCESS 44 | ||
65 | #define EXIT_REASON_EPT_VIOLATION 48 | ||
66 | #define EXIT_REASON_EPT_MISCONFIG 49 | ||
67 | #define EXIT_REASON_WBINVD 54 | ||
68 | #define EXIT_REASON_XSETBV 55 | ||
69 | #define EXIT_REASON_INVPCID 58 | ||
70 | |||
71 | #define VMX_EXIT_REASONS \ | ||
72 | { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ | ||
73 | { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \ | ||
74 | { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \ | ||
75 | { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \ | ||
76 | { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \ | ||
77 | { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \ | ||
78 | { EXIT_REASON_CPUID, "CPUID" }, \ | ||
79 | { EXIT_REASON_HLT, "HLT" }, \ | ||
80 | { EXIT_REASON_INVLPG, "INVLPG" }, \ | ||
81 | { EXIT_REASON_RDPMC, "RDPMC" }, \ | ||
82 | { EXIT_REASON_RDTSC, "RDTSC" }, \ | ||
83 | { EXIT_REASON_VMCALL, "VMCALL" }, \ | ||
84 | { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \ | ||
85 | { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \ | ||
86 | { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \ | ||
87 | { EXIT_REASON_VMPTRST, "VMPTRST" }, \ | ||
88 | { EXIT_REASON_VMREAD, "VMREAD" }, \ | ||
89 | { EXIT_REASON_VMRESUME, "VMRESUME" }, \ | ||
90 | { EXIT_REASON_VMWRITE, "VMWRITE" }, \ | ||
91 | { EXIT_REASON_VMOFF, "VMOFF" }, \ | ||
92 | { EXIT_REASON_VMON, "VMON" }, \ | ||
93 | { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \ | ||
94 | { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \ | ||
95 | { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \ | ||
96 | { EXIT_REASON_MSR_READ, "MSR_READ" }, \ | ||
97 | { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \ | ||
98 | { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \ | ||
99 | { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \ | ||
100 | { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \ | ||
101 | { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \ | ||
102 | { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \ | ||
103 | { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \ | ||
104 | { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \ | ||
105 | { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \ | ||
106 | { EXIT_REASON_WBINVD, "WBINVD" } | ||
107 | |||
108 | #ifdef __KERNEL__ | ||
109 | |||
28 | #include <linux/types.h> | 110 | #include <linux/types.h> |
29 | 111 | ||
30 | /* | 112 | /* |
@@ -241,49 +323,6 @@ enum vmcs_field { | |||
241 | HOST_RIP = 0x00006c16, | 323 | HOST_RIP = 0x00006c16, |
242 | }; | 324 | }; |
243 | 325 | ||
244 | #define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 | ||
245 | |||
246 | #define EXIT_REASON_EXCEPTION_NMI 0 | ||
247 | #define EXIT_REASON_EXTERNAL_INTERRUPT 1 | ||
248 | #define EXIT_REASON_TRIPLE_FAULT 2 | ||
249 | |||
250 | #define EXIT_REASON_PENDING_INTERRUPT 7 | ||
251 | #define EXIT_REASON_NMI_WINDOW 8 | ||
252 | #define EXIT_REASON_TASK_SWITCH 9 | ||
253 | #define EXIT_REASON_CPUID 10 | ||
254 | #define EXIT_REASON_HLT 12 | ||
255 | #define EXIT_REASON_INVD 13 | ||
256 | #define EXIT_REASON_INVLPG 14 | ||
257 | #define EXIT_REASON_RDPMC 15 | ||
258 | #define EXIT_REASON_RDTSC 16 | ||
259 | #define EXIT_REASON_VMCALL 18 | ||
260 | #define EXIT_REASON_VMCLEAR 19 | ||
261 | #define EXIT_REASON_VMLAUNCH 20 | ||
262 | #define EXIT_REASON_VMPTRLD 21 | ||
263 | #define EXIT_REASON_VMPTRST 22 | ||
264 | #define EXIT_REASON_VMREAD 23 | ||
265 | #define EXIT_REASON_VMRESUME 24 | ||
266 | #define EXIT_REASON_VMWRITE 25 | ||
267 | #define EXIT_REASON_VMOFF 26 | ||
268 | #define EXIT_REASON_VMON 27 | ||
269 | #define EXIT_REASON_CR_ACCESS 28 | ||
270 | #define EXIT_REASON_DR_ACCESS 29 | ||
271 | #define EXIT_REASON_IO_INSTRUCTION 30 | ||
272 | #define EXIT_REASON_MSR_READ 31 | ||
273 | #define EXIT_REASON_MSR_WRITE 32 | ||
274 | #define EXIT_REASON_INVALID_STATE 33 | ||
275 | #define EXIT_REASON_MWAIT_INSTRUCTION 36 | ||
276 | #define EXIT_REASON_MONITOR_INSTRUCTION 39 | ||
277 | #define EXIT_REASON_PAUSE_INSTRUCTION 40 | ||
278 | #define EXIT_REASON_MCE_DURING_VMENTRY 41 | ||
279 | #define EXIT_REASON_TPR_BELOW_THRESHOLD 43 | ||
280 | #define EXIT_REASON_APIC_ACCESS 44 | ||
281 | #define EXIT_REASON_EPT_VIOLATION 48 | ||
282 | #define EXIT_REASON_EPT_MISCONFIG 49 | ||
283 | #define EXIT_REASON_WBINVD 54 | ||
284 | #define EXIT_REASON_XSETBV 55 | ||
285 | #define EXIT_REASON_INVPCID 58 | ||
286 | |||
287 | /* | 326 | /* |
288 | * Interruption-information format | 327 | * Interruption-information format |
289 | */ | 328 | */ |
@@ -488,3 +527,5 @@ enum vm_instruction_error_number { | |||
488 | }; | 527 | }; |
489 | 528 | ||
490 | #endif | 529 | #endif |
530 | |||
531 | #endif | ||
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 38155f667144..57693498519c 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h | |||
@@ -81,12 +81,13 @@ struct x86_init_mapping { | |||
81 | 81 | ||
82 | /** | 82 | /** |
83 | * struct x86_init_paging - platform specific paging functions | 83 | * struct x86_init_paging - platform specific paging functions |
84 | * @pagetable_setup_start: platform specific pre paging_init() call | 84 | * @pagetable_init: platform specific paging initialization call to setup |
85 | * @pagetable_setup_done: platform specific post paging_init() call | 85 | * the kernel pagetables and prepare accessors functions. |
86 | * Callback must call paging_init(). Called once after the | ||
87 | * direct mapping for phys memory is available. | ||
86 | */ | 88 | */ |
87 | struct x86_init_paging { | 89 | struct x86_init_paging { |
88 | void (*pagetable_setup_start)(pgd_t *base); | 90 | void (*pagetable_init)(void); |
89 | void (*pagetable_setup_done)(pgd_t *base); | ||
90 | }; | 91 | }; |
91 | 92 | ||
92 | /** | 93 | /** |
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 93971e841dd5..472b9b783019 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
@@ -51,7 +51,8 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s, | |||
51 | 51 | ||
52 | extern int m2p_add_override(unsigned long mfn, struct page *page, | 52 | extern int m2p_add_override(unsigned long mfn, struct page *page, |
53 | struct gnttab_map_grant_ref *kmap_op); | 53 | struct gnttab_map_grant_ref *kmap_op); |
54 | extern int m2p_remove_override(struct page *page, bool clear_pte); | 54 | extern int m2p_remove_override(struct page *page, |
55 | struct gnttab_map_grant_ref *kmap_op); | ||
55 | extern struct page *m2p_find_override(unsigned long mfn); | 56 | extern struct page *m2p_find_override(unsigned long mfn); |
56 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); | 57 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); |
57 | 58 | ||
diff --git a/arch/x86/include/asm/xor_32.h b/arch/x86/include/asm/xor_32.h index 454570891bdc..aabd5850bdb9 100644 --- a/arch/x86/include/asm/xor_32.h +++ b/arch/x86/include/asm/xor_32.h | |||
@@ -534,38 +534,6 @@ static struct xor_block_template xor_block_p5_mmx = { | |||
534 | * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo) | 534 | * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo) |
535 | */ | 535 | */ |
536 | 536 | ||
537 | #define XMMS_SAVE \ | ||
538 | do { \ | ||
539 | preempt_disable(); \ | ||
540 | cr0 = read_cr0(); \ | ||
541 | clts(); \ | ||
542 | asm volatile( \ | ||
543 | "movups %%xmm0,(%0) ;\n\t" \ | ||
544 | "movups %%xmm1,0x10(%0) ;\n\t" \ | ||
545 | "movups %%xmm2,0x20(%0) ;\n\t" \ | ||
546 | "movups %%xmm3,0x30(%0) ;\n\t" \ | ||
547 | : \ | ||
548 | : "r" (xmm_save) \ | ||
549 | : "memory"); \ | ||
550 | } while (0) | ||
551 | |||
552 | #define XMMS_RESTORE \ | ||
553 | do { \ | ||
554 | asm volatile( \ | ||
555 | "sfence ;\n\t" \ | ||
556 | "movups (%0),%%xmm0 ;\n\t" \ | ||
557 | "movups 0x10(%0),%%xmm1 ;\n\t" \ | ||
558 | "movups 0x20(%0),%%xmm2 ;\n\t" \ | ||
559 | "movups 0x30(%0),%%xmm3 ;\n\t" \ | ||
560 | : \ | ||
561 | : "r" (xmm_save) \ | ||
562 | : "memory"); \ | ||
563 | write_cr0(cr0); \ | ||
564 | preempt_enable(); \ | ||
565 | } while (0) | ||
566 | |||
567 | #define ALIGN16 __attribute__((aligned(16))) | ||
568 | |||
569 | #define OFFS(x) "16*("#x")" | 537 | #define OFFS(x) "16*("#x")" |
570 | #define PF_OFFS(x) "256+16*("#x")" | 538 | #define PF_OFFS(x) "256+16*("#x")" |
571 | #define PF0(x) " prefetchnta "PF_OFFS(x)"(%1) ;\n" | 539 | #define PF0(x) " prefetchnta "PF_OFFS(x)"(%1) ;\n" |
@@ -587,10 +555,8 @@ static void | |||
587 | xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) | 555 | xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) |
588 | { | 556 | { |
589 | unsigned long lines = bytes >> 8; | 557 | unsigned long lines = bytes >> 8; |
590 | char xmm_save[16*4] ALIGN16; | ||
591 | int cr0; | ||
592 | 558 | ||
593 | XMMS_SAVE; | 559 | kernel_fpu_begin(); |
594 | 560 | ||
595 | asm volatile( | 561 | asm volatile( |
596 | #undef BLOCK | 562 | #undef BLOCK |
@@ -633,7 +599,7 @@ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) | |||
633 | : | 599 | : |
634 | : "memory"); | 600 | : "memory"); |
635 | 601 | ||
636 | XMMS_RESTORE; | 602 | kernel_fpu_end(); |
637 | } | 603 | } |
638 | 604 | ||
639 | static void | 605 | static void |
@@ -641,10 +607,8 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
641 | unsigned long *p3) | 607 | unsigned long *p3) |
642 | { | 608 | { |
643 | unsigned long lines = bytes >> 8; | 609 | unsigned long lines = bytes >> 8; |
644 | char xmm_save[16*4] ALIGN16; | ||
645 | int cr0; | ||
646 | 610 | ||
647 | XMMS_SAVE; | 611 | kernel_fpu_begin(); |
648 | 612 | ||
649 | asm volatile( | 613 | asm volatile( |
650 | #undef BLOCK | 614 | #undef BLOCK |
@@ -694,7 +658,7 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
694 | : | 658 | : |
695 | : "memory" ); | 659 | : "memory" ); |
696 | 660 | ||
697 | XMMS_RESTORE; | 661 | kernel_fpu_end(); |
698 | } | 662 | } |
699 | 663 | ||
700 | static void | 664 | static void |
@@ -702,10 +666,8 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
702 | unsigned long *p3, unsigned long *p4) | 666 | unsigned long *p3, unsigned long *p4) |
703 | { | 667 | { |
704 | unsigned long lines = bytes >> 8; | 668 | unsigned long lines = bytes >> 8; |
705 | char xmm_save[16*4] ALIGN16; | ||
706 | int cr0; | ||
707 | 669 | ||
708 | XMMS_SAVE; | 670 | kernel_fpu_begin(); |
709 | 671 | ||
710 | asm volatile( | 672 | asm volatile( |
711 | #undef BLOCK | 673 | #undef BLOCK |
@@ -762,7 +724,7 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
762 | : | 724 | : |
763 | : "memory" ); | 725 | : "memory" ); |
764 | 726 | ||
765 | XMMS_RESTORE; | 727 | kernel_fpu_end(); |
766 | } | 728 | } |
767 | 729 | ||
768 | static void | 730 | static void |
@@ -770,10 +732,8 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
770 | unsigned long *p3, unsigned long *p4, unsigned long *p5) | 732 | unsigned long *p3, unsigned long *p4, unsigned long *p5) |
771 | { | 733 | { |
772 | unsigned long lines = bytes >> 8; | 734 | unsigned long lines = bytes >> 8; |
773 | char xmm_save[16*4] ALIGN16; | ||
774 | int cr0; | ||
775 | 735 | ||
776 | XMMS_SAVE; | 736 | kernel_fpu_begin(); |
777 | 737 | ||
778 | /* Make sure GCC forgets anything it knows about p4 or p5, | 738 | /* Make sure GCC forgets anything it knows about p4 or p5, |
779 | such that it won't pass to the asm volatile below a | 739 | such that it won't pass to the asm volatile below a |
@@ -850,7 +810,7 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
850 | like assuming they have some legal value. */ | 810 | like assuming they have some legal value. */ |
851 | asm("" : "=r" (p4), "=r" (p5)); | 811 | asm("" : "=r" (p4), "=r" (p5)); |
852 | 812 | ||
853 | XMMS_RESTORE; | 813 | kernel_fpu_end(); |
854 | } | 814 | } |
855 | 815 | ||
856 | static struct xor_block_template xor_block_pIII_sse = { | 816 | static struct xor_block_template xor_block_pIII_sse = { |
diff --git a/arch/x86/include/asm/xor_64.h b/arch/x86/include/asm/xor_64.h index b9b2323e90fe..5fc06d0b7eb5 100644 --- a/arch/x86/include/asm/xor_64.h +++ b/arch/x86/include/asm/xor_64.h | |||
@@ -34,41 +34,7 @@ | |||
34 | * no advantages to be gotten from x86-64 here anyways. | 34 | * no advantages to be gotten from x86-64 here anyways. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | typedef struct { | 37 | #include <asm/i387.h> |
38 | unsigned long a, b; | ||
39 | } __attribute__((aligned(16))) xmm_store_t; | ||
40 | |||
41 | /* Doesn't use gcc to save the XMM registers, because there is no easy way to | ||
42 | tell it to do a clts before the register saving. */ | ||
43 | #define XMMS_SAVE \ | ||
44 | do { \ | ||
45 | preempt_disable(); \ | ||
46 | asm volatile( \ | ||
47 | "movq %%cr0,%0 ;\n\t" \ | ||
48 | "clts ;\n\t" \ | ||
49 | "movups %%xmm0,(%1) ;\n\t" \ | ||
50 | "movups %%xmm1,0x10(%1) ;\n\t" \ | ||
51 | "movups %%xmm2,0x20(%1) ;\n\t" \ | ||
52 | "movups %%xmm3,0x30(%1) ;\n\t" \ | ||
53 | : "=&r" (cr0) \ | ||
54 | : "r" (xmm_save) \ | ||
55 | : "memory"); \ | ||
56 | } while (0) | ||
57 | |||
58 | #define XMMS_RESTORE \ | ||
59 | do { \ | ||
60 | asm volatile( \ | ||
61 | "sfence ;\n\t" \ | ||
62 | "movups (%1),%%xmm0 ;\n\t" \ | ||
63 | "movups 0x10(%1),%%xmm1 ;\n\t" \ | ||
64 | "movups 0x20(%1),%%xmm2 ;\n\t" \ | ||
65 | "movups 0x30(%1),%%xmm3 ;\n\t" \ | ||
66 | "movq %0,%%cr0 ;\n\t" \ | ||
67 | : \ | ||
68 | : "r" (cr0), "r" (xmm_save) \ | ||
69 | : "memory"); \ | ||
70 | preempt_enable(); \ | ||
71 | } while (0) | ||
72 | 38 | ||
73 | #define OFFS(x) "16*("#x")" | 39 | #define OFFS(x) "16*("#x")" |
74 | #define PF_OFFS(x) "256+16*("#x")" | 40 | #define PF_OFFS(x) "256+16*("#x")" |
@@ -91,10 +57,8 @@ static void | |||
91 | xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) | 57 | xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) |
92 | { | 58 | { |
93 | unsigned int lines = bytes >> 8; | 59 | unsigned int lines = bytes >> 8; |
94 | unsigned long cr0; | ||
95 | xmm_store_t xmm_save[4]; | ||
96 | 60 | ||
97 | XMMS_SAVE; | 61 | kernel_fpu_begin(); |
98 | 62 | ||
99 | asm volatile( | 63 | asm volatile( |
100 | #undef BLOCK | 64 | #undef BLOCK |
@@ -135,7 +99,7 @@ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) | |||
135 | : [inc] "r" (256UL) | 99 | : [inc] "r" (256UL) |
136 | : "memory"); | 100 | : "memory"); |
137 | 101 | ||
138 | XMMS_RESTORE; | 102 | kernel_fpu_end(); |
139 | } | 103 | } |
140 | 104 | ||
141 | static void | 105 | static void |
@@ -143,11 +107,8 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
143 | unsigned long *p3) | 107 | unsigned long *p3) |
144 | { | 108 | { |
145 | unsigned int lines = bytes >> 8; | 109 | unsigned int lines = bytes >> 8; |
146 | xmm_store_t xmm_save[4]; | ||
147 | unsigned long cr0; | ||
148 | |||
149 | XMMS_SAVE; | ||
150 | 110 | ||
111 | kernel_fpu_begin(); | ||
151 | asm volatile( | 112 | asm volatile( |
152 | #undef BLOCK | 113 | #undef BLOCK |
153 | #define BLOCK(i) \ | 114 | #define BLOCK(i) \ |
@@ -194,7 +155,7 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
194 | [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3) | 155 | [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3) |
195 | : [inc] "r" (256UL) | 156 | : [inc] "r" (256UL) |
196 | : "memory"); | 157 | : "memory"); |
197 | XMMS_RESTORE; | 158 | kernel_fpu_end(); |
198 | } | 159 | } |
199 | 160 | ||
200 | static void | 161 | static void |
@@ -202,10 +163,8 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
202 | unsigned long *p3, unsigned long *p4) | 163 | unsigned long *p3, unsigned long *p4) |
203 | { | 164 | { |
204 | unsigned int lines = bytes >> 8; | 165 | unsigned int lines = bytes >> 8; |
205 | xmm_store_t xmm_save[4]; | ||
206 | unsigned long cr0; | ||
207 | 166 | ||
208 | XMMS_SAVE; | 167 | kernel_fpu_begin(); |
209 | 168 | ||
210 | asm volatile( | 169 | asm volatile( |
211 | #undef BLOCK | 170 | #undef BLOCK |
@@ -261,7 +220,7 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
261 | : [inc] "r" (256UL) | 220 | : [inc] "r" (256UL) |
262 | : "memory" ); | 221 | : "memory" ); |
263 | 222 | ||
264 | XMMS_RESTORE; | 223 | kernel_fpu_end(); |
265 | } | 224 | } |
266 | 225 | ||
267 | static void | 226 | static void |
@@ -269,10 +228,8 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
269 | unsigned long *p3, unsigned long *p4, unsigned long *p5) | 228 | unsigned long *p3, unsigned long *p4, unsigned long *p5) |
270 | { | 229 | { |
271 | unsigned int lines = bytes >> 8; | 230 | unsigned int lines = bytes >> 8; |
272 | xmm_store_t xmm_save[4]; | ||
273 | unsigned long cr0; | ||
274 | 231 | ||
275 | XMMS_SAVE; | 232 | kernel_fpu_begin(); |
276 | 233 | ||
277 | asm volatile( | 234 | asm volatile( |
278 | #undef BLOCK | 235 | #undef BLOCK |
@@ -336,7 +293,7 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, | |||
336 | : [inc] "r" (256UL) | 293 | : [inc] "r" (256UL) |
337 | : "memory"); | 294 | : "memory"); |
338 | 295 | ||
339 | XMMS_RESTORE; | 296 | kernel_fpu_end(); |
340 | } | 297 | } |
341 | 298 | ||
342 | static struct xor_block_template xor_block_sse = { | 299 | static struct xor_block_template xor_block_sse = { |
diff --git a/arch/x86/include/asm/xor_avx.h b/arch/x86/include/asm/xor_avx.h index 2510d35f480e..7ea79c5fa1f2 100644 --- a/arch/x86/include/asm/xor_avx.h +++ b/arch/x86/include/asm/xor_avx.h | |||
@@ -20,32 +20,6 @@ | |||
20 | #include <linux/compiler.h> | 20 | #include <linux/compiler.h> |
21 | #include <asm/i387.h> | 21 | #include <asm/i387.h> |
22 | 22 | ||
23 | #define ALIGN32 __aligned(32) | ||
24 | |||
25 | #define YMM_SAVED_REGS 4 | ||
26 | |||
27 | #define YMMS_SAVE \ | ||
28 | do { \ | ||
29 | preempt_disable(); \ | ||
30 | cr0 = read_cr0(); \ | ||
31 | clts(); \ | ||
32 | asm volatile("vmovaps %%ymm0, %0" : "=m" (ymm_save[0]) : : "memory"); \ | ||
33 | asm volatile("vmovaps %%ymm1, %0" : "=m" (ymm_save[32]) : : "memory"); \ | ||
34 | asm volatile("vmovaps %%ymm2, %0" : "=m" (ymm_save[64]) : : "memory"); \ | ||
35 | asm volatile("vmovaps %%ymm3, %0" : "=m" (ymm_save[96]) : : "memory"); \ | ||
36 | } while (0); | ||
37 | |||
38 | #define YMMS_RESTORE \ | ||
39 | do { \ | ||
40 | asm volatile("sfence" : : : "memory"); \ | ||
41 | asm volatile("vmovaps %0, %%ymm3" : : "m" (ymm_save[96])); \ | ||
42 | asm volatile("vmovaps %0, %%ymm2" : : "m" (ymm_save[64])); \ | ||
43 | asm volatile("vmovaps %0, %%ymm1" : : "m" (ymm_save[32])); \ | ||
44 | asm volatile("vmovaps %0, %%ymm0" : : "m" (ymm_save[0])); \ | ||
45 | write_cr0(cr0); \ | ||
46 | preempt_enable(); \ | ||
47 | } while (0); | ||
48 | |||
49 | #define BLOCK4(i) \ | 23 | #define BLOCK4(i) \ |
50 | BLOCK(32 * i, 0) \ | 24 | BLOCK(32 * i, 0) \ |
51 | BLOCK(32 * (i + 1), 1) \ | 25 | BLOCK(32 * (i + 1), 1) \ |
@@ -60,10 +34,9 @@ do { \ | |||
60 | 34 | ||
61 | static void xor_avx_2(unsigned long bytes, unsigned long *p0, unsigned long *p1) | 35 | static void xor_avx_2(unsigned long bytes, unsigned long *p0, unsigned long *p1) |
62 | { | 36 | { |
63 | unsigned long cr0, lines = bytes >> 9; | 37 | unsigned long lines = bytes >> 9; |
64 | char ymm_save[32 * YMM_SAVED_REGS] ALIGN32; | ||
65 | 38 | ||
66 | YMMS_SAVE | 39 | kernel_fpu_begin(); |
67 | 40 | ||
68 | while (lines--) { | 41 | while (lines--) { |
69 | #undef BLOCK | 42 | #undef BLOCK |
@@ -82,16 +55,15 @@ do { \ | |||
82 | p1 = (unsigned long *)((uintptr_t)p1 + 512); | 55 | p1 = (unsigned long *)((uintptr_t)p1 + 512); |
83 | } | 56 | } |
84 | 57 | ||
85 | YMMS_RESTORE | 58 | kernel_fpu_end(); |
86 | } | 59 | } |
87 | 60 | ||
88 | static void xor_avx_3(unsigned long bytes, unsigned long *p0, unsigned long *p1, | 61 | static void xor_avx_3(unsigned long bytes, unsigned long *p0, unsigned long *p1, |
89 | unsigned long *p2) | 62 | unsigned long *p2) |
90 | { | 63 | { |
91 | unsigned long cr0, lines = bytes >> 9; | 64 | unsigned long lines = bytes >> 9; |
92 | char ymm_save[32 * YMM_SAVED_REGS] ALIGN32; | ||
93 | 65 | ||
94 | YMMS_SAVE | 66 | kernel_fpu_begin(); |
95 | 67 | ||
96 | while (lines--) { | 68 | while (lines--) { |
97 | #undef BLOCK | 69 | #undef BLOCK |
@@ -113,16 +85,15 @@ do { \ | |||
113 | p2 = (unsigned long *)((uintptr_t)p2 + 512); | 85 | p2 = (unsigned long *)((uintptr_t)p2 + 512); |
114 | } | 86 | } |
115 | 87 | ||
116 | YMMS_RESTORE | 88 | kernel_fpu_end(); |
117 | } | 89 | } |
118 | 90 | ||
119 | static void xor_avx_4(unsigned long bytes, unsigned long *p0, unsigned long *p1, | 91 | static void xor_avx_4(unsigned long bytes, unsigned long *p0, unsigned long *p1, |
120 | unsigned long *p2, unsigned long *p3) | 92 | unsigned long *p2, unsigned long *p3) |
121 | { | 93 | { |
122 | unsigned long cr0, lines = bytes >> 9; | 94 | unsigned long lines = bytes >> 9; |
123 | char ymm_save[32 * YMM_SAVED_REGS] ALIGN32; | ||
124 | 95 | ||
125 | YMMS_SAVE | 96 | kernel_fpu_begin(); |
126 | 97 | ||
127 | while (lines--) { | 98 | while (lines--) { |
128 | #undef BLOCK | 99 | #undef BLOCK |
@@ -147,16 +118,15 @@ do { \ | |||
147 | p3 = (unsigned long *)((uintptr_t)p3 + 512); | 118 | p3 = (unsigned long *)((uintptr_t)p3 + 512); |
148 | } | 119 | } |
149 | 120 | ||
150 | YMMS_RESTORE | 121 | kernel_fpu_end(); |
151 | } | 122 | } |
152 | 123 | ||
153 | static void xor_avx_5(unsigned long bytes, unsigned long *p0, unsigned long *p1, | 124 | static void xor_avx_5(unsigned long bytes, unsigned long *p0, unsigned long *p1, |
154 | unsigned long *p2, unsigned long *p3, unsigned long *p4) | 125 | unsigned long *p2, unsigned long *p3, unsigned long *p4) |
155 | { | 126 | { |
156 | unsigned long cr0, lines = bytes >> 9; | 127 | unsigned long lines = bytes >> 9; |
157 | char ymm_save[32 * YMM_SAVED_REGS] ALIGN32; | ||
158 | 128 | ||
159 | YMMS_SAVE | 129 | kernel_fpu_begin(); |
160 | 130 | ||
161 | while (lines--) { | 131 | while (lines--) { |
162 | #undef BLOCK | 132 | #undef BLOCK |
@@ -184,7 +154,7 @@ do { \ | |||
184 | p4 = (unsigned long *)((uintptr_t)p4 + 512); | 154 | p4 = (unsigned long *)((uintptr_t)p4 + 512); |
185 | } | 155 | } |
186 | 156 | ||
187 | YMMS_RESTORE | 157 | kernel_fpu_end(); |
188 | } | 158 | } |
189 | 159 | ||
190 | static struct xor_block_template xor_block_avx = { | 160 | static struct xor_block_template xor_block_avx = { |
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h index 8a1b6f9b594a..2ddee1b87793 100644 --- a/arch/x86/include/asm/xsave.h +++ b/arch/x86/include/asm/xsave.h | |||
@@ -34,17 +34,14 @@ | |||
34 | extern unsigned int xstate_size; | 34 | extern unsigned int xstate_size; |
35 | extern u64 pcntxt_mask; | 35 | extern u64 pcntxt_mask; |
36 | extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; | 36 | extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; |
37 | extern struct xsave_struct *init_xstate_buf; | ||
37 | 38 | ||
38 | extern void xsave_init(void); | 39 | extern void xsave_init(void); |
39 | extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask); | 40 | extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask); |
40 | extern int init_fpu(struct task_struct *child); | 41 | extern int init_fpu(struct task_struct *child); |
41 | extern int check_for_xstate(struct i387_fxsave_struct __user *buf, | ||
42 | void __user *fpstate, | ||
43 | struct _fpx_sw_bytes *sw); | ||
44 | 42 | ||
45 | static inline int fpu_xrstor_checking(struct fpu *fpu) | 43 | static inline int fpu_xrstor_checking(struct xsave_struct *fx) |
46 | { | 44 | { |
47 | struct xsave_struct *fx = &fpu->state->xsave; | ||
48 | int err; | 45 | int err; |
49 | 46 | ||
50 | asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" | 47 | asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" |
@@ -69,8 +66,7 @@ static inline int xsave_user(struct xsave_struct __user *buf) | |||
69 | * Clear the xsave header first, so that reserved fields are | 66 | * Clear the xsave header first, so that reserved fields are |
70 | * initialized to zero. | 67 | * initialized to zero. |
71 | */ | 68 | */ |
72 | err = __clear_user(&buf->xsave_hdr, | 69 | err = __clear_user(&buf->xsave_hdr, sizeof(buf->xsave_hdr)); |
73 | sizeof(struct xsave_hdr_struct)); | ||
74 | if (unlikely(err)) | 70 | if (unlikely(err)) |
75 | return -EFAULT; | 71 | return -EFAULT; |
76 | 72 | ||
@@ -84,9 +80,6 @@ static inline int xsave_user(struct xsave_struct __user *buf) | |||
84 | : [err] "=r" (err) | 80 | : [err] "=r" (err) |
85 | : "D" (buf), "a" (-1), "d" (-1), "0" (0) | 81 | : "D" (buf), "a" (-1), "d" (-1), "0" (0) |
86 | : "memory"); | 82 | : "memory"); |
87 | if (unlikely(err) && __clear_user(buf, xstate_size)) | ||
88 | err = -EFAULT; | ||
89 | /* No need to clear here because the caller clears USED_MATH */ | ||
90 | return err; | 83 | return err; |
91 | } | 84 | } |
92 | 85 | ||
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 8215e5652d97..8d7a619718b5 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -100,6 +100,8 @@ obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o | |||
100 | obj-$(CONFIG_OF) += devicetree.o | 100 | obj-$(CONFIG_OF) += devicetree.o |
101 | obj-$(CONFIG_UPROBES) += uprobes.o | 101 | obj-$(CONFIG_UPROBES) += uprobes.o |
102 | 102 | ||
103 | obj-$(CONFIG_PERF_EVENTS) += perf_regs.o | ||
104 | |||
103 | ### | 105 | ### |
104 | # 64 bit specific files | 106 | # 64 bit specific files |
105 | ifeq ($(CONFIG_X86_64),y) | 107 | ifeq ($(CONFIG_X86_64),y) |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index b2297e58c6ed..e651f7a589ac 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -656,7 +656,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) | |||
656 | acpi_register_lapic(physid, ACPI_MADT_ENABLED); | 656 | acpi_register_lapic(physid, ACPI_MADT_ENABLED); |
657 | 657 | ||
658 | /* | 658 | /* |
659 | * If mp_register_lapic successfully generates a new logical cpu | 659 | * If acpi_register_lapic successfully generates a new logical cpu |
660 | * number, then the following will get us exactly what was mapped | 660 | * number, then the following will get us exactly what was mapped |
661 | */ | 661 | */ |
662 | cpumask_andnot(new_map, cpu_present_mask, tmp_map); | 662 | cpumask_andnot(new_map, cpu_present_mask, tmp_map); |
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index ced4534baed5..ef5ccca79a6c 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -23,19 +23,6 @@ | |||
23 | 23 | ||
24 | #define MAX_PATCH_LEN (255-1) | 24 | #define MAX_PATCH_LEN (255-1) |
25 | 25 | ||
26 | #ifdef CONFIG_HOTPLUG_CPU | ||
27 | static int smp_alt_once; | ||
28 | |||
29 | static int __init bootonly(char *str) | ||
30 | { | ||
31 | smp_alt_once = 1; | ||
32 | return 1; | ||
33 | } | ||
34 | __setup("smp-alt-boot", bootonly); | ||
35 | #else | ||
36 | #define smp_alt_once 1 | ||
37 | #endif | ||
38 | |||
39 | static int __initdata_or_module debug_alternative; | 26 | static int __initdata_or_module debug_alternative; |
40 | 27 | ||
41 | static int __init debug_alt(char *str) | 28 | static int __init debug_alt(char *str) |
@@ -317,7 +304,7 @@ static void alternatives_smp_lock(const s32 *start, const s32 *end, | |||
317 | /* turn DS segment override prefix into lock prefix */ | 304 | /* turn DS segment override prefix into lock prefix */ |
318 | if (*ptr == 0x3e) | 305 | if (*ptr == 0x3e) |
319 | text_poke(ptr, ((unsigned char []){0xf0}), 1); | 306 | text_poke(ptr, ((unsigned char []){0xf0}), 1); |
320 | }; | 307 | } |
321 | mutex_unlock(&text_mutex); | 308 | mutex_unlock(&text_mutex); |
322 | } | 309 | } |
323 | 310 | ||
@@ -326,9 +313,6 @@ static void alternatives_smp_unlock(const s32 *start, const s32 *end, | |||
326 | { | 313 | { |
327 | const s32 *poff; | 314 | const s32 *poff; |
328 | 315 | ||
329 | if (noreplace_smp) | ||
330 | return; | ||
331 | |||
332 | mutex_lock(&text_mutex); | 316 | mutex_lock(&text_mutex); |
333 | for (poff = start; poff < end; poff++) { | 317 | for (poff = start; poff < end; poff++) { |
334 | u8 *ptr = (u8 *)poff + *poff; | 318 | u8 *ptr = (u8 *)poff + *poff; |
@@ -338,7 +322,7 @@ static void alternatives_smp_unlock(const s32 *start, const s32 *end, | |||
338 | /* turn lock prefix into DS segment override prefix */ | 322 | /* turn lock prefix into DS segment override prefix */ |
339 | if (*ptr == 0xf0) | 323 | if (*ptr == 0xf0) |
340 | text_poke(ptr, ((unsigned char []){0x3E}), 1); | 324 | text_poke(ptr, ((unsigned char []){0x3E}), 1); |
341 | }; | 325 | } |
342 | mutex_unlock(&text_mutex); | 326 | mutex_unlock(&text_mutex); |
343 | } | 327 | } |
344 | 328 | ||
@@ -359,7 +343,7 @@ struct smp_alt_module { | |||
359 | }; | 343 | }; |
360 | static LIST_HEAD(smp_alt_modules); | 344 | static LIST_HEAD(smp_alt_modules); |
361 | static DEFINE_MUTEX(smp_alt); | 345 | static DEFINE_MUTEX(smp_alt); |
362 | static int smp_mode = 1; /* protected by smp_alt */ | 346 | static bool uniproc_patched = false; /* protected by smp_alt */ |
363 | 347 | ||
364 | void __init_or_module alternatives_smp_module_add(struct module *mod, | 348 | void __init_or_module alternatives_smp_module_add(struct module *mod, |
365 | char *name, | 349 | char *name, |
@@ -368,19 +352,18 @@ void __init_or_module alternatives_smp_module_add(struct module *mod, | |||
368 | { | 352 | { |
369 | struct smp_alt_module *smp; | 353 | struct smp_alt_module *smp; |
370 | 354 | ||
371 | if (noreplace_smp) | 355 | mutex_lock(&smp_alt); |
372 | return; | 356 | if (!uniproc_patched) |
357 | goto unlock; | ||
373 | 358 | ||
374 | if (smp_alt_once) { | 359 | if (num_possible_cpus() == 1) |
375 | if (boot_cpu_has(X86_FEATURE_UP)) | 360 | /* Don't bother remembering, we'll never have to undo it. */ |
376 | alternatives_smp_unlock(locks, locks_end, | 361 | goto smp_unlock; |
377 | text, text_end); | ||
378 | return; | ||
379 | } | ||
380 | 362 | ||
381 | smp = kzalloc(sizeof(*smp), GFP_KERNEL); | 363 | smp = kzalloc(sizeof(*smp), GFP_KERNEL); |
382 | if (NULL == smp) | 364 | if (NULL == smp) |
383 | return; /* we'll run the (safe but slow) SMP code then ... */ | 365 | /* we'll run the (safe but slow) SMP code then ... */ |
366 | goto unlock; | ||
384 | 367 | ||
385 | smp->mod = mod; | 368 | smp->mod = mod; |
386 | smp->name = name; | 369 | smp->name = name; |
@@ -392,11 +375,10 @@ void __init_or_module alternatives_smp_module_add(struct module *mod, | |||
392 | __func__, smp->locks, smp->locks_end, | 375 | __func__, smp->locks, smp->locks_end, |
393 | smp->text, smp->text_end, smp->name); | 376 | smp->text, smp->text_end, smp->name); |
394 | 377 | ||
395 | mutex_lock(&smp_alt); | ||
396 | list_add_tail(&smp->next, &smp_alt_modules); | 378 | list_add_tail(&smp->next, &smp_alt_modules); |
397 | if (boot_cpu_has(X86_FEATURE_UP)) | 379 | smp_unlock: |
398 | alternatives_smp_unlock(smp->locks, smp->locks_end, | 380 | alternatives_smp_unlock(locks, locks_end, text, text_end); |
399 | smp->text, smp->text_end); | 381 | unlock: |
400 | mutex_unlock(&smp_alt); | 382 | mutex_unlock(&smp_alt); |
401 | } | 383 | } |
402 | 384 | ||
@@ -404,24 +386,18 @@ void __init_or_module alternatives_smp_module_del(struct module *mod) | |||
404 | { | 386 | { |
405 | struct smp_alt_module *item; | 387 | struct smp_alt_module *item; |
406 | 388 | ||
407 | if (smp_alt_once || noreplace_smp) | ||
408 | return; | ||
409 | |||
410 | mutex_lock(&smp_alt); | 389 | mutex_lock(&smp_alt); |
411 | list_for_each_entry(item, &smp_alt_modules, next) { | 390 | list_for_each_entry(item, &smp_alt_modules, next) { |
412 | if (mod != item->mod) | 391 | if (mod != item->mod) |
413 | continue; | 392 | continue; |
414 | list_del(&item->next); | 393 | list_del(&item->next); |
415 | mutex_unlock(&smp_alt); | ||
416 | DPRINTK("%s: %s\n", __func__, item->name); | ||
417 | kfree(item); | 394 | kfree(item); |
418 | return; | 395 | break; |
419 | } | 396 | } |
420 | mutex_unlock(&smp_alt); | 397 | mutex_unlock(&smp_alt); |
421 | } | 398 | } |
422 | 399 | ||
423 | bool skip_smp_alternatives; | 400 | void alternatives_enable_smp(void) |
424 | void alternatives_smp_switch(int smp) | ||
425 | { | 401 | { |
426 | struct smp_alt_module *mod; | 402 | struct smp_alt_module *mod; |
427 | 403 | ||
@@ -436,34 +412,21 @@ void alternatives_smp_switch(int smp) | |||
436 | pr_info("lockdep: fixing up alternatives\n"); | 412 | pr_info("lockdep: fixing up alternatives\n"); |
437 | #endif | 413 | #endif |
438 | 414 | ||
439 | if (noreplace_smp || smp_alt_once || skip_smp_alternatives) | 415 | /* Why bother if there are no other CPUs? */ |
440 | return; | 416 | BUG_ON(num_possible_cpus() == 1); |
441 | BUG_ON(!smp && (num_online_cpus() > 1)); | ||
442 | 417 | ||
443 | mutex_lock(&smp_alt); | 418 | mutex_lock(&smp_alt); |
444 | 419 | ||
445 | /* | 420 | if (uniproc_patched) { |
446 | * Avoid unnecessary switches because it forces JIT based VMs to | ||
447 | * throw away all cached translations, which can be quite costly. | ||
448 | */ | ||
449 | if (smp == smp_mode) { | ||
450 | /* nothing */ | ||
451 | } else if (smp) { | ||
452 | pr_info("switching to SMP code\n"); | 421 | pr_info("switching to SMP code\n"); |
422 | BUG_ON(num_online_cpus() != 1); | ||
453 | clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); | 423 | clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); |
454 | clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP); | 424 | clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP); |
455 | list_for_each_entry(mod, &smp_alt_modules, next) | 425 | list_for_each_entry(mod, &smp_alt_modules, next) |
456 | alternatives_smp_lock(mod->locks, mod->locks_end, | 426 | alternatives_smp_lock(mod->locks, mod->locks_end, |
457 | mod->text, mod->text_end); | 427 | mod->text, mod->text_end); |
458 | } else { | 428 | uniproc_patched = false; |
459 | pr_info("switching to UP code\n"); | ||
460 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); | ||
461 | set_cpu_cap(&cpu_data(0), X86_FEATURE_UP); | ||
462 | list_for_each_entry(mod, &smp_alt_modules, next) | ||
463 | alternatives_smp_unlock(mod->locks, mod->locks_end, | ||
464 | mod->text, mod->text_end); | ||
465 | } | 429 | } |
466 | smp_mode = smp; | ||
467 | mutex_unlock(&smp_alt); | 430 | mutex_unlock(&smp_alt); |
468 | } | 431 | } |
469 | 432 | ||
@@ -540,40 +503,22 @@ void __init alternative_instructions(void) | |||
540 | 503 | ||
541 | apply_alternatives(__alt_instructions, __alt_instructions_end); | 504 | apply_alternatives(__alt_instructions, __alt_instructions_end); |
542 | 505 | ||
543 | /* switch to patch-once-at-boottime-only mode and free the | ||
544 | * tables in case we know the number of CPUs will never ever | ||
545 | * change */ | ||
546 | #ifdef CONFIG_HOTPLUG_CPU | ||
547 | if (num_possible_cpus() < 2) | ||
548 | smp_alt_once = 1; | ||
549 | #endif | ||
550 | |||
551 | #ifdef CONFIG_SMP | 506 | #ifdef CONFIG_SMP |
552 | if (smp_alt_once) { | 507 | /* Patch to UP if other cpus not imminent. */ |
553 | if (1 == num_possible_cpus()) { | 508 | if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1)) { |
554 | pr_info("switching to UP code\n"); | 509 | uniproc_patched = true; |
555 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); | ||
556 | set_cpu_cap(&cpu_data(0), X86_FEATURE_UP); | ||
557 | |||
558 | alternatives_smp_unlock(__smp_locks, __smp_locks_end, | ||
559 | _text, _etext); | ||
560 | } | ||
561 | } else { | ||
562 | alternatives_smp_module_add(NULL, "core kernel", | 510 | alternatives_smp_module_add(NULL, "core kernel", |
563 | __smp_locks, __smp_locks_end, | 511 | __smp_locks, __smp_locks_end, |
564 | _text, _etext); | 512 | _text, _etext); |
565 | |||
566 | /* Only switch to UP mode if we don't immediately boot others */ | ||
567 | if (num_present_cpus() == 1 || setup_max_cpus <= 1) | ||
568 | alternatives_smp_switch(0); | ||
569 | } | 513 | } |
570 | #endif | ||
571 | apply_paravirt(__parainstructions, __parainstructions_end); | ||
572 | 514 | ||
573 | if (smp_alt_once) | 515 | if (!uniproc_patched || num_possible_cpus() == 1) |
574 | free_init_pages("SMP alternatives", | 516 | free_init_pages("SMP alternatives", |
575 | (unsigned long)__smp_locks, | 517 | (unsigned long)__smp_locks, |
576 | (unsigned long)__smp_locks_end); | 518 | (unsigned long)__smp_locks_end); |
519 | #endif | ||
520 | |||
521 | apply_paravirt(__parainstructions, __parainstructions_end); | ||
577 | 522 | ||
578 | restart_nmi(); | 523 | restart_nmi(); |
579 | } | 524 | } |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 24deb3082328..b17416e72fbd 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -1934,7 +1934,7 @@ void smp_error_interrupt(struct pt_regs *regs) | |||
1934 | apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); | 1934 | apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); |
1935 | i++; | 1935 | i++; |
1936 | v1 >>= 1; | 1936 | v1 >>= 1; |
1937 | }; | 1937 | } |
1938 | 1938 | ||
1939 | apic_printk(APIC_DEBUG, KERN_CONT "\n"); | 1939 | apic_printk(APIC_DEBUG, KERN_CONT "\n"); |
1940 | 1940 | ||
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 9d92e19039f0..f7e98a2c0d12 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -737,6 +737,72 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, | |||
737 | } | 737 | } |
738 | #endif | 738 | #endif |
739 | 739 | ||
740 | static void __cpuinit cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c) | ||
741 | { | ||
742 | if (!cpu_has_invlpg) | ||
743 | return; | ||
744 | |||
745 | tlb_flushall_shift = 5; | ||
746 | |||
747 | if (c->x86 <= 0x11) | ||
748 | tlb_flushall_shift = 4; | ||
749 | } | ||
750 | |||
751 | static void __cpuinit cpu_detect_tlb_amd(struct cpuinfo_x86 *c) | ||
752 | { | ||
753 | u32 ebx, eax, ecx, edx; | ||
754 | u16 mask = 0xfff; | ||
755 | |||
756 | if (c->x86 < 0xf) | ||
757 | return; | ||
758 | |||
759 | if (c->extended_cpuid_level < 0x80000006) | ||
760 | return; | ||
761 | |||
762 | cpuid(0x80000006, &eax, &ebx, &ecx, &edx); | ||
763 | |||
764 | tlb_lld_4k[ENTRIES] = (ebx >> 16) & mask; | ||
765 | tlb_lli_4k[ENTRIES] = ebx & mask; | ||
766 | |||
767 | /* | ||
768 | * K8 doesn't have 2M/4M entries in the L2 TLB so read out the L1 TLB | ||
769 | * characteristics from the CPUID function 0x80000005 instead. | ||
770 | */ | ||
771 | if (c->x86 == 0xf) { | ||
772 | cpuid(0x80000005, &eax, &ebx, &ecx, &edx); | ||
773 | mask = 0xff; | ||
774 | } | ||
775 | |||
776 | /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ | ||
777 | if (!((eax >> 16) & mask)) { | ||
778 | u32 a, b, c, d; | ||
779 | |||
780 | cpuid(0x80000005, &a, &b, &c, &d); | ||
781 | tlb_lld_2m[ENTRIES] = (a >> 16) & 0xff; | ||
782 | } else { | ||
783 | tlb_lld_2m[ENTRIES] = (eax >> 16) & mask; | ||
784 | } | ||
785 | |||
786 | /* a 4M entry uses two 2M entries */ | ||
787 | tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1; | ||
788 | |||
789 | /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */ | ||
790 | if (!(eax & mask)) { | ||
791 | /* Erratum 658 */ | ||
792 | if (c->x86 == 0x15 && c->x86_model <= 0x1f) { | ||
793 | tlb_lli_2m[ENTRIES] = 1024; | ||
794 | } else { | ||
795 | cpuid(0x80000005, &eax, &ebx, &ecx, &edx); | ||
796 | tlb_lli_2m[ENTRIES] = eax & 0xff; | ||
797 | } | ||
798 | } else | ||
799 | tlb_lli_2m[ENTRIES] = eax & mask; | ||
800 | |||
801 | tlb_lli_4m[ENTRIES] = tlb_lli_2m[ENTRIES] >> 1; | ||
802 | |||
803 | cpu_set_tlb_flushall_shift(c); | ||
804 | } | ||
805 | |||
740 | static const struct cpu_dev __cpuinitconst amd_cpu_dev = { | 806 | static const struct cpu_dev __cpuinitconst amd_cpu_dev = { |
741 | .c_vendor = "AMD", | 807 | .c_vendor = "AMD", |
742 | .c_ident = { "AuthenticAMD" }, | 808 | .c_ident = { "AuthenticAMD" }, |
@@ -756,6 +822,7 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = { | |||
756 | .c_size_cache = amd_size_cache, | 822 | .c_size_cache = amd_size_cache, |
757 | #endif | 823 | #endif |
758 | .c_early_init = early_init_amd, | 824 | .c_early_init = early_init_amd, |
825 | .c_detect_tlb = cpu_detect_tlb_amd, | ||
759 | .c_bsp_init = bsp_init_amd, | 826 | .c_bsp_init = bsp_init_amd, |
760 | .c_init = init_amd, | 827 | .c_init = init_amd, |
761 | .c_x86_vendor = X86_VENDOR_AMD, | 828 | .c_x86_vendor = X86_VENDOR_AMD, |
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index c97bb7b5a9f8..d0e910da16c5 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c | |||
@@ -165,10 +165,15 @@ void __init check_bugs(void) | |||
165 | print_cpu_info(&boot_cpu_data); | 165 | print_cpu_info(&boot_cpu_data); |
166 | #endif | 166 | #endif |
167 | check_config(); | 167 | check_config(); |
168 | check_fpu(); | ||
169 | check_hlt(); | 168 | check_hlt(); |
170 | check_popad(); | 169 | check_popad(); |
171 | init_utsname()->machine[1] = | 170 | init_utsname()->machine[1] = |
172 | '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); | 171 | '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); |
173 | alternative_instructions(); | 172 | alternative_instructions(); |
173 | |||
174 | /* | ||
175 | * kernel_fpu_begin/end() in check_fpu() relies on the patched | ||
176 | * alternative instructions. | ||
177 | */ | ||
178 | check_fpu(); | ||
174 | } | 179 | } |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index a5fbc3c5fccc..532691b6c8fe 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -476,7 +476,7 @@ void __cpuinit cpu_detect_tlb(struct cpuinfo_x86 *c) | |||
476 | 476 | ||
477 | printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ | 477 | printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ |
478 | "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ | 478 | "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \ |
479 | "tlb_flushall_shift is 0x%x\n", | 479 | "tlb_flushall_shift: %d\n", |
480 | tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES], | 480 | tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES], |
481 | tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES], | 481 | tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES], |
482 | tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES], | 482 | tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES], |
@@ -942,8 +942,7 @@ void __init identify_boot_cpu(void) | |||
942 | #else | 942 | #else |
943 | vgetcpu_set_mode(); | 943 | vgetcpu_set_mode(); |
944 | #endif | 944 | #endif |
945 | if (boot_cpu_data.cpuid_level >= 2) | 945 | cpu_detect_tlb(&boot_cpu_data); |
946 | cpu_detect_tlb(&boot_cpu_data); | ||
947 | } | 946 | } |
948 | 947 | ||
949 | void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) | 948 | void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) |
@@ -1023,14 +1022,16 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) | |||
1023 | printk(KERN_CONT "%s ", vendor); | 1022 | printk(KERN_CONT "%s ", vendor); |
1024 | 1023 | ||
1025 | if (c->x86_model_id[0]) | 1024 | if (c->x86_model_id[0]) |
1026 | printk(KERN_CONT "%s", c->x86_model_id); | 1025 | printk(KERN_CONT "%s", strim(c->x86_model_id)); |
1027 | else | 1026 | else |
1028 | printk(KERN_CONT "%d86", c->x86); | 1027 | printk(KERN_CONT "%d86", c->x86); |
1029 | 1028 | ||
1029 | printk(KERN_CONT " (fam: %02x, model: %02x", c->x86, c->x86_model); | ||
1030 | |||
1030 | if (c->x86_mask || c->cpuid_level >= 0) | 1031 | if (c->x86_mask || c->cpuid_level >= 0) |
1031 | printk(KERN_CONT " stepping %02x\n", c->x86_mask); | 1032 | printk(KERN_CONT ", stepping: %02x)\n", c->x86_mask); |
1032 | else | 1033 | else |
1033 | printk(KERN_CONT "\n"); | 1034 | printk(KERN_CONT ")\n"); |
1034 | 1035 | ||
1035 | print_cpu_msr(c); | 1036 | print_cpu_msr(c); |
1036 | } | 1037 | } |
@@ -1116,8 +1117,6 @@ void syscall_init(void) | |||
1116 | X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL); | 1117 | X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL); |
1117 | } | 1118 | } |
1118 | 1119 | ||
1119 | unsigned long kernel_eflags; | ||
1120 | |||
1121 | /* | 1120 | /* |
1122 | * Copies of the original ist values from the tss are only accessed during | 1121 | * Copies of the original ist values from the tss are only accessed during |
1123 | * debugging, no special alignment required. | 1122 | * debugging, no special alignment required. |
@@ -1297,9 +1296,6 @@ void __cpuinit cpu_init(void) | |||
1297 | dbg_restore_debug_regs(); | 1296 | dbg_restore_debug_regs(); |
1298 | 1297 | ||
1299 | fpu_init(); | 1298 | fpu_init(); |
1300 | xsave_init(); | ||
1301 | |||
1302 | raw_local_save_flags(kernel_eflags); | ||
1303 | 1299 | ||
1304 | if (is_uv_system()) | 1300 | if (is_uv_system()) |
1305 | uv_cpu_init(); | 1301 | uv_cpu_init(); |
@@ -1352,6 +1348,5 @@ void __cpuinit cpu_init(void) | |||
1352 | dbg_restore_debug_regs(); | 1348 | dbg_restore_debug_regs(); |
1353 | 1349 | ||
1354 | fpu_init(); | 1350 | fpu_init(); |
1355 | xsave_init(); | ||
1356 | } | 1351 | } |
1357 | #endif | 1352 | #endif |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 0a4ce2980a5a..198e019a531a 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -648,6 +648,10 @@ static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c) | |||
648 | int i, j, n; | 648 | int i, j, n; |
649 | unsigned int regs[4]; | 649 | unsigned int regs[4]; |
650 | unsigned char *desc = (unsigned char *)regs; | 650 | unsigned char *desc = (unsigned char *)regs; |
651 | |||
652 | if (c->cpuid_level < 2) | ||
653 | return; | ||
654 | |||
651 | /* Number of times to iterate */ | 655 | /* Number of times to iterate */ |
652 | n = cpuid_eax(2) & 0xFF; | 656 | n = cpuid_eax(2) & 0xFF; |
653 | 657 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index fc4beb393577..ddc72f839332 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c | |||
@@ -78,6 +78,7 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs) | |||
78 | } | 78 | } |
79 | 79 | ||
80 | static cpumask_var_t mce_inject_cpumask; | 80 | static cpumask_var_t mce_inject_cpumask; |
81 | static DEFINE_MUTEX(mce_inject_mutex); | ||
81 | 82 | ||
82 | static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs) | 83 | static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs) |
83 | { | 84 | { |
@@ -194,7 +195,11 @@ static void raise_mce(struct mce *m) | |||
194 | put_online_cpus(); | 195 | put_online_cpus(); |
195 | } else | 196 | } else |
196 | #endif | 197 | #endif |
198 | { | ||
199 | preempt_disable(); | ||
197 | raise_local(); | 200 | raise_local(); |
201 | preempt_enable(); | ||
202 | } | ||
198 | } | 203 | } |
199 | 204 | ||
200 | /* Error injection interface */ | 205 | /* Error injection interface */ |
@@ -225,7 +230,10 @@ static ssize_t mce_write(struct file *filp, const char __user *ubuf, | |||
225 | * so do it a jiffie or two later everywhere. | 230 | * so do it a jiffie or two later everywhere. |
226 | */ | 231 | */ |
227 | schedule_timeout(2); | 232 | schedule_timeout(2); |
233 | |||
234 | mutex_lock(&mce_inject_mutex); | ||
228 | raise_mce(&m); | 235 | raise_mce(&m); |
236 | mutex_unlock(&mce_inject_mutex); | ||
229 | return usize; | 237 | return usize; |
230 | } | 238 | } |
231 | 239 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h index ed44c8a65858..6a05c1d327a9 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-internal.h +++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h | |||
@@ -28,6 +28,18 @@ extern int mce_ser; | |||
28 | 28 | ||
29 | extern struct mce_bank *mce_banks; | 29 | extern struct mce_bank *mce_banks; |
30 | 30 | ||
31 | #ifdef CONFIG_X86_MCE_INTEL | ||
32 | unsigned long mce_intel_adjust_timer(unsigned long interval); | ||
33 | void mce_intel_cmci_poll(void); | ||
34 | void mce_intel_hcpu_update(unsigned long cpu); | ||
35 | #else | ||
36 | # define mce_intel_adjust_timer mce_adjust_timer_default | ||
37 | static inline void mce_intel_cmci_poll(void) { } | ||
38 | static inline void mce_intel_hcpu_update(unsigned long cpu) { } | ||
39 | #endif | ||
40 | |||
41 | void mce_timer_kick(unsigned long interval); | ||
42 | |||
31 | #ifdef CONFIG_ACPI_APEI | 43 | #ifdef CONFIG_ACPI_APEI |
32 | int apei_write_mce(struct mce *m); | 44 | int apei_write_mce(struct mce *m); |
33 | ssize_t apei_read_mce(struct mce *m, u64 *record_id); | 45 | ssize_t apei_read_mce(struct mce *m, u64 *record_id); |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 292d0258311c..29e87d3b2843 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -83,6 +83,7 @@ static int mce_dont_log_ce __read_mostly; | |||
83 | int mce_cmci_disabled __read_mostly; | 83 | int mce_cmci_disabled __read_mostly; |
84 | int mce_ignore_ce __read_mostly; | 84 | int mce_ignore_ce __read_mostly; |
85 | int mce_ser __read_mostly; | 85 | int mce_ser __read_mostly; |
86 | int mce_bios_cmci_threshold __read_mostly; | ||
86 | 87 | ||
87 | struct mce_bank *mce_banks __read_mostly; | 88 | struct mce_bank *mce_banks __read_mostly; |
88 | 89 | ||
@@ -1266,6 +1267,14 @@ static unsigned long check_interval = 5 * 60; /* 5 minutes */ | |||
1266 | static DEFINE_PER_CPU(unsigned long, mce_next_interval); /* in jiffies */ | 1267 | static DEFINE_PER_CPU(unsigned long, mce_next_interval); /* in jiffies */ |
1267 | static DEFINE_PER_CPU(struct timer_list, mce_timer); | 1268 | static DEFINE_PER_CPU(struct timer_list, mce_timer); |
1268 | 1269 | ||
1270 | static unsigned long mce_adjust_timer_default(unsigned long interval) | ||
1271 | { | ||
1272 | return interval; | ||
1273 | } | ||
1274 | |||
1275 | static unsigned long (*mce_adjust_timer)(unsigned long interval) = | ||
1276 | mce_adjust_timer_default; | ||
1277 | |||
1269 | static void mce_timer_fn(unsigned long data) | 1278 | static void mce_timer_fn(unsigned long data) |
1270 | { | 1279 | { |
1271 | struct timer_list *t = &__get_cpu_var(mce_timer); | 1280 | struct timer_list *t = &__get_cpu_var(mce_timer); |
@@ -1276,6 +1285,7 @@ static void mce_timer_fn(unsigned long data) | |||
1276 | if (mce_available(__this_cpu_ptr(&cpu_info))) { | 1285 | if (mce_available(__this_cpu_ptr(&cpu_info))) { |
1277 | machine_check_poll(MCP_TIMESTAMP, | 1286 | machine_check_poll(MCP_TIMESTAMP, |
1278 | &__get_cpu_var(mce_poll_banks)); | 1287 | &__get_cpu_var(mce_poll_banks)); |
1288 | mce_intel_cmci_poll(); | ||
1279 | } | 1289 | } |
1280 | 1290 | ||
1281 | /* | 1291 | /* |
@@ -1283,14 +1293,38 @@ static void mce_timer_fn(unsigned long data) | |||
1283 | * polling interval, otherwise increase the polling interval. | 1293 | * polling interval, otherwise increase the polling interval. |
1284 | */ | 1294 | */ |
1285 | iv = __this_cpu_read(mce_next_interval); | 1295 | iv = __this_cpu_read(mce_next_interval); |
1286 | if (mce_notify_irq()) | 1296 | if (mce_notify_irq()) { |
1287 | iv = max(iv / 2, (unsigned long) HZ/100); | 1297 | iv = max(iv / 2, (unsigned long) HZ/100); |
1288 | else | 1298 | } else { |
1289 | iv = min(iv * 2, round_jiffies_relative(check_interval * HZ)); | 1299 | iv = min(iv * 2, round_jiffies_relative(check_interval * HZ)); |
1300 | iv = mce_adjust_timer(iv); | ||
1301 | } | ||
1290 | __this_cpu_write(mce_next_interval, iv); | 1302 | __this_cpu_write(mce_next_interval, iv); |
1303 | /* Might have become 0 after CMCI storm subsided */ | ||
1304 | if (iv) { | ||
1305 | t->expires = jiffies + iv; | ||
1306 | add_timer_on(t, smp_processor_id()); | ||
1307 | } | ||
1308 | } | ||
1291 | 1309 | ||
1292 | t->expires = jiffies + iv; | 1310 | /* |
1293 | add_timer_on(t, smp_processor_id()); | 1311 | * Ensure that the timer is firing in @interval from now. |
1312 | */ | ||
1313 | void mce_timer_kick(unsigned long interval) | ||
1314 | { | ||
1315 | struct timer_list *t = &__get_cpu_var(mce_timer); | ||
1316 | unsigned long when = jiffies + interval; | ||
1317 | unsigned long iv = __this_cpu_read(mce_next_interval); | ||
1318 | |||
1319 | if (timer_pending(t)) { | ||
1320 | if (time_before(when, t->expires)) | ||
1321 | mod_timer_pinned(t, when); | ||
1322 | } else { | ||
1323 | t->expires = round_jiffies(when); | ||
1324 | add_timer_on(t, smp_processor_id()); | ||
1325 | } | ||
1326 | if (interval < iv) | ||
1327 | __this_cpu_write(mce_next_interval, interval); | ||
1294 | } | 1328 | } |
1295 | 1329 | ||
1296 | /* Must not be called in IRQ context where del_timer_sync() can deadlock */ | 1330 | /* Must not be called in IRQ context where del_timer_sync() can deadlock */ |
@@ -1585,6 +1619,7 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) | |||
1585 | switch (c->x86_vendor) { | 1619 | switch (c->x86_vendor) { |
1586 | case X86_VENDOR_INTEL: | 1620 | case X86_VENDOR_INTEL: |
1587 | mce_intel_feature_init(c); | 1621 | mce_intel_feature_init(c); |
1622 | mce_adjust_timer = mce_intel_adjust_timer; | ||
1588 | break; | 1623 | break; |
1589 | case X86_VENDOR_AMD: | 1624 | case X86_VENDOR_AMD: |
1590 | mce_amd_feature_init(c); | 1625 | mce_amd_feature_init(c); |
@@ -1594,23 +1629,28 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) | |||
1594 | } | 1629 | } |
1595 | } | 1630 | } |
1596 | 1631 | ||
1597 | static void __mcheck_cpu_init_timer(void) | 1632 | static void mce_start_timer(unsigned int cpu, struct timer_list *t) |
1598 | { | 1633 | { |
1599 | struct timer_list *t = &__get_cpu_var(mce_timer); | 1634 | unsigned long iv = mce_adjust_timer(check_interval * HZ); |
1600 | unsigned long iv = check_interval * HZ; | ||
1601 | 1635 | ||
1602 | setup_timer(t, mce_timer_fn, smp_processor_id()); | 1636 | __this_cpu_write(mce_next_interval, iv); |
1603 | 1637 | ||
1604 | if (mce_ignore_ce) | 1638 | if (mce_ignore_ce || !iv) |
1605 | return; | 1639 | return; |
1606 | 1640 | ||
1607 | __this_cpu_write(mce_next_interval, iv); | ||
1608 | if (!iv) | ||
1609 | return; | ||
1610 | t->expires = round_jiffies(jiffies + iv); | 1641 | t->expires = round_jiffies(jiffies + iv); |
1611 | add_timer_on(t, smp_processor_id()); | 1642 | add_timer_on(t, smp_processor_id()); |
1612 | } | 1643 | } |
1613 | 1644 | ||
1645 | static void __mcheck_cpu_init_timer(void) | ||
1646 | { | ||
1647 | struct timer_list *t = &__get_cpu_var(mce_timer); | ||
1648 | unsigned int cpu = smp_processor_id(); | ||
1649 | |||
1650 | setup_timer(t, mce_timer_fn, cpu); | ||
1651 | mce_start_timer(cpu, t); | ||
1652 | } | ||
1653 | |||
1614 | /* Handle unconfigured int18 (should never happen) */ | 1654 | /* Handle unconfigured int18 (should never happen) */ |
1615 | static void unexpected_machine_check(struct pt_regs *regs, long error_code) | 1655 | static void unexpected_machine_check(struct pt_regs *regs, long error_code) |
1616 | { | 1656 | { |
@@ -1907,6 +1947,7 @@ static struct miscdevice mce_chrdev_device = { | |||
1907 | * check, or 0 to not wait | 1947 | * check, or 0 to not wait |
1908 | * mce=bootlog Log MCEs from before booting. Disabled by default on AMD. | 1948 | * mce=bootlog Log MCEs from before booting. Disabled by default on AMD. |
1909 | * mce=nobootlog Don't log MCEs from before booting. | 1949 | * mce=nobootlog Don't log MCEs from before booting. |
1950 | * mce=bios_cmci_threshold Don't program the CMCI threshold | ||
1910 | */ | 1951 | */ |
1911 | static int __init mcheck_enable(char *str) | 1952 | static int __init mcheck_enable(char *str) |
1912 | { | 1953 | { |
@@ -1926,6 +1967,8 @@ static int __init mcheck_enable(char *str) | |||
1926 | mce_ignore_ce = 1; | 1967 | mce_ignore_ce = 1; |
1927 | else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog")) | 1968 | else if (!strcmp(str, "bootlog") || !strcmp(str, "nobootlog")) |
1928 | mce_bootlog = (str[0] == 'b'); | 1969 | mce_bootlog = (str[0] == 'b'); |
1970 | else if (!strcmp(str, "bios_cmci_threshold")) | ||
1971 | mce_bios_cmci_threshold = 1; | ||
1929 | else if (isdigit(str[0])) { | 1972 | else if (isdigit(str[0])) { |
1930 | get_option(&str, &tolerant); | 1973 | get_option(&str, &tolerant); |
1931 | if (*str == ',') { | 1974 | if (*str == ',') { |
@@ -2166,6 +2209,11 @@ static struct dev_ext_attribute dev_attr_cmci_disabled = { | |||
2166 | &mce_cmci_disabled | 2209 | &mce_cmci_disabled |
2167 | }; | 2210 | }; |
2168 | 2211 | ||
2212 | static struct dev_ext_attribute dev_attr_bios_cmci_threshold = { | ||
2213 | __ATTR(bios_cmci_threshold, 0444, device_show_int, NULL), | ||
2214 | &mce_bios_cmci_threshold | ||
2215 | }; | ||
2216 | |||
2169 | static struct device_attribute *mce_device_attrs[] = { | 2217 | static struct device_attribute *mce_device_attrs[] = { |
2170 | &dev_attr_tolerant.attr, | 2218 | &dev_attr_tolerant.attr, |
2171 | &dev_attr_check_interval.attr, | 2219 | &dev_attr_check_interval.attr, |
@@ -2174,6 +2222,7 @@ static struct device_attribute *mce_device_attrs[] = { | |||
2174 | &dev_attr_dont_log_ce.attr, | 2222 | &dev_attr_dont_log_ce.attr, |
2175 | &dev_attr_ignore_ce.attr, | 2223 | &dev_attr_ignore_ce.attr, |
2176 | &dev_attr_cmci_disabled.attr, | 2224 | &dev_attr_cmci_disabled.attr, |
2225 | &dev_attr_bios_cmci_threshold.attr, | ||
2177 | NULL | 2226 | NULL |
2178 | }; | 2227 | }; |
2179 | 2228 | ||
@@ -2294,38 +2343,33 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
2294 | unsigned int cpu = (unsigned long)hcpu; | 2343 | unsigned int cpu = (unsigned long)hcpu; |
2295 | struct timer_list *t = &per_cpu(mce_timer, cpu); | 2344 | struct timer_list *t = &per_cpu(mce_timer, cpu); |
2296 | 2345 | ||
2297 | switch (action) { | 2346 | switch (action & ~CPU_TASKS_FROZEN) { |
2298 | case CPU_ONLINE: | 2347 | case CPU_ONLINE: |
2299 | case CPU_ONLINE_FROZEN: | ||
2300 | mce_device_create(cpu); | 2348 | mce_device_create(cpu); |
2301 | if (threshold_cpu_callback) | 2349 | if (threshold_cpu_callback) |
2302 | threshold_cpu_callback(action, cpu); | 2350 | threshold_cpu_callback(action, cpu); |
2303 | break; | 2351 | break; |
2304 | case CPU_DEAD: | 2352 | case CPU_DEAD: |
2305 | case CPU_DEAD_FROZEN: | ||
2306 | if (threshold_cpu_callback) | 2353 | if (threshold_cpu_callback) |
2307 | threshold_cpu_callback(action, cpu); | 2354 | threshold_cpu_callback(action, cpu); |
2308 | mce_device_remove(cpu); | 2355 | mce_device_remove(cpu); |
2356 | mce_intel_hcpu_update(cpu); | ||
2309 | break; | 2357 | break; |
2310 | case CPU_DOWN_PREPARE: | 2358 | case CPU_DOWN_PREPARE: |
2311 | case CPU_DOWN_PREPARE_FROZEN: | ||
2312 | del_timer_sync(t); | ||
2313 | smp_call_function_single(cpu, mce_disable_cpu, &action, 1); | 2359 | smp_call_function_single(cpu, mce_disable_cpu, &action, 1); |
2360 | del_timer_sync(t); | ||
2314 | break; | 2361 | break; |
2315 | case CPU_DOWN_FAILED: | 2362 | case CPU_DOWN_FAILED: |
2316 | case CPU_DOWN_FAILED_FROZEN: | ||
2317 | if (!mce_ignore_ce && check_interval) { | ||
2318 | t->expires = round_jiffies(jiffies + | ||
2319 | per_cpu(mce_next_interval, cpu)); | ||
2320 | add_timer_on(t, cpu); | ||
2321 | } | ||
2322 | smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); | 2363 | smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); |
2364 | mce_start_timer(cpu, t); | ||
2323 | break; | 2365 | break; |
2324 | case CPU_POST_DEAD: | 2366 | } |
2367 | |||
2368 | if (action == CPU_POST_DEAD) { | ||
2325 | /* intentionally ignoring frozen here */ | 2369 | /* intentionally ignoring frozen here */ |
2326 | cmci_rediscover(cpu); | 2370 | cmci_rediscover(cpu); |
2327 | break; | ||
2328 | } | 2371 | } |
2372 | |||
2329 | return NOTIFY_OK; | 2373 | return NOTIFY_OK; |
2330 | } | 2374 | } |
2331 | 2375 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 38e49bc95ffc..5f88abf07e9c 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <asm/msr.h> | 15 | #include <asm/msr.h> |
16 | #include <asm/mce.h> | 16 | #include <asm/mce.h> |
17 | 17 | ||
18 | #include "mce-internal.h" | ||
19 | |||
18 | /* | 20 | /* |
19 | * Support for Intel Correct Machine Check Interrupts. This allows | 21 | * Support for Intel Correct Machine Check Interrupts. This allows |
20 | * the CPU to raise an interrupt when a corrected machine check happened. | 22 | * the CPU to raise an interrupt when a corrected machine check happened. |
@@ -30,7 +32,22 @@ static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned); | |||
30 | */ | 32 | */ |
31 | static DEFINE_RAW_SPINLOCK(cmci_discover_lock); | 33 | static DEFINE_RAW_SPINLOCK(cmci_discover_lock); |
32 | 34 | ||
33 | #define CMCI_THRESHOLD 1 | 35 | #define CMCI_THRESHOLD 1 |
36 | #define CMCI_POLL_INTERVAL (30 * HZ) | ||
37 | #define CMCI_STORM_INTERVAL (1 * HZ) | ||
38 | #define CMCI_STORM_THRESHOLD 15 | ||
39 | |||
40 | static DEFINE_PER_CPU(unsigned long, cmci_time_stamp); | ||
41 | static DEFINE_PER_CPU(unsigned int, cmci_storm_cnt); | ||
42 | static DEFINE_PER_CPU(unsigned int, cmci_storm_state); | ||
43 | |||
44 | enum { | ||
45 | CMCI_STORM_NONE, | ||
46 | CMCI_STORM_ACTIVE, | ||
47 | CMCI_STORM_SUBSIDED, | ||
48 | }; | ||
49 | |||
50 | static atomic_t cmci_storm_on_cpus; | ||
34 | 51 | ||
35 | static int cmci_supported(int *banks) | 52 | static int cmci_supported(int *banks) |
36 | { | 53 | { |
@@ -53,6 +70,93 @@ static int cmci_supported(int *banks) | |||
53 | return !!(cap & MCG_CMCI_P); | 70 | return !!(cap & MCG_CMCI_P); |
54 | } | 71 | } |
55 | 72 | ||
73 | void mce_intel_cmci_poll(void) | ||
74 | { | ||
75 | if (__this_cpu_read(cmci_storm_state) == CMCI_STORM_NONE) | ||
76 | return; | ||
77 | machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned)); | ||
78 | } | ||
79 | |||
80 | void mce_intel_hcpu_update(unsigned long cpu) | ||
81 | { | ||
82 | if (per_cpu(cmci_storm_state, cpu) == CMCI_STORM_ACTIVE) | ||
83 | atomic_dec(&cmci_storm_on_cpus); | ||
84 | |||
85 | per_cpu(cmci_storm_state, cpu) = CMCI_STORM_NONE; | ||
86 | } | ||
87 | |||
88 | unsigned long mce_intel_adjust_timer(unsigned long interval) | ||
89 | { | ||
90 | int r; | ||
91 | |||
92 | if (interval < CMCI_POLL_INTERVAL) | ||
93 | return interval; | ||
94 | |||
95 | switch (__this_cpu_read(cmci_storm_state)) { | ||
96 | case CMCI_STORM_ACTIVE: | ||
97 | /* | ||
98 | * We switch back to interrupt mode once the poll timer has | ||
99 | * silenced itself. That means no events recorded and the | ||
100 | * timer interval is back to our poll interval. | ||
101 | */ | ||
102 | __this_cpu_write(cmci_storm_state, CMCI_STORM_SUBSIDED); | ||
103 | r = atomic_sub_return(1, &cmci_storm_on_cpus); | ||
104 | if (r == 0) | ||
105 | pr_notice("CMCI storm subsided: switching to interrupt mode\n"); | ||
106 | /* FALLTHROUGH */ | ||
107 | |||
108 | case CMCI_STORM_SUBSIDED: | ||
109 | /* | ||
110 | * We wait for all cpus to go back to SUBSIDED | ||
111 | * state. When that happens we switch back to | ||
112 | * interrupt mode. | ||
113 | */ | ||
114 | if (!atomic_read(&cmci_storm_on_cpus)) { | ||
115 | __this_cpu_write(cmci_storm_state, CMCI_STORM_NONE); | ||
116 | cmci_reenable(); | ||
117 | cmci_recheck(); | ||
118 | } | ||
119 | return CMCI_POLL_INTERVAL; | ||
120 | default: | ||
121 | /* | ||
122 | * We have shiny weather. Let the poll do whatever it | ||
123 | * thinks. | ||
124 | */ | ||
125 | return interval; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static bool cmci_storm_detect(void) | ||
130 | { | ||
131 | unsigned int cnt = __this_cpu_read(cmci_storm_cnt); | ||
132 | unsigned long ts = __this_cpu_read(cmci_time_stamp); | ||
133 | unsigned long now = jiffies; | ||
134 | int r; | ||
135 | |||
136 | if (__this_cpu_read(cmci_storm_state) != CMCI_STORM_NONE) | ||
137 | return true; | ||
138 | |||
139 | if (time_before_eq(now, ts + CMCI_STORM_INTERVAL)) { | ||
140 | cnt++; | ||
141 | } else { | ||
142 | cnt = 1; | ||
143 | __this_cpu_write(cmci_time_stamp, now); | ||
144 | } | ||
145 | __this_cpu_write(cmci_storm_cnt, cnt); | ||
146 | |||
147 | if (cnt <= CMCI_STORM_THRESHOLD) | ||
148 | return false; | ||
149 | |||
150 | cmci_clear(); | ||
151 | __this_cpu_write(cmci_storm_state, CMCI_STORM_ACTIVE); | ||
152 | r = atomic_add_return(1, &cmci_storm_on_cpus); | ||
153 | mce_timer_kick(CMCI_POLL_INTERVAL); | ||
154 | |||
155 | if (r == 1) | ||
156 | pr_notice("CMCI storm detected: switching to poll mode\n"); | ||
157 | return true; | ||
158 | } | ||
159 | |||
56 | /* | 160 | /* |
57 | * The interrupt handler. This is called on every event. | 161 | * The interrupt handler. This is called on every event. |
58 | * Just call the poller directly to log any events. | 162 | * Just call the poller directly to log any events. |
@@ -61,33 +165,28 @@ static int cmci_supported(int *banks) | |||
61 | */ | 165 | */ |
62 | static void intel_threshold_interrupt(void) | 166 | static void intel_threshold_interrupt(void) |
63 | { | 167 | { |
168 | if (cmci_storm_detect()) | ||
169 | return; | ||
64 | machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned)); | 170 | machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned)); |
65 | mce_notify_irq(); | 171 | mce_notify_irq(); |
66 | } | 172 | } |
67 | 173 | ||
68 | static void print_update(char *type, int *hdr, int num) | ||
69 | { | ||
70 | if (*hdr == 0) | ||
71 | printk(KERN_INFO "CPU %d MCA banks", smp_processor_id()); | ||
72 | *hdr = 1; | ||
73 | printk(KERN_CONT " %s:%d", type, num); | ||
74 | } | ||
75 | |||
76 | /* | 174 | /* |
77 | * Enable CMCI (Corrected Machine Check Interrupt) for available MCE banks | 175 | * Enable CMCI (Corrected Machine Check Interrupt) for available MCE banks |
78 | * on this CPU. Use the algorithm recommended in the SDM to discover shared | 176 | * on this CPU. Use the algorithm recommended in the SDM to discover shared |
79 | * banks. | 177 | * banks. |
80 | */ | 178 | */ |
81 | static void cmci_discover(int banks, int boot) | 179 | static void cmci_discover(int banks) |
82 | { | 180 | { |
83 | unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned); | 181 | unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned); |
84 | unsigned long flags; | 182 | unsigned long flags; |
85 | int hdr = 0; | ||
86 | int i; | 183 | int i; |
184 | int bios_wrong_thresh = 0; | ||
87 | 185 | ||
88 | raw_spin_lock_irqsave(&cmci_discover_lock, flags); | 186 | raw_spin_lock_irqsave(&cmci_discover_lock, flags); |
89 | for (i = 0; i < banks; i++) { | 187 | for (i = 0; i < banks; i++) { |
90 | u64 val; | 188 | u64 val; |
189 | int bios_zero_thresh = 0; | ||
91 | 190 | ||
92 | if (test_bit(i, owned)) | 191 | if (test_bit(i, owned)) |
93 | continue; | 192 | continue; |
@@ -96,29 +195,52 @@ static void cmci_discover(int banks, int boot) | |||
96 | 195 | ||
97 | /* Already owned by someone else? */ | 196 | /* Already owned by someone else? */ |
98 | if (val & MCI_CTL2_CMCI_EN) { | 197 | if (val & MCI_CTL2_CMCI_EN) { |
99 | if (test_and_clear_bit(i, owned) && !boot) | 198 | clear_bit(i, owned); |
100 | print_update("SHD", &hdr, i); | ||
101 | __clear_bit(i, __get_cpu_var(mce_poll_banks)); | 199 | __clear_bit(i, __get_cpu_var(mce_poll_banks)); |
102 | continue; | 200 | continue; |
103 | } | 201 | } |
104 | 202 | ||
105 | val &= ~MCI_CTL2_CMCI_THRESHOLD_MASK; | 203 | if (!mce_bios_cmci_threshold) { |
106 | val |= MCI_CTL2_CMCI_EN | CMCI_THRESHOLD; | 204 | val &= ~MCI_CTL2_CMCI_THRESHOLD_MASK; |
205 | val |= CMCI_THRESHOLD; | ||
206 | } else if (!(val & MCI_CTL2_CMCI_THRESHOLD_MASK)) { | ||
207 | /* | ||
208 | * If bios_cmci_threshold boot option was specified | ||
209 | * but the threshold is zero, we'll try to initialize | ||
210 | * it to 1. | ||
211 | */ | ||
212 | bios_zero_thresh = 1; | ||
213 | val |= CMCI_THRESHOLD; | ||
214 | } | ||
215 | |||
216 | val |= MCI_CTL2_CMCI_EN; | ||
107 | wrmsrl(MSR_IA32_MCx_CTL2(i), val); | 217 | wrmsrl(MSR_IA32_MCx_CTL2(i), val); |
108 | rdmsrl(MSR_IA32_MCx_CTL2(i), val); | 218 | rdmsrl(MSR_IA32_MCx_CTL2(i), val); |
109 | 219 | ||
110 | /* Did the enable bit stick? -- the bank supports CMCI */ | 220 | /* Did the enable bit stick? -- the bank supports CMCI */ |
111 | if (val & MCI_CTL2_CMCI_EN) { | 221 | if (val & MCI_CTL2_CMCI_EN) { |
112 | if (!test_and_set_bit(i, owned) && !boot) | 222 | set_bit(i, owned); |
113 | print_update("CMCI", &hdr, i); | ||
114 | __clear_bit(i, __get_cpu_var(mce_poll_banks)); | 223 | __clear_bit(i, __get_cpu_var(mce_poll_banks)); |
224 | /* | ||
225 | * We are able to set thresholds for some banks that | ||
226 | * had a threshold of 0. This means the BIOS has not | ||
227 | * set the thresholds properly or does not work with | ||
228 | * this boot option. Note down now and report later. | ||
229 | */ | ||
230 | if (mce_bios_cmci_threshold && bios_zero_thresh && | ||
231 | (val & MCI_CTL2_CMCI_THRESHOLD_MASK)) | ||
232 | bios_wrong_thresh = 1; | ||
115 | } else { | 233 | } else { |
116 | WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks))); | 234 | WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks))); |
117 | } | 235 | } |
118 | } | 236 | } |
119 | raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); | 237 | raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); |
120 | if (hdr) | 238 | if (mce_bios_cmci_threshold && bios_wrong_thresh) { |
121 | printk(KERN_CONT "\n"); | 239 | pr_info_once( |
240 | "bios_cmci_threshold: Some banks do not have valid thresholds set\n"); | ||
241 | pr_info_once( | ||
242 | "bios_cmci_threshold: Make sure your BIOS supports this boot option\n"); | ||
243 | } | ||
122 | } | 244 | } |
123 | 245 | ||
124 | /* | 246 | /* |
@@ -156,7 +278,7 @@ void cmci_clear(void) | |||
156 | continue; | 278 | continue; |
157 | /* Disable CMCI */ | 279 | /* Disable CMCI */ |
158 | rdmsrl(MSR_IA32_MCx_CTL2(i), val); | 280 | rdmsrl(MSR_IA32_MCx_CTL2(i), val); |
159 | val &= ~(MCI_CTL2_CMCI_EN|MCI_CTL2_CMCI_THRESHOLD_MASK); | 281 | val &= ~MCI_CTL2_CMCI_EN; |
160 | wrmsrl(MSR_IA32_MCx_CTL2(i), val); | 282 | wrmsrl(MSR_IA32_MCx_CTL2(i), val); |
161 | __clear_bit(i, __get_cpu_var(mce_banks_owned)); | 283 | __clear_bit(i, __get_cpu_var(mce_banks_owned)); |
162 | } | 284 | } |
@@ -186,7 +308,7 @@ void cmci_rediscover(int dying) | |||
186 | continue; | 308 | continue; |
187 | /* Recheck banks in case CPUs don't all have the same */ | 309 | /* Recheck banks in case CPUs don't all have the same */ |
188 | if (cmci_supported(&banks)) | 310 | if (cmci_supported(&banks)) |
189 | cmci_discover(banks, 0); | 311 | cmci_discover(banks); |
190 | } | 312 | } |
191 | 313 | ||
192 | set_cpus_allowed_ptr(current, old); | 314 | set_cpus_allowed_ptr(current, old); |
@@ -200,7 +322,7 @@ void cmci_reenable(void) | |||
200 | { | 322 | { |
201 | int banks; | 323 | int banks; |
202 | if (cmci_supported(&banks)) | 324 | if (cmci_supported(&banks)) |
203 | cmci_discover(banks, 0); | 325 | cmci_discover(banks); |
204 | } | 326 | } |
205 | 327 | ||
206 | static void intel_init_cmci(void) | 328 | static void intel_init_cmci(void) |
@@ -211,7 +333,7 @@ static void intel_init_cmci(void) | |||
211 | return; | 333 | return; |
212 | 334 | ||
213 | mce_threshold_vector = intel_threshold_interrupt; | 335 | mce_threshold_vector = intel_threshold_interrupt; |
214 | cmci_discover(banks, 1); | 336 | cmci_discover(banks); |
215 | /* | 337 | /* |
216 | * For CPU #0 this runs with still disabled APIC, but that's | 338 | * For CPU #0 this runs with still disabled APIC, but that's |
217 | * ok because only the vector is set up. We still do another | 339 | * ok because only the vector is set up. We still do another |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 6605a81ba339..8b6defe7eefc 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
@@ -586,6 +586,8 @@ extern struct event_constraint intel_westmere_pebs_event_constraints[]; | |||
586 | 586 | ||
587 | extern struct event_constraint intel_snb_pebs_event_constraints[]; | 587 | extern struct event_constraint intel_snb_pebs_event_constraints[]; |
588 | 588 | ||
589 | extern struct event_constraint intel_ivb_pebs_event_constraints[]; | ||
590 | |||
589 | struct event_constraint *intel_pebs_constraints(struct perf_event *event); | 591 | struct event_constraint *intel_pebs_constraints(struct perf_event *event); |
590 | 592 | ||
591 | void intel_pmu_pebs_enable(struct perf_event *event); | 593 | void intel_pmu_pebs_enable(struct perf_event *event); |
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index 7bfb5bec8630..eebd5ffe1bba 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c | |||
@@ -209,6 +209,15 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config) | |||
209 | return -EOPNOTSUPP; | 209 | return -EOPNOTSUPP; |
210 | } | 210 | } |
211 | 211 | ||
212 | static const struct perf_event_attr ibs_notsupp = { | ||
213 | .exclude_user = 1, | ||
214 | .exclude_kernel = 1, | ||
215 | .exclude_hv = 1, | ||
216 | .exclude_idle = 1, | ||
217 | .exclude_host = 1, | ||
218 | .exclude_guest = 1, | ||
219 | }; | ||
220 | |||
212 | static int perf_ibs_init(struct perf_event *event) | 221 | static int perf_ibs_init(struct perf_event *event) |
213 | { | 222 | { |
214 | struct hw_perf_event *hwc = &event->hw; | 223 | struct hw_perf_event *hwc = &event->hw; |
@@ -229,6 +238,9 @@ static int perf_ibs_init(struct perf_event *event) | |||
229 | if (event->pmu != &perf_ibs->pmu) | 238 | if (event->pmu != &perf_ibs->pmu) |
230 | return -ENOENT; | 239 | return -ENOENT; |
231 | 240 | ||
241 | if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp)) | ||
242 | return -EINVAL; | ||
243 | |||
232 | if (config & ~perf_ibs->config_mask) | 244 | if (config & ~perf_ibs->config_mask) |
233 | return -EINVAL; | 245 | return -EINVAL; |
234 | 246 | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 7f2739e03e79..6bca492b8547 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -2008,6 +2008,7 @@ __init int intel_pmu_init(void) | |||
2008 | break; | 2008 | break; |
2009 | 2009 | ||
2010 | case 28: /* Atom */ | 2010 | case 28: /* Atom */ |
2011 | case 54: /* Cedariew */ | ||
2011 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, | 2012 | memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, |
2012 | sizeof(hw_cache_event_ids)); | 2013 | sizeof(hw_cache_event_ids)); |
2013 | 2014 | ||
@@ -2047,7 +2048,6 @@ __init int intel_pmu_init(void) | |||
2047 | case 42: /* SandyBridge */ | 2048 | case 42: /* SandyBridge */ |
2048 | case 45: /* SandyBridge, "Romely-EP" */ | 2049 | case 45: /* SandyBridge, "Romely-EP" */ |
2049 | x86_add_quirk(intel_sandybridge_quirk); | 2050 | x86_add_quirk(intel_sandybridge_quirk); |
2050 | case 58: /* IvyBridge */ | ||
2051 | memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, | 2051 | memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, |
2052 | sizeof(hw_cache_event_ids)); | 2052 | sizeof(hw_cache_event_ids)); |
2053 | memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, | 2053 | memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, |
@@ -2072,6 +2072,29 @@ __init int intel_pmu_init(void) | |||
2072 | 2072 | ||
2073 | pr_cont("SandyBridge events, "); | 2073 | pr_cont("SandyBridge events, "); |
2074 | break; | 2074 | break; |
2075 | case 58: /* IvyBridge */ | ||
2076 | memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, | ||
2077 | sizeof(hw_cache_event_ids)); | ||
2078 | memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, | ||
2079 | sizeof(hw_cache_extra_regs)); | ||
2080 | |||
2081 | intel_pmu_lbr_init_snb(); | ||
2082 | |||
2083 | x86_pmu.event_constraints = intel_snb_event_constraints; | ||
2084 | x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints; | ||
2085 | x86_pmu.pebs_aliases = intel_pebs_aliases_snb; | ||
2086 | x86_pmu.extra_regs = intel_snb_extra_regs; | ||
2087 | /* all extra regs are per-cpu when HT is on */ | ||
2088 | x86_pmu.er_flags |= ERF_HAS_RSP_1; | ||
2089 | x86_pmu.er_flags |= ERF_NO_HT_SHARING; | ||
2090 | |||
2091 | /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */ | ||
2092 | intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = | ||
2093 | X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1); | ||
2094 | |||
2095 | pr_cont("IvyBridge events, "); | ||
2096 | break; | ||
2097 | |||
2075 | 2098 | ||
2076 | default: | 2099 | default: |
2077 | switch (x86_pmu.version) { | 2100 | switch (x86_pmu.version) { |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index e38d97bf4259..826054a4f2ee 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c | |||
@@ -407,6 +407,20 @@ struct event_constraint intel_snb_pebs_event_constraints[] = { | |||
407 | EVENT_CONSTRAINT_END | 407 | EVENT_CONSTRAINT_END |
408 | }; | 408 | }; |
409 | 409 | ||
410 | struct event_constraint intel_ivb_pebs_event_constraints[] = { | ||
411 | INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ | ||
412 | INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ | ||
413 | INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */ | ||
414 | INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ | ||
415 | INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ | ||
416 | INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */ | ||
417 | INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ | ||
418 | INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ | ||
419 | INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ | ||
420 | INTEL_EVENT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */ | ||
421 | EVENT_CONSTRAINT_END | ||
422 | }; | ||
423 | |||
410 | struct event_constraint *intel_pebs_constraints(struct perf_event *event) | 424 | struct event_constraint *intel_pebs_constraints(struct perf_event *event) |
411 | { | 425 | { |
412 | struct event_constraint *c; | 426 | struct event_constraint *c; |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index 520b4265fcd2..da02e9cc3754 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c | |||
@@ -686,7 +686,8 @@ void intel_pmu_lbr_init_atom(void) | |||
686 | * to have an operational LBR which can freeze | 686 | * to have an operational LBR which can freeze |
687 | * on PMU interrupt | 687 | * on PMU interrupt |
688 | */ | 688 | */ |
689 | if (boot_cpu_data.x86_mask < 10) { | 689 | if (boot_cpu_data.x86_model == 28 |
690 | && boot_cpu_data.x86_mask < 10) { | ||
690 | pr_cont("LBR disabled due to erratum"); | 691 | pr_cont("LBR disabled due to erratum"); |
691 | return; | 692 | return; |
692 | } | 693 | } |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 0a5571080e74..99d96a4978b5 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -661,6 +661,11 @@ static void snb_uncore_msr_init_box(struct intel_uncore_box *box) | |||
661 | } | 661 | } |
662 | } | 662 | } |
663 | 663 | ||
664 | static struct uncore_event_desc snb_uncore_events[] = { | ||
665 | INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"), | ||
666 | { /* end: all zeroes */ }, | ||
667 | }; | ||
668 | |||
664 | static struct attribute *snb_uncore_formats_attr[] = { | 669 | static struct attribute *snb_uncore_formats_attr[] = { |
665 | &format_attr_event.attr, | 670 | &format_attr_event.attr, |
666 | &format_attr_umask.attr, | 671 | &format_attr_umask.attr, |
@@ -704,6 +709,7 @@ static struct intel_uncore_type snb_uncore_cbox = { | |||
704 | .constraints = snb_uncore_cbox_constraints, | 709 | .constraints = snb_uncore_cbox_constraints, |
705 | .ops = &snb_uncore_msr_ops, | 710 | .ops = &snb_uncore_msr_ops, |
706 | .format_group = &snb_uncore_format_group, | 711 | .format_group = &snb_uncore_format_group, |
712 | .event_descs = snb_uncore_events, | ||
707 | }; | 713 | }; |
708 | 714 | ||
709 | static struct intel_uncore_type *snb_msr_uncores[] = { | 715 | static struct intel_uncore_type *snb_msr_uncores[] = { |
@@ -1944,7 +1950,7 @@ struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type, int cp | |||
1944 | static struct intel_uncore_box * | 1950 | static struct intel_uncore_box * |
1945 | uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu) | 1951 | uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu) |
1946 | { | 1952 | { |
1947 | static struct intel_uncore_box *box; | 1953 | struct intel_uncore_box *box; |
1948 | 1954 | ||
1949 | box = *per_cpu_ptr(pmu->box, cpu); | 1955 | box = *per_cpu_ptr(pmu->box, cpu); |
1950 | if (box) | 1956 | if (box) |
@@ -2341,6 +2347,27 @@ int uncore_pmu_event_init(struct perf_event *event) | |||
2341 | return ret; | 2347 | return ret; |
2342 | } | 2348 | } |
2343 | 2349 | ||
2350 | static ssize_t uncore_get_attr_cpumask(struct device *dev, | ||
2351 | struct device_attribute *attr, char *buf) | ||
2352 | { | ||
2353 | int n = cpulist_scnprintf(buf, PAGE_SIZE - 2, &uncore_cpu_mask); | ||
2354 | |||
2355 | buf[n++] = '\n'; | ||
2356 | buf[n] = '\0'; | ||
2357 | return n; | ||
2358 | } | ||
2359 | |||
2360 | static DEVICE_ATTR(cpumask, S_IRUGO, uncore_get_attr_cpumask, NULL); | ||
2361 | |||
2362 | static struct attribute *uncore_pmu_attrs[] = { | ||
2363 | &dev_attr_cpumask.attr, | ||
2364 | NULL, | ||
2365 | }; | ||
2366 | |||
2367 | static struct attribute_group uncore_pmu_attr_group = { | ||
2368 | .attrs = uncore_pmu_attrs, | ||
2369 | }; | ||
2370 | |||
2344 | static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu) | 2371 | static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu) |
2345 | { | 2372 | { |
2346 | int ret; | 2373 | int ret; |
@@ -2378,8 +2405,8 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) | |||
2378 | free_percpu(type->pmus[i].box); | 2405 | free_percpu(type->pmus[i].box); |
2379 | kfree(type->pmus); | 2406 | kfree(type->pmus); |
2380 | type->pmus = NULL; | 2407 | type->pmus = NULL; |
2381 | kfree(type->attr_groups[1]); | 2408 | kfree(type->events_group); |
2382 | type->attr_groups[1] = NULL; | 2409 | type->events_group = NULL; |
2383 | } | 2410 | } |
2384 | 2411 | ||
2385 | static void __init uncore_types_exit(struct intel_uncore_type **types) | 2412 | static void __init uncore_types_exit(struct intel_uncore_type **types) |
@@ -2431,9 +2458,10 @@ static int __init uncore_type_init(struct intel_uncore_type *type) | |||
2431 | for (j = 0; j < i; j++) | 2458 | for (j = 0; j < i; j++) |
2432 | attrs[j] = &type->event_descs[j].attr.attr; | 2459 | attrs[j] = &type->event_descs[j].attr.attr; |
2433 | 2460 | ||
2434 | type->attr_groups[1] = events_group; | 2461 | type->events_group = events_group; |
2435 | } | 2462 | } |
2436 | 2463 | ||
2464 | type->pmu_group = &uncore_pmu_attr_group; | ||
2437 | type->pmus = pmus; | 2465 | type->pmus = pmus; |
2438 | return 0; | 2466 | return 0; |
2439 | fail: | 2467 | fail: |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index 5b81c1856aac..e68a4550e952 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h | |||
@@ -369,10 +369,12 @@ struct intel_uncore_type { | |||
369 | struct intel_uncore_pmu *pmus; | 369 | struct intel_uncore_pmu *pmus; |
370 | struct intel_uncore_ops *ops; | 370 | struct intel_uncore_ops *ops; |
371 | struct uncore_event_desc *event_descs; | 371 | struct uncore_event_desc *event_descs; |
372 | const struct attribute_group *attr_groups[3]; | 372 | const struct attribute_group *attr_groups[4]; |
373 | }; | 373 | }; |
374 | 374 | ||
375 | #define format_group attr_groups[0] | 375 | #define pmu_group attr_groups[0] |
376 | #define format_group attr_groups[1] | ||
377 | #define events_group attr_groups[2] | ||
376 | 378 | ||
377 | struct intel_uncore_ops { | 379 | struct intel_uncore_ops { |
378 | void (*init_box)(struct intel_uncore_box *); | 380 | void (*init_box)(struct intel_uncore_box *); |
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 8022c6681485..fbd895562292 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c | |||
@@ -140,10 +140,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
140 | 140 | ||
141 | static void *c_start(struct seq_file *m, loff_t *pos) | 141 | static void *c_start(struct seq_file *m, loff_t *pos) |
142 | { | 142 | { |
143 | if (*pos == 0) /* just in case, cpu 0 is not the first */ | 143 | *pos = cpumask_next(*pos - 1, cpu_online_mask); |
144 | *pos = cpumask_first(cpu_online_mask); | ||
145 | else | ||
146 | *pos = cpumask_next(*pos - 1, cpu_online_mask); | ||
147 | if ((*pos) < nr_cpu_ids) | 144 | if ((*pos) < nr_cpu_ids) |
148 | return &cpu_data(*pos); | 145 | return &cpu_data(*pos); |
149 | return NULL; | 146 | return NULL; |
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 39472dd2323f..60c78917190c 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c | |||
@@ -199,12 +199,14 @@ static int __init cpuid_init(void) | |||
199 | goto out_chrdev; | 199 | goto out_chrdev; |
200 | } | 200 | } |
201 | cpuid_class->devnode = cpuid_devnode; | 201 | cpuid_class->devnode = cpuid_devnode; |
202 | get_online_cpus(); | ||
202 | for_each_online_cpu(i) { | 203 | for_each_online_cpu(i) { |
203 | err = cpuid_device_create(i); | 204 | err = cpuid_device_create(i); |
204 | if (err != 0) | 205 | if (err != 0) |
205 | goto out_class; | 206 | goto out_class; |
206 | } | 207 | } |
207 | register_hotcpu_notifier(&cpuid_class_cpu_notifier); | 208 | register_hotcpu_notifier(&cpuid_class_cpu_notifier); |
209 | put_online_cpus(); | ||
208 | 210 | ||
209 | err = 0; | 211 | err = 0; |
210 | goto out; | 212 | goto out; |
@@ -214,6 +216,7 @@ out_class: | |||
214 | for_each_online_cpu(i) { | 216 | for_each_online_cpu(i) { |
215 | cpuid_device_destroy(i); | 217 | cpuid_device_destroy(i); |
216 | } | 218 | } |
219 | put_online_cpus(); | ||
217 | class_destroy(cpuid_class); | 220 | class_destroy(cpuid_class); |
218 | out_chrdev: | 221 | out_chrdev: |
219 | __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); | 222 | __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); |
@@ -225,11 +228,13 @@ static void __exit cpuid_exit(void) | |||
225 | { | 228 | { |
226 | int cpu = 0; | 229 | int cpu = 0; |
227 | 230 | ||
231 | get_online_cpus(); | ||
228 | for_each_online_cpu(cpu) | 232 | for_each_online_cpu(cpu) |
229 | cpuid_device_destroy(cpu); | 233 | cpuid_device_destroy(cpu); |
230 | class_destroy(cpuid_class); | 234 | class_destroy(cpuid_class); |
231 | __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); | 235 | __unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid"); |
232 | unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); | 236 | unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); |
237 | put_online_cpus(); | ||
233 | } | 238 | } |
234 | 239 | ||
235 | module_init(cpuid_init); | 240 | module_init(cpuid_init); |
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 3ae2ced4a874..b1581527a236 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c | |||
@@ -342,6 +342,47 @@ const struct irq_domain_ops ioapic_irq_domain_ops = { | |||
342 | .xlate = ioapic_xlate, | 342 | .xlate = ioapic_xlate, |
343 | }; | 343 | }; |
344 | 344 | ||
345 | static void dt_add_ioapic_domain(unsigned int ioapic_num, | ||
346 | struct device_node *np) | ||
347 | { | ||
348 | struct irq_domain *id; | ||
349 | struct mp_ioapic_gsi *gsi_cfg; | ||
350 | int ret; | ||
351 | int num; | ||
352 | |||
353 | gsi_cfg = mp_ioapic_gsi_routing(ioapic_num); | ||
354 | num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1; | ||
355 | |||
356 | id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops, | ||
357 | (void *)ioapic_num); | ||
358 | BUG_ON(!id); | ||
359 | if (gsi_cfg->gsi_base == 0) { | ||
360 | /* | ||
361 | * The first NR_IRQS_LEGACY irq descs are allocated in | ||
362 | * early_irq_init() and need just a mapping. The | ||
363 | * remaining irqs need both. All of them are preallocated | ||
364 | * and assigned so we can keep the 1:1 mapping which the ioapic | ||
365 | * is having. | ||
366 | */ | ||
367 | ret = irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY); | ||
368 | if (ret) | ||
369 | pr_err("Error mapping legacy IRQs: %d\n", ret); | ||
370 | |||
371 | if (num > NR_IRQS_LEGACY) { | ||
372 | ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY, | ||
373 | NR_IRQS_LEGACY, num - NR_IRQS_LEGACY); | ||
374 | if (ret) | ||
375 | pr_err("Error creating mapping for the " | ||
376 | "remaining IRQs: %d\n", ret); | ||
377 | } | ||
378 | irq_set_default_host(id); | ||
379 | } else { | ||
380 | ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num); | ||
381 | if (ret) | ||
382 | pr_err("Error creating IRQ mapping: %d\n", ret); | ||
383 | } | ||
384 | } | ||
385 | |||
345 | static void __init ioapic_add_ofnode(struct device_node *np) | 386 | static void __init ioapic_add_ofnode(struct device_node *np) |
346 | { | 387 | { |
347 | struct resource r; | 388 | struct resource r; |
@@ -356,15 +397,7 @@ static void __init ioapic_add_ofnode(struct device_node *np) | |||
356 | 397 | ||
357 | for (i = 0; i < nr_ioapics; i++) { | 398 | for (i = 0; i < nr_ioapics; i++) { |
358 | if (r.start == mpc_ioapic_addr(i)) { | 399 | if (r.start == mpc_ioapic_addr(i)) { |
359 | struct irq_domain *id; | 400 | dt_add_ioapic_domain(i, np); |
360 | struct mp_ioapic_gsi *gsi_cfg; | ||
361 | |||
362 | gsi_cfg = mp_ioapic_gsi_routing(i); | ||
363 | |||
364 | id = irq_domain_add_legacy(np, 32, gsi_cfg->gsi_base, 0, | ||
365 | &ioapic_irq_domain_ops, | ||
366 | (void*)i); | ||
367 | BUG_ON(!id); | ||
368 | return; | 401 | return; |
369 | } | 402 | } |
370 | } | 403 | } |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 623f28837476..f438a44bf8f9 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -1109,17 +1109,21 @@ ENTRY(ftrace_caller) | |||
1109 | pushl %eax | 1109 | pushl %eax |
1110 | pushl %ecx | 1110 | pushl %ecx |
1111 | pushl %edx | 1111 | pushl %edx |
1112 | movl 0xc(%esp), %eax | 1112 | pushl $0 /* Pass NULL as regs pointer */ |
1113 | movl 4*4(%esp), %eax | ||
1113 | movl 0x4(%ebp), %edx | 1114 | movl 0x4(%ebp), %edx |
1115 | leal function_trace_op, %ecx | ||
1114 | subl $MCOUNT_INSN_SIZE, %eax | 1116 | subl $MCOUNT_INSN_SIZE, %eax |
1115 | 1117 | ||
1116 | .globl ftrace_call | 1118 | .globl ftrace_call |
1117 | ftrace_call: | 1119 | ftrace_call: |
1118 | call ftrace_stub | 1120 | call ftrace_stub |
1119 | 1121 | ||
1122 | addl $4,%esp /* skip NULL pointer */ | ||
1120 | popl %edx | 1123 | popl %edx |
1121 | popl %ecx | 1124 | popl %ecx |
1122 | popl %eax | 1125 | popl %eax |
1126 | ftrace_ret: | ||
1123 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 1127 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1124 | .globl ftrace_graph_call | 1128 | .globl ftrace_graph_call |
1125 | ftrace_graph_call: | 1129 | ftrace_graph_call: |
@@ -1131,6 +1135,71 @@ ftrace_stub: | |||
1131 | ret | 1135 | ret |
1132 | END(ftrace_caller) | 1136 | END(ftrace_caller) |
1133 | 1137 | ||
1138 | ENTRY(ftrace_regs_caller) | ||
1139 | pushf /* push flags before compare (in cs location) */ | ||
1140 | cmpl $0, function_trace_stop | ||
1141 | jne ftrace_restore_flags | ||
1142 | |||
1143 | /* | ||
1144 | * i386 does not save SS and ESP when coming from kernel. | ||
1145 | * Instead, to get sp, ®s->sp is used (see ptrace.h). | ||
1146 | * Unfortunately, that means eflags must be at the same location | ||
1147 | * as the current return ip is. We move the return ip into the | ||
1148 | * ip location, and move flags into the return ip location. | ||
1149 | */ | ||
1150 | pushl 4(%esp) /* save return ip into ip slot */ | ||
1151 | |||
1152 | pushl $0 /* Load 0 into orig_ax */ | ||
1153 | pushl %gs | ||
1154 | pushl %fs | ||
1155 | pushl %es | ||
1156 | pushl %ds | ||
1157 | pushl %eax | ||
1158 | pushl %ebp | ||
1159 | pushl %edi | ||
1160 | pushl %esi | ||
1161 | pushl %edx | ||
1162 | pushl %ecx | ||
1163 | pushl %ebx | ||
1164 | |||
1165 | movl 13*4(%esp), %eax /* Get the saved flags */ | ||
1166 | movl %eax, 14*4(%esp) /* Move saved flags into regs->flags location */ | ||
1167 | /* clobbering return ip */ | ||
1168 | movl $__KERNEL_CS,13*4(%esp) | ||
1169 | |||
1170 | movl 12*4(%esp), %eax /* Load ip (1st parameter) */ | ||
1171 | subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ | ||
1172 | movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ | ||
1173 | leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */ | ||
1174 | pushl %esp /* Save pt_regs as 4th parameter */ | ||
1175 | |||
1176 | GLOBAL(ftrace_regs_call) | ||
1177 | call ftrace_stub | ||
1178 | |||
1179 | addl $4, %esp /* Skip pt_regs */ | ||
1180 | movl 14*4(%esp), %eax /* Move flags back into cs */ | ||
1181 | movl %eax, 13*4(%esp) /* Needed to keep addl from modifying flags */ | ||
1182 | movl 12*4(%esp), %eax /* Get return ip from regs->ip */ | ||
1183 | movl %eax, 14*4(%esp) /* Put return ip back for ret */ | ||
1184 | |||
1185 | popl %ebx | ||
1186 | popl %ecx | ||
1187 | popl %edx | ||
1188 | popl %esi | ||
1189 | popl %edi | ||
1190 | popl %ebp | ||
1191 | popl %eax | ||
1192 | popl %ds | ||
1193 | popl %es | ||
1194 | popl %fs | ||
1195 | popl %gs | ||
1196 | addl $8, %esp /* Skip orig_ax and ip */ | ||
1197 | popf /* Pop flags at end (no addl to corrupt flags) */ | ||
1198 | jmp ftrace_ret | ||
1199 | |||
1200 | ftrace_restore_flags: | ||
1201 | popf | ||
1202 | jmp ftrace_stub | ||
1134 | #else /* ! CONFIG_DYNAMIC_FTRACE */ | 1203 | #else /* ! CONFIG_DYNAMIC_FTRACE */ |
1135 | 1204 | ||
1136 | ENTRY(mcount) | 1205 | ENTRY(mcount) |
@@ -1171,9 +1240,6 @@ END(mcount) | |||
1171 | 1240 | ||
1172 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 1241 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1173 | ENTRY(ftrace_graph_caller) | 1242 | ENTRY(ftrace_graph_caller) |
1174 | cmpl $0, function_trace_stop | ||
1175 | jne ftrace_stub | ||
1176 | |||
1177 | pushl %eax | 1243 | pushl %eax |
1178 | pushl %ecx | 1244 | pushl %ecx |
1179 | pushl %edx | 1245 | pushl %edx |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 69babd8c834f..066334be7b74 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <asm/ftrace.h> | 56 | #include <asm/ftrace.h> |
57 | #include <asm/percpu.h> | 57 | #include <asm/percpu.h> |
58 | #include <asm/asm.h> | 58 | #include <asm/asm.h> |
59 | #include <asm/rcu.h> | ||
59 | #include <linux/err.h> | 60 | #include <linux/err.h> |
60 | 61 | ||
61 | /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */ | 62 | /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */ |
@@ -68,25 +69,51 @@ | |||
68 | .section .entry.text, "ax" | 69 | .section .entry.text, "ax" |
69 | 70 | ||
70 | #ifdef CONFIG_FUNCTION_TRACER | 71 | #ifdef CONFIG_FUNCTION_TRACER |
72 | |||
73 | #ifdef CC_USING_FENTRY | ||
74 | # define function_hook __fentry__ | ||
75 | #else | ||
76 | # define function_hook mcount | ||
77 | #endif | ||
78 | |||
71 | #ifdef CONFIG_DYNAMIC_FTRACE | 79 | #ifdef CONFIG_DYNAMIC_FTRACE |
72 | ENTRY(mcount) | 80 | |
81 | ENTRY(function_hook) | ||
73 | retq | 82 | retq |
74 | END(mcount) | 83 | END(function_hook) |
84 | |||
85 | /* skip is set if stack has been adjusted */ | ||
86 | .macro ftrace_caller_setup skip=0 | ||
87 | MCOUNT_SAVE_FRAME \skip | ||
88 | |||
89 | /* Load the ftrace_ops into the 3rd parameter */ | ||
90 | leaq function_trace_op, %rdx | ||
91 | |||
92 | /* Load ip into the first parameter */ | ||
93 | movq RIP(%rsp), %rdi | ||
94 | subq $MCOUNT_INSN_SIZE, %rdi | ||
95 | /* Load the parent_ip into the second parameter */ | ||
96 | #ifdef CC_USING_FENTRY | ||
97 | movq SS+16(%rsp), %rsi | ||
98 | #else | ||
99 | movq 8(%rbp), %rsi | ||
100 | #endif | ||
101 | .endm | ||
75 | 102 | ||
76 | ENTRY(ftrace_caller) | 103 | ENTRY(ftrace_caller) |
104 | /* Check if tracing was disabled (quick check) */ | ||
77 | cmpl $0, function_trace_stop | 105 | cmpl $0, function_trace_stop |
78 | jne ftrace_stub | 106 | jne ftrace_stub |
79 | 107 | ||
80 | MCOUNT_SAVE_FRAME | 108 | ftrace_caller_setup |
81 | 109 | /* regs go into 4th parameter (but make it NULL) */ | |
82 | movq 0x38(%rsp), %rdi | 110 | movq $0, %rcx |
83 | movq 8(%rbp), %rsi | ||
84 | subq $MCOUNT_INSN_SIZE, %rdi | ||
85 | 111 | ||
86 | GLOBAL(ftrace_call) | 112 | GLOBAL(ftrace_call) |
87 | call ftrace_stub | 113 | call ftrace_stub |
88 | 114 | ||
89 | MCOUNT_RESTORE_FRAME | 115 | MCOUNT_RESTORE_FRAME |
116 | ftrace_return: | ||
90 | 117 | ||
91 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 118 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
92 | GLOBAL(ftrace_graph_call) | 119 | GLOBAL(ftrace_graph_call) |
@@ -97,8 +124,78 @@ GLOBAL(ftrace_stub) | |||
97 | retq | 124 | retq |
98 | END(ftrace_caller) | 125 | END(ftrace_caller) |
99 | 126 | ||
127 | ENTRY(ftrace_regs_caller) | ||
128 | /* Save the current flags before compare (in SS location)*/ | ||
129 | pushfq | ||
130 | |||
131 | /* Check if tracing was disabled (quick check) */ | ||
132 | cmpl $0, function_trace_stop | ||
133 | jne ftrace_restore_flags | ||
134 | |||
135 | /* skip=8 to skip flags saved in SS */ | ||
136 | ftrace_caller_setup 8 | ||
137 | |||
138 | /* Save the rest of pt_regs */ | ||
139 | movq %r15, R15(%rsp) | ||
140 | movq %r14, R14(%rsp) | ||
141 | movq %r13, R13(%rsp) | ||
142 | movq %r12, R12(%rsp) | ||
143 | movq %r11, R11(%rsp) | ||
144 | movq %r10, R10(%rsp) | ||
145 | movq %rbp, RBP(%rsp) | ||
146 | movq %rbx, RBX(%rsp) | ||
147 | /* Copy saved flags */ | ||
148 | movq SS(%rsp), %rcx | ||
149 | movq %rcx, EFLAGS(%rsp) | ||
150 | /* Kernel segments */ | ||
151 | movq $__KERNEL_DS, %rcx | ||
152 | movq %rcx, SS(%rsp) | ||
153 | movq $__KERNEL_CS, %rcx | ||
154 | movq %rcx, CS(%rsp) | ||
155 | /* Stack - skipping return address */ | ||
156 | leaq SS+16(%rsp), %rcx | ||
157 | movq %rcx, RSP(%rsp) | ||
158 | |||
159 | /* regs go into 4th parameter */ | ||
160 | leaq (%rsp), %rcx | ||
161 | |||
162 | GLOBAL(ftrace_regs_call) | ||
163 | call ftrace_stub | ||
164 | |||
165 | /* Copy flags back to SS, to restore them */ | ||
166 | movq EFLAGS(%rsp), %rax | ||
167 | movq %rax, SS(%rsp) | ||
168 | |||
169 | /* Handlers can change the RIP */ | ||
170 | movq RIP(%rsp), %rax | ||
171 | movq %rax, SS+8(%rsp) | ||
172 | |||
173 | /* restore the rest of pt_regs */ | ||
174 | movq R15(%rsp), %r15 | ||
175 | movq R14(%rsp), %r14 | ||
176 | movq R13(%rsp), %r13 | ||
177 | movq R12(%rsp), %r12 | ||
178 | movq R10(%rsp), %r10 | ||
179 | movq RBP(%rsp), %rbp | ||
180 | movq RBX(%rsp), %rbx | ||
181 | |||
182 | /* skip=8 to skip flags saved in SS */ | ||
183 | MCOUNT_RESTORE_FRAME 8 | ||
184 | |||
185 | /* Restore flags */ | ||
186 | popfq | ||
187 | |||
188 | jmp ftrace_return | ||
189 | ftrace_restore_flags: | ||
190 | popfq | ||
191 | jmp ftrace_stub | ||
192 | |||
193 | END(ftrace_regs_caller) | ||
194 | |||
195 | |||
100 | #else /* ! CONFIG_DYNAMIC_FTRACE */ | 196 | #else /* ! CONFIG_DYNAMIC_FTRACE */ |
101 | ENTRY(mcount) | 197 | |
198 | ENTRY(function_hook) | ||
102 | cmpl $0, function_trace_stop | 199 | cmpl $0, function_trace_stop |
103 | jne ftrace_stub | 200 | jne ftrace_stub |
104 | 201 | ||
@@ -119,8 +216,12 @@ GLOBAL(ftrace_stub) | |||
119 | trace: | 216 | trace: |
120 | MCOUNT_SAVE_FRAME | 217 | MCOUNT_SAVE_FRAME |
121 | 218 | ||
122 | movq 0x38(%rsp), %rdi | 219 | movq RIP(%rsp), %rdi |
220 | #ifdef CC_USING_FENTRY | ||
221 | movq SS+16(%rsp), %rsi | ||
222 | #else | ||
123 | movq 8(%rbp), %rsi | 223 | movq 8(%rbp), %rsi |
224 | #endif | ||
124 | subq $MCOUNT_INSN_SIZE, %rdi | 225 | subq $MCOUNT_INSN_SIZE, %rdi |
125 | 226 | ||
126 | call *ftrace_trace_function | 227 | call *ftrace_trace_function |
@@ -128,20 +229,22 @@ trace: | |||
128 | MCOUNT_RESTORE_FRAME | 229 | MCOUNT_RESTORE_FRAME |
129 | 230 | ||
130 | jmp ftrace_stub | 231 | jmp ftrace_stub |
131 | END(mcount) | 232 | END(function_hook) |
132 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 233 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
133 | #endif /* CONFIG_FUNCTION_TRACER */ | 234 | #endif /* CONFIG_FUNCTION_TRACER */ |
134 | 235 | ||
135 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 236 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
136 | ENTRY(ftrace_graph_caller) | 237 | ENTRY(ftrace_graph_caller) |
137 | cmpl $0, function_trace_stop | ||
138 | jne ftrace_stub | ||
139 | |||
140 | MCOUNT_SAVE_FRAME | 238 | MCOUNT_SAVE_FRAME |
141 | 239 | ||
240 | #ifdef CC_USING_FENTRY | ||
241 | leaq SS+16(%rsp), %rdi | ||
242 | movq $0, %rdx /* No framepointers needed */ | ||
243 | #else | ||
142 | leaq 8(%rbp), %rdi | 244 | leaq 8(%rbp), %rdi |
143 | movq 0x38(%rsp), %rsi | ||
144 | movq (%rbp), %rdx | 245 | movq (%rbp), %rdx |
246 | #endif | ||
247 | movq RIP(%rsp), %rsi | ||
145 | subq $MCOUNT_INSN_SIZE, %rsi | 248 | subq $MCOUNT_INSN_SIZE, %rsi |
146 | 249 | ||
147 | call prepare_ftrace_return | 250 | call prepare_ftrace_return |
@@ -342,15 +445,15 @@ ENDPROC(native_usergs_sysret64) | |||
342 | .macro SAVE_ARGS_IRQ | 445 | .macro SAVE_ARGS_IRQ |
343 | cld | 446 | cld |
344 | /* start from rbp in pt_regs and jump over */ | 447 | /* start from rbp in pt_regs and jump over */ |
345 | movq_cfi rdi, RDI-RBP | 448 | movq_cfi rdi, (RDI-RBP) |
346 | movq_cfi rsi, RSI-RBP | 449 | movq_cfi rsi, (RSI-RBP) |
347 | movq_cfi rdx, RDX-RBP | 450 | movq_cfi rdx, (RDX-RBP) |
348 | movq_cfi rcx, RCX-RBP | 451 | movq_cfi rcx, (RCX-RBP) |
349 | movq_cfi rax, RAX-RBP | 452 | movq_cfi rax, (RAX-RBP) |
350 | movq_cfi r8, R8-RBP | 453 | movq_cfi r8, (R8-RBP) |
351 | movq_cfi r9, R9-RBP | 454 | movq_cfi r9, (R9-RBP) |
352 | movq_cfi r10, R10-RBP | 455 | movq_cfi r10, (R10-RBP) |
353 | movq_cfi r11, R11-RBP | 456 | movq_cfi r11, (R11-RBP) |
354 | 457 | ||
355 | /* Save rbp so that we can unwind from get_irq_regs() */ | 458 | /* Save rbp so that we can unwind from get_irq_regs() */ |
356 | movq_cfi rbp, 0 | 459 | movq_cfi rbp, 0 |
@@ -384,7 +487,7 @@ ENDPROC(native_usergs_sysret64) | |||
384 | .endm | 487 | .endm |
385 | 488 | ||
386 | ENTRY(save_rest) | 489 | ENTRY(save_rest) |
387 | PARTIAL_FRAME 1 REST_SKIP+8 | 490 | PARTIAL_FRAME 1 (REST_SKIP+8) |
388 | movq 5*8+16(%rsp), %r11 /* save return address */ | 491 | movq 5*8+16(%rsp), %r11 /* save return address */ |
389 | movq_cfi rbx, RBX+16 | 492 | movq_cfi rbx, RBX+16 |
390 | movq_cfi rbp, RBP+16 | 493 | movq_cfi rbp, RBP+16 |
@@ -440,7 +543,7 @@ ENTRY(ret_from_fork) | |||
440 | 543 | ||
441 | LOCK ; btr $TIF_FORK,TI_flags(%r8) | 544 | LOCK ; btr $TIF_FORK,TI_flags(%r8) |
442 | 545 | ||
443 | pushq_cfi kernel_eflags(%rip) | 546 | pushq_cfi $0x0002 |
444 | popfq_cfi # reset kernel eflags | 547 | popfq_cfi # reset kernel eflags |
445 | 548 | ||
446 | call schedule_tail # rdi: 'prev' task parameter | 549 | call schedule_tail # rdi: 'prev' task parameter |
@@ -565,7 +668,7 @@ sysret_careful: | |||
565 | TRACE_IRQS_ON | 668 | TRACE_IRQS_ON |
566 | ENABLE_INTERRUPTS(CLBR_NONE) | 669 | ENABLE_INTERRUPTS(CLBR_NONE) |
567 | pushq_cfi %rdi | 670 | pushq_cfi %rdi |
568 | call schedule | 671 | SCHEDULE_USER |
569 | popq_cfi %rdi | 672 | popq_cfi %rdi |
570 | jmp sysret_check | 673 | jmp sysret_check |
571 | 674 | ||
@@ -678,7 +781,7 @@ int_careful: | |||
678 | TRACE_IRQS_ON | 781 | TRACE_IRQS_ON |
679 | ENABLE_INTERRUPTS(CLBR_NONE) | 782 | ENABLE_INTERRUPTS(CLBR_NONE) |
680 | pushq_cfi %rdi | 783 | pushq_cfi %rdi |
681 | call schedule | 784 | SCHEDULE_USER |
682 | popq_cfi %rdi | 785 | popq_cfi %rdi |
683 | DISABLE_INTERRUPTS(CLBR_NONE) | 786 | DISABLE_INTERRUPTS(CLBR_NONE) |
684 | TRACE_IRQS_OFF | 787 | TRACE_IRQS_OFF |
@@ -974,7 +1077,7 @@ retint_careful: | |||
974 | TRACE_IRQS_ON | 1077 | TRACE_IRQS_ON |
975 | ENABLE_INTERRUPTS(CLBR_NONE) | 1078 | ENABLE_INTERRUPTS(CLBR_NONE) |
976 | pushq_cfi %rdi | 1079 | pushq_cfi %rdi |
977 | call schedule | 1080 | SCHEDULE_USER |
978 | popq_cfi %rdi | 1081 | popq_cfi %rdi |
979 | GET_THREAD_INFO(%rcx) | 1082 | GET_THREAD_INFO(%rcx) |
980 | DISABLE_INTERRUPTS(CLBR_NONE) | 1083 | DISABLE_INTERRUPTS(CLBR_NONE) |
@@ -1449,7 +1552,7 @@ paranoid_userspace: | |||
1449 | paranoid_schedule: | 1552 | paranoid_schedule: |
1450 | TRACE_IRQS_ON | 1553 | TRACE_IRQS_ON |
1451 | ENABLE_INTERRUPTS(CLBR_ANY) | 1554 | ENABLE_INTERRUPTS(CLBR_ANY) |
1452 | call schedule | 1555 | SCHEDULE_USER |
1453 | DISABLE_INTERRUPTS(CLBR_ANY) | 1556 | DISABLE_INTERRUPTS(CLBR_ANY) |
1454 | TRACE_IRQS_OFF | 1557 | TRACE_IRQS_OFF |
1455 | jmp paranoid_userspace | 1558 | jmp paranoid_userspace |
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index c3a7cb4bf6e6..1d414029f1d8 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
@@ -206,6 +206,21 @@ static int | |||
206 | ftrace_modify_code(unsigned long ip, unsigned const char *old_code, | 206 | ftrace_modify_code(unsigned long ip, unsigned const char *old_code, |
207 | unsigned const char *new_code); | 207 | unsigned const char *new_code); |
208 | 208 | ||
209 | /* | ||
210 | * Should never be called: | ||
211 | * As it is only called by __ftrace_replace_code() which is called by | ||
212 | * ftrace_replace_code() that x86 overrides, and by ftrace_update_code() | ||
213 | * which is called to turn mcount into nops or nops into function calls | ||
214 | * but not to convert a function from not using regs to one that uses | ||
215 | * regs, which ftrace_modify_call() is for. | ||
216 | */ | ||
217 | int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, | ||
218 | unsigned long addr) | ||
219 | { | ||
220 | WARN_ON(1); | ||
221 | return -EINVAL; | ||
222 | } | ||
223 | |||
209 | int ftrace_update_ftrace_func(ftrace_func_t func) | 224 | int ftrace_update_ftrace_func(ftrace_func_t func) |
210 | { | 225 | { |
211 | unsigned long ip = (unsigned long)(&ftrace_call); | 226 | unsigned long ip = (unsigned long)(&ftrace_call); |
@@ -220,6 +235,14 @@ int ftrace_update_ftrace_func(ftrace_func_t func) | |||
220 | 235 | ||
221 | ret = ftrace_modify_code(ip, old, new); | 236 | ret = ftrace_modify_code(ip, old, new); |
222 | 237 | ||
238 | /* Also update the regs callback function */ | ||
239 | if (!ret) { | ||
240 | ip = (unsigned long)(&ftrace_regs_call); | ||
241 | memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE); | ||
242 | new = ftrace_call_replace(ip, (unsigned long)func); | ||
243 | ret = ftrace_modify_code(ip, old, new); | ||
244 | } | ||
245 | |||
223 | atomic_dec(&modifying_ftrace_code); | 246 | atomic_dec(&modifying_ftrace_code); |
224 | 247 | ||
225 | return ret; | 248 | return ret; |
@@ -299,6 +322,32 @@ static int add_brk_on_nop(struct dyn_ftrace *rec) | |||
299 | return add_break(rec->ip, old); | 322 | return add_break(rec->ip, old); |
300 | } | 323 | } |
301 | 324 | ||
325 | /* | ||
326 | * If the record has the FTRACE_FL_REGS set, that means that it | ||
327 | * wants to convert to a callback that saves all regs. If FTRACE_FL_REGS | ||
328 | * is not not set, then it wants to convert to the normal callback. | ||
329 | */ | ||
330 | static unsigned long get_ftrace_addr(struct dyn_ftrace *rec) | ||
331 | { | ||
332 | if (rec->flags & FTRACE_FL_REGS) | ||
333 | return (unsigned long)FTRACE_REGS_ADDR; | ||
334 | else | ||
335 | return (unsigned long)FTRACE_ADDR; | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | * The FTRACE_FL_REGS_EN is set when the record already points to | ||
340 | * a function that saves all the regs. Basically the '_EN' version | ||
341 | * represents the current state of the function. | ||
342 | */ | ||
343 | static unsigned long get_ftrace_old_addr(struct dyn_ftrace *rec) | ||
344 | { | ||
345 | if (rec->flags & FTRACE_FL_REGS_EN) | ||
346 | return (unsigned long)FTRACE_REGS_ADDR; | ||
347 | else | ||
348 | return (unsigned long)FTRACE_ADDR; | ||
349 | } | ||
350 | |||
302 | static int add_breakpoints(struct dyn_ftrace *rec, int enable) | 351 | static int add_breakpoints(struct dyn_ftrace *rec, int enable) |
303 | { | 352 | { |
304 | unsigned long ftrace_addr; | 353 | unsigned long ftrace_addr; |
@@ -306,7 +355,7 @@ static int add_breakpoints(struct dyn_ftrace *rec, int enable) | |||
306 | 355 | ||
307 | ret = ftrace_test_record(rec, enable); | 356 | ret = ftrace_test_record(rec, enable); |
308 | 357 | ||
309 | ftrace_addr = (unsigned long)FTRACE_ADDR; | 358 | ftrace_addr = get_ftrace_addr(rec); |
310 | 359 | ||
311 | switch (ret) { | 360 | switch (ret) { |
312 | case FTRACE_UPDATE_IGNORE: | 361 | case FTRACE_UPDATE_IGNORE: |
@@ -316,6 +365,10 @@ static int add_breakpoints(struct dyn_ftrace *rec, int enable) | |||
316 | /* converting nop to call */ | 365 | /* converting nop to call */ |
317 | return add_brk_on_nop(rec); | 366 | return add_brk_on_nop(rec); |
318 | 367 | ||
368 | case FTRACE_UPDATE_MODIFY_CALL_REGS: | ||
369 | case FTRACE_UPDATE_MODIFY_CALL: | ||
370 | ftrace_addr = get_ftrace_old_addr(rec); | ||
371 | /* fall through */ | ||
319 | case FTRACE_UPDATE_MAKE_NOP: | 372 | case FTRACE_UPDATE_MAKE_NOP: |
320 | /* converting a call to a nop */ | 373 | /* converting a call to a nop */ |
321 | return add_brk_on_call(rec, ftrace_addr); | 374 | return add_brk_on_call(rec, ftrace_addr); |
@@ -360,13 +413,21 @@ static int remove_breakpoint(struct dyn_ftrace *rec) | |||
360 | * If not, don't touch the breakpoint, we make just create | 413 | * If not, don't touch the breakpoint, we make just create |
361 | * a disaster. | 414 | * a disaster. |
362 | */ | 415 | */ |
363 | ftrace_addr = (unsigned long)FTRACE_ADDR; | 416 | ftrace_addr = get_ftrace_addr(rec); |
417 | nop = ftrace_call_replace(ip, ftrace_addr); | ||
418 | |||
419 | if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) == 0) | ||
420 | goto update; | ||
421 | |||
422 | /* Check both ftrace_addr and ftrace_old_addr */ | ||
423 | ftrace_addr = get_ftrace_old_addr(rec); | ||
364 | nop = ftrace_call_replace(ip, ftrace_addr); | 424 | nop = ftrace_call_replace(ip, ftrace_addr); |
365 | 425 | ||
366 | if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0) | 426 | if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0) |
367 | return -EINVAL; | 427 | return -EINVAL; |
368 | } | 428 | } |
369 | 429 | ||
430 | update: | ||
370 | return probe_kernel_write((void *)ip, &nop[0], 1); | 431 | return probe_kernel_write((void *)ip, &nop[0], 1); |
371 | } | 432 | } |
372 | 433 | ||
@@ -405,12 +466,14 @@ static int add_update(struct dyn_ftrace *rec, int enable) | |||
405 | 466 | ||
406 | ret = ftrace_test_record(rec, enable); | 467 | ret = ftrace_test_record(rec, enable); |
407 | 468 | ||
408 | ftrace_addr = (unsigned long)FTRACE_ADDR; | 469 | ftrace_addr = get_ftrace_addr(rec); |
409 | 470 | ||
410 | switch (ret) { | 471 | switch (ret) { |
411 | case FTRACE_UPDATE_IGNORE: | 472 | case FTRACE_UPDATE_IGNORE: |
412 | return 0; | 473 | return 0; |
413 | 474 | ||
475 | case FTRACE_UPDATE_MODIFY_CALL_REGS: | ||
476 | case FTRACE_UPDATE_MODIFY_CALL: | ||
414 | case FTRACE_UPDATE_MAKE_CALL: | 477 | case FTRACE_UPDATE_MAKE_CALL: |
415 | /* converting nop to call */ | 478 | /* converting nop to call */ |
416 | return add_update_call(rec, ftrace_addr); | 479 | return add_update_call(rec, ftrace_addr); |
@@ -455,12 +518,14 @@ static int finish_update(struct dyn_ftrace *rec, int enable) | |||
455 | 518 | ||
456 | ret = ftrace_update_record(rec, enable); | 519 | ret = ftrace_update_record(rec, enable); |
457 | 520 | ||
458 | ftrace_addr = (unsigned long)FTRACE_ADDR; | 521 | ftrace_addr = get_ftrace_addr(rec); |
459 | 522 | ||
460 | switch (ret) { | 523 | switch (ret) { |
461 | case FTRACE_UPDATE_IGNORE: | 524 | case FTRACE_UPDATE_IGNORE: |
462 | return 0; | 525 | return 0; |
463 | 526 | ||
527 | case FTRACE_UPDATE_MODIFY_CALL_REGS: | ||
528 | case FTRACE_UPDATE_MODIFY_CALL: | ||
464 | case FTRACE_UPDATE_MAKE_CALL: | 529 | case FTRACE_UPDATE_MAKE_CALL: |
465 | /* converting nop to call */ | 530 | /* converting nop to call */ |
466 | return finish_update_call(rec, ftrace_addr); | 531 | return finish_update_call(rec, ftrace_addr); |
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index f250431fb505..675a05012449 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
@@ -19,24 +19,17 @@ | |||
19 | #include <asm/fpu-internal.h> | 19 | #include <asm/fpu-internal.h> |
20 | #include <asm/user.h> | 20 | #include <asm/user.h> |
21 | 21 | ||
22 | #ifdef CONFIG_X86_64 | ||
23 | # include <asm/sigcontext32.h> | ||
24 | # include <asm/user32.h> | ||
25 | #else | ||
26 | # define save_i387_xstate_ia32 save_i387_xstate | ||
27 | # define restore_i387_xstate_ia32 restore_i387_xstate | ||
28 | # define _fpstate_ia32 _fpstate | ||
29 | # define _xstate_ia32 _xstate | ||
30 | # define sig_xstate_ia32_size sig_xstate_size | ||
31 | # define fx_sw_reserved_ia32 fx_sw_reserved | ||
32 | # define user_i387_ia32_struct user_i387_struct | ||
33 | # define user32_fxsr_struct user_fxsr_struct | ||
34 | #endif | ||
35 | |||
36 | /* | 22 | /* |
37 | * Were we in an interrupt that interrupted kernel mode? | 23 | * Were we in an interrupt that interrupted kernel mode? |
38 | * | 24 | * |
39 | * We can do a kernel_fpu_begin/end() pair *ONLY* if that | 25 | * For now, with eagerfpu we will return interrupted kernel FPU |
26 | * state as not-idle. TBD: Ideally we can change the return value | ||
27 | * to something like __thread_has_fpu(current). But we need to | ||
28 | * be careful of doing __thread_clear_has_fpu() before saving | ||
29 | * the FPU etc for supporting nested uses etc. For now, take | ||
30 | * the simple route! | ||
31 | * | ||
32 | * On others, we can do a kernel_fpu_begin/end() pair *ONLY* if that | ||
40 | * pair does nothing at all: the thread must not have fpu (so | 33 | * pair does nothing at all: the thread must not have fpu (so |
41 | * that we don't try to save the FPU state), and TS must | 34 | * that we don't try to save the FPU state), and TS must |
42 | * be set (so that the clts/stts pair does nothing that is | 35 | * be set (so that the clts/stts pair does nothing that is |
@@ -44,6 +37,9 @@ | |||
44 | */ | 37 | */ |
45 | static inline bool interrupted_kernel_fpu_idle(void) | 38 | static inline bool interrupted_kernel_fpu_idle(void) |
46 | { | 39 | { |
40 | if (use_eager_fpu()) | ||
41 | return 0; | ||
42 | |||
47 | return !__thread_has_fpu(current) && | 43 | return !__thread_has_fpu(current) && |
48 | (read_cr0() & X86_CR0_TS); | 44 | (read_cr0() & X86_CR0_TS); |
49 | } | 45 | } |
@@ -77,29 +73,29 @@ bool irq_fpu_usable(void) | |||
77 | } | 73 | } |
78 | EXPORT_SYMBOL(irq_fpu_usable); | 74 | EXPORT_SYMBOL(irq_fpu_usable); |
79 | 75 | ||
80 | void kernel_fpu_begin(void) | 76 | void __kernel_fpu_begin(void) |
81 | { | 77 | { |
82 | struct task_struct *me = current; | 78 | struct task_struct *me = current; |
83 | 79 | ||
84 | WARN_ON_ONCE(!irq_fpu_usable()); | ||
85 | preempt_disable(); | ||
86 | if (__thread_has_fpu(me)) { | 80 | if (__thread_has_fpu(me)) { |
87 | __save_init_fpu(me); | 81 | __save_init_fpu(me); |
88 | __thread_clear_has_fpu(me); | 82 | __thread_clear_has_fpu(me); |
89 | /* We do 'stts()' in kernel_fpu_end() */ | 83 | /* We do 'stts()' in __kernel_fpu_end() */ |
90 | } else { | 84 | } else if (!use_eager_fpu()) { |
91 | this_cpu_write(fpu_owner_task, NULL); | 85 | this_cpu_write(fpu_owner_task, NULL); |
92 | clts(); | 86 | clts(); |
93 | } | 87 | } |
94 | } | 88 | } |
95 | EXPORT_SYMBOL(kernel_fpu_begin); | 89 | EXPORT_SYMBOL(__kernel_fpu_begin); |
96 | 90 | ||
97 | void kernel_fpu_end(void) | 91 | void __kernel_fpu_end(void) |
98 | { | 92 | { |
99 | stts(); | 93 | if (use_eager_fpu()) |
100 | preempt_enable(); | 94 | math_state_restore(); |
95 | else | ||
96 | stts(); | ||
101 | } | 97 | } |
102 | EXPORT_SYMBOL(kernel_fpu_end); | 98 | EXPORT_SYMBOL(__kernel_fpu_end); |
103 | 99 | ||
104 | void unlazy_fpu(struct task_struct *tsk) | 100 | void unlazy_fpu(struct task_struct *tsk) |
105 | { | 101 | { |
@@ -113,23 +109,15 @@ void unlazy_fpu(struct task_struct *tsk) | |||
113 | } | 109 | } |
114 | EXPORT_SYMBOL(unlazy_fpu); | 110 | EXPORT_SYMBOL(unlazy_fpu); |
115 | 111 | ||
116 | #ifdef CONFIG_MATH_EMULATION | 112 | unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; |
117 | # define HAVE_HWFP (boot_cpu_data.hard_math) | ||
118 | #else | ||
119 | # define HAVE_HWFP 1 | ||
120 | #endif | ||
121 | |||
122 | static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; | ||
123 | unsigned int xstate_size; | 113 | unsigned int xstate_size; |
124 | EXPORT_SYMBOL_GPL(xstate_size); | 114 | EXPORT_SYMBOL_GPL(xstate_size); |
125 | unsigned int sig_xstate_ia32_size = sizeof(struct _fpstate_ia32); | ||
126 | static struct i387_fxsave_struct fx_scratch __cpuinitdata; | 115 | static struct i387_fxsave_struct fx_scratch __cpuinitdata; |
127 | 116 | ||
128 | static void __cpuinit mxcsr_feature_mask_init(void) | 117 | static void __cpuinit mxcsr_feature_mask_init(void) |
129 | { | 118 | { |
130 | unsigned long mask = 0; | 119 | unsigned long mask = 0; |
131 | 120 | ||
132 | clts(); | ||
133 | if (cpu_has_fxsr) { | 121 | if (cpu_has_fxsr) { |
134 | memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); | 122 | memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); |
135 | asm volatile("fxsave %0" : : "m" (fx_scratch)); | 123 | asm volatile("fxsave %0" : : "m" (fx_scratch)); |
@@ -138,7 +126,6 @@ static void __cpuinit mxcsr_feature_mask_init(void) | |||
138 | mask = 0x0000ffbf; | 126 | mask = 0x0000ffbf; |
139 | } | 127 | } |
140 | mxcsr_feature_mask &= mask; | 128 | mxcsr_feature_mask &= mask; |
141 | stts(); | ||
142 | } | 129 | } |
143 | 130 | ||
144 | static void __cpuinit init_thread_xstate(void) | 131 | static void __cpuinit init_thread_xstate(void) |
@@ -192,9 +179,8 @@ void __cpuinit fpu_init(void) | |||
192 | init_thread_xstate(); | 179 | init_thread_xstate(); |
193 | 180 | ||
194 | mxcsr_feature_mask_init(); | 181 | mxcsr_feature_mask_init(); |
195 | /* clean state in init */ | 182 | xsave_init(); |
196 | current_thread_info()->status = 0; | 183 | eager_fpu_init(); |
197 | clear_used_math(); | ||
198 | } | 184 | } |
199 | 185 | ||
200 | void fpu_finit(struct fpu *fpu) | 186 | void fpu_finit(struct fpu *fpu) |
@@ -205,12 +191,7 @@ void fpu_finit(struct fpu *fpu) | |||
205 | } | 191 | } |
206 | 192 | ||
207 | if (cpu_has_fxsr) { | 193 | if (cpu_has_fxsr) { |
208 | struct i387_fxsave_struct *fx = &fpu->state->fxsave; | 194 | fx_finit(&fpu->state->fxsave); |
209 | |||
210 | memset(fx, 0, xstate_size); | ||
211 | fx->cwd = 0x37f; | ||
212 | if (cpu_has_xmm) | ||
213 | fx->mxcsr = MXCSR_DEFAULT; | ||
214 | } else { | 195 | } else { |
215 | struct i387_fsave_struct *fp = &fpu->state->fsave; | 196 | struct i387_fsave_struct *fp = &fpu->state->fsave; |
216 | memset(fp, 0, xstate_size); | 197 | memset(fp, 0, xstate_size); |
@@ -454,7 +435,7 @@ static inline u32 twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave) | |||
454 | * FXSR floating point environment conversions. | 435 | * FXSR floating point environment conversions. |
455 | */ | 436 | */ |
456 | 437 | ||
457 | static void | 438 | void |
458 | convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk) | 439 | convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk) |
459 | { | 440 | { |
460 | struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave; | 441 | struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave; |
@@ -491,8 +472,8 @@ convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk) | |||
491 | memcpy(&to[i], &from[i], sizeof(to[0])); | 472 | memcpy(&to[i], &from[i], sizeof(to[0])); |
492 | } | 473 | } |
493 | 474 | ||
494 | static void convert_to_fxsr(struct task_struct *tsk, | 475 | void convert_to_fxsr(struct task_struct *tsk, |
495 | const struct user_i387_ia32_struct *env) | 476 | const struct user_i387_ia32_struct *env) |
496 | 477 | ||
497 | { | 478 | { |
498 | struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave; | 479 | struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave; |
@@ -589,223 +570,6 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, | |||
589 | } | 570 | } |
590 | 571 | ||
591 | /* | 572 | /* |
592 | * Signal frame handlers. | ||
593 | */ | ||
594 | |||
595 | static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf) | ||
596 | { | ||
597 | struct task_struct *tsk = current; | ||
598 | struct i387_fsave_struct *fp = &tsk->thread.fpu.state->fsave; | ||
599 | |||
600 | fp->status = fp->swd; | ||
601 | if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct))) | ||
602 | return -1; | ||
603 | return 1; | ||
604 | } | ||
605 | |||
606 | static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) | ||
607 | { | ||
608 | struct task_struct *tsk = current; | ||
609 | struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave; | ||
610 | struct user_i387_ia32_struct env; | ||
611 | int err = 0; | ||
612 | |||
613 | convert_from_fxsr(&env, tsk); | ||
614 | if (__copy_to_user(buf, &env, sizeof(env))) | ||
615 | return -1; | ||
616 | |||
617 | err |= __put_user(fx->swd, &buf->status); | ||
618 | err |= __put_user(X86_FXSR_MAGIC, &buf->magic); | ||
619 | if (err) | ||
620 | return -1; | ||
621 | |||
622 | if (__copy_to_user(&buf->_fxsr_env[0], fx, xstate_size)) | ||
623 | return -1; | ||
624 | return 1; | ||
625 | } | ||
626 | |||
627 | static int save_i387_xsave(void __user *buf) | ||
628 | { | ||
629 | struct task_struct *tsk = current; | ||
630 | struct _fpstate_ia32 __user *fx = buf; | ||
631 | int err = 0; | ||
632 | |||
633 | |||
634 | sanitize_i387_state(tsk); | ||
635 | |||
636 | /* | ||
637 | * For legacy compatible, we always set FP/SSE bits in the bit | ||
638 | * vector while saving the state to the user context. | ||
639 | * This will enable us capturing any changes(during sigreturn) to | ||
640 | * the FP/SSE bits by the legacy applications which don't touch | ||
641 | * xstate_bv in the xsave header. | ||
642 | * | ||
643 | * xsave aware applications can change the xstate_bv in the xsave | ||
644 | * header as well as change any contents in the memory layout. | ||
645 | * xrestore as part of sigreturn will capture all the changes. | ||
646 | */ | ||
647 | tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; | ||
648 | |||
649 | if (save_i387_fxsave(fx) < 0) | ||
650 | return -1; | ||
651 | |||
652 | err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved_ia32, | ||
653 | sizeof(struct _fpx_sw_bytes)); | ||
654 | err |= __put_user(FP_XSTATE_MAGIC2, | ||
655 | (__u32 __user *) (buf + sig_xstate_ia32_size | ||
656 | - FP_XSTATE_MAGIC2_SIZE)); | ||
657 | if (err) | ||
658 | return -1; | ||
659 | |||
660 | return 1; | ||
661 | } | ||
662 | |||
663 | int save_i387_xstate_ia32(void __user *buf) | ||
664 | { | ||
665 | struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; | ||
666 | struct task_struct *tsk = current; | ||
667 | |||
668 | if (!used_math()) | ||
669 | return 0; | ||
670 | |||
671 | if (!access_ok(VERIFY_WRITE, buf, sig_xstate_ia32_size)) | ||
672 | return -EACCES; | ||
673 | /* | ||
674 | * This will cause a "finit" to be triggered by the next | ||
675 | * attempted FPU operation by the 'current' process. | ||
676 | */ | ||
677 | clear_used_math(); | ||
678 | |||
679 | if (!HAVE_HWFP) { | ||
680 | return fpregs_soft_get(current, NULL, | ||
681 | 0, sizeof(struct user_i387_ia32_struct), | ||
682 | NULL, fp) ? -1 : 1; | ||
683 | } | ||
684 | |||
685 | unlazy_fpu(tsk); | ||
686 | |||
687 | if (cpu_has_xsave) | ||
688 | return save_i387_xsave(fp); | ||
689 | if (cpu_has_fxsr) | ||
690 | return save_i387_fxsave(fp); | ||
691 | else | ||
692 | return save_i387_fsave(fp); | ||
693 | } | ||
694 | |||
695 | static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) | ||
696 | { | ||
697 | struct task_struct *tsk = current; | ||
698 | |||
699 | return __copy_from_user(&tsk->thread.fpu.state->fsave, buf, | ||
700 | sizeof(struct i387_fsave_struct)); | ||
701 | } | ||
702 | |||
703 | static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf, | ||
704 | unsigned int size) | ||
705 | { | ||
706 | struct task_struct *tsk = current; | ||
707 | struct user_i387_ia32_struct env; | ||
708 | int err; | ||
709 | |||
710 | err = __copy_from_user(&tsk->thread.fpu.state->fxsave, &buf->_fxsr_env[0], | ||
711 | size); | ||
712 | /* mxcsr reserved bits must be masked to zero for security reasons */ | ||
713 | tsk->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask; | ||
714 | if (err || __copy_from_user(&env, buf, sizeof(env))) | ||
715 | return 1; | ||
716 | convert_to_fxsr(tsk, &env); | ||
717 | |||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | static int restore_i387_xsave(void __user *buf) | ||
722 | { | ||
723 | struct _fpx_sw_bytes fx_sw_user; | ||
724 | struct _fpstate_ia32 __user *fx_user = | ||
725 | ((struct _fpstate_ia32 __user *) buf); | ||
726 | struct i387_fxsave_struct __user *fx = | ||
727 | (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0]; | ||
728 | struct xsave_hdr_struct *xsave_hdr = | ||
729 | ¤t->thread.fpu.state->xsave.xsave_hdr; | ||
730 | u64 mask; | ||
731 | int err; | ||
732 | |||
733 | if (check_for_xstate(fx, buf, &fx_sw_user)) | ||
734 | goto fx_only; | ||
735 | |||
736 | mask = fx_sw_user.xstate_bv; | ||
737 | |||
738 | err = restore_i387_fxsave(buf, fx_sw_user.xstate_size); | ||
739 | |||
740 | xsave_hdr->xstate_bv &= pcntxt_mask; | ||
741 | /* | ||
742 | * These bits must be zero. | ||
743 | */ | ||
744 | xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; | ||
745 | |||
746 | /* | ||
747 | * Init the state that is not present in the memory layout | ||
748 | * and enabled by the OS. | ||
749 | */ | ||
750 | mask = ~(pcntxt_mask & ~mask); | ||
751 | xsave_hdr->xstate_bv &= mask; | ||
752 | |||
753 | return err; | ||
754 | fx_only: | ||
755 | /* | ||
756 | * Couldn't find the extended state information in the memory | ||
757 | * layout. Restore the FP/SSE and init the other extended state | ||
758 | * enabled by the OS. | ||
759 | */ | ||
760 | xsave_hdr->xstate_bv = XSTATE_FPSSE; | ||
761 | return restore_i387_fxsave(buf, sizeof(struct i387_fxsave_struct)); | ||
762 | } | ||
763 | |||
764 | int restore_i387_xstate_ia32(void __user *buf) | ||
765 | { | ||
766 | int err; | ||
767 | struct task_struct *tsk = current; | ||
768 | struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf; | ||
769 | |||
770 | if (HAVE_HWFP) | ||
771 | clear_fpu(tsk); | ||
772 | |||
773 | if (!buf) { | ||
774 | if (used_math()) { | ||
775 | clear_fpu(tsk); | ||
776 | clear_used_math(); | ||
777 | } | ||
778 | |||
779 | return 0; | ||
780 | } else | ||
781 | if (!access_ok(VERIFY_READ, buf, sig_xstate_ia32_size)) | ||
782 | return -EACCES; | ||
783 | |||
784 | if (!used_math()) { | ||
785 | err = init_fpu(tsk); | ||
786 | if (err) | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | if (HAVE_HWFP) { | ||
791 | if (cpu_has_xsave) | ||
792 | err = restore_i387_xsave(buf); | ||
793 | else if (cpu_has_fxsr) | ||
794 | err = restore_i387_fxsave(fp, sizeof(struct | ||
795 | i387_fxsave_struct)); | ||
796 | else | ||
797 | err = restore_i387_fsave(fp); | ||
798 | } else { | ||
799 | err = fpregs_soft_set(current, NULL, | ||
800 | 0, sizeof(struct user_i387_ia32_struct), | ||
801 | NULL, fp) != 0; | ||
802 | } | ||
803 | set_used_math(); | ||
804 | |||
805 | return err; | ||
806 | } | ||
807 | |||
808 | /* | ||
809 | * FPU state for core dumps. | 573 | * FPU state for core dumps. |
810 | * This is only used for a.out dumps now. | 574 | * This is only used for a.out dumps now. |
811 | * It is declared generically using elf_fpregset_t (which is | 575 | * It is declared generically using elf_fpregset_t (which is |
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index 36d1853e91af..9a5c460404dc 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c | |||
@@ -263,7 +263,7 @@ static void i8259A_shutdown(void) | |||
263 | * out of. | 263 | * out of. |
264 | */ | 264 | */ |
265 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ | 265 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ |
266 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ | 266 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ |
267 | } | 267 | } |
268 | 268 | ||
269 | static struct syscore_ops i8259_syscore_ops = { | 269 | static struct syscore_ops i8259_syscore_ops = { |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index d44f7829968e..e4595f105910 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -92,7 +92,8 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
92 | seq_printf(p, " Rescheduling interrupts\n"); | 92 | seq_printf(p, " Rescheduling interrupts\n"); |
93 | seq_printf(p, "%*s: ", prec, "CAL"); | 93 | seq_printf(p, "%*s: ", prec, "CAL"); |
94 | for_each_online_cpu(j) | 94 | for_each_online_cpu(j) |
95 | seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); | 95 | seq_printf(p, "%10u ", irq_stats(j)->irq_call_count - |
96 | irq_stats(j)->irq_tlb_count); | ||
96 | seq_printf(p, " Function call interrupts\n"); | 97 | seq_printf(p, " Function call interrupts\n"); |
97 | seq_printf(p, "%*s: ", prec, "TLB"); | 98 | seq_printf(p, "%*s: ", prec, "TLB"); |
98 | for_each_online_cpu(j) | 99 | for_each_online_cpu(j) |
@@ -147,7 +148,6 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
147 | #ifdef CONFIG_SMP | 148 | #ifdef CONFIG_SMP |
148 | sum += irq_stats(cpu)->irq_resched_count; | 149 | sum += irq_stats(cpu)->irq_resched_count; |
149 | sum += irq_stats(cpu)->irq_call_count; | 150 | sum += irq_stats(cpu)->irq_call_count; |
150 | sum += irq_stats(cpu)->irq_tlb_count; | ||
151 | #endif | 151 | #endif |
152 | #ifdef CONFIG_X86_THERMAL_VECTOR | 152 | #ifdef CONFIG_X86_THERMAL_VECTOR |
153 | sum += irq_stats(cpu)->irq_thermal_count; | 153 | sum += irq_stats(cpu)->irq_thermal_count; |
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index e2f751efb7b1..57916c0d3cf6 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c | |||
@@ -541,6 +541,23 @@ reenter_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb | |||
541 | return 1; | 541 | return 1; |
542 | } | 542 | } |
543 | 543 | ||
544 | #ifdef KPROBES_CAN_USE_FTRACE | ||
545 | static void __kprobes skip_singlestep(struct kprobe *p, struct pt_regs *regs, | ||
546 | struct kprobe_ctlblk *kcb) | ||
547 | { | ||
548 | /* | ||
549 | * Emulate singlestep (and also recover regs->ip) | ||
550 | * as if there is a 5byte nop | ||
551 | */ | ||
552 | regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE; | ||
553 | if (unlikely(p->post_handler)) { | ||
554 | kcb->kprobe_status = KPROBE_HIT_SSDONE; | ||
555 | p->post_handler(p, regs, 0); | ||
556 | } | ||
557 | __this_cpu_write(current_kprobe, NULL); | ||
558 | } | ||
559 | #endif | ||
560 | |||
544 | /* | 561 | /* |
545 | * Interrupts are disabled on entry as trap3 is an interrupt gate and they | 562 | * Interrupts are disabled on entry as trap3 is an interrupt gate and they |
546 | * remain disabled throughout this function. | 563 | * remain disabled throughout this function. |
@@ -599,6 +616,12 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
599 | } else if (kprobe_running()) { | 616 | } else if (kprobe_running()) { |
600 | p = __this_cpu_read(current_kprobe); | 617 | p = __this_cpu_read(current_kprobe); |
601 | if (p->break_handler && p->break_handler(p, regs)) { | 618 | if (p->break_handler && p->break_handler(p, regs)) { |
619 | #ifdef KPROBES_CAN_USE_FTRACE | ||
620 | if (kprobe_ftrace(p)) { | ||
621 | skip_singlestep(p, regs, kcb); | ||
622 | return 1; | ||
623 | } | ||
624 | #endif | ||
602 | setup_singlestep(p, regs, kcb, 0); | 625 | setup_singlestep(p, regs, kcb, 0); |
603 | return 1; | 626 | return 1; |
604 | } | 627 | } |
@@ -1052,6 +1075,50 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
1052 | return 0; | 1075 | return 0; |
1053 | } | 1076 | } |
1054 | 1077 | ||
1078 | #ifdef KPROBES_CAN_USE_FTRACE | ||
1079 | /* Ftrace callback handler for kprobes */ | ||
1080 | void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, | ||
1081 | struct ftrace_ops *ops, struct pt_regs *regs) | ||
1082 | { | ||
1083 | struct kprobe *p; | ||
1084 | struct kprobe_ctlblk *kcb; | ||
1085 | unsigned long flags; | ||
1086 | |||
1087 | /* Disable irq for emulating a breakpoint and avoiding preempt */ | ||
1088 | local_irq_save(flags); | ||
1089 | |||
1090 | p = get_kprobe((kprobe_opcode_t *)ip); | ||
1091 | if (unlikely(!p) || kprobe_disabled(p)) | ||
1092 | goto end; | ||
1093 | |||
1094 | kcb = get_kprobe_ctlblk(); | ||
1095 | if (kprobe_running()) { | ||
1096 | kprobes_inc_nmissed_count(p); | ||
1097 | } else { | ||
1098 | /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */ | ||
1099 | regs->ip = ip + sizeof(kprobe_opcode_t); | ||
1100 | |||
1101 | __this_cpu_write(current_kprobe, p); | ||
1102 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
1103 | if (!p->pre_handler || !p->pre_handler(p, regs)) | ||
1104 | skip_singlestep(p, regs, kcb); | ||
1105 | /* | ||
1106 | * If pre_handler returns !0, it sets regs->ip and | ||
1107 | * resets current kprobe. | ||
1108 | */ | ||
1109 | } | ||
1110 | end: | ||
1111 | local_irq_restore(flags); | ||
1112 | } | ||
1113 | |||
1114 | int __kprobes arch_prepare_kprobe_ftrace(struct kprobe *p) | ||
1115 | { | ||
1116 | p->ainsn.insn = NULL; | ||
1117 | p->ainsn.boostable = -1; | ||
1118 | return 0; | ||
1119 | } | ||
1120 | #endif | ||
1121 | |||
1055 | int __init arch_init_kprobes(void) | 1122 | int __init arch_init_kprobes(void) |
1056 | { | 1123 | { |
1057 | return arch_init_optprobes(); | 1124 | return arch_init_optprobes(); |
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 82746f942cd8..7720ff5a9ee2 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
@@ -75,20 +75,113 @@ struct microcode_amd { | |||
75 | 75 | ||
76 | static struct equiv_cpu_entry *equiv_cpu_table; | 76 | static struct equiv_cpu_entry *equiv_cpu_table; |
77 | 77 | ||
78 | /* page-sized ucode patch buffer */ | 78 | struct ucode_patch { |
79 | void *patch; | 79 | struct list_head plist; |
80 | void *data; | ||
81 | u32 patch_id; | ||
82 | u16 equiv_cpu; | ||
83 | }; | ||
84 | |||
85 | static LIST_HEAD(pcache); | ||
86 | |||
87 | static u16 find_equiv_id(unsigned int cpu) | ||
88 | { | ||
89 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
90 | int i = 0; | ||
91 | |||
92 | if (!equiv_cpu_table) | ||
93 | return 0; | ||
94 | |||
95 | while (equiv_cpu_table[i].installed_cpu != 0) { | ||
96 | if (uci->cpu_sig.sig == equiv_cpu_table[i].installed_cpu) | ||
97 | return equiv_cpu_table[i].equiv_cpu; | ||
98 | |||
99 | i++; | ||
100 | } | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu) | ||
105 | { | ||
106 | int i = 0; | ||
107 | |||
108 | BUG_ON(!equiv_cpu_table); | ||
109 | |||
110 | while (equiv_cpu_table[i].equiv_cpu != 0) { | ||
111 | if (equiv_cpu == equiv_cpu_table[i].equiv_cpu) | ||
112 | return equiv_cpu_table[i].installed_cpu; | ||
113 | i++; | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * a small, trivial cache of per-family ucode patches | ||
120 | */ | ||
121 | static struct ucode_patch *cache_find_patch(u16 equiv_cpu) | ||
122 | { | ||
123 | struct ucode_patch *p; | ||
124 | |||
125 | list_for_each_entry(p, &pcache, plist) | ||
126 | if (p->equiv_cpu == equiv_cpu) | ||
127 | return p; | ||
128 | return NULL; | ||
129 | } | ||
130 | |||
131 | static void update_cache(struct ucode_patch *new_patch) | ||
132 | { | ||
133 | struct ucode_patch *p; | ||
134 | |||
135 | list_for_each_entry(p, &pcache, plist) { | ||
136 | if (p->equiv_cpu == new_patch->equiv_cpu) { | ||
137 | if (p->patch_id >= new_patch->patch_id) | ||
138 | /* we already have the latest patch */ | ||
139 | return; | ||
140 | |||
141 | list_replace(&p->plist, &new_patch->plist); | ||
142 | kfree(p->data); | ||
143 | kfree(p); | ||
144 | return; | ||
145 | } | ||
146 | } | ||
147 | /* no patch found, add it */ | ||
148 | list_add_tail(&new_patch->plist, &pcache); | ||
149 | } | ||
150 | |||
151 | static void free_cache(void) | ||
152 | { | ||
153 | struct ucode_patch *p, *tmp; | ||
154 | |||
155 | list_for_each_entry_safe(p, tmp, &pcache, plist) { | ||
156 | __list_del(p->plist.prev, p->plist.next); | ||
157 | kfree(p->data); | ||
158 | kfree(p); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static struct ucode_patch *find_patch(unsigned int cpu) | ||
163 | { | ||
164 | u16 equiv_id; | ||
165 | |||
166 | equiv_id = find_equiv_id(cpu); | ||
167 | if (!equiv_id) | ||
168 | return NULL; | ||
169 | |||
170 | return cache_find_patch(equiv_id); | ||
171 | } | ||
80 | 172 | ||
81 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) | 173 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) |
82 | { | 174 | { |
83 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 175 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
84 | 176 | ||
177 | csig->sig = cpuid_eax(0x00000001); | ||
85 | csig->rev = c->microcode; | 178 | csig->rev = c->microcode; |
86 | pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); | 179 | pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); |
87 | 180 | ||
88 | return 0; | 181 | return 0; |
89 | } | 182 | } |
90 | 183 | ||
91 | static unsigned int verify_ucode_size(int cpu, u32 patch_size, | 184 | static unsigned int verify_patch_size(int cpu, u32 patch_size, |
92 | unsigned int size) | 185 | unsigned int size) |
93 | { | 186 | { |
94 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 187 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
@@ -118,95 +211,37 @@ static unsigned int verify_ucode_size(int cpu, u32 patch_size, | |||
118 | return patch_size; | 211 | return patch_size; |
119 | } | 212 | } |
120 | 213 | ||
121 | static u16 find_equiv_id(void) | 214 | static int apply_microcode_amd(int cpu) |
122 | { | 215 | { |
123 | unsigned int current_cpu_id, i = 0; | 216 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
124 | 217 | struct microcode_amd *mc_amd; | |
125 | BUG_ON(equiv_cpu_table == NULL); | 218 | struct ucode_cpu_info *uci; |
126 | 219 | struct ucode_patch *p; | |
127 | current_cpu_id = cpuid_eax(0x00000001); | 220 | u32 rev, dummy; |
128 | |||
129 | while (equiv_cpu_table[i].installed_cpu != 0) { | ||
130 | if (current_cpu_id == equiv_cpu_table[i].installed_cpu) | ||
131 | return equiv_cpu_table[i].equiv_cpu; | ||
132 | |||
133 | i++; | ||
134 | } | ||
135 | return 0; | ||
136 | } | ||
137 | 221 | ||
138 | /* | 222 | BUG_ON(raw_smp_processor_id() != cpu); |
139 | * we signal a good patch is found by returning its size > 0 | ||
140 | */ | ||
141 | static int get_matching_microcode(int cpu, const u8 *ucode_ptr, | ||
142 | unsigned int leftover_size, int rev, | ||
143 | unsigned int *current_size) | ||
144 | { | ||
145 | struct microcode_header_amd *mc_hdr; | ||
146 | unsigned int actual_size, patch_size; | ||
147 | u16 equiv_cpu_id; | ||
148 | 223 | ||
149 | /* size of the current patch we're staring at */ | 224 | uci = ucode_cpu_info + cpu; |
150 | patch_size = *(u32 *)(ucode_ptr + 4); | ||
151 | *current_size = patch_size + SECTION_HDR_SIZE; | ||
152 | 225 | ||
153 | equiv_cpu_id = find_equiv_id(); | 226 | p = find_patch(cpu); |
154 | if (!equiv_cpu_id) | 227 | if (!p) |
155 | return 0; | 228 | return 0; |
156 | 229 | ||
157 | /* | 230 | mc_amd = p->data; |
158 | * let's look at the patch header itself now | 231 | uci->mc = p->data; |
159 | */ | ||
160 | mc_hdr = (struct microcode_header_amd *)(ucode_ptr + SECTION_HDR_SIZE); | ||
161 | 232 | ||
162 | if (mc_hdr->processor_rev_id != equiv_cpu_id) | 233 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); |
163 | return 0; | ||
164 | 234 | ||
165 | /* ucode might be chipset specific -- currently we don't support this */ | 235 | /* need to apply patch? */ |
166 | if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { | 236 | if (rev >= mc_amd->hdr.patch_id) { |
167 | pr_err("CPU%d: chipset specific code not yet supported\n", | 237 | c->microcode = rev; |
168 | cpu); | ||
169 | return 0; | 238 | return 0; |
170 | } | 239 | } |
171 | 240 | ||
172 | if (mc_hdr->patch_id <= rev) | ||
173 | return 0; | ||
174 | |||
175 | /* | ||
176 | * now that the header looks sane, verify its size | ||
177 | */ | ||
178 | actual_size = verify_ucode_size(cpu, patch_size, leftover_size); | ||
179 | if (!actual_size) | ||
180 | return 0; | ||
181 | |||
182 | /* clear the patch buffer */ | ||
183 | memset(patch, 0, PAGE_SIZE); | ||
184 | |||
185 | /* all looks ok, get the binary patch */ | ||
186 | get_ucode_data(patch, ucode_ptr + SECTION_HDR_SIZE, actual_size); | ||
187 | |||
188 | return actual_size; | ||
189 | } | ||
190 | |||
191 | static int apply_microcode_amd(int cpu) | ||
192 | { | ||
193 | u32 rev, dummy; | ||
194 | int cpu_num = raw_smp_processor_id(); | ||
195 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | ||
196 | struct microcode_amd *mc_amd = uci->mc; | ||
197 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
198 | |||
199 | /* We should bind the task to the CPU */ | ||
200 | BUG_ON(cpu_num != cpu); | ||
201 | |||
202 | if (mc_amd == NULL) | ||
203 | return 0; | ||
204 | |||
205 | wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); | 241 | wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); |
206 | /* get patch id after patching */ | ||
207 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); | ||
208 | 242 | ||
209 | /* check current patch id and patch's id for match */ | 243 | /* verify patch application was successful */ |
244 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); | ||
210 | if (rev != mc_amd->hdr.patch_id) { | 245 | if (rev != mc_amd->hdr.patch_id) { |
211 | pr_err("CPU%d: update failed for patch_level=0x%08x\n", | 246 | pr_err("CPU%d: update failed for patch_level=0x%08x\n", |
212 | cpu, mc_amd->hdr.patch_id); | 247 | cpu, mc_amd->hdr.patch_id); |
@@ -238,7 +273,7 @@ static int install_equiv_cpu_table(const u8 *buf) | |||
238 | return -ENOMEM; | 273 | return -ENOMEM; |
239 | } | 274 | } |
240 | 275 | ||
241 | get_ucode_data(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size); | 276 | memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size); |
242 | 277 | ||
243 | /* add header length */ | 278 | /* add header length */ |
244 | return size + CONTAINER_HDR_SZ; | 279 | return size + CONTAINER_HDR_SZ; |
@@ -250,61 +285,113 @@ static void free_equiv_cpu_table(void) | |||
250 | equiv_cpu_table = NULL; | 285 | equiv_cpu_table = NULL; |
251 | } | 286 | } |
252 | 287 | ||
253 | static enum ucode_state | 288 | static void cleanup(void) |
254 | generic_load_microcode(int cpu, const u8 *data, size_t size) | ||
255 | { | 289 | { |
256 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 290 | free_equiv_cpu_table(); |
257 | struct microcode_header_amd *mc_hdr = NULL; | 291 | free_cache(); |
258 | unsigned int mc_size, leftover, current_size = 0; | 292 | } |
293 | |||
294 | /* | ||
295 | * We return the current size even if some of the checks failed so that | ||
296 | * we can skip over the next patch. If we return a negative value, we | ||
297 | * signal a grave error like a memory allocation has failed and the | ||
298 | * driver cannot continue functioning normally. In such cases, we tear | ||
299 | * down everything we've used up so far and exit. | ||
300 | */ | ||
301 | static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover) | ||
302 | { | ||
303 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
304 | struct microcode_header_amd *mc_hdr; | ||
305 | struct ucode_patch *patch; | ||
306 | unsigned int patch_size, crnt_size, ret; | ||
307 | u32 proc_fam; | ||
308 | u16 proc_id; | ||
309 | |||
310 | patch_size = *(u32 *)(fw + 4); | ||
311 | crnt_size = patch_size + SECTION_HDR_SIZE; | ||
312 | mc_hdr = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE); | ||
313 | proc_id = mc_hdr->processor_rev_id; | ||
314 | |||
315 | proc_fam = find_cpu_family_by_equiv_cpu(proc_id); | ||
316 | if (!proc_fam) { | ||
317 | pr_err("No patch family for equiv ID: 0x%04x\n", proc_id); | ||
318 | return crnt_size; | ||
319 | } | ||
320 | |||
321 | /* check if patch is for the current family */ | ||
322 | proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff); | ||
323 | if (proc_fam != c->x86) | ||
324 | return crnt_size; | ||
325 | |||
326 | if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) { | ||
327 | pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", | ||
328 | mc_hdr->patch_id); | ||
329 | return crnt_size; | ||
330 | } | ||
331 | |||
332 | ret = verify_patch_size(cpu, patch_size, leftover); | ||
333 | if (!ret) { | ||
334 | pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id); | ||
335 | return crnt_size; | ||
336 | } | ||
337 | |||
338 | patch = kzalloc(sizeof(*patch), GFP_KERNEL); | ||
339 | if (!patch) { | ||
340 | pr_err("Patch allocation failure.\n"); | ||
341 | return -EINVAL; | ||
342 | } | ||
343 | |||
344 | patch->data = kzalloc(patch_size, GFP_KERNEL); | ||
345 | if (!patch->data) { | ||
346 | pr_err("Patch data allocation failure.\n"); | ||
347 | kfree(patch); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | |||
351 | /* All looks ok, copy patch... */ | ||
352 | memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size); | ||
353 | INIT_LIST_HEAD(&patch->plist); | ||
354 | patch->patch_id = mc_hdr->patch_id; | ||
355 | patch->equiv_cpu = proc_id; | ||
356 | |||
357 | /* ... and add to cache. */ | ||
358 | update_cache(patch); | ||
359 | |||
360 | return crnt_size; | ||
361 | } | ||
362 | |||
363 | static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) | ||
364 | { | ||
365 | enum ucode_state ret = UCODE_ERROR; | ||
366 | unsigned int leftover; | ||
367 | u8 *fw = (u8 *)data; | ||
368 | int crnt_size = 0; | ||
259 | int offset; | 369 | int offset; |
260 | const u8 *ucode_ptr = data; | ||
261 | void *new_mc = NULL; | ||
262 | unsigned int new_rev = uci->cpu_sig.rev; | ||
263 | enum ucode_state state = UCODE_ERROR; | ||
264 | 370 | ||
265 | offset = install_equiv_cpu_table(ucode_ptr); | 371 | offset = install_equiv_cpu_table(data); |
266 | if (offset < 0) { | 372 | if (offset < 0) { |
267 | pr_err("failed to create equivalent cpu table\n"); | 373 | pr_err("failed to create equivalent cpu table\n"); |
268 | goto out; | 374 | return ret; |
269 | } | 375 | } |
270 | ucode_ptr += offset; | 376 | fw += offset; |
271 | leftover = size - offset; | 377 | leftover = size - offset; |
272 | 378 | ||
273 | if (*(u32 *)ucode_ptr != UCODE_UCODE_TYPE) { | 379 | if (*(u32 *)fw != UCODE_UCODE_TYPE) { |
274 | pr_err("invalid type field in container file section header\n"); | 380 | pr_err("invalid type field in container file section header\n"); |
275 | goto free_table; | 381 | free_equiv_cpu_table(); |
382 | return ret; | ||
276 | } | 383 | } |
277 | 384 | ||
278 | while (leftover) { | 385 | while (leftover) { |
279 | mc_size = get_matching_microcode(cpu, ucode_ptr, leftover, | 386 | crnt_size = verify_and_add_patch(cpu, fw, leftover); |
280 | new_rev, ¤t_size); | 387 | if (crnt_size < 0) |
281 | if (mc_size) { | 388 | return ret; |
282 | mc_hdr = patch; | ||
283 | new_mc = patch; | ||
284 | new_rev = mc_hdr->patch_id; | ||
285 | goto out_ok; | ||
286 | } | ||
287 | |||
288 | ucode_ptr += current_size; | ||
289 | leftover -= current_size; | ||
290 | } | ||
291 | 389 | ||
292 | if (!new_mc) { | 390 | fw += crnt_size; |
293 | state = UCODE_NFOUND; | 391 | leftover -= crnt_size; |
294 | goto free_table; | ||
295 | } | 392 | } |
296 | 393 | ||
297 | out_ok: | 394 | return UCODE_OK; |
298 | uci->mc = new_mc; | ||
299 | state = UCODE_OK; | ||
300 | pr_debug("CPU%d update ucode (0x%08x -> 0x%08x)\n", | ||
301 | cpu, uci->cpu_sig.rev, new_rev); | ||
302 | |||
303 | free_table: | ||
304 | free_equiv_cpu_table(); | ||
305 | |||
306 | out: | ||
307 | return state; | ||
308 | } | 395 | } |
309 | 396 | ||
310 | /* | 397 | /* |
@@ -315,7 +402,7 @@ out: | |||
315 | * | 402 | * |
316 | * This legacy file is always smaller than 2K in size. | 403 | * This legacy file is always smaller than 2K in size. |
317 | * | 404 | * |
318 | * Starting at family 15h they are in family specific firmware files: | 405 | * Beginning with family 15h, they are in family-specific firmware files: |
319 | * | 406 | * |
320 | * amd-ucode/microcode_amd_fam15h.bin | 407 | * amd-ucode/microcode_amd_fam15h.bin |
321 | * amd-ucode/microcode_amd_fam16h.bin | 408 | * amd-ucode/microcode_amd_fam16h.bin |
@@ -323,12 +410,17 @@ out: | |||
323 | * | 410 | * |
324 | * These might be larger than 2K. | 411 | * These might be larger than 2K. |
325 | */ | 412 | */ |
326 | static enum ucode_state request_microcode_amd(int cpu, struct device *device) | 413 | static enum ucode_state request_microcode_amd(int cpu, struct device *device, |
414 | bool refresh_fw) | ||
327 | { | 415 | { |
328 | char fw_name[36] = "amd-ucode/microcode_amd.bin"; | 416 | char fw_name[36] = "amd-ucode/microcode_amd.bin"; |
329 | const struct firmware *fw; | ||
330 | enum ucode_state ret = UCODE_NFOUND; | ||
331 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 417 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
418 | enum ucode_state ret = UCODE_NFOUND; | ||
419 | const struct firmware *fw; | ||
420 | |||
421 | /* reload ucode container only on the boot cpu */ | ||
422 | if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index) | ||
423 | return UCODE_OK; | ||
332 | 424 | ||
333 | if (c->x86 >= 0x15) | 425 | if (c->x86 >= 0x15) |
334 | snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); | 426 | snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); |
@@ -344,12 +436,17 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device) | |||
344 | goto fw_release; | 436 | goto fw_release; |
345 | } | 437 | } |
346 | 438 | ||
347 | ret = generic_load_microcode(cpu, fw->data, fw->size); | 439 | /* free old equiv table */ |
440 | free_equiv_cpu_table(); | ||
441 | |||
442 | ret = load_microcode_amd(cpu, fw->data, fw->size); | ||
443 | if (ret != UCODE_OK) | ||
444 | cleanup(); | ||
348 | 445 | ||
349 | fw_release: | 446 | fw_release: |
350 | release_firmware(fw); | 447 | release_firmware(fw); |
351 | 448 | ||
352 | out: | 449 | out: |
353 | return ret; | 450 | return ret; |
354 | } | 451 | } |
355 | 452 | ||
@@ -383,14 +480,10 @@ struct microcode_ops * __init init_amd_microcode(void) | |||
383 | return NULL; | 480 | return NULL; |
384 | } | 481 | } |
385 | 482 | ||
386 | patch = (void *)get_zeroed_page(GFP_KERNEL); | ||
387 | if (!patch) | ||
388 | return NULL; | ||
389 | |||
390 | return µcode_amd_ops; | 483 | return µcode_amd_ops; |
391 | } | 484 | } |
392 | 485 | ||
393 | void __exit exit_amd_microcode(void) | 486 | void __exit exit_amd_microcode(void) |
394 | { | 487 | { |
395 | free_page((unsigned long)patch); | 488 | cleanup(); |
396 | } | 489 | } |
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 4873e62db6a1..3a04b224d0c0 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c | |||
@@ -225,6 +225,9 @@ static ssize_t microcode_write(struct file *file, const char __user *buf, | |||
225 | if (do_microcode_update(buf, len) == 0) | 225 | if (do_microcode_update(buf, len) == 0) |
226 | ret = (ssize_t)len; | 226 | ret = (ssize_t)len; |
227 | 227 | ||
228 | if (ret > 0) | ||
229 | perf_check_microcode(); | ||
230 | |||
228 | mutex_unlock(µcode_mutex); | 231 | mutex_unlock(µcode_mutex); |
229 | put_online_cpus(); | 232 | put_online_cpus(); |
230 | 233 | ||
@@ -276,19 +279,18 @@ static struct platform_device *microcode_pdev; | |||
276 | static int reload_for_cpu(int cpu) | 279 | static int reload_for_cpu(int cpu) |
277 | { | 280 | { |
278 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 281 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
282 | enum ucode_state ustate; | ||
279 | int err = 0; | 283 | int err = 0; |
280 | 284 | ||
281 | if (uci->valid) { | 285 | if (!uci->valid) |
282 | enum ucode_state ustate; | 286 | return err; |
283 | |||
284 | ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev); | ||
285 | if (ustate == UCODE_OK) | ||
286 | apply_microcode_on_target(cpu); | ||
287 | else | ||
288 | if (ustate == UCODE_ERROR) | ||
289 | err = -EINVAL; | ||
290 | } | ||
291 | 287 | ||
288 | ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev, true); | ||
289 | if (ustate == UCODE_OK) | ||
290 | apply_microcode_on_target(cpu); | ||
291 | else | ||
292 | if (ustate == UCODE_ERROR) | ||
293 | err = -EINVAL; | ||
292 | return err; | 294 | return err; |
293 | } | 295 | } |
294 | 296 | ||
@@ -370,18 +372,15 @@ static void microcode_fini_cpu(int cpu) | |||
370 | 372 | ||
371 | static enum ucode_state microcode_resume_cpu(int cpu) | 373 | static enum ucode_state microcode_resume_cpu(int cpu) |
372 | { | 374 | { |
373 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
374 | |||
375 | if (!uci->mc) | ||
376 | return UCODE_NFOUND; | ||
377 | |||
378 | pr_debug("CPU%d updated upon resume\n", cpu); | 375 | pr_debug("CPU%d updated upon resume\n", cpu); |
379 | apply_microcode_on_target(cpu); | 376 | |
377 | if (apply_microcode_on_target(cpu)) | ||
378 | return UCODE_ERROR; | ||
380 | 379 | ||
381 | return UCODE_OK; | 380 | return UCODE_OK; |
382 | } | 381 | } |
383 | 382 | ||
384 | static enum ucode_state microcode_init_cpu(int cpu) | 383 | static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw) |
385 | { | 384 | { |
386 | enum ucode_state ustate; | 385 | enum ucode_state ustate; |
387 | 386 | ||
@@ -392,7 +391,8 @@ static enum ucode_state microcode_init_cpu(int cpu) | |||
392 | if (system_state != SYSTEM_RUNNING) | 391 | if (system_state != SYSTEM_RUNNING) |
393 | return UCODE_NFOUND; | 392 | return UCODE_NFOUND; |
394 | 393 | ||
395 | ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev); | 394 | ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev, |
395 | refresh_fw); | ||
396 | 396 | ||
397 | if (ustate == UCODE_OK) { | 397 | if (ustate == UCODE_OK) { |
398 | pr_debug("CPU%d updated upon init\n", cpu); | 398 | pr_debug("CPU%d updated upon init\n", cpu); |
@@ -405,14 +405,11 @@ static enum ucode_state microcode_init_cpu(int cpu) | |||
405 | static enum ucode_state microcode_update_cpu(int cpu) | 405 | static enum ucode_state microcode_update_cpu(int cpu) |
406 | { | 406 | { |
407 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 407 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
408 | enum ucode_state ustate; | ||
409 | 408 | ||
410 | if (uci->valid) | 409 | if (uci->valid) |
411 | ustate = microcode_resume_cpu(cpu); | 410 | return microcode_resume_cpu(cpu); |
412 | else | ||
413 | ustate = microcode_init_cpu(cpu); | ||
414 | 411 | ||
415 | return ustate; | 412 | return microcode_init_cpu(cpu, false); |
416 | } | 413 | } |
417 | 414 | ||
418 | static int mc_device_add(struct device *dev, struct subsys_interface *sif) | 415 | static int mc_device_add(struct device *dev, struct subsys_interface *sif) |
@@ -428,7 +425,7 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif) | |||
428 | if (err) | 425 | if (err) |
429 | return err; | 426 | return err; |
430 | 427 | ||
431 | if (microcode_init_cpu(cpu) == UCODE_ERROR) | 428 | if (microcode_init_cpu(cpu, true) == UCODE_ERROR) |
432 | return -EINVAL; | 429 | return -EINVAL; |
433 | 430 | ||
434 | return err; | 431 | return err; |
@@ -477,34 +474,41 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) | |||
477 | struct device *dev; | 474 | struct device *dev; |
478 | 475 | ||
479 | dev = get_cpu_device(cpu); | 476 | dev = get_cpu_device(cpu); |
480 | switch (action) { | 477 | |
478 | switch (action & ~CPU_TASKS_FROZEN) { | ||
481 | case CPU_ONLINE: | 479 | case CPU_ONLINE: |
482 | case CPU_ONLINE_FROZEN: | ||
483 | microcode_update_cpu(cpu); | 480 | microcode_update_cpu(cpu); |
484 | case CPU_DOWN_FAILED: | ||
485 | case CPU_DOWN_FAILED_FROZEN: | ||
486 | pr_debug("CPU%d added\n", cpu); | 481 | pr_debug("CPU%d added\n", cpu); |
482 | /* | ||
483 | * "break" is missing on purpose here because we want to fall | ||
484 | * through in order to create the sysfs group. | ||
485 | */ | ||
486 | |||
487 | case CPU_DOWN_FAILED: | ||
487 | if (sysfs_create_group(&dev->kobj, &mc_attr_group)) | 488 | if (sysfs_create_group(&dev->kobj, &mc_attr_group)) |
488 | pr_err("Failed to create group for CPU%d\n", cpu); | 489 | pr_err("Failed to create group for CPU%d\n", cpu); |
489 | break; | 490 | break; |
491 | |||
490 | case CPU_DOWN_PREPARE: | 492 | case CPU_DOWN_PREPARE: |
491 | case CPU_DOWN_PREPARE_FROZEN: | ||
492 | /* Suspend is in progress, only remove the interface */ | 493 | /* Suspend is in progress, only remove the interface */ |
493 | sysfs_remove_group(&dev->kobj, &mc_attr_group); | 494 | sysfs_remove_group(&dev->kobj, &mc_attr_group); |
494 | pr_debug("CPU%d removed\n", cpu); | 495 | pr_debug("CPU%d removed\n", cpu); |
495 | break; | 496 | break; |
496 | 497 | ||
497 | /* | 498 | /* |
499 | * case CPU_DEAD: | ||
500 | * | ||
498 | * When a CPU goes offline, don't free up or invalidate the copy of | 501 | * When a CPU goes offline, don't free up or invalidate the copy of |
499 | * the microcode in kernel memory, so that we can reuse it when the | 502 | * the microcode in kernel memory, so that we can reuse it when the |
500 | * CPU comes back online without unnecessarily requesting the userspace | 503 | * CPU comes back online without unnecessarily requesting the userspace |
501 | * for it again. | 504 | * for it again. |
502 | */ | 505 | */ |
503 | case CPU_UP_CANCELED_FROZEN: | ||
504 | /* The CPU refused to come up during a system resume */ | ||
505 | microcode_fini_cpu(cpu); | ||
506 | break; | ||
507 | } | 506 | } |
507 | |||
508 | /* The CPU refused to come up during a system resume */ | ||
509 | if (action == CPU_UP_CANCELED_FROZEN) | ||
510 | microcode_fini_cpu(cpu); | ||
511 | |||
508 | return NOTIFY_OK; | 512 | return NOTIFY_OK; |
509 | } | 513 | } |
510 | 514 | ||
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 0327e2b3c408..3544aed39338 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
@@ -405,7 +405,8 @@ static int get_ucode_fw(void *to, const void *from, size_t n) | |||
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | 407 | ||
408 | static enum ucode_state request_microcode_fw(int cpu, struct device *device) | 408 | static enum ucode_state request_microcode_fw(int cpu, struct device *device, |
409 | bool refresh_fw) | ||
409 | { | 410 | { |
410 | char name[30]; | 411 | char name[30]; |
411 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 412 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index eb113693f043..a7c5661f8496 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c | |||
@@ -257,12 +257,14 @@ static int __init msr_init(void) | |||
257 | goto out_chrdev; | 257 | goto out_chrdev; |
258 | } | 258 | } |
259 | msr_class->devnode = msr_devnode; | 259 | msr_class->devnode = msr_devnode; |
260 | get_online_cpus(); | ||
260 | for_each_online_cpu(i) { | 261 | for_each_online_cpu(i) { |
261 | err = msr_device_create(i); | 262 | err = msr_device_create(i); |
262 | if (err != 0) | 263 | if (err != 0) |
263 | goto out_class; | 264 | goto out_class; |
264 | } | 265 | } |
265 | register_hotcpu_notifier(&msr_class_cpu_notifier); | 266 | register_hotcpu_notifier(&msr_class_cpu_notifier); |
267 | put_online_cpus(); | ||
266 | 268 | ||
267 | err = 0; | 269 | err = 0; |
268 | goto out; | 270 | goto out; |
@@ -271,6 +273,7 @@ out_class: | |||
271 | i = 0; | 273 | i = 0; |
272 | for_each_online_cpu(i) | 274 | for_each_online_cpu(i) |
273 | msr_device_destroy(i); | 275 | msr_device_destroy(i); |
276 | put_online_cpus(); | ||
274 | class_destroy(msr_class); | 277 | class_destroy(msr_class); |
275 | out_chrdev: | 278 | out_chrdev: |
276 | __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); | 279 | __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); |
@@ -281,11 +284,13 @@ out: | |||
281 | static void __exit msr_exit(void) | 284 | static void __exit msr_exit(void) |
282 | { | 285 | { |
283 | int cpu = 0; | 286 | int cpu = 0; |
287 | get_online_cpus(); | ||
284 | for_each_online_cpu(cpu) | 288 | for_each_online_cpu(cpu) |
285 | msr_device_destroy(cpu); | 289 | msr_device_destroy(cpu); |
286 | class_destroy(msr_class); | 290 | class_destroy(msr_class); |
287 | __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); | 291 | __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); |
288 | unregister_hotcpu_notifier(&msr_class_cpu_notifier); | 292 | unregister_hotcpu_notifier(&msr_class_cpu_notifier); |
293 | put_online_cpus(); | ||
289 | } | 294 | } |
290 | 295 | ||
291 | module_init(msr_init); | 296 | module_init(msr_init); |
diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c new file mode 100644 index 000000000000..e309cc5c276e --- /dev/null +++ b/arch/x86/kernel/perf_regs.c | |||
@@ -0,0 +1,105 @@ | |||
1 | #include <linux/errno.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/sched.h> | ||
4 | #include <linux/perf_event.h> | ||
5 | #include <linux/bug.h> | ||
6 | #include <linux/stddef.h> | ||
7 | #include <asm/perf_regs.h> | ||
8 | #include <asm/ptrace.h> | ||
9 | |||
10 | #ifdef CONFIG_X86_32 | ||
11 | #define PERF_REG_X86_MAX PERF_REG_X86_32_MAX | ||
12 | #else | ||
13 | #define PERF_REG_X86_MAX PERF_REG_X86_64_MAX | ||
14 | #endif | ||
15 | |||
16 | #define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r) | ||
17 | |||
18 | static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = { | ||
19 | PT_REGS_OFFSET(PERF_REG_X86_AX, ax), | ||
20 | PT_REGS_OFFSET(PERF_REG_X86_BX, bx), | ||
21 | PT_REGS_OFFSET(PERF_REG_X86_CX, cx), | ||
22 | PT_REGS_OFFSET(PERF_REG_X86_DX, dx), | ||
23 | PT_REGS_OFFSET(PERF_REG_X86_SI, si), | ||
24 | PT_REGS_OFFSET(PERF_REG_X86_DI, di), | ||
25 | PT_REGS_OFFSET(PERF_REG_X86_BP, bp), | ||
26 | PT_REGS_OFFSET(PERF_REG_X86_SP, sp), | ||
27 | PT_REGS_OFFSET(PERF_REG_X86_IP, ip), | ||
28 | PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags), | ||
29 | PT_REGS_OFFSET(PERF_REG_X86_CS, cs), | ||
30 | PT_REGS_OFFSET(PERF_REG_X86_SS, ss), | ||
31 | #ifdef CONFIG_X86_32 | ||
32 | PT_REGS_OFFSET(PERF_REG_X86_DS, ds), | ||
33 | PT_REGS_OFFSET(PERF_REG_X86_ES, es), | ||
34 | PT_REGS_OFFSET(PERF_REG_X86_FS, fs), | ||
35 | PT_REGS_OFFSET(PERF_REG_X86_GS, gs), | ||
36 | #else | ||
37 | /* | ||
38 | * The pt_regs struct does not store | ||
39 | * ds, es, fs, gs in 64 bit mode. | ||
40 | */ | ||
41 | (unsigned int) -1, | ||
42 | (unsigned int) -1, | ||
43 | (unsigned int) -1, | ||
44 | (unsigned int) -1, | ||
45 | #endif | ||
46 | #ifdef CONFIG_X86_64 | ||
47 | PT_REGS_OFFSET(PERF_REG_X86_R8, r8), | ||
48 | PT_REGS_OFFSET(PERF_REG_X86_R9, r9), | ||
49 | PT_REGS_OFFSET(PERF_REG_X86_R10, r10), | ||
50 | PT_REGS_OFFSET(PERF_REG_X86_R11, r11), | ||
51 | PT_REGS_OFFSET(PERF_REG_X86_R12, r12), | ||
52 | PT_REGS_OFFSET(PERF_REG_X86_R13, r13), | ||
53 | PT_REGS_OFFSET(PERF_REG_X86_R14, r14), | ||
54 | PT_REGS_OFFSET(PERF_REG_X86_R15, r15), | ||
55 | #endif | ||
56 | }; | ||
57 | |||
58 | u64 perf_reg_value(struct pt_regs *regs, int idx) | ||
59 | { | ||
60 | if (WARN_ON_ONCE(idx >= ARRAY_SIZE(pt_regs_offset))) | ||
61 | return 0; | ||
62 | |||
63 | return regs_get_register(regs, pt_regs_offset[idx]); | ||
64 | } | ||
65 | |||
66 | #define REG_RESERVED (~((1ULL << PERF_REG_X86_MAX) - 1ULL)) | ||
67 | |||
68 | #ifdef CONFIG_X86_32 | ||
69 | int perf_reg_validate(u64 mask) | ||
70 | { | ||
71 | if (!mask || mask & REG_RESERVED) | ||
72 | return -EINVAL; | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | u64 perf_reg_abi(struct task_struct *task) | ||
78 | { | ||
79 | return PERF_SAMPLE_REGS_ABI_32; | ||
80 | } | ||
81 | #else /* CONFIG_X86_64 */ | ||
82 | #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ | ||
83 | (1ULL << PERF_REG_X86_ES) | \ | ||
84 | (1ULL << PERF_REG_X86_FS) | \ | ||
85 | (1ULL << PERF_REG_X86_GS)) | ||
86 | |||
87 | int perf_reg_validate(u64 mask) | ||
88 | { | ||
89 | if (!mask || mask & REG_RESERVED) | ||
90 | return -EINVAL; | ||
91 | |||
92 | if (mask & REG_NOSUPPORT) | ||
93 | return -EINVAL; | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | u64 perf_reg_abi(struct task_struct *task) | ||
99 | { | ||
100 | if (test_tsk_thread_flag(task, TIF_IA32)) | ||
101 | return PERF_SAMPLE_REGS_ABI_32; | ||
102 | else | ||
103 | return PERF_SAMPLE_REGS_ABI_64; | ||
104 | } | ||
105 | #endif /* CONFIG_X86_32 */ | ||
diff --git a/arch/x86/kernel/probe_roms.c b/arch/x86/kernel/probe_roms.c index 0bc72e2069e3..d5f15c3f7b25 100644 --- a/arch/x86/kernel/probe_roms.c +++ b/arch/x86/kernel/probe_roms.c | |||
@@ -150,7 +150,7 @@ static struct resource *find_oprom(struct pci_dev *pdev) | |||
150 | return oprom; | 150 | return oprom; |
151 | } | 151 | } |
152 | 152 | ||
153 | void *pci_map_biosrom(struct pci_dev *pdev) | 153 | void __iomem *pci_map_biosrom(struct pci_dev *pdev) |
154 | { | 154 | { |
155 | struct resource *oprom = find_oprom(pdev); | 155 | struct resource *oprom = find_oprom(pdev); |
156 | 156 | ||
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index ef6a8456f719..dc3567e083f9 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -66,15 +66,13 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
66 | { | 66 | { |
67 | int ret; | 67 | int ret; |
68 | 68 | ||
69 | unlazy_fpu(src); | ||
70 | |||
71 | *dst = *src; | 69 | *dst = *src; |
72 | if (fpu_allocated(&src->thread.fpu)) { | 70 | if (fpu_allocated(&src->thread.fpu)) { |
73 | memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu)); | 71 | memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu)); |
74 | ret = fpu_alloc(&dst->thread.fpu); | 72 | ret = fpu_alloc(&dst->thread.fpu); |
75 | if (ret) | 73 | if (ret) |
76 | return ret; | 74 | return ret; |
77 | fpu_copy(&dst->thread.fpu, &src->thread.fpu); | 75 | fpu_copy(dst, src); |
78 | } | 76 | } |
79 | return 0; | 77 | return 0; |
80 | } | 78 | } |
@@ -97,16 +95,6 @@ void arch_task_cache_init(void) | |||
97 | SLAB_PANIC | SLAB_NOTRACK, NULL); | 95 | SLAB_PANIC | SLAB_NOTRACK, NULL); |
98 | } | 96 | } |
99 | 97 | ||
100 | static inline void drop_fpu(struct task_struct *tsk) | ||
101 | { | ||
102 | /* | ||
103 | * Forget coprocessor state.. | ||
104 | */ | ||
105 | tsk->fpu_counter = 0; | ||
106 | clear_fpu(tsk); | ||
107 | clear_used_math(); | ||
108 | } | ||
109 | |||
110 | /* | 98 | /* |
111 | * Free current thread data structures etc.. | 99 | * Free current thread data structures etc.. |
112 | */ | 100 | */ |
@@ -163,7 +151,13 @@ void flush_thread(void) | |||
163 | 151 | ||
164 | flush_ptrace_hw_breakpoint(tsk); | 152 | flush_ptrace_hw_breakpoint(tsk); |
165 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | 153 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); |
166 | drop_fpu(tsk); | 154 | drop_init_fpu(tsk); |
155 | /* | ||
156 | * Free the FPU state for non xsave platforms. They get reallocated | ||
157 | * lazily at the first use. | ||
158 | */ | ||
159 | if (!use_eager_fpu()) | ||
160 | free_thread_xstate(tsk); | ||
167 | } | 161 | } |
168 | 162 | ||
169 | static void hard_disable_TSC(void) | 163 | static void hard_disable_TSC(void) |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 516fa186121b..b9ff83c7135b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -190,10 +190,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | |||
190 | regs->cs = __USER_CS; | 190 | regs->cs = __USER_CS; |
191 | regs->ip = new_ip; | 191 | regs->ip = new_ip; |
192 | regs->sp = new_sp; | 192 | regs->sp = new_sp; |
193 | /* | ||
194 | * Free the old FP and other extended state | ||
195 | */ | ||
196 | free_thread_xstate(current); | ||
197 | } | 193 | } |
198 | EXPORT_SYMBOL_GPL(start_thread); | 194 | EXPORT_SYMBOL_GPL(start_thread); |
199 | 195 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 0a980c9d7cb8..8a6d20ce1978 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -232,10 +232,6 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip, | |||
232 | regs->cs = _cs; | 232 | regs->cs = _cs; |
233 | regs->ss = _ss; | 233 | regs->ss = _ss; |
234 | regs->flags = X86_EFLAGS_IF; | 234 | regs->flags = X86_EFLAGS_IF; |
235 | /* | ||
236 | * Free the old FP and other extended state | ||
237 | */ | ||
238 | free_thread_xstate(current); | ||
239 | } | 235 | } |
240 | 236 | ||
241 | void | 237 | void |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index c4c6a5c2bf0f..b00b33a18390 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/signal.h> | 21 | #include <linux/signal.h> |
22 | #include <linux/perf_event.h> | 22 | #include <linux/perf_event.h> |
23 | #include <linux/hw_breakpoint.h> | 23 | #include <linux/hw_breakpoint.h> |
24 | #include <linux/rcupdate.h> | ||
24 | 25 | ||
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | #include <asm/pgtable.h> | 27 | #include <asm/pgtable.h> |
@@ -1332,9 +1333,6 @@ static const struct user_regset_view user_x86_64_view = { | |||
1332 | #define genregs32_get genregs_get | 1333 | #define genregs32_get genregs_get |
1333 | #define genregs32_set genregs_set | 1334 | #define genregs32_set genregs_set |
1334 | 1335 | ||
1335 | #define user_i387_ia32_struct user_i387_struct | ||
1336 | #define user32_fxsr_struct user_fxsr_struct | ||
1337 | |||
1338 | #endif /* CONFIG_X86_64 */ | 1336 | #endif /* CONFIG_X86_64 */ |
1339 | 1337 | ||
1340 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 1338 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
@@ -1463,6 +1461,8 @@ long syscall_trace_enter(struct pt_regs *regs) | |||
1463 | { | 1461 | { |
1464 | long ret = 0; | 1462 | long ret = 0; |
1465 | 1463 | ||
1464 | rcu_user_exit(); | ||
1465 | |||
1466 | /* | 1466 | /* |
1467 | * If we stepped into a sysenter/syscall insn, it trapped in | 1467 | * If we stepped into a sysenter/syscall insn, it trapped in |
1468 | * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP. | 1468 | * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP. |
@@ -1526,4 +1526,6 @@ void syscall_trace_leave(struct pt_regs *regs) | |||
1526 | !test_thread_flag(TIF_SYSCALL_EMU); | 1526 | !test_thread_flag(TIF_SYSCALL_EMU); |
1527 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) | 1527 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) |
1528 | tracehook_report_syscall_exit(regs, step); | 1528 | tracehook_report_syscall_exit(regs, step); |
1529 | |||
1530 | rcu_user_enter(); | ||
1529 | } | 1531 | } |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index f4b9b80e1b95..4f165479c453 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -961,9 +961,7 @@ void __init setup_arch(char **cmdline_p) | |||
961 | kvmclock_init(); | 961 | kvmclock_init(); |
962 | #endif | 962 | #endif |
963 | 963 | ||
964 | x86_init.paging.pagetable_setup_start(swapper_pg_dir); | 964 | x86_init.paging.pagetable_init(); |
965 | paging_init(); | ||
966 | x86_init.paging.pagetable_setup_done(swapper_pg_dir); | ||
967 | 965 | ||
968 | if (boot_cpu_data.cpuid_level >= 0) { | 966 | if (boot_cpu_data.cpuid_level >= 0) { |
969 | /* A CPU has %cr4 if and only if it has CPUID */ | 967 | /* A CPU has %cr4 if and only if it has CPUID */ |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index b280908a376e..3160c26db5e7 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -114,7 +114,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
114 | regs->orig_ax = -1; /* disable syscall checks */ | 114 | regs->orig_ax = -1; /* disable syscall checks */ |
115 | 115 | ||
116 | get_user_ex(buf, &sc->fpstate); | 116 | get_user_ex(buf, &sc->fpstate); |
117 | err |= restore_i387_xstate(buf); | 117 | err |= restore_xstate_sig(buf, config_enabled(CONFIG_X86_32)); |
118 | 118 | ||
119 | get_user_ex(*pax, &sc->ax); | 119 | get_user_ex(*pax, &sc->ax); |
120 | } get_user_catch(err); | 120 | } get_user_catch(err); |
@@ -206,35 +206,32 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, | |||
206 | void __user **fpstate) | 206 | void __user **fpstate) |
207 | { | 207 | { |
208 | /* Default to using normal stack */ | 208 | /* Default to using normal stack */ |
209 | unsigned long math_size = 0; | ||
209 | unsigned long sp = regs->sp; | 210 | unsigned long sp = regs->sp; |
211 | unsigned long buf_fx = 0; | ||
210 | int onsigstack = on_sig_stack(sp); | 212 | int onsigstack = on_sig_stack(sp); |
211 | 213 | ||
212 | #ifdef CONFIG_X86_64 | ||
213 | /* redzone */ | 214 | /* redzone */ |
214 | sp -= 128; | 215 | if (config_enabled(CONFIG_X86_64)) |
215 | #endif /* CONFIG_X86_64 */ | 216 | sp -= 128; |
216 | 217 | ||
217 | if (!onsigstack) { | 218 | if (!onsigstack) { |
218 | /* This is the X/Open sanctioned signal stack switching. */ | 219 | /* This is the X/Open sanctioned signal stack switching. */ |
219 | if (ka->sa.sa_flags & SA_ONSTACK) { | 220 | if (ka->sa.sa_flags & SA_ONSTACK) { |
220 | if (current->sas_ss_size) | 221 | if (current->sas_ss_size) |
221 | sp = current->sas_ss_sp + current->sas_ss_size; | 222 | sp = current->sas_ss_sp + current->sas_ss_size; |
222 | } else { | 223 | } else if (config_enabled(CONFIG_X86_32) && |
223 | #ifdef CONFIG_X86_32 | 224 | (regs->ss & 0xffff) != __USER_DS && |
224 | /* This is the legacy signal stack switching. */ | 225 | !(ka->sa.sa_flags & SA_RESTORER) && |
225 | if ((regs->ss & 0xffff) != __USER_DS && | 226 | ka->sa.sa_restorer) { |
226 | !(ka->sa.sa_flags & SA_RESTORER) && | 227 | /* This is the legacy signal stack switching. */ |
227 | ka->sa.sa_restorer) | ||
228 | sp = (unsigned long) ka->sa.sa_restorer; | 228 | sp = (unsigned long) ka->sa.sa_restorer; |
229 | #endif /* CONFIG_X86_32 */ | ||
230 | } | 229 | } |
231 | } | 230 | } |
232 | 231 | ||
233 | if (used_math()) { | 232 | if (used_math()) { |
234 | sp -= sig_xstate_size; | 233 | sp = alloc_mathframe(sp, config_enabled(CONFIG_X86_32), |
235 | #ifdef CONFIG_X86_64 | 234 | &buf_fx, &math_size); |
236 | sp = round_down(sp, 64); | ||
237 | #endif /* CONFIG_X86_64 */ | ||
238 | *fpstate = (void __user *)sp; | 235 | *fpstate = (void __user *)sp; |
239 | } | 236 | } |
240 | 237 | ||
@@ -247,8 +244,9 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, | |||
247 | if (onsigstack && !likely(on_sig_stack(sp))) | 244 | if (onsigstack && !likely(on_sig_stack(sp))) |
248 | return (void __user *)-1L; | 245 | return (void __user *)-1L; |
249 | 246 | ||
250 | /* save i387 state */ | 247 | /* save i387 and extended state */ |
251 | if (used_math() && save_i387_xstate(*fpstate) < 0) | 248 | if (used_math() && |
249 | save_xstate_sig(*fpstate, (void __user *)buf_fx, math_size) < 0) | ||
252 | return (void __user *)-1L; | 250 | return (void __user *)-1L; |
253 | 251 | ||
254 | return (void __user *)sp; | 252 | return (void __user *)sp; |
@@ -474,6 +472,74 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
474 | } | 472 | } |
475 | #endif /* CONFIG_X86_32 */ | 473 | #endif /* CONFIG_X86_32 */ |
476 | 474 | ||
475 | static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | ||
476 | siginfo_t *info, compat_sigset_t *set, | ||
477 | struct pt_regs *regs) | ||
478 | { | ||
479 | #ifdef CONFIG_X86_X32_ABI | ||
480 | struct rt_sigframe_x32 __user *frame; | ||
481 | void __user *restorer; | ||
482 | int err = 0; | ||
483 | void __user *fpstate = NULL; | ||
484 | |||
485 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | ||
486 | |||
487 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
488 | return -EFAULT; | ||
489 | |||
490 | if (ka->sa.sa_flags & SA_SIGINFO) { | ||
491 | if (copy_siginfo_to_user32(&frame->info, info)) | ||
492 | return -EFAULT; | ||
493 | } | ||
494 | |||
495 | put_user_try { | ||
496 | /* Create the ucontext. */ | ||
497 | if (cpu_has_xsave) | ||
498 | put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); | ||
499 | else | ||
500 | put_user_ex(0, &frame->uc.uc_flags); | ||
501 | put_user_ex(0, &frame->uc.uc_link); | ||
502 | put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
503 | put_user_ex(sas_ss_flags(regs->sp), | ||
504 | &frame->uc.uc_stack.ss_flags); | ||
505 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
506 | put_user_ex(0, &frame->uc.uc__pad0); | ||
507 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
508 | regs, set->sig[0]); | ||
509 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
510 | |||
511 | if (ka->sa.sa_flags & SA_RESTORER) { | ||
512 | restorer = ka->sa.sa_restorer; | ||
513 | } else { | ||
514 | /* could use a vstub here */ | ||
515 | restorer = NULL; | ||
516 | err |= -EFAULT; | ||
517 | } | ||
518 | put_user_ex(restorer, &frame->pretcode); | ||
519 | } put_user_catch(err); | ||
520 | |||
521 | if (err) | ||
522 | return -EFAULT; | ||
523 | |||
524 | /* Set up registers for signal handler */ | ||
525 | regs->sp = (unsigned long) frame; | ||
526 | regs->ip = (unsigned long) ka->sa.sa_handler; | ||
527 | |||
528 | /* We use the x32 calling convention here... */ | ||
529 | regs->di = sig; | ||
530 | regs->si = (unsigned long) &frame->info; | ||
531 | regs->dx = (unsigned long) &frame->uc; | ||
532 | |||
533 | loadsegment(ds, __USER_DS); | ||
534 | loadsegment(es, __USER_DS); | ||
535 | |||
536 | regs->cs = __USER_CS; | ||
537 | regs->ss = __USER_DS; | ||
538 | #endif /* CONFIG_X86_X32_ABI */ | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
477 | #ifdef CONFIG_X86_32 | 543 | #ifdef CONFIG_X86_32 |
478 | /* | 544 | /* |
479 | * Atomically swap in the new signal mask, and wait for a signal. | 545 | * Atomically swap in the new signal mask, and wait for a signal. |
@@ -612,55 +678,22 @@ static int signr_convert(int sig) | |||
612 | return sig; | 678 | return sig; |
613 | } | 679 | } |
614 | 680 | ||
615 | #ifdef CONFIG_X86_32 | ||
616 | |||
617 | #define is_ia32 1 | ||
618 | #define ia32_setup_frame __setup_frame | ||
619 | #define ia32_setup_rt_frame __setup_rt_frame | ||
620 | |||
621 | #else /* !CONFIG_X86_32 */ | ||
622 | |||
623 | #ifdef CONFIG_IA32_EMULATION | ||
624 | #define is_ia32 test_thread_flag(TIF_IA32) | ||
625 | #else /* !CONFIG_IA32_EMULATION */ | ||
626 | #define is_ia32 0 | ||
627 | #endif /* CONFIG_IA32_EMULATION */ | ||
628 | |||
629 | #ifdef CONFIG_X86_X32_ABI | ||
630 | #define is_x32 test_thread_flag(TIF_X32) | ||
631 | |||
632 | static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | ||
633 | siginfo_t *info, compat_sigset_t *set, | ||
634 | struct pt_regs *regs); | ||
635 | #else /* !CONFIG_X86_X32_ABI */ | ||
636 | #define is_x32 0 | ||
637 | #endif /* CONFIG_X86_X32_ABI */ | ||
638 | |||
639 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
640 | sigset_t *set, struct pt_regs *regs); | ||
641 | int ia32_setup_frame(int sig, struct k_sigaction *ka, | ||
642 | sigset_t *set, struct pt_regs *regs); | ||
643 | |||
644 | #endif /* CONFIG_X86_32 */ | ||
645 | |||
646 | static int | 681 | static int |
647 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 682 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
648 | struct pt_regs *regs) | 683 | struct pt_regs *regs) |
649 | { | 684 | { |
650 | int usig = signr_convert(sig); | 685 | int usig = signr_convert(sig); |
651 | sigset_t *set = sigmask_to_save(); | 686 | sigset_t *set = sigmask_to_save(); |
687 | compat_sigset_t *cset = (compat_sigset_t *) set; | ||
652 | 688 | ||
653 | /* Set up the stack frame */ | 689 | /* Set up the stack frame */ |
654 | if (is_ia32) { | 690 | if (is_ia32_frame()) { |
655 | if (ka->sa.sa_flags & SA_SIGINFO) | 691 | if (ka->sa.sa_flags & SA_SIGINFO) |
656 | return ia32_setup_rt_frame(usig, ka, info, set, regs); | 692 | return ia32_setup_rt_frame(usig, ka, info, cset, regs); |
657 | else | 693 | else |
658 | return ia32_setup_frame(usig, ka, set, regs); | 694 | return ia32_setup_frame(usig, ka, cset, regs); |
659 | #ifdef CONFIG_X86_X32_ABI | 695 | } else if (is_x32_frame()) { |
660 | } else if (is_x32) { | 696 | return x32_setup_rt_frame(usig, ka, info, cset, regs); |
661 | return x32_setup_rt_frame(usig, ka, info, | ||
662 | (compat_sigset_t *)set, regs); | ||
663 | #endif | ||
664 | } else { | 697 | } else { |
665 | return __setup_rt_frame(sig, ka, info, set, regs); | 698 | return __setup_rt_frame(sig, ka, info, set, regs); |
666 | } | 699 | } |
@@ -779,6 +812,8 @@ static void do_signal(struct pt_regs *regs) | |||
779 | void | 812 | void |
780 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | 813 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) |
781 | { | 814 | { |
815 | rcu_user_exit(); | ||
816 | |||
782 | #ifdef CONFIG_X86_MCE | 817 | #ifdef CONFIG_X86_MCE |
783 | /* notify userspace of pending MCEs */ | 818 | /* notify userspace of pending MCEs */ |
784 | if (thread_info_flags & _TIF_MCE_NOTIFY) | 819 | if (thread_info_flags & _TIF_MCE_NOTIFY) |
@@ -804,6 +839,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | |||
804 | #ifdef CONFIG_X86_32 | 839 | #ifdef CONFIG_X86_32 |
805 | clear_thread_flag(TIF_IRET); | 840 | clear_thread_flag(TIF_IRET); |
806 | #endif /* CONFIG_X86_32 */ | 841 | #endif /* CONFIG_X86_32 */ |
842 | |||
843 | rcu_user_enter(); | ||
807 | } | 844 | } |
808 | 845 | ||
809 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | 846 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) |
@@ -824,72 +861,6 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | |||
824 | } | 861 | } |
825 | 862 | ||
826 | #ifdef CONFIG_X86_X32_ABI | 863 | #ifdef CONFIG_X86_X32_ABI |
827 | static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | ||
828 | siginfo_t *info, compat_sigset_t *set, | ||
829 | struct pt_regs *regs) | ||
830 | { | ||
831 | struct rt_sigframe_x32 __user *frame; | ||
832 | void __user *restorer; | ||
833 | int err = 0; | ||
834 | void __user *fpstate = NULL; | ||
835 | |||
836 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | ||
837 | |||
838 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
839 | return -EFAULT; | ||
840 | |||
841 | if (ka->sa.sa_flags & SA_SIGINFO) { | ||
842 | if (copy_siginfo_to_user32(&frame->info, info)) | ||
843 | return -EFAULT; | ||
844 | } | ||
845 | |||
846 | put_user_try { | ||
847 | /* Create the ucontext. */ | ||
848 | if (cpu_has_xsave) | ||
849 | put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags); | ||
850 | else | ||
851 | put_user_ex(0, &frame->uc.uc_flags); | ||
852 | put_user_ex(0, &frame->uc.uc_link); | ||
853 | put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | ||
854 | put_user_ex(sas_ss_flags(regs->sp), | ||
855 | &frame->uc.uc_stack.ss_flags); | ||
856 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
857 | put_user_ex(0, &frame->uc.uc__pad0); | ||
858 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
859 | regs, set->sig[0]); | ||
860 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
861 | |||
862 | if (ka->sa.sa_flags & SA_RESTORER) { | ||
863 | restorer = ka->sa.sa_restorer; | ||
864 | } else { | ||
865 | /* could use a vstub here */ | ||
866 | restorer = NULL; | ||
867 | err |= -EFAULT; | ||
868 | } | ||
869 | put_user_ex(restorer, &frame->pretcode); | ||
870 | } put_user_catch(err); | ||
871 | |||
872 | if (err) | ||
873 | return -EFAULT; | ||
874 | |||
875 | /* Set up registers for signal handler */ | ||
876 | regs->sp = (unsigned long) frame; | ||
877 | regs->ip = (unsigned long) ka->sa.sa_handler; | ||
878 | |||
879 | /* We use the x32 calling convention here... */ | ||
880 | regs->di = sig; | ||
881 | regs->si = (unsigned long) &frame->info; | ||
882 | regs->dx = (unsigned long) &frame->uc; | ||
883 | |||
884 | loadsegment(ds, __USER_DS); | ||
885 | loadsegment(es, __USER_DS); | ||
886 | |||
887 | regs->cs = __USER_CS; | ||
888 | regs->ss = __USER_DS; | ||
889 | |||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs) | 864 | asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs) |
894 | { | 865 | { |
895 | struct rt_sigframe_x32 __user *frame; | 866 | struct rt_sigframe_x32 __user *frame; |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7c5a8c314c02..c80a33bc528b 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -665,7 +665,8 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | |||
665 | unsigned long boot_error = 0; | 665 | unsigned long boot_error = 0; |
666 | int timeout; | 666 | int timeout; |
667 | 667 | ||
668 | alternatives_smp_switch(1); | 668 | /* Just in case we booted with a single CPU. */ |
669 | alternatives_enable_smp(); | ||
669 | 670 | ||
670 | idle->thread.sp = (unsigned long) (((struct pt_regs *) | 671 | idle->thread.sp = (unsigned long) (((struct pt_regs *) |
671 | (THREAD_SIZE + task_stack_page(idle))) - 1); | 672 | (THREAD_SIZE + task_stack_page(idle))) - 1); |
@@ -1053,20 +1054,6 @@ out: | |||
1053 | preempt_enable(); | 1054 | preempt_enable(); |
1054 | } | 1055 | } |
1055 | 1056 | ||
1056 | void arch_disable_nonboot_cpus_begin(void) | ||
1057 | { | ||
1058 | /* | ||
1059 | * Avoid the smp alternatives switch during the disable_nonboot_cpus(). | ||
1060 | * In the suspend path, we will be back in the SMP mode shortly anyways. | ||
1061 | */ | ||
1062 | skip_smp_alternatives = true; | ||
1063 | } | ||
1064 | |||
1065 | void arch_disable_nonboot_cpus_end(void) | ||
1066 | { | ||
1067 | skip_smp_alternatives = false; | ||
1068 | } | ||
1069 | |||
1070 | void arch_enable_nonboot_cpus_begin(void) | 1057 | void arch_enable_nonboot_cpus_begin(void) |
1071 | { | 1058 | { |
1072 | set_mtrr_aps_delayed_init(); | 1059 | set_mtrr_aps_delayed_init(); |
@@ -1256,9 +1243,6 @@ void native_cpu_die(unsigned int cpu) | |||
1256 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) { | 1243 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) { |
1257 | if (system_state == SYSTEM_RUNNING) | 1244 | if (system_state == SYSTEM_RUNNING) |
1258 | pr_info("CPU %u is now offline\n", cpu); | 1245 | pr_info("CPU %u is now offline\n", cpu); |
1259 | |||
1260 | if (1 == num_online_cpus()) | ||
1261 | alternatives_smp_switch(0); | ||
1262 | return; | 1246 | return; |
1263 | } | 1247 | } |
1264 | msleep(100); | 1248 | msleep(100); |
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index c346d1161488..cd3b2438a980 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c | |||
@@ -157,6 +157,33 @@ static int enable_single_step(struct task_struct *child) | |||
157 | return 1; | 157 | return 1; |
158 | } | 158 | } |
159 | 159 | ||
160 | void set_task_blockstep(struct task_struct *task, bool on) | ||
161 | { | ||
162 | unsigned long debugctl; | ||
163 | |||
164 | /* | ||
165 | * Ensure irq/preemption can't change debugctl in between. | ||
166 | * Note also that both TIF_BLOCKSTEP and debugctl should | ||
167 | * be changed atomically wrt preemption. | ||
168 | * FIXME: this means that set/clear TIF_BLOCKSTEP is simply | ||
169 | * wrong if task != current, SIGKILL can wakeup the stopped | ||
170 | * tracee and set/clear can play with the running task, this | ||
171 | * can confuse the next __switch_to_xtra(). | ||
172 | */ | ||
173 | local_irq_disable(); | ||
174 | debugctl = get_debugctlmsr(); | ||
175 | if (on) { | ||
176 | debugctl |= DEBUGCTLMSR_BTF; | ||
177 | set_tsk_thread_flag(task, TIF_BLOCKSTEP); | ||
178 | } else { | ||
179 | debugctl &= ~DEBUGCTLMSR_BTF; | ||
180 | clear_tsk_thread_flag(task, TIF_BLOCKSTEP); | ||
181 | } | ||
182 | if (task == current) | ||
183 | update_debugctlmsr(debugctl); | ||
184 | local_irq_enable(); | ||
185 | } | ||
186 | |||
160 | /* | 187 | /* |
161 | * Enable single or block step. | 188 | * Enable single or block step. |
162 | */ | 189 | */ |
@@ -169,19 +196,10 @@ static void enable_step(struct task_struct *child, bool block) | |||
169 | * So no one should try to use debugger block stepping in a program | 196 | * So no one should try to use debugger block stepping in a program |
170 | * that uses user-mode single stepping itself. | 197 | * that uses user-mode single stepping itself. |
171 | */ | 198 | */ |
172 | if (enable_single_step(child) && block) { | 199 | if (enable_single_step(child) && block) |
173 | unsigned long debugctl = get_debugctlmsr(); | 200 | set_task_blockstep(child, true); |
174 | 201 | else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) | |
175 | debugctl |= DEBUGCTLMSR_BTF; | 202 | set_task_blockstep(child, false); |
176 | update_debugctlmsr(debugctl); | ||
177 | set_tsk_thread_flag(child, TIF_BLOCKSTEP); | ||
178 | } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { | ||
179 | unsigned long debugctl = get_debugctlmsr(); | ||
180 | |||
181 | debugctl &= ~DEBUGCTLMSR_BTF; | ||
182 | update_debugctlmsr(debugctl); | ||
183 | clear_tsk_thread_flag(child, TIF_BLOCKSTEP); | ||
184 | } | ||
185 | } | 203 | } |
186 | 204 | ||
187 | void user_enable_single_step(struct task_struct *child) | 205 | void user_enable_single_step(struct task_struct *child) |
@@ -199,13 +217,8 @@ void user_disable_single_step(struct task_struct *child) | |||
199 | /* | 217 | /* |
200 | * Make sure block stepping (BTF) is disabled. | 218 | * Make sure block stepping (BTF) is disabled. |
201 | */ | 219 | */ |
202 | if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { | 220 | if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) |
203 | unsigned long debugctl = get_debugctlmsr(); | 221 | set_task_blockstep(child, false); |
204 | |||
205 | debugctl &= ~DEBUGCTLMSR_BTF; | ||
206 | update_debugctlmsr(debugctl); | ||
207 | clear_tsk_thread_flag(child, TIF_BLOCKSTEP); | ||
208 | } | ||
209 | 222 | ||
210 | /* Always clear TIF_SINGLESTEP... */ | 223 | /* Always clear TIF_SINGLESTEP... */ |
211 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); | 224 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index b481341c9369..8276dc6794cc 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <asm/i387.h> | 55 | #include <asm/i387.h> |
56 | #include <asm/fpu-internal.h> | 56 | #include <asm/fpu-internal.h> |
57 | #include <asm/mce.h> | 57 | #include <asm/mce.h> |
58 | #include <asm/rcu.h> | ||
58 | 59 | ||
59 | #include <asm/mach_traps.h> | 60 | #include <asm/mach_traps.h> |
60 | 61 | ||
@@ -107,30 +108,45 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) | |||
107 | dec_preempt_count(); | 108 | dec_preempt_count(); |
108 | } | 109 | } |
109 | 110 | ||
110 | static void __kprobes | 111 | static int __kprobes |
111 | do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, | 112 | do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, |
112 | long error_code, siginfo_t *info) | 113 | struct pt_regs *regs, long error_code) |
113 | { | 114 | { |
114 | struct task_struct *tsk = current; | ||
115 | |||
116 | #ifdef CONFIG_X86_32 | 115 | #ifdef CONFIG_X86_32 |
117 | if (regs->flags & X86_VM_MASK) { | 116 | if (regs->flags & X86_VM_MASK) { |
118 | /* | 117 | /* |
119 | * traps 0, 1, 3, 4, and 5 should be forwarded to vm86. | 118 | * Traps 0, 1, 3, 4, and 5 should be forwarded to vm86. |
120 | * On nmi (interrupt 2), do_trap should not be called. | 119 | * On nmi (interrupt 2), do_trap should not be called. |
121 | */ | 120 | */ |
122 | if (trapnr < X86_TRAP_UD) | 121 | if (trapnr < X86_TRAP_UD) { |
123 | goto vm86_trap; | 122 | if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, |
124 | goto trap_signal; | 123 | error_code, trapnr)) |
124 | return 0; | ||
125 | } | ||
126 | return -1; | ||
125 | } | 127 | } |
126 | #endif | 128 | #endif |
129 | if (!user_mode(regs)) { | ||
130 | if (!fixup_exception(regs)) { | ||
131 | tsk->thread.error_code = error_code; | ||
132 | tsk->thread.trap_nr = trapnr; | ||
133 | die(str, regs, error_code); | ||
134 | } | ||
135 | return 0; | ||
136 | } | ||
127 | 137 | ||
128 | if (!user_mode(regs)) | 138 | return -1; |
129 | goto kernel_trap; | 139 | } |
130 | 140 | ||
131 | #ifdef CONFIG_X86_32 | 141 | static void __kprobes |
132 | trap_signal: | 142 | do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, |
133 | #endif | 143 | long error_code, siginfo_t *info) |
144 | { | ||
145 | struct task_struct *tsk = current; | ||
146 | |||
147 | |||
148 | if (!do_trap_no_signal(tsk, trapnr, str, regs, error_code)) | ||
149 | return; | ||
134 | /* | 150 | /* |
135 | * We want error_code and trap_nr set for userspace faults and | 151 | * We want error_code and trap_nr set for userspace faults and |
136 | * kernelspace faults which result in die(), but not | 152 | * kernelspace faults which result in die(), but not |
@@ -158,33 +174,20 @@ trap_signal: | |||
158 | force_sig_info(signr, info, tsk); | 174 | force_sig_info(signr, info, tsk); |
159 | else | 175 | else |
160 | force_sig(signr, tsk); | 176 | force_sig(signr, tsk); |
161 | return; | ||
162 | |||
163 | kernel_trap: | ||
164 | if (!fixup_exception(regs)) { | ||
165 | tsk->thread.error_code = error_code; | ||
166 | tsk->thread.trap_nr = trapnr; | ||
167 | die(str, regs, error_code); | ||
168 | } | ||
169 | return; | ||
170 | |||
171 | #ifdef CONFIG_X86_32 | ||
172 | vm86_trap: | ||
173 | if (handle_vm86_trap((struct kernel_vm86_regs *) regs, | ||
174 | error_code, trapnr)) | ||
175 | goto trap_signal; | ||
176 | return; | ||
177 | #endif | ||
178 | } | 177 | } |
179 | 178 | ||
180 | #define DO_ERROR(trapnr, signr, str, name) \ | 179 | #define DO_ERROR(trapnr, signr, str, name) \ |
181 | dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ | 180 | dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ |
182 | { \ | 181 | { \ |
183 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 182 | exception_enter(regs); \ |
184 | == NOTIFY_STOP) \ | 183 | if (notify_die(DIE_TRAP, str, regs, error_code, \ |
184 | trapnr, signr) == NOTIFY_STOP) { \ | ||
185 | exception_exit(regs); \ | ||
185 | return; \ | 186 | return; \ |
187 | } \ | ||
186 | conditional_sti(regs); \ | 188 | conditional_sti(regs); \ |
187 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ | 189 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ |
190 | exception_exit(regs); \ | ||
188 | } | 191 | } |
189 | 192 | ||
190 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | 193 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ |
@@ -195,11 +198,15 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ | |||
195 | info.si_errno = 0; \ | 198 | info.si_errno = 0; \ |
196 | info.si_code = sicode; \ | 199 | info.si_code = sicode; \ |
197 | info.si_addr = (void __user *)siaddr; \ | 200 | info.si_addr = (void __user *)siaddr; \ |
198 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 201 | exception_enter(regs); \ |
199 | == NOTIFY_STOP) \ | 202 | if (notify_die(DIE_TRAP, str, regs, error_code, \ |
203 | trapnr, signr) == NOTIFY_STOP) { \ | ||
204 | exception_exit(regs); \ | ||
200 | return; \ | 205 | return; \ |
206 | } \ | ||
201 | conditional_sti(regs); \ | 207 | conditional_sti(regs); \ |
202 | do_trap(trapnr, signr, str, regs, error_code, &info); \ | 208 | do_trap(trapnr, signr, str, regs, error_code, &info); \ |
209 | exception_exit(regs); \ | ||
203 | } | 210 | } |
204 | 211 | ||
205 | DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, | 212 | DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, |
@@ -222,12 +229,14 @@ DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, | |||
222 | /* Runs on IST stack */ | 229 | /* Runs on IST stack */ |
223 | dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) | 230 | dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) |
224 | { | 231 | { |
232 | exception_enter(regs); | ||
225 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, | 233 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, |
226 | X86_TRAP_SS, SIGBUS) == NOTIFY_STOP) | 234 | X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) { |
227 | return; | 235 | preempt_conditional_sti(regs); |
228 | preempt_conditional_sti(regs); | 236 | do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); |
229 | do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); | 237 | preempt_conditional_cli(regs); |
230 | preempt_conditional_cli(regs); | 238 | } |
239 | exception_exit(regs); | ||
231 | } | 240 | } |
232 | 241 | ||
233 | dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) | 242 | dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) |
@@ -235,6 +244,7 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) | |||
235 | static const char str[] = "double fault"; | 244 | static const char str[] = "double fault"; |
236 | struct task_struct *tsk = current; | 245 | struct task_struct *tsk = current; |
237 | 246 | ||
247 | exception_enter(regs); | ||
238 | /* Return not checked because double check cannot be ignored */ | 248 | /* Return not checked because double check cannot be ignored */ |
239 | notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV); | 249 | notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV); |
240 | 250 | ||
@@ -255,16 +265,29 @@ do_general_protection(struct pt_regs *regs, long error_code) | |||
255 | { | 265 | { |
256 | struct task_struct *tsk; | 266 | struct task_struct *tsk; |
257 | 267 | ||
268 | exception_enter(regs); | ||
258 | conditional_sti(regs); | 269 | conditional_sti(regs); |
259 | 270 | ||
260 | #ifdef CONFIG_X86_32 | 271 | #ifdef CONFIG_X86_32 |
261 | if (regs->flags & X86_VM_MASK) | 272 | if (regs->flags & X86_VM_MASK) { |
262 | goto gp_in_vm86; | 273 | local_irq_enable(); |
274 | handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); | ||
275 | goto exit; | ||
276 | } | ||
263 | #endif | 277 | #endif |
264 | 278 | ||
265 | tsk = current; | 279 | tsk = current; |
266 | if (!user_mode(regs)) | 280 | if (!user_mode(regs)) { |
267 | goto gp_in_kernel; | 281 | if (fixup_exception(regs)) |
282 | goto exit; | ||
283 | |||
284 | tsk->thread.error_code = error_code; | ||
285 | tsk->thread.trap_nr = X86_TRAP_GP; | ||
286 | if (notify_die(DIE_GPF, "general protection fault", regs, error_code, | ||
287 | X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP) | ||
288 | die("general protection fault", regs, error_code); | ||
289 | goto exit; | ||
290 | } | ||
268 | 291 | ||
269 | tsk->thread.error_code = error_code; | 292 | tsk->thread.error_code = error_code; |
270 | tsk->thread.trap_nr = X86_TRAP_GP; | 293 | tsk->thread.trap_nr = X86_TRAP_GP; |
@@ -279,25 +302,8 @@ do_general_protection(struct pt_regs *regs, long error_code) | |||
279 | } | 302 | } |
280 | 303 | ||
281 | force_sig(SIGSEGV, tsk); | 304 | force_sig(SIGSEGV, tsk); |
282 | return; | 305 | exit: |
283 | 306 | exception_exit(regs); | |
284 | #ifdef CONFIG_X86_32 | ||
285 | gp_in_vm86: | ||
286 | local_irq_enable(); | ||
287 | handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); | ||
288 | return; | ||
289 | #endif | ||
290 | |||
291 | gp_in_kernel: | ||
292 | if (fixup_exception(regs)) | ||
293 | return; | ||
294 | |||
295 | tsk->thread.error_code = error_code; | ||
296 | tsk->thread.trap_nr = X86_TRAP_GP; | ||
297 | if (notify_die(DIE_GPF, "general protection fault", regs, error_code, | ||
298 | X86_TRAP_GP, SIGSEGV) == NOTIFY_STOP) | ||
299 | return; | ||
300 | die("general protection fault", regs, error_code); | ||
301 | } | 307 | } |
302 | 308 | ||
303 | /* May run on IST stack. */ | 309 | /* May run on IST stack. */ |
@@ -312,15 +318,16 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co | |||
312 | ftrace_int3_handler(regs)) | 318 | ftrace_int3_handler(regs)) |
313 | return; | 319 | return; |
314 | #endif | 320 | #endif |
321 | exception_enter(regs); | ||
315 | #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP | 322 | #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP |
316 | if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, | 323 | if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, |
317 | SIGTRAP) == NOTIFY_STOP) | 324 | SIGTRAP) == NOTIFY_STOP) |
318 | return; | 325 | goto exit; |
319 | #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ | 326 | #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ |
320 | 327 | ||
321 | if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, | 328 | if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, |
322 | SIGTRAP) == NOTIFY_STOP) | 329 | SIGTRAP) == NOTIFY_STOP) |
323 | return; | 330 | goto exit; |
324 | 331 | ||
325 | /* | 332 | /* |
326 | * Let others (NMI) know that the debug stack is in use | 333 | * Let others (NMI) know that the debug stack is in use |
@@ -331,6 +338,8 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co | |||
331 | do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); | 338 | do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); |
332 | preempt_conditional_cli(regs); | 339 | preempt_conditional_cli(regs); |
333 | debug_stack_usage_dec(); | 340 | debug_stack_usage_dec(); |
341 | exit: | ||
342 | exception_exit(regs); | ||
334 | } | 343 | } |
335 | 344 | ||
336 | #ifdef CONFIG_X86_64 | 345 | #ifdef CONFIG_X86_64 |
@@ -391,6 +400,8 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
391 | unsigned long dr6; | 400 | unsigned long dr6; |
392 | int si_code; | 401 | int si_code; |
393 | 402 | ||
403 | exception_enter(regs); | ||
404 | |||
394 | get_debugreg(dr6, 6); | 405 | get_debugreg(dr6, 6); |
395 | 406 | ||
396 | /* Filter out all the reserved bits which are preset to 1 */ | 407 | /* Filter out all the reserved bits which are preset to 1 */ |
@@ -406,7 +417,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
406 | 417 | ||
407 | /* Catch kmemcheck conditions first of all! */ | 418 | /* Catch kmemcheck conditions first of all! */ |
408 | if ((dr6 & DR_STEP) && kmemcheck_trap(regs)) | 419 | if ((dr6 & DR_STEP) && kmemcheck_trap(regs)) |
409 | return; | 420 | goto exit; |
410 | 421 | ||
411 | /* DR6 may or may not be cleared by the CPU */ | 422 | /* DR6 may or may not be cleared by the CPU */ |
412 | set_debugreg(0, 6); | 423 | set_debugreg(0, 6); |
@@ -421,7 +432,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
421 | 432 | ||
422 | if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code, | 433 | if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code, |
423 | SIGTRAP) == NOTIFY_STOP) | 434 | SIGTRAP) == NOTIFY_STOP) |
424 | return; | 435 | goto exit; |
425 | 436 | ||
426 | /* | 437 | /* |
427 | * Let others (NMI) know that the debug stack is in use | 438 | * Let others (NMI) know that the debug stack is in use |
@@ -437,7 +448,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
437 | X86_TRAP_DB); | 448 | X86_TRAP_DB); |
438 | preempt_conditional_cli(regs); | 449 | preempt_conditional_cli(regs); |
439 | debug_stack_usage_dec(); | 450 | debug_stack_usage_dec(); |
440 | return; | 451 | goto exit; |
441 | } | 452 | } |
442 | 453 | ||
443 | /* | 454 | /* |
@@ -458,7 +469,8 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
458 | preempt_conditional_cli(regs); | 469 | preempt_conditional_cli(regs); |
459 | debug_stack_usage_dec(); | 470 | debug_stack_usage_dec(); |
460 | 471 | ||
461 | return; | 472 | exit: |
473 | exception_exit(regs); | ||
462 | } | 474 | } |
463 | 475 | ||
464 | /* | 476 | /* |
@@ -555,14 +567,17 @@ dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) | |||
555 | #ifdef CONFIG_X86_32 | 567 | #ifdef CONFIG_X86_32 |
556 | ignore_fpu_irq = 1; | 568 | ignore_fpu_irq = 1; |
557 | #endif | 569 | #endif |
558 | 570 | exception_enter(regs); | |
559 | math_error(regs, error_code, X86_TRAP_MF); | 571 | math_error(regs, error_code, X86_TRAP_MF); |
572 | exception_exit(regs); | ||
560 | } | 573 | } |
561 | 574 | ||
562 | dotraplinkage void | 575 | dotraplinkage void |
563 | do_simd_coprocessor_error(struct pt_regs *regs, long error_code) | 576 | do_simd_coprocessor_error(struct pt_regs *regs, long error_code) |
564 | { | 577 | { |
578 | exception_enter(regs); | ||
565 | math_error(regs, error_code, X86_TRAP_XF); | 579 | math_error(regs, error_code, X86_TRAP_XF); |
580 | exception_exit(regs); | ||
566 | } | 581 | } |
567 | 582 | ||
568 | dotraplinkage void | 583 | dotraplinkage void |
@@ -613,11 +628,12 @@ void math_state_restore(void) | |||
613 | } | 628 | } |
614 | 629 | ||
615 | __thread_fpu_begin(tsk); | 630 | __thread_fpu_begin(tsk); |
631 | |||
616 | /* | 632 | /* |
617 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. | 633 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. |
618 | */ | 634 | */ |
619 | if (unlikely(restore_fpu_checking(tsk))) { | 635 | if (unlikely(restore_fpu_checking(tsk))) { |
620 | __thread_fpu_end(tsk); | 636 | drop_init_fpu(tsk); |
621 | force_sig(SIGSEGV, tsk); | 637 | force_sig(SIGSEGV, tsk); |
622 | return; | 638 | return; |
623 | } | 639 | } |
@@ -629,6 +645,9 @@ EXPORT_SYMBOL_GPL(math_state_restore); | |||
629 | dotraplinkage void __kprobes | 645 | dotraplinkage void __kprobes |
630 | do_device_not_available(struct pt_regs *regs, long error_code) | 646 | do_device_not_available(struct pt_regs *regs, long error_code) |
631 | { | 647 | { |
648 | exception_enter(regs); | ||
649 | BUG_ON(use_eager_fpu()); | ||
650 | |||
632 | #ifdef CONFIG_MATH_EMULATION | 651 | #ifdef CONFIG_MATH_EMULATION |
633 | if (read_cr0() & X86_CR0_EM) { | 652 | if (read_cr0() & X86_CR0_EM) { |
634 | struct math_emu_info info = { }; | 653 | struct math_emu_info info = { }; |
@@ -637,6 +656,7 @@ do_device_not_available(struct pt_regs *regs, long error_code) | |||
637 | 656 | ||
638 | info.regs = regs; | 657 | info.regs = regs; |
639 | math_emulate(&info); | 658 | math_emulate(&info); |
659 | exception_exit(regs); | ||
640 | return; | 660 | return; |
641 | } | 661 | } |
642 | #endif | 662 | #endif |
@@ -644,12 +664,15 @@ do_device_not_available(struct pt_regs *regs, long error_code) | |||
644 | #ifdef CONFIG_X86_32 | 664 | #ifdef CONFIG_X86_32 |
645 | conditional_sti(regs); | 665 | conditional_sti(regs); |
646 | #endif | 666 | #endif |
667 | exception_exit(regs); | ||
647 | } | 668 | } |
648 | 669 | ||
649 | #ifdef CONFIG_X86_32 | 670 | #ifdef CONFIG_X86_32 |
650 | dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) | 671 | dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) |
651 | { | 672 | { |
652 | siginfo_t info; | 673 | siginfo_t info; |
674 | |||
675 | exception_enter(regs); | ||
653 | local_irq_enable(); | 676 | local_irq_enable(); |
654 | 677 | ||
655 | info.si_signo = SIGILL; | 678 | info.si_signo = SIGILL; |
@@ -657,10 +680,11 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) | |||
657 | info.si_code = ILL_BADSTK; | 680 | info.si_code = ILL_BADSTK; |
658 | info.si_addr = NULL; | 681 | info.si_addr = NULL; |
659 | if (notify_die(DIE_TRAP, "iret exception", regs, error_code, | 682 | if (notify_die(DIE_TRAP, "iret exception", regs, error_code, |
660 | X86_TRAP_IRET, SIGILL) == NOTIFY_STOP) | 683 | X86_TRAP_IRET, SIGILL) != NOTIFY_STOP) { |
661 | return; | 684 | do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code, |
662 | do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code, | 685 | &info); |
663 | &info); | 686 | } |
687 | exception_exit(regs); | ||
664 | } | 688 | } |
665 | #endif | 689 | #endif |
666 | 690 | ||
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 36fd42091fa7..9538f00827a9 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
@@ -41,6 +41,9 @@ | |||
41 | /* Adjust the return address of a call insn */ | 41 | /* Adjust the return address of a call insn */ |
42 | #define UPROBE_FIX_CALL 0x2 | 42 | #define UPROBE_FIX_CALL 0x2 |
43 | 43 | ||
44 | /* Instruction will modify TF, don't change it */ | ||
45 | #define UPROBE_FIX_SETF 0x4 | ||
46 | |||
44 | #define UPROBE_FIX_RIP_AX 0x8000 | 47 | #define UPROBE_FIX_RIP_AX 0x8000 |
45 | #define UPROBE_FIX_RIP_CX 0x4000 | 48 | #define UPROBE_FIX_RIP_CX 0x4000 |
46 | 49 | ||
@@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn) | |||
239 | insn_get_opcode(insn); /* should be a nop */ | 242 | insn_get_opcode(insn); /* should be a nop */ |
240 | 243 | ||
241 | switch (OPCODE1(insn)) { | 244 | switch (OPCODE1(insn)) { |
245 | case 0x9d: | ||
246 | /* popf */ | ||
247 | auprobe->fixups |= UPROBE_FIX_SETF; | ||
248 | break; | ||
242 | case 0xc3: /* ret/lret */ | 249 | case 0xc3: /* ret/lret */ |
243 | case 0xcb: | 250 | case 0xcb: |
244 | case 0xc2: | 251 | case 0xc2: |
@@ -646,7 +653,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
646 | * Skip these instructions as per the currently known x86 ISA. | 653 | * Skip these instructions as per the currently known x86 ISA. |
647 | * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } | 654 | * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } |
648 | */ | 655 | */ |
649 | bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | 656 | static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) |
650 | { | 657 | { |
651 | int i; | 658 | int i; |
652 | 659 | ||
@@ -673,3 +680,46 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
673 | } | 680 | } |
674 | return false; | 681 | return false; |
675 | } | 682 | } |
683 | |||
684 | bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | ||
685 | { | ||
686 | bool ret = __skip_sstep(auprobe, regs); | ||
687 | if (ret && (regs->flags & X86_EFLAGS_TF)) | ||
688 | send_sig(SIGTRAP, current, 0); | ||
689 | return ret; | ||
690 | } | ||
691 | |||
692 | void arch_uprobe_enable_step(struct arch_uprobe *auprobe) | ||
693 | { | ||
694 | struct task_struct *task = current; | ||
695 | struct arch_uprobe_task *autask = &task->utask->autask; | ||
696 | struct pt_regs *regs = task_pt_regs(task); | ||
697 | |||
698 | autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); | ||
699 | |||
700 | regs->flags |= X86_EFLAGS_TF; | ||
701 | if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) | ||
702 | set_task_blockstep(task, false); | ||
703 | } | ||
704 | |||
705 | void arch_uprobe_disable_step(struct arch_uprobe *auprobe) | ||
706 | { | ||
707 | struct task_struct *task = current; | ||
708 | struct arch_uprobe_task *autask = &task->utask->autask; | ||
709 | bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED); | ||
710 | struct pt_regs *regs = task_pt_regs(task); | ||
711 | /* | ||
712 | * The state of TIF_BLOCKSTEP was not saved so we can get an extra | ||
713 | * SIGTRAP if we do not clear TF. We need to examine the opcode to | ||
714 | * make it right. | ||
715 | */ | ||
716 | if (unlikely(trapped)) { | ||
717 | if (!autask->saved_tf) | ||
718 | regs->flags &= ~X86_EFLAGS_TF; | ||
719 | } else { | ||
720 | if (autask->saved_tf) | ||
721 | send_sig(SIGTRAP, task, 0); | ||
722 | else if (!(auprobe->fixups & UPROBE_FIX_SETF)) | ||
723 | regs->flags &= ~X86_EFLAGS_TF; | ||
724 | } | ||
725 | } | ||
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index 6020f6f5927c..1330dd102950 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c | |||
@@ -13,9 +13,13 @@ | |||
13 | #include <asm/ftrace.h> | 13 | #include <asm/ftrace.h> |
14 | 14 | ||
15 | #ifdef CONFIG_FUNCTION_TRACER | 15 | #ifdef CONFIG_FUNCTION_TRACER |
16 | /* mcount is defined in assembly */ | 16 | /* mcount and __fentry__ are defined in assembly */ |
17 | #ifdef CC_USING_FENTRY | ||
18 | EXPORT_SYMBOL(__fentry__); | ||
19 | #else | ||
17 | EXPORT_SYMBOL(mcount); | 20 | EXPORT_SYMBOL(mcount); |
18 | #endif | 21 | #endif |
22 | #endif | ||
19 | 23 | ||
20 | EXPORT_SYMBOL(__get_user_1); | 24 | EXPORT_SYMBOL(__get_user_1); |
21 | EXPORT_SYMBOL(__get_user_2); | 25 | EXPORT_SYMBOL(__get_user_2); |
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 9f3167e891ef..7a3d075a814a 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c | |||
@@ -26,7 +26,6 @@ | |||
26 | 26 | ||
27 | void __cpuinit x86_init_noop(void) { } | 27 | void __cpuinit x86_init_noop(void) { } |
28 | void __init x86_init_uint_noop(unsigned int unused) { } | 28 | void __init x86_init_uint_noop(unsigned int unused) { } |
29 | void __init x86_init_pgd_noop(pgd_t *unused) { } | ||
30 | int __init iommu_init_noop(void) { return 0; } | 29 | int __init iommu_init_noop(void) { return 0; } |
31 | void iommu_shutdown_noop(void) { } | 30 | void iommu_shutdown_noop(void) { } |
32 | 31 | ||
@@ -68,8 +67,7 @@ struct x86_init_ops x86_init __initdata = { | |||
68 | }, | 67 | }, |
69 | 68 | ||
70 | .paging = { | 69 | .paging = { |
71 | .pagetable_setup_start = native_pagetable_setup_start, | 70 | .pagetable_init = native_pagetable_init, |
72 | .pagetable_setup_done = native_pagetable_setup_done, | ||
73 | }, | 71 | }, |
74 | 72 | ||
75 | .timers = { | 73 | .timers = { |
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 3d3e20709119..4e89b3dd408d 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
@@ -10,9 +10,7 @@ | |||
10 | #include <linux/compat.h> | 10 | #include <linux/compat.h> |
11 | #include <asm/i387.h> | 11 | #include <asm/i387.h> |
12 | #include <asm/fpu-internal.h> | 12 | #include <asm/fpu-internal.h> |
13 | #ifdef CONFIG_IA32_EMULATION | 13 | #include <asm/sigframe.h> |
14 | #include <asm/sigcontext32.h> | ||
15 | #endif | ||
16 | #include <asm/xcr.h> | 14 | #include <asm/xcr.h> |
17 | 15 | ||
18 | /* | 16 | /* |
@@ -23,13 +21,9 @@ u64 pcntxt_mask; | |||
23 | /* | 21 | /* |
24 | * Represents init state for the supported extended state. | 22 | * Represents init state for the supported extended state. |
25 | */ | 23 | */ |
26 | static struct xsave_struct *init_xstate_buf; | 24 | struct xsave_struct *init_xstate_buf; |
27 | |||
28 | struct _fpx_sw_bytes fx_sw_reserved; | ||
29 | #ifdef CONFIG_IA32_EMULATION | ||
30 | struct _fpx_sw_bytes fx_sw_reserved_ia32; | ||
31 | #endif | ||
32 | 25 | ||
26 | static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32; | ||
33 | static unsigned int *xstate_offsets, *xstate_sizes, xstate_features; | 27 | static unsigned int *xstate_offsets, *xstate_sizes, xstate_features; |
34 | 28 | ||
35 | /* | 29 | /* |
@@ -44,9 +38,9 @@ static unsigned int *xstate_offsets, *xstate_sizes, xstate_features; | |||
44 | */ | 38 | */ |
45 | void __sanitize_i387_state(struct task_struct *tsk) | 39 | void __sanitize_i387_state(struct task_struct *tsk) |
46 | { | 40 | { |
47 | u64 xstate_bv; | ||
48 | int feature_bit = 0x2; | ||
49 | struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave; | 41 | struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave; |
42 | int feature_bit = 0x2; | ||
43 | u64 xstate_bv; | ||
50 | 44 | ||
51 | if (!fx) | 45 | if (!fx) |
52 | return; | 46 | return; |
@@ -104,213 +98,326 @@ void __sanitize_i387_state(struct task_struct *tsk) | |||
104 | * Check for the presence of extended state information in the | 98 | * Check for the presence of extended state information in the |
105 | * user fpstate pointer in the sigcontext. | 99 | * user fpstate pointer in the sigcontext. |
106 | */ | 100 | */ |
107 | int check_for_xstate(struct i387_fxsave_struct __user *buf, | 101 | static inline int check_for_xstate(struct i387_fxsave_struct __user *buf, |
108 | void __user *fpstate, | 102 | void __user *fpstate, |
109 | struct _fpx_sw_bytes *fx_sw_user) | 103 | struct _fpx_sw_bytes *fx_sw) |
110 | { | 104 | { |
111 | int min_xstate_size = sizeof(struct i387_fxsave_struct) + | 105 | int min_xstate_size = sizeof(struct i387_fxsave_struct) + |
112 | sizeof(struct xsave_hdr_struct); | 106 | sizeof(struct xsave_hdr_struct); |
113 | unsigned int magic2; | 107 | unsigned int magic2; |
114 | int err; | ||
115 | 108 | ||
116 | err = __copy_from_user(fx_sw_user, &buf->sw_reserved[0], | 109 | if (__copy_from_user(fx_sw, &buf->sw_reserved[0], sizeof(*fx_sw))) |
117 | sizeof(struct _fpx_sw_bytes)); | 110 | return -1; |
118 | if (err) | ||
119 | return -EFAULT; | ||
120 | 111 | ||
121 | /* | 112 | /* Check for the first magic field and other error scenarios. */ |
122 | * First Magic check failed. | 113 | if (fx_sw->magic1 != FP_XSTATE_MAGIC1 || |
123 | */ | 114 | fx_sw->xstate_size < min_xstate_size || |
124 | if (fx_sw_user->magic1 != FP_XSTATE_MAGIC1) | 115 | fx_sw->xstate_size > xstate_size || |
125 | return -EINVAL; | 116 | fx_sw->xstate_size > fx_sw->extended_size) |
117 | return -1; | ||
126 | 118 | ||
127 | /* | 119 | /* |
128 | * Check for error scenarios. | ||
129 | */ | ||
130 | if (fx_sw_user->xstate_size < min_xstate_size || | ||
131 | fx_sw_user->xstate_size > xstate_size || | ||
132 | fx_sw_user->xstate_size > fx_sw_user->extended_size) | ||
133 | return -EINVAL; | ||
134 | |||
135 | err = __get_user(magic2, (__u32 *) (((void *)fpstate) + | ||
136 | fx_sw_user->extended_size - | ||
137 | FP_XSTATE_MAGIC2_SIZE)); | ||
138 | if (err) | ||
139 | return err; | ||
140 | /* | ||
141 | * Check for the presence of second magic word at the end of memory | 120 | * Check for the presence of second magic word at the end of memory |
142 | * layout. This detects the case where the user just copied the legacy | 121 | * layout. This detects the case where the user just copied the legacy |
143 | * fpstate layout with out copying the extended state information | 122 | * fpstate layout with out copying the extended state information |
144 | * in the memory layout. | 123 | * in the memory layout. |
145 | */ | 124 | */ |
146 | if (magic2 != FP_XSTATE_MAGIC2) | 125 | if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size)) |
147 | return -EFAULT; | 126 | || magic2 != FP_XSTATE_MAGIC2) |
127 | return -1; | ||
148 | 128 | ||
149 | return 0; | 129 | return 0; |
150 | } | 130 | } |
151 | 131 | ||
152 | #ifdef CONFIG_X86_64 | ||
153 | /* | 132 | /* |
154 | * Signal frame handlers. | 133 | * Signal frame handlers. |
155 | */ | 134 | */ |
156 | 135 | static inline int save_fsave_header(struct task_struct *tsk, void __user *buf) | |
157 | int save_i387_xstate(void __user *buf) | ||
158 | { | 136 | { |
159 | struct task_struct *tsk = current; | 137 | if (use_fxsr()) { |
160 | int err = 0; | 138 | struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; |
161 | 139 | struct user_i387_ia32_struct env; | |
162 | if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) | 140 | struct _fpstate_ia32 __user *fp = buf; |
163 | return -EACCES; | ||
164 | 141 | ||
165 | BUG_ON(sig_xstate_size < xstate_size); | 142 | convert_from_fxsr(&env, tsk); |
166 | 143 | ||
167 | if ((unsigned long)buf % 64) | 144 | if (__copy_to_user(buf, &env, sizeof(env)) || |
168 | pr_err("%s: bad fpstate %p\n", __func__, buf); | 145 | __put_user(xsave->i387.swd, &fp->status) || |
169 | 146 | __put_user(X86_FXSR_MAGIC, &fp->magic)) | |
170 | if (!used_math()) | 147 | return -1; |
171 | return 0; | ||
172 | |||
173 | if (user_has_fpu()) { | ||
174 | if (use_xsave()) | ||
175 | err = xsave_user(buf); | ||
176 | else | ||
177 | err = fxsave_user(buf); | ||
178 | |||
179 | if (err) | ||
180 | return err; | ||
181 | user_fpu_end(); | ||
182 | } else { | 148 | } else { |
183 | sanitize_i387_state(tsk); | 149 | struct i387_fsave_struct __user *fp = buf; |
184 | if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, | 150 | u32 swd; |
185 | xstate_size)) | 151 | if (__get_user(swd, &fp->swd) || __put_user(swd, &fp->status)) |
186 | return -1; | 152 | return -1; |
187 | } | 153 | } |
188 | 154 | ||
189 | clear_used_math(); /* trigger finit */ | 155 | return 0; |
156 | } | ||
190 | 157 | ||
191 | if (use_xsave()) { | 158 | static inline int save_xstate_epilog(void __user *buf, int ia32_frame) |
192 | struct _fpstate __user *fx = buf; | 159 | { |
193 | struct _xstate __user *x = buf; | 160 | struct xsave_struct __user *x = buf; |
194 | u64 xstate_bv; | 161 | struct _fpx_sw_bytes *sw_bytes; |
162 | u32 xstate_bv; | ||
163 | int err; | ||
195 | 164 | ||
196 | err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, | 165 | /* Setup the bytes not touched by the [f]xsave and reserved for SW. */ |
197 | sizeof(struct _fpx_sw_bytes)); | 166 | sw_bytes = ia32_frame ? &fx_sw_reserved_ia32 : &fx_sw_reserved; |
167 | err = __copy_to_user(&x->i387.sw_reserved, sw_bytes, sizeof(*sw_bytes)); | ||
198 | 168 | ||
199 | err |= __put_user(FP_XSTATE_MAGIC2, | 169 | if (!use_xsave()) |
200 | (__u32 __user *) (buf + sig_xstate_size | 170 | return err; |
201 | - FP_XSTATE_MAGIC2_SIZE)); | ||
202 | 171 | ||
203 | /* | 172 | err |= __put_user(FP_XSTATE_MAGIC2, (__u32 *)(buf + xstate_size)); |
204 | * Read the xstate_bv which we copied (directly from the cpu or | ||
205 | * from the state in task struct) to the user buffers and | ||
206 | * set the FP/SSE bits. | ||
207 | */ | ||
208 | err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv); | ||
209 | 173 | ||
210 | /* | 174 | /* |
211 | * For legacy compatible, we always set FP/SSE bits in the bit | 175 | * Read the xstate_bv which we copied (directly from the cpu or |
212 | * vector while saving the state to the user context. This will | 176 | * from the state in task struct) to the user buffers. |
213 | * enable us capturing any changes(during sigreturn) to | 177 | */ |
214 | * the FP/SSE bits by the legacy applications which don't touch | 178 | err |= __get_user(xstate_bv, (__u32 *)&x->xsave_hdr.xstate_bv); |
215 | * xstate_bv in the xsave header. | ||
216 | * | ||
217 | * xsave aware apps can change the xstate_bv in the xsave | ||
218 | * header as well as change any contents in the memory layout. | ||
219 | * xrestore as part of sigreturn will capture all the changes. | ||
220 | */ | ||
221 | xstate_bv |= XSTATE_FPSSE; | ||
222 | 179 | ||
223 | err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv); | 180 | /* |
181 | * For legacy compatible, we always set FP/SSE bits in the bit | ||
182 | * vector while saving the state to the user context. This will | ||
183 | * enable us capturing any changes(during sigreturn) to | ||
184 | * the FP/SSE bits by the legacy applications which don't touch | ||
185 | * xstate_bv in the xsave header. | ||
186 | * | ||
187 | * xsave aware apps can change the xstate_bv in the xsave | ||
188 | * header as well as change any contents in the memory layout. | ||
189 | * xrestore as part of sigreturn will capture all the changes. | ||
190 | */ | ||
191 | xstate_bv |= XSTATE_FPSSE; | ||
224 | 192 | ||
225 | if (err) | 193 | err |= __put_user(xstate_bv, (__u32 *)&x->xsave_hdr.xstate_bv); |
226 | return err; | ||
227 | } | ||
228 | 194 | ||
229 | return 1; | 195 | return err; |
196 | } | ||
197 | |||
198 | static inline int save_user_xstate(struct xsave_struct __user *buf) | ||
199 | { | ||
200 | int err; | ||
201 | |||
202 | if (use_xsave()) | ||
203 | err = xsave_user(buf); | ||
204 | else if (use_fxsr()) | ||
205 | err = fxsave_user((struct i387_fxsave_struct __user *) buf); | ||
206 | else | ||
207 | err = fsave_user((struct i387_fsave_struct __user *) buf); | ||
208 | |||
209 | if (unlikely(err) && __clear_user(buf, xstate_size)) | ||
210 | err = -EFAULT; | ||
211 | return err; | ||
230 | } | 212 | } |
231 | 213 | ||
232 | /* | 214 | /* |
233 | * Restore the extended state if present. Otherwise, restore the FP/SSE | 215 | * Save the fpu, extended register state to the user signal frame. |
234 | * state. | 216 | * |
217 | * 'buf_fx' is the 64-byte aligned pointer at which the [f|fx|x]save | ||
218 | * state is copied. | ||
219 | * 'buf' points to the 'buf_fx' or to the fsave header followed by 'buf_fx'. | ||
220 | * | ||
221 | * buf == buf_fx for 64-bit frames and 32-bit fsave frame. | ||
222 | * buf != buf_fx for 32-bit frames with fxstate. | ||
223 | * | ||
224 | * If the fpu, extended register state is live, save the state directly | ||
225 | * to the user frame pointed by the aligned pointer 'buf_fx'. Otherwise, | ||
226 | * copy the thread's fpu state to the user frame starting at 'buf_fx'. | ||
227 | * | ||
228 | * If this is a 32-bit frame with fxstate, put a fsave header before | ||
229 | * the aligned state at 'buf_fx'. | ||
230 | * | ||
231 | * For [f]xsave state, update the SW reserved fields in the [f]xsave frame | ||
232 | * indicating the absence/presence of the extended state to the user. | ||
235 | */ | 233 | */ |
236 | static int restore_user_xstate(void __user *buf) | 234 | int save_xstate_sig(void __user *buf, void __user *buf_fx, int size) |
237 | { | 235 | { |
238 | struct _fpx_sw_bytes fx_sw_user; | 236 | struct xsave_struct *xsave = ¤t->thread.fpu.state->xsave; |
239 | u64 mask; | 237 | struct task_struct *tsk = current; |
240 | int err; | 238 | int ia32_fxstate = (buf != buf_fx); |
241 | 239 | ||
242 | if (((unsigned long)buf % 64) || | 240 | ia32_fxstate &= (config_enabled(CONFIG_X86_32) || |
243 | check_for_xstate(buf, buf, &fx_sw_user)) | 241 | config_enabled(CONFIG_IA32_EMULATION)); |
244 | goto fx_only; | ||
245 | 242 | ||
246 | mask = fx_sw_user.xstate_bv; | 243 | if (!access_ok(VERIFY_WRITE, buf, size)) |
244 | return -EACCES; | ||
247 | 245 | ||
248 | /* | 246 | if (!HAVE_HWFP) |
249 | * restore the state passed by the user. | 247 | return fpregs_soft_get(current, NULL, 0, |
250 | */ | 248 | sizeof(struct user_i387_ia32_struct), NULL, |
251 | err = xrestore_user(buf, mask); | 249 | (struct _fpstate_ia32 __user *) buf) ? -1 : 1; |
252 | if (err) | ||
253 | return err; | ||
254 | 250 | ||
255 | /* | 251 | if (user_has_fpu()) { |
256 | * init the state skipped by the user. | 252 | /* Save the live register state to the user directly. */ |
257 | */ | 253 | if (save_user_xstate(buf_fx)) |
258 | mask = pcntxt_mask & ~mask; | 254 | return -1; |
259 | if (unlikely(mask)) | 255 | /* Update the thread's fxstate to save the fsave header. */ |
260 | xrstor_state(init_xstate_buf, mask); | 256 | if (ia32_fxstate) |
257 | fpu_fxsave(&tsk->thread.fpu); | ||
258 | } else { | ||
259 | sanitize_i387_state(tsk); | ||
260 | if (__copy_to_user(buf_fx, xsave, xstate_size)) | ||
261 | return -1; | ||
262 | } | ||
263 | |||
264 | /* Save the fsave header for the 32-bit frames. */ | ||
265 | if ((ia32_fxstate || !use_fxsr()) && save_fsave_header(tsk, buf)) | ||
266 | return -1; | ||
267 | |||
268 | if (use_fxsr() && save_xstate_epilog(buf_fx, ia32_fxstate)) | ||
269 | return -1; | ||
270 | |||
271 | drop_init_fpu(tsk); /* trigger finit */ | ||
261 | 272 | ||
262 | return 0; | 273 | return 0; |
274 | } | ||
263 | 275 | ||
264 | fx_only: | 276 | static inline void |
265 | /* | 277 | sanitize_restored_xstate(struct task_struct *tsk, |
266 | * couldn't find the extended state information in the | 278 | struct user_i387_ia32_struct *ia32_env, |
267 | * memory layout. Restore just the FP/SSE and init all | 279 | u64 xstate_bv, int fx_only) |
268 | * the other extended state. | 280 | { |
269 | */ | 281 | struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; |
270 | xrstor_state(init_xstate_buf, pcntxt_mask & ~XSTATE_FPSSE); | 282 | struct xsave_hdr_struct *xsave_hdr = &xsave->xsave_hdr; |
271 | return fxrstor_checking((__force struct i387_fxsave_struct *)buf); | 283 | |
284 | if (use_xsave()) { | ||
285 | /* These bits must be zero. */ | ||
286 | xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; | ||
287 | |||
288 | /* | ||
289 | * Init the state that is not present in the memory | ||
290 | * layout and not enabled by the OS. | ||
291 | */ | ||
292 | if (fx_only) | ||
293 | xsave_hdr->xstate_bv = XSTATE_FPSSE; | ||
294 | else | ||
295 | xsave_hdr->xstate_bv &= (pcntxt_mask & xstate_bv); | ||
296 | } | ||
297 | |||
298 | if (use_fxsr()) { | ||
299 | /* | ||
300 | * mscsr reserved bits must be masked to zero for security | ||
301 | * reasons. | ||
302 | */ | ||
303 | xsave->i387.mxcsr &= mxcsr_feature_mask; | ||
304 | |||
305 | convert_to_fxsr(tsk, ia32_env); | ||
306 | } | ||
272 | } | 307 | } |
273 | 308 | ||
274 | /* | 309 | /* |
275 | * This restores directly out of user space. Exceptions are handled. | 310 | * Restore the extended state if present. Otherwise, restore the FP/SSE state. |
276 | */ | 311 | */ |
277 | int restore_i387_xstate(void __user *buf) | 312 | static inline int restore_user_xstate(void __user *buf, u64 xbv, int fx_only) |
278 | { | 313 | { |
314 | if (use_xsave()) { | ||
315 | if ((unsigned long)buf % 64 || fx_only) { | ||
316 | u64 init_bv = pcntxt_mask & ~XSTATE_FPSSE; | ||
317 | xrstor_state(init_xstate_buf, init_bv); | ||
318 | return fxrstor_checking((__force void *) buf); | ||
319 | } else { | ||
320 | u64 init_bv = pcntxt_mask & ~xbv; | ||
321 | if (unlikely(init_bv)) | ||
322 | xrstor_state(init_xstate_buf, init_bv); | ||
323 | return xrestore_user(buf, xbv); | ||
324 | } | ||
325 | } else if (use_fxsr()) { | ||
326 | return fxrstor_checking((__force void *) buf); | ||
327 | } else | ||
328 | return frstor_checking((__force void *) buf); | ||
329 | } | ||
330 | |||
331 | int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) | ||
332 | { | ||
333 | int ia32_fxstate = (buf != buf_fx); | ||
279 | struct task_struct *tsk = current; | 334 | struct task_struct *tsk = current; |
280 | int err = 0; | 335 | int state_size = xstate_size; |
336 | u64 xstate_bv = 0; | ||
337 | int fx_only = 0; | ||
338 | |||
339 | ia32_fxstate &= (config_enabled(CONFIG_X86_32) || | ||
340 | config_enabled(CONFIG_IA32_EMULATION)); | ||
281 | 341 | ||
282 | if (!buf) { | 342 | if (!buf) { |
283 | if (used_math()) | 343 | drop_init_fpu(tsk); |
284 | goto clear; | ||
285 | return 0; | 344 | return 0; |
286 | } else | 345 | } |
287 | if (!access_ok(VERIFY_READ, buf, sig_xstate_size)) | ||
288 | return -EACCES; | ||
289 | 346 | ||
290 | if (!used_math()) { | 347 | if (!access_ok(VERIFY_READ, buf, size)) |
291 | err = init_fpu(tsk); | 348 | return -EACCES; |
292 | if (err) | 349 | |
293 | return err; | 350 | if (!used_math() && init_fpu(tsk)) |
351 | return -1; | ||
352 | |||
353 | if (!HAVE_HWFP) { | ||
354 | return fpregs_soft_set(current, NULL, | ||
355 | 0, sizeof(struct user_i387_ia32_struct), | ||
356 | NULL, buf) != 0; | ||
294 | } | 357 | } |
295 | 358 | ||
296 | user_fpu_begin(); | 359 | if (use_xsave()) { |
297 | if (use_xsave()) | 360 | struct _fpx_sw_bytes fx_sw_user; |
298 | err = restore_user_xstate(buf); | 361 | if (unlikely(check_for_xstate(buf_fx, buf_fx, &fx_sw_user))) { |
299 | else | 362 | /* |
300 | err = fxrstor_checking((__force struct i387_fxsave_struct *) | 363 | * Couldn't find the extended state information in the |
301 | buf); | 364 | * memory layout. Restore just the FP/SSE and init all |
302 | if (unlikely(err)) { | 365 | * the other extended state. |
366 | */ | ||
367 | state_size = sizeof(struct i387_fxsave_struct); | ||
368 | fx_only = 1; | ||
369 | } else { | ||
370 | state_size = fx_sw_user.xstate_size; | ||
371 | xstate_bv = fx_sw_user.xstate_bv; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | if (ia32_fxstate) { | ||
376 | /* | ||
377 | * For 32-bit frames with fxstate, copy the user state to the | ||
378 | * thread's fpu state, reconstruct fxstate from the fsave | ||
379 | * header. Sanitize the copied state etc. | ||
380 | */ | ||
381 | struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; | ||
382 | struct user_i387_ia32_struct env; | ||
383 | int err = 0; | ||
384 | |||
385 | /* | ||
386 | * Drop the current fpu which clears used_math(). This ensures | ||
387 | * that any context-switch during the copy of the new state, | ||
388 | * avoids the intermediate state from getting restored/saved. | ||
389 | * Thus avoiding the new restored state from getting corrupted. | ||
390 | * We will be ready to restore/save the state only after | ||
391 | * set_used_math() is again set. | ||
392 | */ | ||
393 | drop_fpu(tsk); | ||
394 | |||
395 | if (__copy_from_user(xsave, buf_fx, state_size) || | ||
396 | __copy_from_user(&env, buf, sizeof(env))) { | ||
397 | err = -1; | ||
398 | } else { | ||
399 | sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only); | ||
400 | set_used_math(); | ||
401 | } | ||
402 | |||
403 | if (use_eager_fpu()) | ||
404 | math_state_restore(); | ||
405 | |||
406 | return err; | ||
407 | } else { | ||
303 | /* | 408 | /* |
304 | * Encountered an error while doing the restore from the | 409 | * For 64-bit frames and 32-bit fsave frames, restore the user |
305 | * user buffer, clear the fpu state. | 410 | * state to the registers directly (with exceptions handled). |
306 | */ | 411 | */ |
307 | clear: | 412 | user_fpu_begin(); |
308 | clear_fpu(tsk); | 413 | if (restore_user_xstate(buf_fx, xstate_bv, fx_only)) { |
309 | clear_used_math(); | 414 | drop_init_fpu(tsk); |
415 | return -1; | ||
416 | } | ||
310 | } | 417 | } |
311 | return err; | 418 | |
419 | return 0; | ||
312 | } | 420 | } |
313 | #endif | ||
314 | 421 | ||
315 | /* | 422 | /* |
316 | * Prepare the SW reserved portion of the fxsave memory layout, indicating | 423 | * Prepare the SW reserved portion of the fxsave memory layout, indicating |
@@ -321,31 +428,22 @@ clear: | |||
321 | */ | 428 | */ |
322 | static void prepare_fx_sw_frame(void) | 429 | static void prepare_fx_sw_frame(void) |
323 | { | 430 | { |
324 | int size_extended = (xstate_size - sizeof(struct i387_fxsave_struct)) + | 431 | int fsave_header_size = sizeof(struct i387_fsave_struct); |
325 | FP_XSTATE_MAGIC2_SIZE; | 432 | int size = xstate_size + FP_XSTATE_MAGIC2_SIZE; |
326 | 433 | ||
327 | sig_xstate_size = sizeof(struct _fpstate) + size_extended; | 434 | if (config_enabled(CONFIG_X86_32)) |
328 | 435 | size += fsave_header_size; | |
329 | #ifdef CONFIG_IA32_EMULATION | ||
330 | sig_xstate_ia32_size = sizeof(struct _fpstate_ia32) + size_extended; | ||
331 | #endif | ||
332 | |||
333 | memset(&fx_sw_reserved, 0, sizeof(fx_sw_reserved)); | ||
334 | 436 | ||
335 | fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1; | 437 | fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1; |
336 | fx_sw_reserved.extended_size = sig_xstate_size; | 438 | fx_sw_reserved.extended_size = size; |
337 | fx_sw_reserved.xstate_bv = pcntxt_mask; | 439 | fx_sw_reserved.xstate_bv = pcntxt_mask; |
338 | fx_sw_reserved.xstate_size = xstate_size; | 440 | fx_sw_reserved.xstate_size = xstate_size; |
339 | #ifdef CONFIG_IA32_EMULATION | ||
340 | memcpy(&fx_sw_reserved_ia32, &fx_sw_reserved, | ||
341 | sizeof(struct _fpx_sw_bytes)); | ||
342 | fx_sw_reserved_ia32.extended_size = sig_xstate_ia32_size; | ||
343 | #endif | ||
344 | } | ||
345 | 441 | ||
346 | #ifdef CONFIG_X86_64 | 442 | if (config_enabled(CONFIG_IA32_EMULATION)) { |
347 | unsigned int sig_xstate_size = sizeof(struct _fpstate); | 443 | fx_sw_reserved_ia32 = fx_sw_reserved; |
348 | #endif | 444 | fx_sw_reserved_ia32.extended_size += fsave_header_size; |
445 | } | ||
446 | } | ||
349 | 447 | ||
350 | /* | 448 | /* |
351 | * Enable the extended processor state save/restore feature | 449 | * Enable the extended processor state save/restore feature |
@@ -384,19 +482,21 @@ static void __init setup_xstate_features(void) | |||
384 | /* | 482 | /* |
385 | * setup the xstate image representing the init state | 483 | * setup the xstate image representing the init state |
386 | */ | 484 | */ |
387 | static void __init setup_xstate_init(void) | 485 | static void __init setup_init_fpu_buf(void) |
388 | { | 486 | { |
389 | setup_xstate_features(); | ||
390 | |||
391 | /* | 487 | /* |
392 | * Setup init_xstate_buf to represent the init state of | 488 | * Setup init_xstate_buf to represent the init state of |
393 | * all the features managed by the xsave | 489 | * all the features managed by the xsave |
394 | */ | 490 | */ |
395 | init_xstate_buf = alloc_bootmem_align(xstate_size, | 491 | init_xstate_buf = alloc_bootmem_align(xstate_size, |
396 | __alignof__(struct xsave_struct)); | 492 | __alignof__(struct xsave_struct)); |
397 | init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; | 493 | fx_finit(&init_xstate_buf->i387); |
494 | |||
495 | if (!cpu_has_xsave) | ||
496 | return; | ||
497 | |||
498 | setup_xstate_features(); | ||
398 | 499 | ||
399 | clts(); | ||
400 | /* | 500 | /* |
401 | * Init all the features state with header_bv being 0x0 | 501 | * Init all the features state with header_bv being 0x0 |
402 | */ | 502 | */ |
@@ -406,9 +506,21 @@ static void __init setup_xstate_init(void) | |||
406 | * of any feature which is not represented by all zero's. | 506 | * of any feature which is not represented by all zero's. |
407 | */ | 507 | */ |
408 | xsave_state(init_xstate_buf, -1); | 508 | xsave_state(init_xstate_buf, -1); |
409 | stts(); | ||
410 | } | 509 | } |
411 | 510 | ||
511 | static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO; | ||
512 | static int __init eager_fpu_setup(char *s) | ||
513 | { | ||
514 | if (!strcmp(s, "on")) | ||
515 | eagerfpu = ENABLE; | ||
516 | else if (!strcmp(s, "off")) | ||
517 | eagerfpu = DISABLE; | ||
518 | else if (!strcmp(s, "auto")) | ||
519 | eagerfpu = AUTO; | ||
520 | return 1; | ||
521 | } | ||
522 | __setup("eagerfpu=", eager_fpu_setup); | ||
523 | |||
412 | /* | 524 | /* |
413 | * Enable and initialize the xsave feature. | 525 | * Enable and initialize the xsave feature. |
414 | */ | 526 | */ |
@@ -445,8 +557,11 @@ static void __init xstate_enable_boot_cpu(void) | |||
445 | 557 | ||
446 | update_regset_xstate_info(xstate_size, pcntxt_mask); | 558 | update_regset_xstate_info(xstate_size, pcntxt_mask); |
447 | prepare_fx_sw_frame(); | 559 | prepare_fx_sw_frame(); |
560 | setup_init_fpu_buf(); | ||
448 | 561 | ||
449 | setup_xstate_init(); | 562 | /* Auto enable eagerfpu for xsaveopt */ |
563 | if (cpu_has_xsaveopt && eagerfpu != DISABLE) | ||
564 | eagerfpu = ENABLE; | ||
450 | 565 | ||
451 | pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n", | 566 | pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n", |
452 | pcntxt_mask, xstate_size); | 567 | pcntxt_mask, xstate_size); |
@@ -471,3 +586,43 @@ void __cpuinit xsave_init(void) | |||
471 | next_func = xstate_enable; | 586 | next_func = xstate_enable; |
472 | this_func(); | 587 | this_func(); |
473 | } | 588 | } |
589 | |||
590 | static inline void __init eager_fpu_init_bp(void) | ||
591 | { | ||
592 | current->thread.fpu.state = | ||
593 | alloc_bootmem_align(xstate_size, __alignof__(struct xsave_struct)); | ||
594 | if (!init_xstate_buf) | ||
595 | setup_init_fpu_buf(); | ||
596 | } | ||
597 | |||
598 | void __cpuinit eager_fpu_init(void) | ||
599 | { | ||
600 | static __refdata void (*boot_func)(void) = eager_fpu_init_bp; | ||
601 | |||
602 | clear_used_math(); | ||
603 | current_thread_info()->status = 0; | ||
604 | |||
605 | if (eagerfpu == ENABLE) | ||
606 | setup_force_cpu_cap(X86_FEATURE_EAGER_FPU); | ||
607 | |||
608 | if (!cpu_has_eager_fpu) { | ||
609 | stts(); | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | if (boot_func) { | ||
614 | boot_func(); | ||
615 | boot_func = NULL; | ||
616 | } | ||
617 | |||
618 | /* | ||
619 | * This is same as math_state_restore(). But use_xsave() is | ||
620 | * not yet patched to use math_state_restore(). | ||
621 | */ | ||
622 | init_fpu(current); | ||
623 | __thread_fpu_begin(current); | ||
624 | if (cpu_has_xsave) | ||
625 | xrstor_state(init_xstate_buf, -1); | ||
626 | else | ||
627 | fxrstor_checking(&init_xstate_buf->i387); | ||
628 | } | ||
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index e498b18f010c..9fc9aa7ac703 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c | |||
@@ -318,7 +318,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val) | |||
318 | if (val & 0x10) { | 318 | if (val & 0x10) { |
319 | u8 edge_irr = s->irr & ~s->elcr; | 319 | u8 edge_irr = s->irr & ~s->elcr; |
320 | int i; | 320 | int i; |
321 | bool found; | 321 | bool found = false; |
322 | struct kvm_vcpu *vcpu; | 322 | struct kvm_vcpu *vcpu; |
323 | 323 | ||
324 | s->init4 = val & 1; | 324 | s->init4 = val & 1; |
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index a71faf727ff3..bca63f04dccb 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h | |||
@@ -183,95 +183,6 @@ TRACE_EVENT(kvm_apic, | |||
183 | #define KVM_ISA_VMX 1 | 183 | #define KVM_ISA_VMX 1 |
184 | #define KVM_ISA_SVM 2 | 184 | #define KVM_ISA_SVM 2 |
185 | 185 | ||
186 | #define VMX_EXIT_REASONS \ | ||
187 | { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ | ||
188 | { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \ | ||
189 | { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \ | ||
190 | { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \ | ||
191 | { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \ | ||
192 | { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \ | ||
193 | { EXIT_REASON_CPUID, "CPUID" }, \ | ||
194 | { EXIT_REASON_HLT, "HLT" }, \ | ||
195 | { EXIT_REASON_INVLPG, "INVLPG" }, \ | ||
196 | { EXIT_REASON_RDPMC, "RDPMC" }, \ | ||
197 | { EXIT_REASON_RDTSC, "RDTSC" }, \ | ||
198 | { EXIT_REASON_VMCALL, "VMCALL" }, \ | ||
199 | { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \ | ||
200 | { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \ | ||
201 | { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \ | ||
202 | { EXIT_REASON_VMPTRST, "VMPTRST" }, \ | ||
203 | { EXIT_REASON_VMREAD, "VMREAD" }, \ | ||
204 | { EXIT_REASON_VMRESUME, "VMRESUME" }, \ | ||
205 | { EXIT_REASON_VMWRITE, "VMWRITE" }, \ | ||
206 | { EXIT_REASON_VMOFF, "VMOFF" }, \ | ||
207 | { EXIT_REASON_VMON, "VMON" }, \ | ||
208 | { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \ | ||
209 | { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \ | ||
210 | { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \ | ||
211 | { EXIT_REASON_MSR_READ, "MSR_READ" }, \ | ||
212 | { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \ | ||
213 | { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \ | ||
214 | { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \ | ||
215 | { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \ | ||
216 | { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \ | ||
217 | { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \ | ||
218 | { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \ | ||
219 | { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \ | ||
220 | { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \ | ||
221 | { EXIT_REASON_WBINVD, "WBINVD" } | ||
222 | |||
223 | #define SVM_EXIT_REASONS \ | ||
224 | { SVM_EXIT_READ_CR0, "read_cr0" }, \ | ||
225 | { SVM_EXIT_READ_CR3, "read_cr3" }, \ | ||
226 | { SVM_EXIT_READ_CR4, "read_cr4" }, \ | ||
227 | { SVM_EXIT_READ_CR8, "read_cr8" }, \ | ||
228 | { SVM_EXIT_WRITE_CR0, "write_cr0" }, \ | ||
229 | { SVM_EXIT_WRITE_CR3, "write_cr3" }, \ | ||
230 | { SVM_EXIT_WRITE_CR4, "write_cr4" }, \ | ||
231 | { SVM_EXIT_WRITE_CR8, "write_cr8" }, \ | ||
232 | { SVM_EXIT_READ_DR0, "read_dr0" }, \ | ||
233 | { SVM_EXIT_READ_DR1, "read_dr1" }, \ | ||
234 | { SVM_EXIT_READ_DR2, "read_dr2" }, \ | ||
235 | { SVM_EXIT_READ_DR3, "read_dr3" }, \ | ||
236 | { SVM_EXIT_WRITE_DR0, "write_dr0" }, \ | ||
237 | { SVM_EXIT_WRITE_DR1, "write_dr1" }, \ | ||
238 | { SVM_EXIT_WRITE_DR2, "write_dr2" }, \ | ||
239 | { SVM_EXIT_WRITE_DR3, "write_dr3" }, \ | ||
240 | { SVM_EXIT_WRITE_DR5, "write_dr5" }, \ | ||
241 | { SVM_EXIT_WRITE_DR7, "write_dr7" }, \ | ||
242 | { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \ | ||
243 | { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \ | ||
244 | { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \ | ||
245 | { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \ | ||
246 | { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \ | ||
247 | { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \ | ||
248 | { SVM_EXIT_INTR, "interrupt" }, \ | ||
249 | { SVM_EXIT_NMI, "nmi" }, \ | ||
250 | { SVM_EXIT_SMI, "smi" }, \ | ||
251 | { SVM_EXIT_INIT, "init" }, \ | ||
252 | { SVM_EXIT_VINTR, "vintr" }, \ | ||
253 | { SVM_EXIT_CPUID, "cpuid" }, \ | ||
254 | { SVM_EXIT_INVD, "invd" }, \ | ||
255 | { SVM_EXIT_HLT, "hlt" }, \ | ||
256 | { SVM_EXIT_INVLPG, "invlpg" }, \ | ||
257 | { SVM_EXIT_INVLPGA, "invlpga" }, \ | ||
258 | { SVM_EXIT_IOIO, "io" }, \ | ||
259 | { SVM_EXIT_MSR, "msr" }, \ | ||
260 | { SVM_EXIT_TASK_SWITCH, "task_switch" }, \ | ||
261 | { SVM_EXIT_SHUTDOWN, "shutdown" }, \ | ||
262 | { SVM_EXIT_VMRUN, "vmrun" }, \ | ||
263 | { SVM_EXIT_VMMCALL, "hypercall" }, \ | ||
264 | { SVM_EXIT_VMLOAD, "vmload" }, \ | ||
265 | { SVM_EXIT_VMSAVE, "vmsave" }, \ | ||
266 | { SVM_EXIT_STGI, "stgi" }, \ | ||
267 | { SVM_EXIT_CLGI, "clgi" }, \ | ||
268 | { SVM_EXIT_SKINIT, "skinit" }, \ | ||
269 | { SVM_EXIT_WBINVD, "wbinvd" }, \ | ||
270 | { SVM_EXIT_MONITOR, "monitor" }, \ | ||
271 | { SVM_EXIT_MWAIT, "mwait" }, \ | ||
272 | { SVM_EXIT_XSETBV, "xsetbv" }, \ | ||
273 | { SVM_EXIT_NPF, "npf" } | ||
274 | |||
275 | /* | 186 | /* |
276 | * Tracepoint for kvm guest exit: | 187 | * Tracepoint for kvm guest exit: |
277 | */ | 188 | */ |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c00f03de1b79..851aa7c3b890 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -1493,8 +1493,12 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) | |||
1493 | #ifdef CONFIG_X86_64 | 1493 | #ifdef CONFIG_X86_64 |
1494 | wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); | 1494 | wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); |
1495 | #endif | 1495 | #endif |
1496 | if (user_has_fpu()) | 1496 | /* |
1497 | clts(); | 1497 | * If the FPU is not active (through the host task or |
1498 | * the guest vcpu), then restore the cr0.TS bit. | ||
1499 | */ | ||
1500 | if (!user_has_fpu() && !vmx->vcpu.guest_fpu_loaded) | ||
1501 | stts(); | ||
1498 | load_gdt(&__get_cpu_var(host_gdt)); | 1502 | load_gdt(&__get_cpu_var(host_gdt)); |
1499 | } | 1503 | } |
1500 | 1504 | ||
@@ -3619,6 +3623,7 @@ static void seg_setup(int seg) | |||
3619 | 3623 | ||
3620 | static int alloc_apic_access_page(struct kvm *kvm) | 3624 | static int alloc_apic_access_page(struct kvm *kvm) |
3621 | { | 3625 | { |
3626 | struct page *page; | ||
3622 | struct kvm_userspace_memory_region kvm_userspace_mem; | 3627 | struct kvm_userspace_memory_region kvm_userspace_mem; |
3623 | int r = 0; | 3628 | int r = 0; |
3624 | 3629 | ||
@@ -3633,7 +3638,13 @@ static int alloc_apic_access_page(struct kvm *kvm) | |||
3633 | if (r) | 3638 | if (r) |
3634 | goto out; | 3639 | goto out; |
3635 | 3640 | ||
3636 | kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00); | 3641 | page = gfn_to_page(kvm, 0xfee00); |
3642 | if (is_error_page(page)) { | ||
3643 | r = -EFAULT; | ||
3644 | goto out; | ||
3645 | } | ||
3646 | |||
3647 | kvm->arch.apic_access_page = page; | ||
3637 | out: | 3648 | out: |
3638 | mutex_unlock(&kvm->slots_lock); | 3649 | mutex_unlock(&kvm->slots_lock); |
3639 | return r; | 3650 | return r; |
@@ -3641,6 +3652,7 @@ out: | |||
3641 | 3652 | ||
3642 | static int alloc_identity_pagetable(struct kvm *kvm) | 3653 | static int alloc_identity_pagetable(struct kvm *kvm) |
3643 | { | 3654 | { |
3655 | struct page *page; | ||
3644 | struct kvm_userspace_memory_region kvm_userspace_mem; | 3656 | struct kvm_userspace_memory_region kvm_userspace_mem; |
3645 | int r = 0; | 3657 | int r = 0; |
3646 | 3658 | ||
@@ -3656,8 +3668,13 @@ static int alloc_identity_pagetable(struct kvm *kvm) | |||
3656 | if (r) | 3668 | if (r) |
3657 | goto out; | 3669 | goto out; |
3658 | 3670 | ||
3659 | kvm->arch.ept_identity_pagetable = gfn_to_page(kvm, | 3671 | page = gfn_to_page(kvm, kvm->arch.ept_identity_map_addr >> PAGE_SHIFT); |
3660 | kvm->arch.ept_identity_map_addr >> PAGE_SHIFT); | 3672 | if (is_error_page(page)) { |
3673 | r = -EFAULT; | ||
3674 | goto out; | ||
3675 | } | ||
3676 | |||
3677 | kvm->arch.ept_identity_pagetable = page; | ||
3661 | out: | 3678 | out: |
3662 | mutex_unlock(&kvm->slots_lock); | 3679 | mutex_unlock(&kvm->slots_lock); |
3663 | return r; | 3680 | return r; |
@@ -3730,7 +3747,7 @@ static void vmx_set_constant_host_state(void) | |||
3730 | unsigned long tmpl; | 3747 | unsigned long tmpl; |
3731 | struct desc_ptr dt; | 3748 | struct desc_ptr dt; |
3732 | 3749 | ||
3733 | vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS); /* 22.2.3 */ | 3750 | vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); /* 22.2.3 */ |
3734 | vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */ | 3751 | vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */ |
3735 | vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ | 3752 | vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ |
3736 | 3753 | ||
@@ -4530,7 +4547,7 @@ static int handle_cr(struct kvm_vcpu *vcpu) | |||
4530 | vcpu->run->exit_reason = KVM_EXIT_SET_TPR; | 4547 | vcpu->run->exit_reason = KVM_EXIT_SET_TPR; |
4531 | return 0; | 4548 | return 0; |
4532 | } | 4549 | } |
4533 | }; | 4550 | } |
4534 | break; | 4551 | break; |
4535 | case 2: /* clts */ | 4552 | case 2: /* clts */ |
4536 | handle_clts(vcpu); | 4553 | handle_clts(vcpu); |
@@ -6575,7 +6592,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) | |||
6575 | /* Exposing INVPCID only when PCID is exposed */ | 6592 | /* Exposing INVPCID only when PCID is exposed */ |
6576 | best = kvm_find_cpuid_entry(vcpu, 0x7, 0); | 6593 | best = kvm_find_cpuid_entry(vcpu, 0x7, 0); |
6577 | if (vmx_invpcid_supported() && | 6594 | if (vmx_invpcid_supported() && |
6578 | best && (best->ecx & bit(X86_FEATURE_INVPCID)) && | 6595 | best && (best->ebx & bit(X86_FEATURE_INVPCID)) && |
6579 | guest_cpuid_has_pcid(vcpu)) { | 6596 | guest_cpuid_has_pcid(vcpu)) { |
6580 | exec_control |= SECONDARY_EXEC_ENABLE_INVPCID; | 6597 | exec_control |= SECONDARY_EXEC_ENABLE_INVPCID; |
6581 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, | 6598 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, |
@@ -6585,7 +6602,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) | |||
6585 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, | 6602 | vmcs_write32(SECONDARY_VM_EXEC_CONTROL, |
6586 | exec_control); | 6603 | exec_control); |
6587 | if (best) | 6604 | if (best) |
6588 | best->ecx &= ~bit(X86_FEATURE_INVPCID); | 6605 | best->ebx &= ~bit(X86_FEATURE_INVPCID); |
6589 | } | 6606 | } |
6590 | } | 6607 | } |
6591 | 6608 | ||
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 148ed666e311..1f09552572fa 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -5113,17 +5113,20 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) | |||
5113 | !kvm_event_needs_reinjection(vcpu); | 5113 | !kvm_event_needs_reinjection(vcpu); |
5114 | } | 5114 | } |
5115 | 5115 | ||
5116 | static void vapic_enter(struct kvm_vcpu *vcpu) | 5116 | static int vapic_enter(struct kvm_vcpu *vcpu) |
5117 | { | 5117 | { |
5118 | struct kvm_lapic *apic = vcpu->arch.apic; | 5118 | struct kvm_lapic *apic = vcpu->arch.apic; |
5119 | struct page *page; | 5119 | struct page *page; |
5120 | 5120 | ||
5121 | if (!apic || !apic->vapic_addr) | 5121 | if (!apic || !apic->vapic_addr) |
5122 | return; | 5122 | return 0; |
5123 | 5123 | ||
5124 | page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); | 5124 | page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); |
5125 | if (is_error_page(page)) | ||
5126 | return -EFAULT; | ||
5125 | 5127 | ||
5126 | vcpu->arch.apic->vapic_page = page; | 5128 | vcpu->arch.apic->vapic_page = page; |
5129 | return 0; | ||
5127 | } | 5130 | } |
5128 | 5131 | ||
5129 | static void vapic_exit(struct kvm_vcpu *vcpu) | 5132 | static void vapic_exit(struct kvm_vcpu *vcpu) |
@@ -5430,7 +5433,11 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
5430 | } | 5433 | } |
5431 | 5434 | ||
5432 | vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); | 5435 | vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); |
5433 | vapic_enter(vcpu); | 5436 | r = vapic_enter(vcpu); |
5437 | if (r) { | ||
5438 | srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); | ||
5439 | return r; | ||
5440 | } | ||
5434 | 5441 | ||
5435 | r = 1; | 5442 | r = 1; |
5436 | while (r > 0) { | 5443 | while (r > 0) { |
@@ -5972,7 +5979,7 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) | |||
5972 | */ | 5979 | */ |
5973 | kvm_put_guest_xcr0(vcpu); | 5980 | kvm_put_guest_xcr0(vcpu); |
5974 | vcpu->guest_fpu_loaded = 1; | 5981 | vcpu->guest_fpu_loaded = 1; |
5975 | unlazy_fpu(current); | 5982 | __kernel_fpu_begin(); |
5976 | fpu_restore_checking(&vcpu->arch.guest_fpu); | 5983 | fpu_restore_checking(&vcpu->arch.guest_fpu); |
5977 | trace_kvm_fpu(1); | 5984 | trace_kvm_fpu(1); |
5978 | } | 5985 | } |
@@ -5986,6 +5993,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) | |||
5986 | 5993 | ||
5987 | vcpu->guest_fpu_loaded = 0; | 5994 | vcpu->guest_fpu_loaded = 0; |
5988 | fpu_save_init(&vcpu->arch.guest_fpu); | 5995 | fpu_save_init(&vcpu->arch.guest_fpu); |
5996 | __kernel_fpu_end(); | ||
5989 | ++vcpu->stat.fpu_reload; | 5997 | ++vcpu->stat.fpu_reload; |
5990 | kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu); | 5998 | kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu); |
5991 | trace_kvm_fpu(0); | 5999 | trace_kvm_fpu(0); |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 76dcd9d8e0bc..7dde46d68a25 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/pgalloc.h> /* pgd_*(), ... */ | 18 | #include <asm/pgalloc.h> /* pgd_*(), ... */ |
19 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ | 19 | #include <asm/kmemcheck.h> /* kmemcheck_*(), ... */ |
20 | #include <asm/fixmap.h> /* VSYSCALL_START */ | 20 | #include <asm/fixmap.h> /* VSYSCALL_START */ |
21 | #include <asm/rcu.h> /* exception_enter(), ... */ | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * Page fault error code bits: | 24 | * Page fault error code bits: |
@@ -1000,8 +1001,8 @@ static int fault_in_kernel_space(unsigned long address) | |||
1000 | * and the problem, and then passes it off to one of the appropriate | 1001 | * and the problem, and then passes it off to one of the appropriate |
1001 | * routines. | 1002 | * routines. |
1002 | */ | 1003 | */ |
1003 | dotraplinkage void __kprobes | 1004 | static void __kprobes |
1004 | do_page_fault(struct pt_regs *regs, unsigned long error_code) | 1005 | __do_page_fault(struct pt_regs *regs, unsigned long error_code) |
1005 | { | 1006 | { |
1006 | struct vm_area_struct *vma; | 1007 | struct vm_area_struct *vma; |
1007 | struct task_struct *tsk; | 1008 | struct task_struct *tsk; |
@@ -1209,3 +1210,11 @@ good_area: | |||
1209 | 1210 | ||
1210 | up_read(&mm->mmap_sem); | 1211 | up_read(&mm->mmap_sem); |
1211 | } | 1212 | } |
1213 | |||
1214 | dotraplinkage void __kprobes | ||
1215 | do_page_fault(struct pt_regs *regs, unsigned long error_code) | ||
1216 | { | ||
1217 | exception_enter(regs); | ||
1218 | __do_page_fault(regs, error_code); | ||
1219 | exception_exit(regs); | ||
1220 | } | ||
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index e0e6990723e9..ab1f6a93b527 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -319,7 +319,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
319 | */ | 319 | */ |
320 | int devmem_is_allowed(unsigned long pagenr) | 320 | int devmem_is_allowed(unsigned long pagenr) |
321 | { | 321 | { |
322 | if (pagenr <= 256) | 322 | if (pagenr < 256) |
323 | return 1; | 323 | return 1; |
324 | if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) | 324 | if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) |
325 | return 0; | 325 | return 0; |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 575d86f85ce4..4f04db150027 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -445,10 +445,10 @@ static inline void permanent_kmaps_init(pgd_t *pgd_base) | |||
445 | } | 445 | } |
446 | #endif /* CONFIG_HIGHMEM */ | 446 | #endif /* CONFIG_HIGHMEM */ |
447 | 447 | ||
448 | void __init native_pagetable_setup_start(pgd_t *base) | 448 | void __init native_pagetable_init(void) |
449 | { | 449 | { |
450 | unsigned long pfn, va; | 450 | unsigned long pfn, va; |
451 | pgd_t *pgd; | 451 | pgd_t *pgd, *base = swapper_pg_dir; |
452 | pud_t *pud; | 452 | pud_t *pud; |
453 | pmd_t *pmd; | 453 | pmd_t *pmd; |
454 | pte_t *pte; | 454 | pte_t *pte; |
@@ -475,10 +475,7 @@ void __init native_pagetable_setup_start(pgd_t *base) | |||
475 | pte_clear(NULL, va, pte); | 475 | pte_clear(NULL, va, pte); |
476 | } | 476 | } |
477 | paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT); | 477 | paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT); |
478 | } | 478 | paging_init(); |
479 | |||
480 | void __init native_pagetable_setup_done(pgd_t *base) | ||
481 | { | ||
482 | } | 479 | } |
483 | 480 | ||
484 | /* | 481 | /* |
@@ -493,7 +490,7 @@ void __init native_pagetable_setup_done(pgd_t *base) | |||
493 | * If we're booting paravirtualized under a hypervisor, then there are | 490 | * If we're booting paravirtualized under a hypervisor, then there are |
494 | * more options: we may already be running PAE, and the pagetable may | 491 | * more options: we may already be running PAE, and the pagetable may |
495 | * or may not be based in swapper_pg_dir. In any case, | 492 | * or may not be based in swapper_pg_dir. In any case, |
496 | * paravirt_pagetable_setup_start() will set up swapper_pg_dir | 493 | * paravirt_pagetable_init() will set up swapper_pg_dir |
497 | * appropriately for the rest of the initialization to work. | 494 | * appropriately for the rest of the initialization to work. |
498 | * | 495 | * |
499 | * In general, pagetable_init() assumes that the pagetable may already | 496 | * In general, pagetable_init() assumes that the pagetable may already |
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 613cd83e8c0c..0777f042e400 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c | |||
@@ -98,6 +98,8 @@ static void flush_tlb_func(void *info) | |||
98 | { | 98 | { |
99 | struct flush_tlb_info *f = info; | 99 | struct flush_tlb_info *f = info; |
100 | 100 | ||
101 | inc_irq_stat(irq_tlb_count); | ||
102 | |||
101 | if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm)) | 103 | if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm)) |
102 | return; | 104 | return; |
103 | 105 | ||
@@ -320,7 +322,7 @@ static ssize_t tlbflush_write_file(struct file *file, | |||
320 | if (kstrtos8(buf, 0, &shift)) | 322 | if (kstrtos8(buf, 0, &shift)) |
321 | return -EINVAL; | 323 | return -EINVAL; |
322 | 324 | ||
323 | if (shift > 64) | 325 | if (shift < -1 || shift >= BITS_PER_LONG) |
324 | return -EINVAL; | 326 | return -EINVAL; |
325 | 327 | ||
326 | tlb_flushall_shift = shift; | 328 | tlb_flushall_shift = shift; |
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 937bcece7006..704b9ec043d7 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c | |||
@@ -585,7 +585,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) | |||
585 | while (i >= sizeof(struct acpi_mcfg_allocation)) { | 585 | while (i >= sizeof(struct acpi_mcfg_allocation)) { |
586 | entries++; | 586 | entries++; |
587 | i -= sizeof(struct acpi_mcfg_allocation); | 587 | i -= sizeof(struct acpi_mcfg_allocation); |
588 | }; | 588 | } |
589 | if (entries == 0) { | 589 | if (entries == 0) { |
590 | pr_err(PREFIX "MMCONFIG has no entries\n"); | 590 | pr_err(PREFIX "MMCONFIG has no entries\n"); |
591 | return -ENODEV; | 591 | return -ENODEV; |
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile index 73b8be0f3675..6db1cc4c7534 100644 --- a/arch/x86/platform/efi/Makefile +++ b/arch/x86/platform/efi/Makefile | |||
@@ -1 +1,2 @@ | |||
1 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 1 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o |
2 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o | ||
diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c new file mode 100644 index 000000000000..f6a0c1b8e518 --- /dev/null +++ b/arch/x86/platform/efi/efi-bgrt.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Intel Corporation | ||
3 | * Author: Josh Triplett <josh@joshtriplett.org> | ||
4 | * | ||
5 | * Based on the bgrt driver: | ||
6 | * Copyright 2012 Red Hat, Inc <mjg@redhat.com> | ||
7 | * Author: Matthew Garrett | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/acpi.h> | ||
15 | #include <linux/efi.h> | ||
16 | #include <linux/efi-bgrt.h> | ||
17 | |||
18 | struct acpi_table_bgrt *bgrt_tab; | ||
19 | void *bgrt_image; | ||
20 | size_t bgrt_image_size; | ||
21 | |||
22 | struct bmp_header { | ||
23 | u16 id; | ||
24 | u32 size; | ||
25 | } __packed; | ||
26 | |||
27 | void efi_bgrt_init(void) | ||
28 | { | ||
29 | acpi_status status; | ||
30 | void __iomem *image; | ||
31 | bool ioremapped = false; | ||
32 | struct bmp_header bmp_header; | ||
33 | |||
34 | if (acpi_disabled) | ||
35 | return; | ||
36 | |||
37 | status = acpi_get_table("BGRT", 0, | ||
38 | (struct acpi_table_header **)&bgrt_tab); | ||
39 | if (ACPI_FAILURE(status)) | ||
40 | return; | ||
41 | |||
42 | if (bgrt_tab->version != 1) | ||
43 | return; | ||
44 | if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address) | ||
45 | return; | ||
46 | |||
47 | image = efi_lookup_mapped_addr(bgrt_tab->image_address); | ||
48 | if (!image) { | ||
49 | image = ioremap(bgrt_tab->image_address, sizeof(bmp_header)); | ||
50 | ioremapped = true; | ||
51 | if (!image) | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | memcpy_fromio(&bmp_header, image, sizeof(bmp_header)); | ||
56 | if (ioremapped) | ||
57 | iounmap(image); | ||
58 | bgrt_image_size = bmp_header.size; | ||
59 | |||
60 | bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL); | ||
61 | if (!bgrt_image) | ||
62 | return; | ||
63 | |||
64 | if (ioremapped) { | ||
65 | image = ioremap(bgrt_tab->image_address, bmp_header.size); | ||
66 | if (!image) { | ||
67 | kfree(bgrt_image); | ||
68 | bgrt_image = NULL; | ||
69 | return; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | memcpy_fromio(bgrt_image, image, bgrt_image_size); | ||
74 | if (ioremapped) | ||
75 | iounmap(image); | ||
76 | } | ||
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 92660edaa1e7..aded2a91162a 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/efi.h> | 33 | #include <linux/efi.h> |
34 | #include <linux/efi-bgrt.h> | ||
34 | #include <linux/export.h> | 35 | #include <linux/export.h> |
35 | #include <linux/bootmem.h> | 36 | #include <linux/bootmem.h> |
36 | #include <linux/memblock.h> | 37 | #include <linux/memblock.h> |
@@ -419,10 +420,21 @@ void __init efi_reserve_boot_services(void) | |||
419 | } | 420 | } |
420 | } | 421 | } |
421 | 422 | ||
422 | static void __init efi_free_boot_services(void) | 423 | static void __init efi_unmap_memmap(void) |
424 | { | ||
425 | if (memmap.map) { | ||
426 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); | ||
427 | memmap.map = NULL; | ||
428 | } | ||
429 | } | ||
430 | |||
431 | void __init efi_free_boot_services(void) | ||
423 | { | 432 | { |
424 | void *p; | 433 | void *p; |
425 | 434 | ||
435 | if (!efi_native) | ||
436 | return; | ||
437 | |||
426 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 438 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
427 | efi_memory_desc_t *md = p; | 439 | efi_memory_desc_t *md = p; |
428 | unsigned long long start = md->phys_addr; | 440 | unsigned long long start = md->phys_addr; |
@@ -438,6 +450,8 @@ static void __init efi_free_boot_services(void) | |||
438 | 450 | ||
439 | free_bootmem_late(start, size); | 451 | free_bootmem_late(start, size); |
440 | } | 452 | } |
453 | |||
454 | efi_unmap_memmap(); | ||
441 | } | 455 | } |
442 | 456 | ||
443 | static int __init efi_systab_init(void *phys) | 457 | static int __init efi_systab_init(void *phys) |
@@ -732,6 +746,11 @@ void __init efi_init(void) | |||
732 | #endif | 746 | #endif |
733 | } | 747 | } |
734 | 748 | ||
749 | void __init efi_late_init(void) | ||
750 | { | ||
751 | efi_bgrt_init(); | ||
752 | } | ||
753 | |||
735 | void __init efi_set_executable(efi_memory_desc_t *md, bool executable) | 754 | void __init efi_set_executable(efi_memory_desc_t *md, bool executable) |
736 | { | 755 | { |
737 | u64 addr, npages; | 756 | u64 addr, npages; |
@@ -764,6 +783,34 @@ static void __init runtime_code_page_mkexec(void) | |||
764 | } | 783 | } |
765 | 784 | ||
766 | /* | 785 | /* |
786 | * We can't ioremap data in EFI boot services RAM, because we've already mapped | ||
787 | * it as RAM. So, look it up in the existing EFI memory map instead. Only | ||
788 | * callable after efi_enter_virtual_mode and before efi_free_boot_services. | ||
789 | */ | ||
790 | void __iomem *efi_lookup_mapped_addr(u64 phys_addr) | ||
791 | { | ||
792 | void *p; | ||
793 | if (WARN_ON(!memmap.map)) | ||
794 | return NULL; | ||
795 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
796 | efi_memory_desc_t *md = p; | ||
797 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | ||
798 | u64 end = md->phys_addr + size; | ||
799 | if (!(md->attribute & EFI_MEMORY_RUNTIME) && | ||
800 | md->type != EFI_BOOT_SERVICES_CODE && | ||
801 | md->type != EFI_BOOT_SERVICES_DATA) | ||
802 | continue; | ||
803 | if (!md->virt_addr) | ||
804 | continue; | ||
805 | if (phys_addr >= md->phys_addr && phys_addr < end) { | ||
806 | phys_addr += md->virt_addr - md->phys_addr; | ||
807 | return (__force void __iomem *)(unsigned long)phys_addr; | ||
808 | } | ||
809 | } | ||
810 | return NULL; | ||
811 | } | ||
812 | |||
813 | /* | ||
767 | * This function will switch the EFI runtime services to virtual mode. | 814 | * This function will switch the EFI runtime services to virtual mode. |
768 | * Essentially, look through the EFI memmap and map every region that | 815 | * Essentially, look through the EFI memmap and map every region that |
769 | * has the runtime attribute bit set in its memory descriptor and update | 816 | * has the runtime attribute bit set in its memory descriptor and update |
@@ -787,8 +834,10 @@ void __init efi_enter_virtual_mode(void) | |||
787 | * non-native EFI | 834 | * non-native EFI |
788 | */ | 835 | */ |
789 | 836 | ||
790 | if (!efi_native) | 837 | if (!efi_native) { |
791 | goto out; | 838 | efi_unmap_memmap(); |
839 | return; | ||
840 | } | ||
792 | 841 | ||
793 | /* Merge contiguous regions of the same type and attribute */ | 842 | /* Merge contiguous regions of the same type and attribute */ |
794 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 843 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
@@ -878,18 +927,12 @@ void __init efi_enter_virtual_mode(void) | |||
878 | } | 927 | } |
879 | 928 | ||
880 | /* | 929 | /* |
881 | * Thankfully, it does seem that no runtime services other than | ||
882 | * SetVirtualAddressMap() will touch boot services code, so we can | ||
883 | * get rid of it all at this point | ||
884 | */ | ||
885 | efi_free_boot_services(); | ||
886 | |||
887 | /* | ||
888 | * Now that EFI is in virtual mode, update the function | 930 | * Now that EFI is in virtual mode, update the function |
889 | * pointers in the runtime service table to the new virtual addresses. | 931 | * pointers in the runtime service table to the new virtual addresses. |
890 | * | 932 | * |
891 | * Call EFI services through wrapper functions. | 933 | * Call EFI services through wrapper functions. |
892 | */ | 934 | */ |
935 | efi.runtime_version = efi_systab.fw_revision; | ||
893 | efi.get_time = virt_efi_get_time; | 936 | efi.get_time = virt_efi_get_time; |
894 | efi.set_time = virt_efi_set_time; | 937 | efi.set_time = virt_efi_set_time; |
895 | efi.get_wakeup_time = virt_efi_get_wakeup_time; | 938 | efi.get_wakeup_time = virt_efi_get_wakeup_time; |
@@ -906,9 +949,6 @@ void __init efi_enter_virtual_mode(void) | |||
906 | if (__supported_pte_mask & _PAGE_NX) | 949 | if (__supported_pte_mask & _PAGE_NX) |
907 | runtime_code_page_mkexec(); | 950 | runtime_code_page_mkexec(); |
908 | 951 | ||
909 | out: | ||
910 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); | ||
911 | memmap.map = NULL; | ||
912 | kfree(new_memmap); | 952 | kfree(new_memmap); |
913 | } | 953 | } |
914 | 954 | ||
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig index 9926e11a772d..aeaff8bef2f1 100644 --- a/arch/x86/um/Kconfig +++ b/arch/x86/um/Kconfig | |||
@@ -21,6 +21,7 @@ config 64BIT | |||
21 | config X86_32 | 21 | config X86_32 |
22 | def_bool !64BIT | 22 | def_bool !64BIT |
23 | select HAVE_AOUT | 23 | select HAVE_AOUT |
24 | select ARCH_WANT_IPC_PARSE_VERSION | ||
24 | 25 | ||
25 | config X86_64 | 26 | config X86_64 |
26 | def_bool 64BIT | 27 | def_bool 64BIT |
diff --git a/arch/x86/um/shared/sysdep/kernel-offsets.h b/arch/x86/um/shared/sysdep/kernel-offsets.h index 5868526b5eef..46a9df99f3c5 100644 --- a/arch/x86/um/shared/sysdep/kernel-offsets.h +++ b/arch/x86/um/shared/sysdep/kernel-offsets.h | |||
@@ -7,9 +7,6 @@ | |||
7 | #define DEFINE(sym, val) \ | 7 | #define DEFINE(sym, val) \ |
8 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | 8 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) |
9 | 9 | ||
10 | #define STR(x) #x | ||
11 | #define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : ) | ||
12 | |||
13 | #define BLANK() asm volatile("\n->" : : ) | 10 | #define BLANK() asm volatile("\n->" : : ) |
14 | 11 | ||
15 | #define OFFSET(sym, str, mem) \ | 12 | #define OFFSET(sym, str, mem) \ |
diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h index bd9a89b67e41..ca255a805ed9 100644 --- a/arch/x86/um/shared/sysdep/syscalls.h +++ b/arch/x86/um/shared/sysdep/syscalls.h | |||
@@ -1,3 +1,5 @@ | |||
1 | extern long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
2 | void __user *parent_tid, void __user *child_tid); | ||
1 | #ifdef __i386__ | 3 | #ifdef __i386__ |
2 | #include "syscalls_32.h" | 4 | #include "syscalls_32.h" |
3 | #else | 5 | #else |
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c index a508cea13503..ba7363ecf896 100644 --- a/arch/x86/um/signal.c +++ b/arch/x86/um/signal.c | |||
@@ -416,9 +416,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
416 | PT_REGS_AX(regs) = (unsigned long) sig; | 416 | PT_REGS_AX(regs) = (unsigned long) sig; |
417 | PT_REGS_DX(regs) = (unsigned long) 0; | 417 | PT_REGS_DX(regs) = (unsigned long) 0; |
418 | PT_REGS_CX(regs) = (unsigned long) 0; | 418 | PT_REGS_CX(regs) = (unsigned long) 0; |
419 | |||
420 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) | ||
421 | ptrace_notify(SIGTRAP); | ||
422 | return 0; | 419 | return 0; |
423 | } | 420 | } |
424 | 421 | ||
@@ -466,9 +463,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
466 | PT_REGS_AX(regs) = (unsigned long) sig; | 463 | PT_REGS_AX(regs) = (unsigned long) sig; |
467 | PT_REGS_DX(regs) = (unsigned long) &frame->info; | 464 | PT_REGS_DX(regs) = (unsigned long) &frame->info; |
468 | PT_REGS_CX(regs) = (unsigned long) &frame->uc; | 465 | PT_REGS_CX(regs) = (unsigned long) &frame->uc; |
469 | |||
470 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) | ||
471 | ptrace_notify(SIGTRAP); | ||
472 | return 0; | 466 | return 0; |
473 | } | 467 | } |
474 | 468 | ||
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index 68d1dc91b37b..b5408cecac6c 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #define ptregs_execve sys_execve | 28 | #define ptregs_execve sys_execve |
29 | #define ptregs_iopl sys_iopl | 29 | #define ptregs_iopl sys_iopl |
30 | #define ptregs_vm86old sys_vm86old | 30 | #define ptregs_vm86old sys_vm86old |
31 | #define ptregs_clone sys_clone | 31 | #define ptregs_clone i386_clone |
32 | #define ptregs_vm86 sys_vm86 | 32 | #define ptregs_vm86 sys_vm86 |
33 | #define ptregs_sigaltstack sys_sigaltstack | 33 | #define ptregs_sigaltstack sys_sigaltstack |
34 | #define ptregs_vfork sys_vfork | 34 | #define ptregs_vfork sys_vfork |
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c index b853e8600b9d..db444c7218fe 100644 --- a/arch/x86/um/syscalls_32.c +++ b/arch/x86/um/syscalls_32.c | |||
@@ -3,37 +3,24 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "linux/sched.h" | 6 | #include <linux/syscalls.h> |
7 | #include "linux/shm.h" | 7 | #include <sysdep/syscalls.h> |
8 | #include "linux/ipc.h" | ||
9 | #include "linux/syscalls.h" | ||
10 | #include "asm/mman.h" | ||
11 | #include "asm/uaccess.h" | ||
12 | #include "asm/unistd.h" | ||
13 | 8 | ||
14 | /* | 9 | /* |
15 | * The prototype on i386 is: | 10 | * The prototype on i386 is: |
16 | * | 11 | * |
17 | * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) | 12 | * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls |
18 | * | 13 | * |
19 | * and the "newtls" arg. on i386 is read by copy_thread directly from the | 14 | * and the "newtls" arg. on i386 is read by copy_thread directly from the |
20 | * register saved on the stack. | 15 | * register saved on the stack. |
21 | */ | 16 | */ |
22 | long sys_clone(unsigned long clone_flags, unsigned long newsp, | 17 | long i386_clone(unsigned long clone_flags, unsigned long newsp, |
23 | int __user *parent_tid, void *newtls, int __user *child_tid) | 18 | int __user *parent_tid, void *newtls, int __user *child_tid) |
24 | { | 19 | { |
25 | long ret; | 20 | return sys_clone(clone_flags, newsp, parent_tid, child_tid); |
26 | |||
27 | if (!newsp) | ||
28 | newsp = UPT_SP(¤t->thread.regs.regs); | ||
29 | |||
30 | current->thread.forking = 1; | ||
31 | ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, | ||
32 | child_tid); | ||
33 | current->thread.forking = 0; | ||
34 | return ret; | ||
35 | } | 21 | } |
36 | 22 | ||
23 | |||
37 | long sys_sigaction(int sig, const struct old_sigaction __user *act, | 24 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
38 | struct old_sigaction __user *oact) | 25 | struct old_sigaction __user *oact) |
39 | { | 26 | { |
diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c index f3d82bb6e15a..adb08eb5c22a 100644 --- a/arch/x86/um/syscalls_64.c +++ b/arch/x86/um/syscalls_64.c | |||
@@ -5,12 +5,9 @@ | |||
5 | * Licensed under the GPL | 5 | * Licensed under the GPL |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "linux/linkage.h" | 8 | #include <linux/sched.h> |
9 | #include "linux/personality.h" | 9 | #include <asm/prctl.h> /* XXX This should get the constants from libc */ |
10 | #include "linux/utsname.h" | 10 | #include <os.h> |
11 | #include "asm/prctl.h" /* XXX This should get the constants from libc */ | ||
12 | #include "asm/uaccess.h" | ||
13 | #include "os.h" | ||
14 | 11 | ||
15 | long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) | 12 | long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) |
16 | { | 13 | { |
@@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr) | |||
79 | return arch_prctl(current, code, (unsigned long __user *) addr); | 76 | return arch_prctl(current, code, (unsigned long __user *) addr); |
80 | } | 77 | } |
81 | 78 | ||
82 | long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
83 | void __user *parent_tid, void __user *child_tid) | ||
84 | { | ||
85 | long ret; | ||
86 | |||
87 | if (!newsp) | ||
88 | newsp = UPT_SP(¤t->thread.regs.regs); | ||
89 | current->thread.forking = 1; | ||
90 | ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, | ||
91 | child_tid); | ||
92 | current->thread.forking = 0; | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | void arch_switch_to(struct task_struct *to) | 79 | void arch_switch_to(struct task_struct *to) |
97 | { | 80 | { |
98 | if ((to->thread.arch.fs == 0) || (to->mm == NULL)) | 81 | if ((to->thread.arch.fs == 0) || (to->mm == NULL)) |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 9642d4a38602..1fbe75a95f15 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1452,6 +1452,10 @@ asmlinkage void __init xen_start_kernel(void) | |||
1452 | pci_request_acs(); | 1452 | pci_request_acs(); |
1453 | 1453 | ||
1454 | xen_acpi_sleep_register(); | 1454 | xen_acpi_sleep_register(); |
1455 | |||
1456 | /* Avoid searching for BIOS MP tables */ | ||
1457 | x86_init.mpparse.find_smp_config = x86_init_noop; | ||
1458 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; | ||
1455 | } | 1459 | } |
1456 | #ifdef CONFIG_PCI | 1460 | #ifdef CONFIG_PCI |
1457 | /* PCI BIOS service won't work from a PV guest. */ | 1461 | /* PCI BIOS service won't work from a PV guest. */ |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 5141d808e751..7a769b7526cb 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -1174,8 +1174,13 @@ static void xen_exit_mmap(struct mm_struct *mm) | |||
1174 | spin_unlock(&mm->page_table_lock); | 1174 | spin_unlock(&mm->page_table_lock); |
1175 | } | 1175 | } |
1176 | 1176 | ||
1177 | static void __init xen_pagetable_setup_start(pgd_t *base) | 1177 | static void xen_post_allocator_init(void); |
1178 | |||
1179 | static void __init xen_pagetable_init(void) | ||
1178 | { | 1180 | { |
1181 | paging_init(); | ||
1182 | xen_setup_shared_info(); | ||
1183 | xen_post_allocator_init(); | ||
1179 | } | 1184 | } |
1180 | 1185 | ||
1181 | static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) | 1186 | static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) |
@@ -1192,14 +1197,6 @@ static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) | |||
1192 | } | 1197 | } |
1193 | } | 1198 | } |
1194 | 1199 | ||
1195 | static void xen_post_allocator_init(void); | ||
1196 | |||
1197 | static void __init xen_pagetable_setup_done(pgd_t *base) | ||
1198 | { | ||
1199 | xen_setup_shared_info(); | ||
1200 | xen_post_allocator_init(); | ||
1201 | } | ||
1202 | |||
1203 | static void xen_write_cr2(unsigned long cr2) | 1200 | static void xen_write_cr2(unsigned long cr2) |
1204 | { | 1201 | { |
1205 | this_cpu_read(xen_vcpu)->arch.cr2 = cr2; | 1202 | this_cpu_read(xen_vcpu)->arch.cr2 = cr2; |
@@ -2068,8 +2065,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { | |||
2068 | void __init xen_init_mmu_ops(void) | 2065 | void __init xen_init_mmu_ops(void) |
2069 | { | 2066 | { |
2070 | x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve; | 2067 | x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve; |
2071 | x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; | 2068 | x86_init.paging.pagetable_init = xen_pagetable_init; |
2072 | x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; | ||
2073 | pv_mmu_ops = xen_mmu_ops; | 2069 | pv_mmu_ops = xen_mmu_ops; |
2074 | 2070 | ||
2075 | memset(dummy_mapping, 0xff, PAGE_SIZE); | 2071 | memset(dummy_mapping, 0xff, PAGE_SIZE); |
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 76ba0e97e530..72213da605f5 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -828,9 +828,6 @@ int m2p_add_override(unsigned long mfn, struct page *page, | |||
828 | 828 | ||
829 | xen_mc_issue(PARAVIRT_LAZY_MMU); | 829 | xen_mc_issue(PARAVIRT_LAZY_MMU); |
830 | } | 830 | } |
831 | /* let's use dev_bus_addr to record the old mfn instead */ | ||
832 | kmap_op->dev_bus_addr = page->index; | ||
833 | page->index = (unsigned long) kmap_op; | ||
834 | } | 831 | } |
835 | spin_lock_irqsave(&m2p_override_lock, flags); | 832 | spin_lock_irqsave(&m2p_override_lock, flags); |
836 | list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); | 833 | list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); |
@@ -857,7 +854,8 @@ int m2p_add_override(unsigned long mfn, struct page *page, | |||
857 | return 0; | 854 | return 0; |
858 | } | 855 | } |
859 | EXPORT_SYMBOL_GPL(m2p_add_override); | 856 | EXPORT_SYMBOL_GPL(m2p_add_override); |
860 | int m2p_remove_override(struct page *page, bool clear_pte) | 857 | int m2p_remove_override(struct page *page, |
858 | struct gnttab_map_grant_ref *kmap_op) | ||
861 | { | 859 | { |
862 | unsigned long flags; | 860 | unsigned long flags; |
863 | unsigned long mfn; | 861 | unsigned long mfn; |
@@ -887,10 +885,8 @@ int m2p_remove_override(struct page *page, bool clear_pte) | |||
887 | WARN_ON(!PagePrivate(page)); | 885 | WARN_ON(!PagePrivate(page)); |
888 | ClearPagePrivate(page); | 886 | ClearPagePrivate(page); |
889 | 887 | ||
890 | if (clear_pte) { | 888 | set_phys_to_machine(pfn, page->index); |
891 | struct gnttab_map_grant_ref *map_op = | 889 | if (kmap_op != NULL) { |
892 | (struct gnttab_map_grant_ref *) page->index; | ||
893 | set_phys_to_machine(pfn, map_op->dev_bus_addr); | ||
894 | if (!PageHighMem(page)) { | 890 | if (!PageHighMem(page)) { |
895 | struct multicall_space mcs; | 891 | struct multicall_space mcs; |
896 | struct gnttab_unmap_grant_ref *unmap_op; | 892 | struct gnttab_unmap_grant_ref *unmap_op; |
@@ -902,13 +898,13 @@ int m2p_remove_override(struct page *page, bool clear_pte) | |||
902 | * issued. In this case handle is going to -1 because | 898 | * issued. In this case handle is going to -1 because |
903 | * it hasn't been modified yet. | 899 | * it hasn't been modified yet. |
904 | */ | 900 | */ |
905 | if (map_op->handle == -1) | 901 | if (kmap_op->handle == -1) |
906 | xen_mc_flush(); | 902 | xen_mc_flush(); |
907 | /* | 903 | /* |
908 | * Now if map_op->handle is negative it means that the | 904 | * Now if kmap_op->handle is negative it means that the |
909 | * hypercall actually returned an error. | 905 | * hypercall actually returned an error. |
910 | */ | 906 | */ |
911 | if (map_op->handle == GNTST_general_error) { | 907 | if (kmap_op->handle == GNTST_general_error) { |
912 | printk(KERN_WARNING "m2p_remove_override: " | 908 | printk(KERN_WARNING "m2p_remove_override: " |
913 | "pfn %lx mfn %lx, failed to modify kernel mappings", | 909 | "pfn %lx mfn %lx, failed to modify kernel mappings", |
914 | pfn, mfn); | 910 | pfn, mfn); |
@@ -918,8 +914,8 @@ int m2p_remove_override(struct page *page, bool clear_pte) | |||
918 | mcs = xen_mc_entry( | 914 | mcs = xen_mc_entry( |
919 | sizeof(struct gnttab_unmap_grant_ref)); | 915 | sizeof(struct gnttab_unmap_grant_ref)); |
920 | unmap_op = mcs.args; | 916 | unmap_op = mcs.args; |
921 | unmap_op->host_addr = map_op->host_addr; | 917 | unmap_op->host_addr = kmap_op->host_addr; |
922 | unmap_op->handle = map_op->handle; | 918 | unmap_op->handle = kmap_op->handle; |
923 | unmap_op->dev_bus_addr = 0; | 919 | unmap_op->dev_bus_addr = 0; |
924 | 920 | ||
925 | MULTI_grant_table_op(mcs.mc, | 921 | MULTI_grant_table_op(mcs.mc, |
@@ -930,10 +926,9 @@ int m2p_remove_override(struct page *page, bool clear_pte) | |||
930 | set_pte_at(&init_mm, address, ptep, | 926 | set_pte_at(&init_mm, address, ptep, |
931 | pfn_pte(pfn, PAGE_KERNEL)); | 927 | pfn_pte(pfn, PAGE_KERNEL)); |
932 | __flush_tlb_single(address); | 928 | __flush_tlb_single(address); |
933 | map_op->host_addr = 0; | 929 | kmap_op->host_addr = 0; |
934 | } | 930 | } |
935 | } else | 931 | } |
936 | set_phys_to_machine(pfn, page->index); | ||
937 | 932 | ||
938 | /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present | 933 | /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present |
939 | * somewhere in this domain, even before being added to the | 934 | * somewhere in this domain, even before being added to the |
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index d11ca11d14fc..e2d62d697b5d 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/e820.h> | 17 | #include <asm/e820.h> |
18 | #include <asm/setup.h> | 18 | #include <asm/setup.h> |
19 | #include <asm/acpi.h> | 19 | #include <asm/acpi.h> |
20 | #include <asm/numa.h> | ||
20 | #include <asm/xen/hypervisor.h> | 21 | #include <asm/xen/hypervisor.h> |
21 | #include <asm/xen/hypercall.h> | 22 | #include <asm/xen/hypercall.h> |
22 | 23 | ||
@@ -544,4 +545,7 @@ void __init xen_arch_setup(void) | |||
544 | disable_cpufreq(); | 545 | disable_cpufreq(); |
545 | WARN_ON(set_pm_idle_to_default()); | 546 | WARN_ON(set_pm_idle_to_default()); |
546 | fiddle_vdso(); | 547 | fiddle_vdso(); |
548 | #ifdef CONFIG_NUMA | ||
549 | numa_off = 1; | ||
550 | #endif | ||
547 | } | 551 | } |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index f58dca7a6e52..353c50f18702 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -377,7 +377,8 @@ static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *idle) | |||
377 | return rc; | 377 | return rc; |
378 | 378 | ||
379 | if (num_online_cpus() == 1) | 379 | if (num_online_cpus() == 1) |
380 | alternatives_smp_switch(1); | 380 | /* Just in case we booted with a single CPU. */ |
381 | alternatives_enable_smp(); | ||
381 | 382 | ||
382 | rc = xen_smp_intr_init(cpu); | 383 | rc = xen_smp_intr_init(cpu); |
383 | if (rc) | 384 | if (rc) |
@@ -424,9 +425,6 @@ static void xen_cpu_die(unsigned int cpu) | |||
424 | unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL); | 425 | unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL); |
425 | xen_uninit_lock_cpu(cpu); | 426 | xen_uninit_lock_cpu(cpu); |
426 | xen_teardown_timer(cpu); | 427 | xen_teardown_timer(cpu); |
427 | |||
428 | if (num_online_cpus() == 1) | ||
429 | alternatives_smp_switch(0); | ||
430 | } | 428 | } |
431 | 429 | ||
432 | static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */ | 430 | static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */ |
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 2c8d6a3d250a..bc44311aa18c 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/mqueue.h> | 31 | #include <linux/mqueue.h> |
32 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/rcupdate.h> | ||
34 | 35 | ||
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
@@ -110,8 +111,10 @@ void cpu_idle(void) | |||
110 | 111 | ||
111 | /* endless idle loop with no priority at all */ | 112 | /* endless idle loop with no priority at all */ |
112 | while (1) { | 113 | while (1) { |
114 | rcu_idle_enter(); | ||
113 | while (!need_resched()) | 115 | while (!need_resched()) |
114 | platform_idle(); | 116 | platform_idle(); |
117 | rcu_idle_exit(); | ||
115 | schedule_preempt_disabled(); | 118 | schedule_preempt_disabled(); |
116 | } | 119 | } |
117 | } | 120 | } |