aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/asm-offsets.c2
-rw-r--r--arch/arm/kernel/calls.S1
-rw-r--r--arch/arm/kernel/entry-common.S9
-rw-r--r--arch/arm/kernel/hw_breakpoint.c62
-rw-r--r--arch/arm/kernel/machine_kexec.c29
-rw-r--r--arch/arm/kernel/ptrace.c19
-rw-r--r--arch/arm/kernel/sched_clock.c8
-rw-r--r--arch/arm/kernel/smp.c13
-rw-r--r--arch/arm/kernel/smp_twd.c48
-rw-r--r--arch/arm/kernel/traps.c11
10 files changed, 167 insertions, 35 deletions
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 1429d8989fb9..c985b481192c 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -59,10 +59,12 @@ int main(void)
59 DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp)); 59 DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp));
60 DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value)); 60 DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
61 DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate)); 61 DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
62#ifdef CONFIG_VFP
62 DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate)); 63 DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate));
63#ifdef CONFIG_SMP 64#ifdef CONFIG_SMP
64 DEFINE(VFP_CPU, offsetof(union vfp_state, hard.cpu)); 65 DEFINE(VFP_CPU, offsetof(union vfp_state, hard.cpu));
65#endif 66#endif
67#endif
66#ifdef CONFIG_ARM_THUMBEE 68#ifdef CONFIG_ARM_THUMBEE
67 DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state)); 69 DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state));
68#endif 70#endif
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/entry-common.S b/arch/arm/kernel/entry-common.S
index 978eac57e04a..f45987037bf1 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -94,6 +94,15 @@ ENDPROC(ret_from_fork)
94 .equ NR_syscalls,0 94 .equ NR_syscalls,0
95#define CALL(x) .equ NR_syscalls,NR_syscalls+1 95#define CALL(x) .equ NR_syscalls,NR_syscalls+1
96#include "calls.S" 96#include "calls.S"
97
98/*
99 * Ensure that the system call table is equal to __NR_syscalls,
100 * which is the value the rest of the system sees
101 */
102.ifne NR_syscalls - __NR_syscalls
103.error "__NR_syscalls is not equal to the size of the syscall table"
104.endif
105
97#undef CALL 106#undef CALL
98#define CALL(x) .long x 107#define CALL(x) .long x
99 108
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? */
163static 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. */
163static int get_num_wrp_resources(void) 169static 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
634out: 658out:
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/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index dfcdb9f7c126..e29c3337ca81 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -8,7 +8,9 @@
8#include <linux/reboot.h> 8#include <linux/reboot.h>
9#include <linux/io.h> 9#include <linux/io.h>
10#include <linux/irq.h> 10#include <linux/irq.h>
11#include <linux/memblock.h>
11#include <asm/pgtable.h> 12#include <asm/pgtable.h>
13#include <linux/of_fdt.h>
12#include <asm/pgalloc.h> 14#include <asm/pgalloc.h>
13#include <asm/mmu_context.h> 15#include <asm/mmu_context.h>
14#include <asm/cacheflush.h> 16#include <asm/cacheflush.h>
@@ -32,6 +34,29 @@ static atomic_t waiting_for_crash_ipi;
32 34
33int machine_kexec_prepare(struct kimage *image) 35int machine_kexec_prepare(struct kimage *image)
34{ 36{
37 struct kexec_segment *current_segment;
38 __be32 header;
39 int i, err;
40
41 /*
42 * No segment at default ATAGs address. try to locate
43 * a dtb using magic.
44 */
45 for (i = 0; i < image->nr_segments; i++) {
46 current_segment = &image->segment[i];
47
48 err = memblock_is_region_memory(current_segment->mem,
49 current_segment->memsz);
50 if (err)
51 return - EINVAL;
52
53 err = get_user(header, (__be32*)current_segment->buf);
54 if (err)
55 return err;
56
57 if (be32_to_cpu(header) == OF_DT_HEADER)
58 kexec_boot_atags = current_segment->mem;
59 }
35 return 0; 60 return 0;
36} 61}
37 62
@@ -122,7 +147,9 @@ void machine_kexec(struct kimage *image)
122 kexec_start_address = image->start; 147 kexec_start_address = image->start;
123 kexec_indirection_page = page_list; 148 kexec_indirection_page = page_list;
124 kexec_mach_type = machine_arch_type; 149 kexec_mach_type = machine_arch_type;
125 kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; 150 if (!kexec_boot_atags)
151 kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
152
126 153
127 /* copy our kernel relocation code to the control code page */ 154 /* copy our kernel relocation code to the control code page */
128 memcpy(reboot_code_buffer, 155 memcpy(reboot_code_buffer,
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 3e0fc5f7ed4b..739db3a1b2d2 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -30,6 +30,9 @@
30#include <asm/pgtable.h> 30#include <asm/pgtable.h>
31#include <asm/traps.h> 31#include <asm/traps.h>
32 32
33#define CREATE_TRACE_POINTS
34#include <trace/events/syscalls.h>
35
33#define REG_PC 15 36#define REG_PC 15
34#define REG_PSR 16 37#define REG_PSR 16
35/* 38/*
@@ -918,11 +921,11 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
918{ 921{
919 unsigned long ip; 922 unsigned long ip;
920 923
924 current_thread_info()->syscall = scno;
925
921 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 926 if (!test_thread_flag(TIF_SYSCALL_TRACE))
922 return scno; 927 return scno;
923 928
924 current_thread_info()->syscall = scno;
925
926 /* 929 /*
927 * IP is used to denote syscall entry/exit: 930 * IP is used to denote syscall entry/exit:
928 * IP = 0 -> entry, =1 -> exit 931 * IP = 0 -> entry, =1 -> exit
@@ -941,15 +944,19 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
941 944
942asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) 945asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
943{ 946{
944 int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER); 947 scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER);
948 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
949 trace_sys_enter(regs, scno);
945 audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1, 950 audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1,
946 regs->ARM_r2, regs->ARM_r3); 951 regs->ARM_r2, regs->ARM_r3);
947 return ret; 952 return scno;
948} 953}
949 954
950asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno) 955asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno)
951{ 956{
952 int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT); 957 scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT);
958 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
959 trace_sys_exit(regs, scno);
953 audit_syscall_exit(regs); 960 audit_syscall_exit(regs);
954 return ret; 961 return scno;
955} 962}
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
index f4515393248d..e21bac20d90d 100644
--- a/arch/arm/kernel/sched_clock.c
+++ b/arch/arm/kernel/sched_clock.c
@@ -9,6 +9,7 @@
9#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/jiffies.h> 10#include <linux/jiffies.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/moduleparam.h>
12#include <linux/sched.h> 13#include <linux/sched.h>
13#include <linux/syscore_ops.h> 14#include <linux/syscore_ops.h>
14#include <linux/timer.h> 15#include <linux/timer.h>
@@ -27,6 +28,9 @@ struct clock_data {
27 28
28static void sched_clock_poll(unsigned long wrap_ticks); 29static void sched_clock_poll(unsigned long wrap_ticks);
29static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); 30static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
31static int irqtime = -1;
32
33core_param(irqtime, irqtime, int, 0400);
30 34
31static struct clock_data cd = { 35static struct clock_data cd = {
32 .mult = NSEC_PER_SEC / HZ, 36 .mult = NSEC_PER_SEC / HZ,
@@ -157,6 +161,10 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
157 */ 161 */
158 cd.epoch_ns = 0; 162 cd.epoch_ns = 0;
159 163
164 /* Enable IRQ time accounting if we have a fast enough sched_clock */
165 if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
166 enable_sched_clock_irqtime();
167
160 pr_debug("Registered %pF as sched_clock source\n", read); 168 pr_debug("Registered %pF as sched_clock source\n", read);
161} 169}
162 170
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ebd8ad274d76..d98c37e97d9d 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -51,7 +51,8 @@
51struct secondary_data secondary_data; 51struct secondary_data secondary_data;
52 52
53enum ipi_msg_type { 53enum ipi_msg_type {
54 IPI_TIMER = 2, 54 IPI_WAKEUP,
55 IPI_TIMER,
55 IPI_RESCHEDULE, 56 IPI_RESCHEDULE,
56 IPI_CALL_FUNC, 57 IPI_CALL_FUNC,
57 IPI_CALL_FUNC_SINGLE, 58 IPI_CALL_FUNC_SINGLE,
@@ -347,7 +348,8 @@ void arch_send_call_function_single_ipi(int cpu)
347} 348}
348 349
349static const char *ipi_types[NR_IPI] = { 350static const char *ipi_types[NR_IPI] = {
350#define S(x,s) [x - IPI_TIMER] = s 351#define S(x,s) [x] = s
352 S(IPI_WAKEUP, "CPU wakeup interrupts"),
351 S(IPI_TIMER, "Timer broadcast interrupts"), 353 S(IPI_TIMER, "Timer broadcast interrupts"),
352 S(IPI_RESCHEDULE, "Rescheduling interrupts"), 354 S(IPI_RESCHEDULE, "Rescheduling interrupts"),
353 S(IPI_CALL_FUNC, "Function call interrupts"), 355 S(IPI_CALL_FUNC, "Function call interrupts"),
@@ -500,10 +502,13 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
500 unsigned int cpu = smp_processor_id(); 502 unsigned int cpu = smp_processor_id();
501 struct pt_regs *old_regs = set_irq_regs(regs); 503 struct pt_regs *old_regs = set_irq_regs(regs);
502 504
503 if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI) 505 if (ipinr < NR_IPI)
504 __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]); 506 __inc_irq_stat(cpu, ipi_irqs[ipinr]);
505 507
506 switch (ipinr) { 508 switch (ipinr) {
509 case IPI_WAKEUP:
510 break;
511
507 case IPI_TIMER: 512 case IPI_TIMER:
508 irq_enter(); 513 irq_enter();
509 ipi_timer(); 514 ipi_timer();
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 */
104static 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
111static 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
128static struct notifier_block twd_clk_nb = {
129 .notifier_call = twd_rate_change,
130};
131
132static 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}
139core_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
439die_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",