aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/arch_timer.c11
-rw-r--r--arch/arm/kernel/armksyms.c3
-rw-r--r--arch/arm/kernel/entry-armv.S1
-rw-r--r--arch/arm/kernel/entry-common.S20
-rw-r--r--arch/arm/kernel/kprobes-test-arm.c4
-rw-r--r--arch/arm/kernel/kprobes-thumb.c2
-rw-r--r--arch/arm/kernel/perf_event.c2
-rw-r--r--arch/arm/kernel/ptrace.c37
-rw-r--r--arch/arm/kernel/signal.c46
-rw-r--r--arch/arm/kernel/signal.h2
-rw-r--r--arch/arm/kernel/smp.c2
-rw-r--r--arch/arm/kernel/traps.c2
-rw-r--r--arch/arm/kernel/vmlinux.lds.S2
13 files changed, 94 insertions, 40 deletions
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index df44c8cf9e2e..cf258807160d 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -32,6 +32,8 @@ static int arch_timer_ppi2;
32 32
33static struct clock_event_device __percpu **arch_timer_evt; 33static struct clock_event_device __percpu **arch_timer_evt;
34 34
35extern void init_current_timer_delay(unsigned long freq);
36
35/* 37/*
36 * Architected system timer support. 38 * Architected system timer support.
37 */ 39 */
@@ -223,6 +225,14 @@ static cycle_t arch_counter_read(struct clocksource *cs)
223 return arch_counter_get_cntpct(); 225 return arch_counter_get_cntpct();
224} 226}
225 227
228int read_current_timer(unsigned long *timer_val)
229{
230 if (!arch_timer_rate)
231 return -ENXIO;
232 *timer_val = arch_counter_get_cntpct();
233 return 0;
234}
235
226static struct clocksource clocksource_counter = { 236static struct clocksource clocksource_counter = {
227 .name = "arch_sys_counter", 237 .name = "arch_sys_counter",
228 .rating = 400, 238 .rating = 400,
@@ -296,6 +306,7 @@ static int __init arch_timer_register(void)
296 if (err) 306 if (err)
297 goto out_free_irq; 307 goto out_free_irq;
298 308
309 init_current_timer_delay(arch_timer_rate);
299 return 0; 310 return 0;
300 311
301out_free_irq: 312out_free_irq:
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index c3dff6abc89d..60d3b738d420 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -49,8 +49,7 @@ extern void __aeabi_ulcmp(void);
49extern void fpundefinstr(void); 49extern void fpundefinstr(void);
50 50
51 /* platform dependent support */ 51 /* platform dependent support */
52EXPORT_SYMBOL(__udelay); 52EXPORT_SYMBOL(arm_delay_ops);
53EXPORT_SYMBOL(__const_udelay);
54 53
55 /* networking */ 54 /* networking */
56EXPORT_SYMBOL(csum_partial); 55EXPORT_SYMBOL(csum_partial);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 437f0c426517..0d1851ca6eb9 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -495,6 +495,7 @@ ENDPROC(__und_usr)
495 * The out of line fixup for the ldrt above. 495 * The out of line fixup for the ldrt above.
496 */ 496 */
497 .pushsection .fixup, "ax" 497 .pushsection .fixup, "ax"
498 .align 2
4984: mov pc, r9 4994: mov pc, r9
499 .popsection 500 .popsection
500 .pushsection __ex_table,"a" 501 .pushsection __ex_table,"a"
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 4afed88d250a..49d9f9305247 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -95,13 +95,7 @@ ENDPROC(ret_to_user)
95ENTRY(ret_from_fork) 95ENTRY(ret_from_fork)
96 bl schedule_tail 96 bl schedule_tail
97 get_thread_info tsk 97 get_thread_info tsk
98 ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing
99 mov why, #1 98 mov why, #1
100 tst r1, #_TIF_SYSCALL_WORK @ are we tracing syscalls?
101 beq ret_slow_syscall
102 mov r1, sp
103 mov r0, #1 @ trace exit [IP = 1]
104 bl syscall_trace
105 b ret_slow_syscall 99 b ret_slow_syscall
106ENDPROC(ret_from_fork) 100ENDPROC(ret_from_fork)
107 101
@@ -448,10 +442,9 @@ ENDPROC(vector_swi)
448 * context switches, and waiting for our parent to respond. 442 * context switches, and waiting for our parent to respond.
449 */ 443 */
450__sys_trace: 444__sys_trace:
451 mov r2, scno 445 mov r1, scno
452 add r1, sp, #S_OFF 446 add r0, sp, #S_OFF
453 mov r0, #0 @ trace entry [IP = 0] 447 bl syscall_trace_enter
454 bl syscall_trace
455 448
456 adr lr, BSYM(__sys_trace_return) @ return address 449 adr lr, BSYM(__sys_trace_return) @ return address
457 mov scno, r0 @ syscall number (possibly new) 450 mov scno, r0 @ syscall number (possibly new)
@@ -463,10 +456,9 @@ __sys_trace:
463 456
464__sys_trace_return: 457__sys_trace_return:
465 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 458 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
466 mov r2, scno 459 mov r1, scno
467 mov r1, sp 460 mov r0, sp
468 mov r0, #1 @ trace exit [IP = 1] 461 bl syscall_trace_exit
469 bl syscall_trace
470 b ret_slow_syscall 462 b ret_slow_syscall
471 463
472 .align 5 464 .align 5
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c
index ba32b393b3f0..38c1a3b103a0 100644
--- a/arch/arm/kernel/kprobes-test-arm.c
+++ b/arch/arm/kernel/kprobes-test-arm.c
@@ -187,8 +187,8 @@ void kprobe_arm_test_cases(void)
187 TEST_BF_R ("mov pc, r",0,2f,"") 187 TEST_BF_R ("mov pc, r",0,2f,"")
188 TEST_BF_RR("mov pc, r",0,2f,", asl r",1,0,"") 188 TEST_BF_RR("mov pc, r",0,2f,", asl r",1,0,"")
189 TEST_BB( "sub pc, pc, #1b-2b+8") 189 TEST_BB( "sub pc, pc, #1b-2b+8")
190#if __LINUX_ARM_ARCH__ >= 6 190#if __LINUX_ARM_ARCH__ == 6 && !defined(CONFIG_CPU_V7)
191 TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */ 191 TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before and after ARMv6 */
192#endif 192#endif
193 TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"") 193 TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"")
194 TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc") 194 TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc")
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 8f96ec778e8d..6123daf397a7 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -660,7 +660,7 @@ static const union decode_item t32_table_1111_100x[] = {
660 /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */ 660 /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
661 /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */ 661 /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
662 /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */ 662 /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
663 DECODE_EMULATEX (0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal, 663 DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal,
664 REGS(PC, NOSPPCX, 0, 0, 0)), 664 REGS(PC, NOSPPCX, 0, 0, 0)),
665 665
666 /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */ 666 /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index df85eda3add3..ab243b87118d 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -500,7 +500,7 @@ __hw_perf_event_init(struct perf_event *event)
500 event_requires_mode_exclusion(&event->attr)) { 500 event_requires_mode_exclusion(&event->attr)) {
501 pr_debug("ARM performance counters do not support " 501 pr_debug("ARM performance counters do not support "
502 "mode exclusion\n"); 502 "mode exclusion\n");
503 return -EPERM; 503 return -EOPNOTSUPP;
504 } 504 }
505 505
506 /* 506 /*
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 5700a7ae7f0b..dab711e6e1ca 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -25,7 +25,6 @@
25#include <linux/regset.h> 25#include <linux/regset.h>
26#include <linux/audit.h> 26#include <linux/audit.h>
27#include <linux/tracehook.h> 27#include <linux/tracehook.h>
28#include <linux/unistd.h>
29 28
30#include <asm/pgtable.h> 29#include <asm/pgtable.h>
31#include <asm/traps.h> 30#include <asm/traps.h>
@@ -908,18 +907,16 @@ long arch_ptrace(struct task_struct *child, long request,
908 return ret; 907 return ret;
909} 908}
910 909
911asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) 910enum ptrace_syscall_dir {
911 PTRACE_SYSCALL_ENTER = 0,
912 PTRACE_SYSCALL_EXIT,
913};
914
915static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
916 enum ptrace_syscall_dir dir)
912{ 917{
913 unsigned long ip; 918 unsigned long ip;
914 919
915 if (why)
916 audit_syscall_exit(regs);
917 else
918 audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0,
919 regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
920
921 if (why == 0 && test_and_clear_thread_flag(TIF_SYSCALL_RESTARTSYS))
922 scno = __NR_restart_syscall - __NR_SYSCALL_BASE;
923 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 920 if (!test_thread_flag(TIF_SYSCALL_TRACE))
924 return scno; 921 return scno;
925 922
@@ -930,14 +927,28 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
930 * IP = 0 -> entry, =1 -> exit 927 * IP = 0 -> entry, =1 -> exit
931 */ 928 */
932 ip = regs->ARM_ip; 929 ip = regs->ARM_ip;
933 regs->ARM_ip = why; 930 regs->ARM_ip = dir;
934 931
935 if (why) 932 if (dir == PTRACE_SYSCALL_EXIT)
936 tracehook_report_syscall_exit(regs, 0); 933 tracehook_report_syscall_exit(regs, 0);
937 else if (tracehook_report_syscall_entry(regs)) 934 else if (tracehook_report_syscall_entry(regs))
938 current_thread_info()->syscall = -1; 935 current_thread_info()->syscall = -1;
939 936
940 regs->ARM_ip = ip; 937 regs->ARM_ip = ip;
941
942 return current_thread_info()->syscall; 938 return current_thread_info()->syscall;
943} 939}
940
941asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
942{
943 int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER);
944 audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1,
945 regs->ARM_r2, regs->ARM_r3);
946 return ret;
947}
948
949asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno)
950{
951 int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT);
952 audit_syscall_exit(regs);
953 return ret;
954}
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index fd2392a17ac1..536c5d6b340b 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -27,6 +27,7 @@
27 */ 27 */
28#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)) 28#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
29#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)) 29#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
30#define SWI_SYS_RESTART (0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE)
30 31
31/* 32/*
32 * With EABI, the syscall number has to be loaded into r7. 33 * With EABI, the syscall number has to be loaded into r7.
@@ -47,6 +48,18 @@ const unsigned long sigreturn_codes[7] = {
47}; 48};
48 49
49/* 50/*
51 * Either we support OABI only, or we have EABI with the OABI
52 * compat layer enabled. In the later case we don't know if
53 * user space is EABI or not, and if not we must not clobber r7.
54 * Always using the OABI syscall solves that issue and works for
55 * all those cases.
56 */
57const unsigned long syscall_restart_code[2] = {
58 SWI_SYS_RESTART, /* swi __NR_restart_syscall */
59 0xe49df004, /* ldr pc, [sp], #4 */
60};
61
62/*
50 * atomically swap in the new signal mask, and wait for a signal. 63 * atomically swap in the new signal mask, and wait for a signal.
51 */ 64 */
52asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) 65asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
@@ -592,10 +605,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
592 case -ERESTARTNOHAND: 605 case -ERESTARTNOHAND:
593 case -ERESTARTSYS: 606 case -ERESTARTSYS:
594 case -ERESTARTNOINTR: 607 case -ERESTARTNOINTR:
595 case -ERESTART_RESTARTBLOCK:
596 regs->ARM_r0 = regs->ARM_ORIG_r0; 608 regs->ARM_r0 = regs->ARM_ORIG_r0;
597 regs->ARM_pc = restart_addr; 609 regs->ARM_pc = restart_addr;
598 break; 610 break;
611 case -ERESTART_RESTARTBLOCK:
612 regs->ARM_r0 = -EINTR;
613 break;
599 } 614 }
600 } 615 }
601 616
@@ -611,14 +626,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
611 * debugger has chosen to restart at a different PC. 626 * debugger has chosen to restart at a different PC.
612 */ 627 */
613 if (regs->ARM_pc == restart_addr) { 628 if (regs->ARM_pc == restart_addr) {
614 if (retval == -ERESTARTNOHAND || 629 if (retval == -ERESTARTNOHAND
615 retval == -ERESTART_RESTARTBLOCK
616 || (retval == -ERESTARTSYS 630 || (retval == -ERESTARTSYS
617 && !(ka.sa.sa_flags & SA_RESTART))) { 631 && !(ka.sa.sa_flags & SA_RESTART))) {
618 regs->ARM_r0 = -EINTR; 632 regs->ARM_r0 = -EINTR;
619 regs->ARM_pc = continue_addr; 633 regs->ARM_pc = continue_addr;
620 } 634 }
621 clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
622 } 635 }
623 636
624 handle_signal(signr, &ka, &info, regs); 637 handle_signal(signr, &ka, &info, regs);
@@ -632,8 +645,29 @@ static void do_signal(struct pt_regs *regs, int syscall)
632 * ignore the restart. 645 * ignore the restart.
633 */ 646 */
634 if (retval == -ERESTART_RESTARTBLOCK 647 if (retval == -ERESTART_RESTARTBLOCK
635 && regs->ARM_pc == restart_addr) 648 && regs->ARM_pc == continue_addr) {
636 set_thread_flag(TIF_SYSCALL_RESTARTSYS); 649 if (thumb_mode(regs)) {
650 regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
651 regs->ARM_pc -= 2;
652 } else {
653#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
654 regs->ARM_r7 = __NR_restart_syscall;
655 regs->ARM_pc -= 4;
656#else
657 u32 __user *usp;
658
659 regs->ARM_sp -= 4;
660 usp = (u32 __user *)regs->ARM_sp;
661
662 if (put_user(regs->ARM_pc, usp) == 0) {
663 regs->ARM_pc = KERN_RESTART_CODE;
664 } else {
665 regs->ARM_sp += 4;
666 force_sigsegv(0, current);
667 }
668#endif
669 }
670 }
637 } 671 }
638 672
639 restore_saved_sigmask(); 673 restore_saved_sigmask();
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
index 5ff067b7c752..6fcfe8398aa4 100644
--- a/arch/arm/kernel/signal.h
+++ b/arch/arm/kernel/signal.h
@@ -8,5 +8,7 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10#define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500) 10#define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500)
11#define KERN_RESTART_CODE (KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))
11 12
12extern const unsigned long sigreturn_codes[7]; 13extern const unsigned long sigreturn_codes[7];
14extern const unsigned long syscall_restart_code[2];
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 2c7217d971db..aea74f5bc34a 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -179,7 +179,7 @@ void __ref cpu_die(void)
179 mb(); 179 mb();
180 180
181 /* Tell __cpu_die() that this CPU is now safe to dispose of */ 181 /* Tell __cpu_die() that this CPU is now safe to dispose of */
182 complete(&cpu_died); 182 RCU_NONIDLE(complete(&cpu_died));
183 183
184 /* 184 /*
185 * actual CPU shutdown procedure is at least platform (if not 185 * actual CPU shutdown procedure is at least platform (if not
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 2df8715c36c0..8b97d739b17b 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -852,6 +852,8 @@ void __init early_trap_init(void *vectors_base)
852 */ 852 */
853 memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), 853 memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
854 sigreturn_codes, sizeof(sigreturn_codes)); 854 sigreturn_codes, sizeof(sigreturn_codes));
855 memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
856 syscall_restart_code, sizeof(syscall_restart_code));
855 857
856 flush_icache_range(vectors, vectors + PAGE_SIZE); 858 flush_icache_range(vectors, vectors + PAGE_SIZE);
857 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); 859 modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 43a31fb06318..36ff15bbfdd4 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -183,7 +183,9 @@ SECTIONS
183 } 183 }
184#endif 184#endif
185 185
186#ifdef CONFIG_SMP
186 PERCPU_SECTION(L1_CACHE_BYTES) 187 PERCPU_SECTION(L1_CACHE_BYTES)
188#endif
187 189
188#ifdef CONFIG_XIP_KERNEL 190#ifdef CONFIG_XIP_KERNEL
189 __data_loc = ALIGN(4); /* location in binary */ 191 __data_loc = ALIGN(4); /* location in binary */