aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/asm-offsets.c10
-rw-r--r--arch/arm/kernel/calls.S4
-rw-r--r--arch/arm/kernel/entry-armv.S111
-rw-r--r--arch/arm/kernel/entry-common.S5
-rw-r--r--arch/arm/kernel/head-common.S7
-rw-r--r--arch/arm/kernel/thumbee.c81
7 files changed, 179 insertions, 40 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 00d44c6fbfe9..d5be3f7ac0e3 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
22obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o 22obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
23obj-$(CONFIG_ATAGS_PROC) += atags.o 23obj-$(CONFIG_ATAGS_PROC) += atags.o
24obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o 24obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
25obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
25 26
26obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o 27obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
27AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 28AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 3278e713c32a..0a0d2479274b 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -58,6 +58,9 @@ int main(void)
58 DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value)); 58 DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
59 DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate)); 59 DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
60 DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate)); 60 DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate));
61#ifdef CONFIG_ARM_THUMBEE
62 DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state));
63#endif
61#ifdef CONFIG_IWMMXT 64#ifdef CONFIG_IWMMXT
62 DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt)); 65 DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt));
63#endif 66#endif
@@ -108,5 +111,12 @@ int main(void)
108 DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush)); 111 DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));
109 DEFINE(PROCINFO_MM_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mm_mmu_flags)); 112 DEFINE(PROCINFO_MM_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mm_mmu_flags));
110 DEFINE(PROCINFO_IO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_io_mmu_flags)); 113 DEFINE(PROCINFO_IO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_io_mmu_flags));
114 BLANK();
115#ifdef MULTI_DABORT
116 DEFINE(PROCESSOR_DABT_FUNC, offsetof(struct processor, _data_abort));
117#endif
118#ifdef MULTI_PABORT
119 DEFINE(PROCESSOR_PABT_FUNC, offsetof(struct processor, _prefetch_abort));
120#endif
111 return 0; 121 return 0;
112} 122}
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 283e14fff993..95f1c121cb30 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -359,9 +359,11 @@
359 CALL(sys_kexec_load) 359 CALL(sys_kexec_load)
360 CALL(sys_utimensat) 360 CALL(sys_utimensat)
361 CALL(sys_signalfd) 361 CALL(sys_signalfd)
362/* 350 */ CALL(sys_ni_syscall) 362/* 350 */ CALL(sys_timerfd_create)
363 CALL(sys_eventfd) 363 CALL(sys_eventfd)
364 CALL(sys_fallocate) 364 CALL(sys_fallocate)
365 CALL(sys_timerfd_settime)
366 CALL(sys_timerfd_gettime)
365#ifndef syscalls_counted 367#ifndef syscalls_counted
366.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls 368.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
367#define syscalls_counted 369#define syscalls_counted
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index a46d5b456765..7dca225752c1 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -166,12 +166,12 @@ __dabt_svc:
166 @ The abort handler must return the aborted address in r0, and 166 @ The abort handler must return the aborted address in r0, and
167 @ the fault status register in r1. r9 must be preserved. 167 @ the fault status register in r1. r9 must be preserved.
168 @ 168 @
169#ifdef MULTI_ABORT 169#ifdef MULTI_DABORT
170 ldr r4, .LCprocfns 170 ldr r4, .LCprocfns
171 mov lr, pc 171 mov lr, pc
172 ldr pc, [r4] 172 ldr pc, [r4, #PROCESSOR_DABT_FUNC]
173#else 173#else
174 bl CPU_ABORT_HANDLER 174 bl CPU_DABORT_HANDLER
175#endif 175#endif
176 176
177 @ 177 @
@@ -209,14 +209,12 @@ __irq_svc:
209 209
210 irq_handler 210 irq_handler
211#ifdef CONFIG_PREEMPT 211#ifdef CONFIG_PREEMPT
212 str r8, [tsk, #TI_PREEMPT] @ restore preempt count
212 ldr r0, [tsk, #TI_FLAGS] @ get flags 213 ldr r0, [tsk, #TI_FLAGS] @ get flags
214 teq r8, #0 @ if preempt count != 0
215 movne r0, #0 @ force flags to 0
213 tst r0, #_TIF_NEED_RESCHED 216 tst r0, #_TIF_NEED_RESCHED
214 blne svc_preempt 217 blne svc_preempt
215preempt_return:
216 ldr r0, [tsk, #TI_PREEMPT] @ read preempt value
217 str r8, [tsk, #TI_PREEMPT] @ restore preempt count
218 teq r0, r7
219 strne r0, [r0, -r0] @ bug()
220#endif 218#endif
221 ldr r0, [sp, #S_PSR] @ irqs are already disabled 219 ldr r0, [sp, #S_PSR] @ irqs are already disabled
222 msr spsr_cxsf, r0 220 msr spsr_cxsf, r0
@@ -230,19 +228,11 @@ preempt_return:
230 228
231#ifdef CONFIG_PREEMPT 229#ifdef CONFIG_PREEMPT
232svc_preempt: 230svc_preempt:
233 teq r8, #0 @ was preempt count = 0 231 mov r8, lr
234 ldreq r6, .LCirq_stat
235 movne pc, lr @ no
236 ldr r0, [r6, #4] @ local_irq_count
237 ldr r1, [r6, #8] @ local_bh_count
238 adds r0, r0, r1
239 movne pc, lr
240 mov r7, #0 @ preempt_schedule_irq
241 str r7, [tsk, #TI_PREEMPT] @ expects preempt_count == 0
2421: bl preempt_schedule_irq @ irq en/disable is done inside 2321: bl preempt_schedule_irq @ irq en/disable is done inside
243 ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS 233 ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
244 tst r0, #_TIF_NEED_RESCHED 234 tst r0, #_TIF_NEED_RESCHED
245 beq preempt_return @ go again 235 moveq pc, r8 @ go again
246 b 1b 236 b 1b
247#endif 237#endif
248 238
@@ -293,7 +283,6 @@ __pabt_svc:
293 mrs r9, cpsr 283 mrs r9, cpsr
294 tst r3, #PSR_I_BIT 284 tst r3, #PSR_I_BIT
295 biceq r9, r9, #PSR_I_BIT 285 biceq r9, r9, #PSR_I_BIT
296 msr cpsr_c, r9
297 286
298 @ 287 @
299 @ set args, then call main handler 288 @ set args, then call main handler
@@ -301,7 +290,15 @@ __pabt_svc:
301 @ r0 - address of faulting instruction 290 @ r0 - address of faulting instruction
302 @ r1 - pointer to registers on stack 291 @ r1 - pointer to registers on stack
303 @ 292 @
304 mov r0, r2 @ address (pc) 293#ifdef MULTI_PABORT
294 mov r0, r2 @ pass address of aborted instruction.
295 ldr r4, .LCprocfns
296 mov lr, pc
297 ldr pc, [r4, #PROCESSOR_PABT_FUNC]
298#else
299 CPU_PABORT_HANDLER(r0, r2)
300#endif
301 msr cpsr_c, r9 @ Maybe enable interrupts
305 mov r1, sp @ regs 302 mov r1, sp @ regs
306 bl do_PrefetchAbort @ call abort handler 303 bl do_PrefetchAbort @ call abort handler
307 304
@@ -320,16 +317,12 @@ __pabt_svc:
320 .align 5 317 .align 5
321.LCcralign: 318.LCcralign:
322 .word cr_alignment 319 .word cr_alignment
323#ifdef MULTI_ABORT 320#ifdef MULTI_DABORT
324.LCprocfns: 321.LCprocfns:
325 .word processor 322 .word processor
326#endif 323#endif
327.LCfp: 324.LCfp:
328 .word fp_enter 325 .word fp_enter
329#ifdef CONFIG_PREEMPT
330.LCirq_stat:
331 .word irq_stat
332#endif
333 326
334/* 327/*
335 * User mode handlers 328 * User mode handlers
@@ -404,12 +397,12 @@ __dabt_usr:
404 @ The abort handler must return the aborted address in r0, and 397 @ The abort handler must return the aborted address in r0, and
405 @ the fault status register in r1. 398 @ the fault status register in r1.
406 @ 399 @
407#ifdef MULTI_ABORT 400#ifdef MULTI_DABORT
408 ldr r4, .LCprocfns 401 ldr r4, .LCprocfns
409 mov lr, pc 402 mov lr, pc
410 ldr pc, [r4] 403 ldr pc, [r4, #PROCESSOR_DABT_FUNC]
411#else 404#else
412 bl CPU_ABORT_HANDLER 405 bl CPU_DABORT_HANDLER
413#endif 406#endif
414 407
415 @ 408 @
@@ -455,10 +448,6 @@ __irq_usr:
455__und_usr: 448__und_usr:
456 usr_entry 449 usr_entry
457 450
458 tst r3, #PSR_T_BIT @ Thumb mode?
459 bne __und_usr_unknown @ ignore FP
460 sub r4, r2, #4
461
462 @ 451 @
463 @ fall through to the emulation code, which returns using r9 if 452 @ fall through to the emulation code, which returns using r9 if
464 @ it has emulated the instruction, or the more conventional lr 453 @ it has emulated the instruction, or the more conventional lr
@@ -468,7 +457,24 @@ __und_usr:
468 @ 457 @
469 adr r9, ret_from_exception 458 adr r9, ret_from_exception
470 adr lr, __und_usr_unknown 459 adr lr, __und_usr_unknown
4711: ldrt r0, [r4] 460 tst r3, #PSR_T_BIT @ Thumb mode?
461 subeq r4, r2, #4 @ ARM instr at LR - 4
462 subne r4, r2, #2 @ Thumb instr at LR - 2
4631: ldreqt r0, [r4]
464 beq call_fpe
465 @ Thumb instruction
466#if __LINUX_ARM_ARCH__ >= 7
4672: ldrht r5, [r4], #2
468 and r0, r5, #0xf800 @ mask bits 111x x... .... ....
469 cmp r0, #0xe800 @ 32bit instruction if xx != 0
470 blo __und_usr_unknown
4713: ldrht r0, [r4]
472 add r2, r2, #2 @ r2 is PC + 2, make it PC + 4
473 orr r0, r0, r5, lsl #16
474#else
475 b __und_usr_unknown
476#endif
477
472 @ 478 @
473 @ fallthrough to call_fpe 479 @ fallthrough to call_fpe
474 @ 480 @
@@ -477,10 +483,14 @@ __und_usr:
477 * The out of line fixup for the ldrt above. 483 * The out of line fixup for the ldrt above.
478 */ 484 */
479 .section .fixup, "ax" 485 .section .fixup, "ax"
4802: mov pc, r9 4864: mov pc, r9
481 .previous 487 .previous
482 .section __ex_table,"a" 488 .section __ex_table,"a"
483 .long 1b, 2b 489 .long 1b, 4b
490#if __LINUX_ARM_ARCH__ >= 7
491 .long 2b, 4b
492 .long 3b, 4b
493#endif
484 .previous 494 .previous
485 495
486/* 496/*
@@ -507,9 +517,16 @@ __und_usr:
507 * r10 = this threads thread_info structure. 517 * r10 = this threads thread_info structure.
508 * lr = unrecognised instruction return address 518 * lr = unrecognised instruction return address
509 */ 519 */
520 @
521 @ Fall-through from Thumb-2 __und_usr
522 @
523#ifdef CONFIG_NEON
524 adr r6, .LCneon_thumb_opcodes
525 b 2f
526#endif
510call_fpe: 527call_fpe:
511#ifdef CONFIG_NEON 528#ifdef CONFIG_NEON
512 adr r6, .LCneon_opcodes 529 adr r6, .LCneon_arm_opcodes
5132: 5302:
514 ldr r7, [r6], #4 @ mask value 531 ldr r7, [r6], #4 @ mask value
515 cmp r7, #0 @ end mask? 532 cmp r7, #0 @ end mask?
@@ -526,6 +543,7 @@ call_fpe:
5261: 5431:
527#endif 544#endif
528 tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 545 tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
546 tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2
529#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) 547#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
530 and r8, r0, #0x0f000000 @ mask out op-code bits 548 and r8, r0, #0x0f000000 @ mask out op-code bits
531 teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)? 549 teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)?
@@ -577,7 +595,7 @@ call_fpe:
577#ifdef CONFIG_NEON 595#ifdef CONFIG_NEON
578 .align 6 596 .align 6
579 597
580.LCneon_opcodes: 598.LCneon_arm_opcodes:
581 .word 0xfe000000 @ mask 599 .word 0xfe000000 @ mask
582 .word 0xf2000000 @ opcode 600 .word 0xf2000000 @ opcode
583 601
@@ -586,6 +604,16 @@ call_fpe:
586 604
587 .word 0x00000000 @ mask 605 .word 0x00000000 @ mask
588 .word 0x00000000 @ opcode 606 .word 0x00000000 @ opcode
607
608.LCneon_thumb_opcodes:
609 .word 0xef000000 @ mask
610 .word 0xef000000 @ opcode
611
612 .word 0xff100000 @ mask
613 .word 0xf9000000 @ opcode
614
615 .word 0x00000000 @ mask
616 .word 0x00000000 @ opcode
589#endif 617#endif
590 618
591do_fpe: 619do_fpe:
@@ -619,8 +647,15 @@ __und_usr_unknown:
619__pabt_usr: 647__pabt_usr:
620 usr_entry 648 usr_entry
621 649
650#ifdef MULTI_PABORT
651 mov r0, r2 @ pass address of aborted instruction.
652 ldr r4, .LCprocfns
653 mov lr, pc
654 ldr pc, [r4, #PROCESSOR_PABT_FUNC]
655#else
656 CPU_PABORT_HANDLER(r0, r2)
657#endif
622 enable_irq @ Enable interrupts 658 enable_irq @ Enable interrupts
623 mov r0, r2 @ address (pc)
624 mov r1, sp @ regs 659 mov r1, sp @ regs
625 bl do_PrefetchAbort @ call abort handler 660 bl do_PrefetchAbort @ call abort handler
626 /* fall through */ 661 /* fall through */
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 6c90c50a9ee3..597ed00a08d8 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -352,6 +352,11 @@ sys_mmap2:
352 b do_mmap2 352 b do_mmap2
353#endif 353#endif
354 354
355ENTRY(pabort_ifar)
356 mrc p15, 0, r0, cr6, cr0, 2
357ENTRY(pabort_noifar)
358 mov pc, lr
359
355#ifdef CONFIG_OABI_COMPAT 360#ifdef CONFIG_OABI_COMPAT
356 361
357/* 362/*
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 50f667febe29..7e9c00a8a412 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -75,8 +75,13 @@ __error_p:
75#ifdef CONFIG_DEBUG_LL 75#ifdef CONFIG_DEBUG_LL
76 adr r0, str_p1 76 adr r0, str_p1
77 bl printascii 77 bl printascii
78 mov r0, r9
79 bl printhex8
80 adr r0, str_p2
81 bl printascii
78 b __error 82 b __error
79str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n" 83str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x"
84str_p2: .asciz ").\n"
80 .align 85 .align
81#endif 86#endif
82 87
diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c
new file mode 100644
index 000000000000..df3f6b7ebcea
--- /dev/null
+++ b/arch/arm/kernel/thumbee.c
@@ -0,0 +1,81 @@
1/*
2 * arch/arm/kernel/thumbee.c
3 *
4 * Copyright (C) 2008 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, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/kernel.h>
21#include <linux/init.h>
22
23#include <asm/thread_notify.h>
24
25/*
26 * Access to the ThumbEE Handler Base register
27 */
28static inline unsigned long teehbr_read()
29{
30 unsigned long v;
31 asm("mrc p14, 6, %0, c1, c0, 0\n" : "=r" (v));
32 return v;
33}
34
35static inline void teehbr_write(unsigned long v)
36{
37 asm("mcr p14, 6, %0, c1, c0, 0\n" : : "r" (v));
38}
39
40static int thumbee_notifier(struct notifier_block *self, unsigned long cmd, void *t)
41{
42 struct thread_info *thread = t;
43
44 switch (cmd) {
45 case THREAD_NOTIFY_FLUSH:
46 thread->thumbee_state = 0;
47 break;
48 case THREAD_NOTIFY_SWITCH:
49 current_thread_info()->thumbee_state = teehbr_read();
50 teehbr_write(thread->thumbee_state);
51 break;
52 }
53
54 return NOTIFY_DONE;
55}
56
57static struct notifier_block thumbee_notifier_block = {
58 .notifier_call = thumbee_notifier,
59};
60
61static int __init thumbee_init(void)
62{
63 unsigned long pfr0;
64 unsigned int cpu_arch = cpu_architecture();
65
66 if (cpu_arch < CPU_ARCH_ARMv7)
67 return 0;
68
69 /* processor feature register 0 */
70 asm("mrc p15, 0, %0, c0, c1, 0\n" : "=r" (pfr0));
71 if ((pfr0 & 0x0000f000) != 0x00001000)
72 return 0;
73
74 printk(KERN_INFO "ThumbEE CPU extension supported.\n");
75 elf_hwcap |= HWCAP_THUMBEE;
76 thread_register_notifier(&thumbee_notifier_block);
77
78 return 0;
79}
80
81late_initcall(thumbee_init);