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.c29
-rw-r--r--arch/arm/kernel/entry-armv.S13
-rw-r--r--arch/arm/kernel/process.c13
-rw-r--r--arch/arm/kernel/sched_clock.c15
-rw-r--r--arch/arm/kernel/smp_twd.c17
-rw-r--r--arch/arm/kernel/time.c7
6 files changed, 49 insertions, 45 deletions
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index d957a51435d8..59dcdced6e30 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -22,9 +22,11 @@ static unsigned long arch_timer_read_counter_long(void)
22 return arch_timer_read_counter(); 22 return arch_timer_read_counter();
23} 23}
24 24
25static u32 arch_timer_read_counter_u32(void) 25static u32 sched_clock_mult __read_mostly;
26
27static unsigned long long notrace arch_timer_sched_clock(void)
26{ 28{
27 return arch_timer_read_counter(); 29 return arch_timer_read_counter() * sched_clock_mult;
28} 30}
29 31
30static struct delay_timer arch_delay_timer; 32static struct delay_timer arch_delay_timer;
@@ -37,25 +39,20 @@ static void __init arch_timer_delay_timer_register(void)
37 register_current_timer_delay(&arch_delay_timer); 39 register_current_timer_delay(&arch_delay_timer);
38} 40}
39 41
40int __init arch_timer_of_register(void) 42int __init arch_timer_arch_init(void)
41{ 43{
42 int ret; 44 u32 arch_timer_rate = arch_timer_get_rate();
43 45
44 ret = arch_timer_init(); 46 if (arch_timer_rate == 0)
45 if (ret) 47 return -ENXIO;
46 return ret;
47 48
48 arch_timer_delay_timer_register(); 49 arch_timer_delay_timer_register();
49 50
50 return 0; 51 /* Cache the sched_clock multiplier to save a divide in the hot path. */
51} 52 sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;
52 53 sched_clock_func = arch_timer_sched_clock;
53int __init arch_timer_sched_clock_init(void) 54 pr_info("sched_clock: ARM arch timer >56 bits at %ukHz, resolution %uns\n",
54{ 55 arch_timer_rate / 1000, sched_clock_mult);
55 if (arch_timer_get_rate() == 0)
56 return -ENXIO;
57 56
58 setup_sched_clock(arch_timer_read_counter_u32,
59 32, arch_timer_get_rate());
60 return 0; 57 return 0;
61} 58}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 0f82098c9bfe..cd22d821bf74 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -562,21 +562,21 @@ ENDPROC(__und_usr)
562 @ Fall-through from Thumb-2 __und_usr 562 @ Fall-through from Thumb-2 __und_usr
563 @ 563 @
564#ifdef CONFIG_NEON 564#ifdef CONFIG_NEON
565 get_thread_info r10 @ get current thread
565 adr r6, .LCneon_thumb_opcodes 566 adr r6, .LCneon_thumb_opcodes
566 b 2f 567 b 2f
567#endif 568#endif
568call_fpe: 569call_fpe:
570 get_thread_info r10 @ get current thread
569#ifdef CONFIG_NEON 571#ifdef CONFIG_NEON
570 adr r6, .LCneon_arm_opcodes 572 adr r6, .LCneon_arm_opcodes
5712: 5732: ldr r5, [r6], #4 @ mask value
572 ldr r7, [r6], #4 @ mask value
573 cmp r7, #0 @ end mask?
574 beq 1f
575 and r8, r0, r7
576 ldr r7, [r6], #4 @ opcode bits matching in mask 574 ldr r7, [r6], #4 @ opcode bits matching in mask
575 cmp r5, #0 @ end mask?
576 beq 1f
577 and r8, r0, r5
577 cmp r8, r7 @ NEON instruction? 578 cmp r8, r7 @ NEON instruction?
578 bne 2b 579 bne 2b
579 get_thread_info r10
580 mov r7, #1 580 mov r7, #1
581 strb r7, [r10, #TI_USED_CP + 10] @ mark CP#10 as used 581 strb r7, [r10, #TI_USED_CP + 10] @ mark CP#10 as used
582 strb r7, [r10, #TI_USED_CP + 11] @ mark CP#11 as used 582 strb r7, [r10, #TI_USED_CP + 11] @ mark CP#11 as used
@@ -586,7 +586,6 @@ call_fpe:
586 tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 586 tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
587 tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2 587 tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2
588 moveq pc, lr 588 moveq pc, lr
589 get_thread_info r10 @ get current thread
590 and r8, r0, #0x00000f00 @ mask out CP number 589 and r8, r0, #0x00000f00 @ mask out CP number
591 THUMB( lsr r8, r8, #8 ) 590 THUMB( lsr r8, r8, #8 )
592 mov r7, #1 591 mov r7, #1
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 047d3e40e470..cbd0f51937cc 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -459,15 +459,16 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
459 * atomic helpers and the signal restart code. Insert it into the 459 * atomic helpers and the signal restart code. Insert it into the
460 * gate_vma so that it is visible through ptrace and /proc/<pid>/mem. 460 * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
461 */ 461 */
462static struct vm_area_struct gate_vma; 462static struct vm_area_struct gate_vma = {
463 .vm_start = 0xffff0000,
464 .vm_end = 0xffff0000 + PAGE_SIZE,
465 .vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC,
466 .vm_mm = &init_mm,
467};
463 468
464static int __init gate_vma_init(void) 469static int __init gate_vma_init(void)
465{ 470{
466 gate_vma.vm_start = 0xffff0000; 471 gate_vma.vm_page_prot = PAGE_READONLY_EXEC;
467 gate_vma.vm_end = 0xffff0000 + PAGE_SIZE;
468 gate_vma.vm_page_prot = PAGE_READONLY_EXEC;
469 gate_vma.vm_flags = VM_READ | VM_EXEC |
470 VM_MAYREAD | VM_MAYEXEC;
471 return 0; 472 return 0;
472} 473}
473arch_initcall(gate_vma_init); 474arch_initcall(gate_vma_init);
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
index bd6f56b9ec21..880584852fca 100644
--- a/arch/arm/kernel/sched_clock.c
+++ b/arch/arm/kernel/sched_clock.c
@@ -20,6 +20,7 @@ struct clock_data {
20 u64 epoch_ns; 20 u64 epoch_ns;
21 u32 epoch_cyc; 21 u32 epoch_cyc;
22 u32 epoch_cyc_copy; 22 u32 epoch_cyc_copy;
23 unsigned long rate;
23 u32 mult; 24 u32 mult;
24 u32 shift; 25 u32 shift;
25 bool suspended; 26 bool suspended;
@@ -113,11 +114,14 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
113 u64 res, wrap; 114 u64 res, wrap;
114 char r_unit; 115 char r_unit;
115 116
117 if (cd.rate > rate)
118 return;
119
116 BUG_ON(bits > 32); 120 BUG_ON(bits > 32);
117 WARN_ON(!irqs_disabled()); 121 WARN_ON(!irqs_disabled());
118 WARN_ON(read_sched_clock != jiffy_sched_clock_read);
119 read_sched_clock = read; 122 read_sched_clock = read;
120 sched_clock_mask = (1 << bits) - 1; 123 sched_clock_mask = (1 << bits) - 1;
124 cd.rate = rate;
121 125
122 /* calculate the mult/shift to convert counter ticks to ns. */ 126 /* calculate the mult/shift to convert counter ticks to ns. */
123 clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0); 127 clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0);
@@ -161,12 +165,19 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
161 pr_debug("Registered %pF as sched_clock source\n", read); 165 pr_debug("Registered %pF as sched_clock source\n", read);
162} 166}
163 167
164unsigned long long notrace sched_clock(void) 168static unsigned long long notrace sched_clock_32(void)
165{ 169{
166 u32 cyc = read_sched_clock(); 170 u32 cyc = read_sched_clock();
167 return cyc_to_sched_clock(cyc, sched_clock_mask); 171 return cyc_to_sched_clock(cyc, sched_clock_mask);
168} 172}
169 173
174unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32;
175
176unsigned long long notrace sched_clock(void)
177{
178 return sched_clock_func();
179}
180
170void __init sched_clock_postinit(void) 181void __init sched_clock_postinit(void)
171{ 182{
172 /* 183 /*
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 3f2565037480..90525d9d290b 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -362,25 +362,13 @@ int __init twd_local_timer_register(struct twd_local_timer *tlt)
362} 362}
363 363
364#ifdef CONFIG_OF 364#ifdef CONFIG_OF
365const static struct of_device_id twd_of_match[] __initconst = { 365static void __init twd_local_timer_of_register(struct device_node *np)
366 { .compatible = "arm,cortex-a9-twd-timer", },
367 { .compatible = "arm,cortex-a5-twd-timer", },
368 { .compatible = "arm,arm11mp-twd-timer", },
369 { },
370};
371
372void __init twd_local_timer_of_register(void)
373{ 366{
374 struct device_node *np;
375 int err; 367 int err;
376 368
377 if (!is_smp() || !setup_max_cpus) 369 if (!is_smp() || !setup_max_cpus)
378 return; 370 return;
379 371
380 np = of_find_matching_node(NULL, twd_of_match);
381 if (!np)
382 return;
383
384 twd_ppi = irq_of_parse_and_map(np, 0); 372 twd_ppi = irq_of_parse_and_map(np, 0);
385 if (!twd_ppi) { 373 if (!twd_ppi) {
386 err = -EINVAL; 374 err = -EINVAL;
@@ -398,4 +386,7 @@ void __init twd_local_timer_of_register(void)
398out: 386out:
399 WARN(err, "twd_local_timer_of_register failed (%d)\n", err); 387 WARN(err, "twd_local_timer_of_register failed (%d)\n", err);
400} 388}
389CLOCKSOURCE_OF_DECLARE(arm_twd_a9, "arm,cortex-a9-twd-timer", twd_local_timer_of_register);
390CLOCKSOURCE_OF_DECLARE(arm_twd_a5, "arm,cortex-a5-twd-timer", twd_local_timer_of_register);
391CLOCKSOURCE_OF_DECLARE(arm_twd_11mp, "arm,arm11mp-twd-timer", twd_local_timer_of_register);
401#endif 392#endif
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 955d92d265e5..abff4e9aaee0 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -22,6 +22,7 @@
22#include <linux/errno.h> 22#include <linux/errno.h>
23#include <linux/profile.h> 23#include <linux/profile.h>
24#include <linux/timer.h> 24#include <linux/timer.h>
25#include <linux/clocksource.h>
25#include <linux/irq.h> 26#include <linux/irq.h>
26 27
27#include <asm/thread_info.h> 28#include <asm/thread_info.h>
@@ -115,6 +116,10 @@ int __init register_persistent_clock(clock_access_fn read_boot,
115 116
116void __init time_init(void) 117void __init time_init(void)
117{ 118{
118 machine_desc->init_time(); 119 if (machine_desc->init_time)
120 machine_desc->init_time();
121 else
122 clocksource_of_init();
123
119 sched_clock_postinit(); 124 sched_clock_postinit();
120} 125}