aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/entry-armv.S3
-rw-r--r--arch/arm/kernel/entry-common.S3
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/signal.c8
-rw-r--r--arch/arm/kernel/smp.c131
-rw-r--r--arch/arm/kernel/smp_scu.c48
-rw-r--r--arch/arm/kernel/smp_twd.c175
-rw-r--r--arch/arm/kernel/vmlinux.lds.S2
9 files changed, 334 insertions, 40 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 11a5197a221f..ff89d0b3abc5 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -22,6 +22,8 @@ obj-$(CONFIG_ARTHUR) += arthur.o
22obj-$(CONFIG_ISA_DMA) += dma-isa.o 22obj-$(CONFIG_ISA_DMA) += dma-isa.o
23obj-$(CONFIG_PCI) += bios32.o isa.o 23obj-$(CONFIG_PCI) += bios32.o isa.o
24obj-$(CONFIG_SMP) += smp.o 24obj-$(CONFIG_SMP) += smp.o
25obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
26obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
25obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 27obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
26obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 28obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
27obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o 29obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 83b1da6b7baa..fc8af43c5000 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -482,6 +482,9 @@ __und_usr:
482 subeq r4, r2, #4 @ ARM instr at LR - 4 482 subeq r4, r2, #4 @ ARM instr at LR - 4
483 subne r4, r2, #2 @ Thumb instr at LR - 2 483 subne r4, r2, #2 @ Thumb instr at LR - 2
4841: ldreqt r0, [r4] 4841: ldreqt r0, [r4]
485#ifdef CONFIG_CPU_ENDIAN_BE8
486 reveq r0, r0 @ little endian instruction
487#endif
485 beq call_fpe 488 beq call_fpe
486 @ Thumb instruction 489 @ Thumb instruction
487#if __LINUX_ARM_ARCH__ >= 7 490#if __LINUX_ARM_ARCH__ >= 7
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index b55cb0331809..366e5097a41a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -210,6 +210,9 @@ ENTRY(vector_swi)
210 A710( teq ip, #0x0f000000 ) 210 A710( teq ip, #0x0f000000 )
211 A710( bne .Larm710bug ) 211 A710( bne .Larm710bug )
212#endif 212#endif
213#ifdef CONFIG_CPU_ENDIAN_BE8
214 rev r10, r10 @ little endian instruction
215#endif
213 216
214#elif defined(CONFIG_AEABI) 217#elif defined(CONFIG_AEABI)
215 218
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index c3265a2e7cd4..1585423699ee 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -365,7 +365,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
365 regs.ARM_r2 = (unsigned long)fn; 365 regs.ARM_r2 = (unsigned long)fn;
366 regs.ARM_r3 = (unsigned long)do_exit; 366 regs.ARM_r3 = (unsigned long)do_exit;
367 regs.ARM_pc = (unsigned long)kernel_thread_helper; 367 regs.ARM_pc = (unsigned long)kernel_thread_helper;
368 regs.ARM_cpsr = SVC_MODE; 368 regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE;
369 369
370 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 370 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
371} 371}
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 80b8b5c7e07a..442b87476f97 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -426,9 +426,13 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
426 */ 426 */
427 thumb = handler & 1; 427 thumb = handler & 1;
428 428
429 if (thumb) 429 if (thumb) {
430 cpsr |= PSR_T_BIT; 430 cpsr |= PSR_T_BIT;
431 else 431#if __LINUX_ARM_ARCH__ >= 7
432 /* clear the If-Then Thumb-2 execution state */
433 cpsr &= ~PSR_IT_MASK;
434#endif
435 } else
432 cpsr &= ~PSR_T_BIT; 436 cpsr &= ~PSR_T_BIT;
433 } 437 }
434#endif 438#endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 6014dfd22af4..de885fd256c5 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -22,16 +22,20 @@
22#include <linux/smp.h> 22#include <linux/smp.h>
23#include <linux/seq_file.h> 23#include <linux/seq_file.h>
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/percpu.h>
26#include <linux/clockchips.h>
25 27
26#include <asm/atomic.h> 28#include <asm/atomic.h>
27#include <asm/cacheflush.h> 29#include <asm/cacheflush.h>
28#include <asm/cpu.h> 30#include <asm/cpu.h>
31#include <asm/cputype.h>
29#include <asm/mmu_context.h> 32#include <asm/mmu_context.h>
30#include <asm/pgtable.h> 33#include <asm/pgtable.h>
31#include <asm/pgalloc.h> 34#include <asm/pgalloc.h>
32#include <asm/processor.h> 35#include <asm/processor.h>
33#include <asm/tlbflush.h> 36#include <asm/tlbflush.h>
34#include <asm/ptrace.h> 37#include <asm/ptrace.h>
38#include <asm/localtimer.h>
35 39
36/* 40/*
37 * as from 2.5, kernels no longer have an init_tasks structure 41 * as from 2.5, kernels no longer have an init_tasks structure
@@ -163,7 +167,7 @@ int __cpuexit __cpu_disable(void)
163 * Take this CPU offline. Once we clear this, we can't return, 167 * Take this CPU offline. Once we clear this, we can't return,
164 * and we must not schedule until we're ready to give up the cpu. 168 * and we must not schedule until we're ready to give up the cpu.
165 */ 169 */
166 cpu_clear(cpu, cpu_online_map); 170 set_cpu_online(cpu, false);
167 171
168 /* 172 /*
169 * OK - migrate IRQs away from this CPU 173 * OK - migrate IRQs away from this CPU
@@ -274,9 +278,9 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
274 local_fiq_enable(); 278 local_fiq_enable();
275 279
276 /* 280 /*
277 * Setup local timer for this CPU. 281 * Setup the percpu timer for this CPU.
278 */ 282 */
279 local_timer_setup(); 283 percpu_timer_setup();
280 284
281 calibrate_delay(); 285 calibrate_delay();
282 286
@@ -285,7 +289,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
285 /* 289 /*
286 * OK, now it's safe to let the boot CPU continue 290 * OK, now it's safe to let the boot CPU continue
287 */ 291 */
288 cpu_set(cpu, cpu_online_map); 292 set_cpu_online(cpu, true);
289 293
290 /* 294 /*
291 * OK, it's off to the idle thread for us 295 * OK, it's off to the idle thread for us
@@ -383,10 +387,16 @@ void show_local_irqs(struct seq_file *p)
383 seq_putc(p, '\n'); 387 seq_putc(p, '\n');
384} 388}
385 389
390/*
391 * Timer (local or broadcast) support
392 */
393static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
394
386static void ipi_timer(void) 395static void ipi_timer(void)
387{ 396{
397 struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
388 irq_enter(); 398 irq_enter();
389 local_timer_interrupt(); 399 evt->event_handler(evt);
390 irq_exit(); 400 irq_exit();
391} 401}
392 402
@@ -405,6 +415,42 @@ asmlinkage void __exception do_local_timer(struct pt_regs *regs)
405} 415}
406#endif 416#endif
407 417
418#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
419static void smp_timer_broadcast(const struct cpumask *mask)
420{
421 send_ipi_message(mask, IPI_TIMER);
422}
423
424static void broadcast_timer_set_mode(enum clock_event_mode mode,
425 struct clock_event_device *evt)
426{
427}
428
429static void local_timer_setup(struct clock_event_device *evt)
430{
431 evt->name = "dummy_timer";
432 evt->features = CLOCK_EVT_FEAT_ONESHOT |
433 CLOCK_EVT_FEAT_PERIODIC |
434 CLOCK_EVT_FEAT_DUMMY;
435 evt->rating = 400;
436 evt->mult = 1;
437 evt->set_mode = broadcast_timer_set_mode;
438 evt->broadcast = smp_timer_broadcast;
439
440 clockevents_register_device(evt);
441}
442#endif
443
444void __cpuinit percpu_timer_setup(void)
445{
446 unsigned int cpu = smp_processor_id();
447 struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
448
449 evt->cpumask = cpumask_of(cpu);
450
451 local_timer_setup(evt);
452}
453
408static DEFINE_SPINLOCK(stop_lock); 454static DEFINE_SPINLOCK(stop_lock);
409 455
410/* 456/*
@@ -417,7 +463,7 @@ static void ipi_cpu_stop(unsigned int cpu)
417 dump_stack(); 463 dump_stack();
418 spin_unlock(&stop_lock); 464 spin_unlock(&stop_lock);
419 465
420 cpu_clear(cpu, cpu_online_map); 466 set_cpu_online(cpu, false);
421 467
422 local_fiq_disable(); 468 local_fiq_disable();
423 local_irq_disable(); 469 local_irq_disable();
@@ -501,11 +547,6 @@ void smp_send_reschedule(int cpu)
501 send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); 547 send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
502} 548}
503 549
504void smp_timer_broadcast(const struct cpumask *mask)
505{
506 send_ipi_message(mask, IPI_TIMER);
507}
508
509void smp_send_stop(void) 550void smp_send_stop(void)
510{ 551{
511 cpumask_t mask = cpu_online_map; 552 cpumask_t mask = cpu_online_map;
@@ -545,6 +586,12 @@ struct tlb_args {
545 unsigned long ta_end; 586 unsigned long ta_end;
546}; 587};
547 588
589/* all SMP configurations have the extended CPUID registers */
590static inline int tlb_ops_need_broadcast(void)
591{
592 return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
593}
594
548static inline void ipi_flush_tlb_all(void *ignored) 595static inline void ipi_flush_tlb_all(void *ignored)
549{ 596{
550 local_flush_tlb_all(); 597 local_flush_tlb_all();
@@ -587,51 +634,61 @@ static inline void ipi_flush_tlb_kernel_range(void *arg)
587 634
588void flush_tlb_all(void) 635void flush_tlb_all(void)
589{ 636{
590 on_each_cpu(ipi_flush_tlb_all, NULL, 1); 637 if (tlb_ops_need_broadcast())
638 on_each_cpu(ipi_flush_tlb_all, NULL, 1);
639 else
640 local_flush_tlb_all();
591} 641}
592 642
593void flush_tlb_mm(struct mm_struct *mm) 643void flush_tlb_mm(struct mm_struct *mm)
594{ 644{
595 on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, &mm->cpu_vm_mask); 645 if (tlb_ops_need_broadcast())
646 on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, &mm->cpu_vm_mask);
647 else
648 local_flush_tlb_mm(mm);
596} 649}
597 650
598void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) 651void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
599{ 652{
600 struct tlb_args ta; 653 if (tlb_ops_need_broadcast()) {
601 654 struct tlb_args ta;
602 ta.ta_vma = vma; 655 ta.ta_vma = vma;
603 ta.ta_start = uaddr; 656 ta.ta_start = uaddr;
604 657 on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, &vma->vm_mm->cpu_vm_mask);
605 on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, &vma->vm_mm->cpu_vm_mask); 658 } else
659 local_flush_tlb_page(vma, uaddr);
606} 660}
607 661
608void flush_tlb_kernel_page(unsigned long kaddr) 662void flush_tlb_kernel_page(unsigned long kaddr)
609{ 663{
610 struct tlb_args ta; 664 if (tlb_ops_need_broadcast()) {
611 665 struct tlb_args ta;
612 ta.ta_start = kaddr; 666 ta.ta_start = kaddr;
613 667 on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
614 on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); 668 } else
669 local_flush_tlb_kernel_page(kaddr);
615} 670}
616 671
617void flush_tlb_range(struct vm_area_struct *vma, 672void flush_tlb_range(struct vm_area_struct *vma,
618 unsigned long start, unsigned long end) 673 unsigned long start, unsigned long end)
619{ 674{
620 struct tlb_args ta; 675 if (tlb_ops_need_broadcast()) {
621 676 struct tlb_args ta;
622 ta.ta_vma = vma; 677 ta.ta_vma = vma;
623 ta.ta_start = start; 678 ta.ta_start = start;
624 ta.ta_end = end; 679 ta.ta_end = end;
625 680 on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, &vma->vm_mm->cpu_vm_mask);
626 on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, &vma->vm_mm->cpu_vm_mask); 681 } else
682 local_flush_tlb_range(vma, start, end);
627} 683}
628 684
629void flush_tlb_kernel_range(unsigned long start, unsigned long end) 685void flush_tlb_kernel_range(unsigned long start, unsigned long end)
630{ 686{
631 struct tlb_args ta; 687 if (tlb_ops_need_broadcast()) {
632 688 struct tlb_args ta;
633 ta.ta_start = start; 689 ta.ta_start = start;
634 ta.ta_end = end; 690 ta.ta_end = end;
635 691 on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
636 on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); 692 } else
693 local_flush_tlb_kernel_range(start, end);
637} 694}
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
new file mode 100644
index 000000000000..d3831f616ee9
--- /dev/null
+++ b/arch/arm/kernel/smp_scu.c
@@ -0,0 +1,48 @@
1/*
2 * linux/arch/arm/kernel/smp_scu.c
3 *
4 * Copyright (C) 2002 ARM Ltd.
5 * All Rights Reserved
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#include <linux/init.h>
12#include <linux/io.h>
13
14#include <asm/smp_scu.h>
15#include <asm/cacheflush.h>
16
17#define SCU_CTRL 0x00
18#define SCU_CONFIG 0x04
19#define SCU_CPU_STATUS 0x08
20#define SCU_INVALIDATE 0x0c
21#define SCU_FPGA_REVISION 0x10
22
23/*
24 * Get the number of CPU cores from the SCU configuration
25 */
26unsigned int __init scu_get_core_count(void __iomem *scu_base)
27{
28 unsigned int ncores = __raw_readl(scu_base + SCU_CONFIG);
29 return (ncores & 0x03) + 1;
30}
31
32/*
33 * Enable the SCU
34 */
35void __init scu_enable(void __iomem *scu_base)
36{
37 u32 scu_ctrl;
38
39 scu_ctrl = __raw_readl(scu_base + SCU_CTRL);
40 scu_ctrl |= 1;
41 __raw_writel(scu_ctrl, scu_base + SCU_CTRL);
42
43 /*
44 * Ensure that the data accessed by CPU0 before the SCU was
45 * initialised is visible to the other CPUs.
46 */
47 flush_cache_all();
48}
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
new file mode 100644
index 000000000000..d8c88c633c6f
--- /dev/null
+++ b/arch/arm/kernel/smp_twd.c
@@ -0,0 +1,175 @@
1/*
2 * linux/arch/arm/kernel/smp_twd.c
3 *
4 * Copyright (C) 2002 ARM Ltd.
5 * All Rights Reserved
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#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/smp.h>
16#include <linux/jiffies.h>
17#include <linux/clockchips.h>
18#include <linux/irq.h>
19#include <linux/io.h>
20
21#include <asm/smp_twd.h>
22#include <asm/hardware/gic.h>
23
24#define TWD_TIMER_LOAD 0x00
25#define TWD_TIMER_COUNTER 0x04
26#define TWD_TIMER_CONTROL 0x08
27#define TWD_TIMER_INTSTAT 0x0C
28
29#define TWD_WDOG_LOAD 0x20
30#define TWD_WDOG_COUNTER 0x24
31#define TWD_WDOG_CONTROL 0x28
32#define TWD_WDOG_INTSTAT 0x2C
33#define TWD_WDOG_RESETSTAT 0x30
34#define TWD_WDOG_DISABLE 0x34
35
36#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
37#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
38#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
39#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
40
41/* set up by the platform code */
42void __iomem *twd_base;
43
44static unsigned long twd_timer_rate;
45
46static void twd_set_mode(enum clock_event_mode mode,
47 struct clock_event_device *clk)
48{
49 unsigned long ctrl;
50
51 switch (mode) {
52 case CLOCK_EVT_MODE_PERIODIC:
53 /* timer load already set up */
54 ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
55 | TWD_TIMER_CONTROL_PERIODIC;
56 break;
57 case CLOCK_EVT_MODE_ONESHOT:
58 /* period set, and timer enabled in 'next_event' hook */
59 ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
60 break;
61 case CLOCK_EVT_MODE_UNUSED:
62 case CLOCK_EVT_MODE_SHUTDOWN:
63 default:
64 ctrl = 0;
65 }
66
67 __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
68}
69
70static int twd_set_next_event(unsigned long evt,
71 struct clock_event_device *unused)
72{
73 unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
74
75 ctrl |= TWD_TIMER_CONTROL_ENABLE;
76
77 __raw_writel(evt, twd_base + TWD_TIMER_COUNTER);
78 __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL);
79
80 return 0;
81}
82
83/*
84 * local_timer_ack: checks for a local timer interrupt.
85 *
86 * If a local timer interrupt has occurred, acknowledge and return 1.
87 * Otherwise, return 0.
88 */
89int twd_timer_ack(void)
90{
91 if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) {
92 __raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
93 return 1;
94 }
95
96 return 0;
97}
98
99static void __cpuinit twd_calibrate_rate(void)
100{
101 unsigned long load, count;
102 u64 waitjiffies;
103
104 /*
105 * If this is the first time round, we need to work out how fast
106 * the timer ticks
107 */
108 if (twd_timer_rate == 0) {
109 printk(KERN_INFO "Calibrating local timer... ");
110
111 /* Wait for a tick to start */
112 waitjiffies = get_jiffies_64() + 1;
113
114 while (get_jiffies_64() < waitjiffies)
115 udelay(10);
116
117 /* OK, now the tick has started, let's get the timer going */
118 waitjiffies += 5;
119
120 /* enable, no interrupt or reload */
121 __raw_writel(0x1, twd_base + TWD_TIMER_CONTROL);
122
123 /* maximum value */
124 __raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER);
125
126 while (get_jiffies_64() < waitjiffies)
127 udelay(10);
128
129 count = __raw_readl(twd_base + TWD_TIMER_COUNTER);
130
131 twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5);
132
133 printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
134 (twd_timer_rate / 100000) % 100);
135 }
136
137 load = twd_timer_rate / HZ;
138
139 __raw_writel(load, twd_base + TWD_TIMER_LOAD);
140}
141
142/*
143 * Setup the local clock events for a CPU.
144 */
145void __cpuinit twd_timer_setup(struct clock_event_device *clk)
146{
147 unsigned long flags;
148
149 twd_calibrate_rate();
150
151 clk->name = "local_timer";
152 clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
153 clk->rating = 350;
154 clk->set_mode = twd_set_mode;
155 clk->set_next_event = twd_set_next_event;
156 clk->shift = 20;
157 clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift);
158 clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
159 clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
160
161 /* Make sure our local interrupt controller has this enabled */
162 local_irq_save(flags);
163 get_irq_chip(clk->irq)->unmask(clk->irq);
164 local_irq_restore(flags);
165
166 clockevents_register_device(clk);
167}
168
169/*
170 * take a local timer down
171 */
172void __cpuexit twd_timer_stop(void)
173{
174 __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
175}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index c90f27250ead..6c0779792546 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -141,6 +141,7 @@ SECTIONS
141 141
142 .data : AT(__data_loc) { 142 .data : AT(__data_loc) {
143 _data = .; /* address in memory */ 143 _data = .; /* address in memory */
144 _sdata = .;
144 145
145 /* 146 /*
146 * first, the init task union, aligned 147 * first, the init task union, aligned
@@ -192,6 +193,7 @@ SECTIONS
192 __bss_start = .; /* BSS */ 193 __bss_start = .; /* BSS */
193 *(.bss) 194 *(.bss)
194 *(COMMON) 195 *(COMMON)
196 __bss_stop = .;
195 _end = .; 197 _end = .;
196 } 198 }
197 /* Stabs debugging sections. */ 199 /* Stabs debugging sections. */