diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-20 12:20:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-20 12:20:55 -0400 |
commit | ac8bf564307962a763a52b34e771205c58b76ec8 (patch) | |
tree | 851fe4ebd22cca979744dace54a8d628143bbc4b | |
parent | 34388d1c4feae50d61d6f4ec7594b9076d6d24db (diff) | |
parent | 28a1f533ae8606020238b840b82ae70a3f87609e (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
sparc64: Fix hardirq tracing in trap return path.
sparc64: Use correct pt_regs in decode_access_size() error paths.
sparc64: Fix PREEMPT_ACTIVE value.
sparc64: Run NMIs on the hardirq stack.
sparc64: Allocate sufficient stack space in ftrace stubs.
sparc: Fix forgotten kmemleak headers inclusion
-rw-r--r-- | arch/sparc/include/asm/thread_info_64.h | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/irq_64.c | 20 | ||||
-rw-r--r-- | arch/sparc/kernel/kstack.h | 19 | ||||
-rw-r--r-- | arch/sparc/kernel/nmi.c | 7 | ||||
-rw-r--r-- | arch/sparc/kernel/rtrap_64.S | 12 | ||||
-rw-r--r-- | arch/sparc/kernel/unaligned_64.c | 6 | ||||
-rw-r--r-- | arch/sparc/lib/mcount.S | 8 |
7 files changed, 47 insertions, 27 deletions
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 9e2d9447f2ad..4827a3aeac7f 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h | |||
@@ -111,7 +111,7 @@ struct thread_info { | |||
111 | #define THREAD_SHIFT PAGE_SHIFT | 111 | #define THREAD_SHIFT PAGE_SHIFT |
112 | #endif /* PAGE_SHIFT == 13 */ | 112 | #endif /* PAGE_SHIFT == 13 */ |
113 | 113 | ||
114 | #define PREEMPT_ACTIVE 0x4000000 | 114 | #define PREEMPT_ACTIVE 0x10000000 |
115 | 115 | ||
116 | /* | 116 | /* |
117 | * macros/functions for gaining access to the thread information structure | 117 | * macros/functions for gaining access to the thread information structure |
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 454ce3a25273..830d70a3e20b 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
23 | #include <linux/ftrace.h> | 23 | #include <linux/ftrace.h> |
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/kmemleak.h> | ||
25 | 26 | ||
26 | #include <asm/ptrace.h> | 27 | #include <asm/ptrace.h> |
27 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
@@ -46,6 +47,7 @@ | |||
46 | 47 | ||
47 | #include "entry.h" | 48 | #include "entry.h" |
48 | #include "cpumap.h" | 49 | #include "cpumap.h" |
50 | #include "kstack.h" | ||
49 | 51 | ||
50 | #define NUM_IVECS (IMAP_INR + 1) | 52 | #define NUM_IVECS (IMAP_INR + 1) |
51 | 53 | ||
@@ -712,24 +714,6 @@ void ack_bad_irq(unsigned int virt_irq) | |||
712 | void *hardirq_stack[NR_CPUS]; | 714 | void *hardirq_stack[NR_CPUS]; |
713 | void *softirq_stack[NR_CPUS]; | 715 | void *softirq_stack[NR_CPUS]; |
714 | 716 | ||
715 | static __attribute__((always_inline)) void *set_hardirq_stack(void) | ||
716 | { | ||
717 | void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; | ||
718 | |||
719 | __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); | ||
720 | if (orig_sp < sp || | ||
721 | orig_sp > (sp + THREAD_SIZE)) { | ||
722 | sp += THREAD_SIZE - 192 - STACK_BIAS; | ||
723 | __asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); | ||
724 | } | ||
725 | |||
726 | return orig_sp; | ||
727 | } | ||
728 | static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) | ||
729 | { | ||
730 | __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); | ||
731 | } | ||
732 | |||
733 | void __irq_entry handler_irq(int irq, struct pt_regs *regs) | 717 | void __irq_entry handler_irq(int irq, struct pt_regs *regs) |
734 | { | 718 | { |
735 | unsigned long pstate, bucket_pa; | 719 | unsigned long pstate, bucket_pa; |
diff --git a/arch/sparc/kernel/kstack.h b/arch/sparc/kernel/kstack.h index 5247283d1c03..53dfb92e09fb 100644 --- a/arch/sparc/kernel/kstack.h +++ b/arch/sparc/kernel/kstack.h | |||
@@ -61,4 +61,23 @@ check_magic: | |||
61 | 61 | ||
62 | } | 62 | } |
63 | 63 | ||
64 | static inline __attribute__((always_inline)) void *set_hardirq_stack(void) | ||
65 | { | ||
66 | void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; | ||
67 | |||
68 | __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); | ||
69 | if (orig_sp < sp || | ||
70 | orig_sp > (sp + THREAD_SIZE)) { | ||
71 | sp += THREAD_SIZE - 192 - STACK_BIAS; | ||
72 | __asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); | ||
73 | } | ||
74 | |||
75 | return orig_sp; | ||
76 | } | ||
77 | |||
78 | static inline __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) | ||
79 | { | ||
80 | __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); | ||
81 | } | ||
82 | |||
64 | #endif /* _KSTACK_H */ | 83 | #endif /* _KSTACK_H */ |
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index 75a3d1a25356..a4bd7ba74c89 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <asm/ptrace.h> | 23 | #include <asm/ptrace.h> |
24 | #include <asm/pcr.h> | 24 | #include <asm/pcr.h> |
25 | 25 | ||
26 | #include "kstack.h" | ||
27 | |||
26 | /* We don't have a real NMI on sparc64, but we can fake one | 28 | /* We don't have a real NMI on sparc64, but we can fake one |
27 | * up using profiling counter overflow interrupts and interrupt | 29 | * up using profiling counter overflow interrupts and interrupt |
28 | * levels. | 30 | * levels. |
@@ -92,6 +94,7 @@ static void die_nmi(const char *str, struct pt_regs *regs, int do_panic) | |||
92 | notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) | 94 | notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) |
93 | { | 95 | { |
94 | unsigned int sum, touched = 0; | 96 | unsigned int sum, touched = 0; |
97 | void *orig_sp; | ||
95 | 98 | ||
96 | clear_softint(1 << irq); | 99 | clear_softint(1 << irq); |
97 | 100 | ||
@@ -99,6 +102,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) | |||
99 | 102 | ||
100 | nmi_enter(); | 103 | nmi_enter(); |
101 | 104 | ||
105 | orig_sp = set_hardirq_stack(); | ||
106 | |||
102 | if (notify_die(DIE_NMI, "nmi", regs, 0, | 107 | if (notify_die(DIE_NMI, "nmi", regs, 0, |
103 | pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) | 108 | pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) |
104 | touched = 1; | 109 | touched = 1; |
@@ -124,6 +129,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) | |||
124 | pcr_ops->write(pcr_enable); | 129 | pcr_ops->write(pcr_enable); |
125 | } | 130 | } |
126 | 131 | ||
132 | restore_hardirq_stack(orig_sp); | ||
133 | |||
127 | nmi_exit(); | 134 | nmi_exit(); |
128 | } | 135 | } |
129 | 136 | ||
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 83f1873c6c13..090b9e9ad5e3 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S | |||
@@ -130,7 +130,17 @@ rtrap_xcall: | |||
130 | nop | 130 | nop |
131 | call trace_hardirqs_on | 131 | call trace_hardirqs_on |
132 | nop | 132 | nop |
133 | wrpr %l4, %pil | 133 | /* Do not actually set the %pil here. We will do that |
134 | * below after we clear PSTATE_IE in the %pstate register. | ||
135 | * If we re-enable interrupts here, we can recurse down | ||
136 | * the hardirq stack potentially endlessly, causing a | ||
137 | * stack overflow. | ||
138 | * | ||
139 | * It is tempting to put this test and trace_hardirqs_on | ||
140 | * call at the 'rt_continue' label, but that will not work | ||
141 | * as that path hits unconditionally and we do not want to | ||
142 | * execute this in NMI return paths, for example. | ||
143 | */ | ||
134 | #endif | 144 | #endif |
135 | rtrap_no_irq_enable: | 145 | rtrap_no_irq_enable: |
136 | andcc %l1, TSTATE_PRIV, %l3 | 146 | andcc %l1, TSTATE_PRIV, %l3 |
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index ebce43018c49..c752c4c479bd 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c | |||
@@ -50,7 +50,7 @@ static inline enum direction decode_direction(unsigned int insn) | |||
50 | } | 50 | } |
51 | 51 | ||
52 | /* 16 = double-word, 8 = extra-word, 4 = word, 2 = half-word */ | 52 | /* 16 = double-word, 8 = extra-word, 4 = word, 2 = half-word */ |
53 | static inline int decode_access_size(unsigned int insn) | 53 | static inline int decode_access_size(struct pt_regs *regs, unsigned int insn) |
54 | { | 54 | { |
55 | unsigned int tmp; | 55 | unsigned int tmp; |
56 | 56 | ||
@@ -66,7 +66,7 @@ static inline int decode_access_size(unsigned int insn) | |||
66 | return 2; | 66 | return 2; |
67 | else { | 67 | else { |
68 | printk("Impossible unaligned trap. insn=%08x\n", insn); | 68 | printk("Impossible unaligned trap. insn=%08x\n", insn); |
69 | die_if_kernel("Byte sized unaligned access?!?!", current_thread_info()->kregs); | 69 | die_if_kernel("Byte sized unaligned access?!?!", regs); |
70 | 70 | ||
71 | /* GCC should never warn that control reaches the end | 71 | /* GCC should never warn that control reaches the end |
72 | * of this function without returning a value because | 72 | * of this function without returning a value because |
@@ -286,7 +286,7 @@ static void log_unaligned(struct pt_regs *regs) | |||
286 | asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) | 286 | asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) |
287 | { | 287 | { |
288 | enum direction dir = decode_direction(insn); | 288 | enum direction dir = decode_direction(insn); |
289 | int size = decode_access_size(insn); | 289 | int size = decode_access_size(regs, insn); |
290 | int orig_asi, asi; | 290 | int orig_asi, asi; |
291 | 291 | ||
292 | current_thread_info()->kern_una_regs = regs; | 292 | current_thread_info()->kern_una_regs = regs; |
diff --git a/arch/sparc/lib/mcount.S b/arch/sparc/lib/mcount.S index 3753e3c6e176..3ad6cbdc2163 100644 --- a/arch/sparc/lib/mcount.S +++ b/arch/sparc/lib/mcount.S | |||
@@ -34,7 +34,7 @@ mcount: | |||
34 | cmp %g1, %g2 | 34 | cmp %g1, %g2 |
35 | be,pn %icc, 1f | 35 | be,pn %icc, 1f |
36 | mov %i7, %g3 | 36 | mov %i7, %g3 |
37 | save %sp, -128, %sp | 37 | save %sp, -176, %sp |
38 | mov %g3, %o1 | 38 | mov %g3, %o1 |
39 | jmpl %g1, %o7 | 39 | jmpl %g1, %o7 |
40 | mov %i7, %o0 | 40 | mov %i7, %o0 |
@@ -56,7 +56,7 @@ mcount: | |||
56 | nop | 56 | nop |
57 | 5: mov %i7, %g2 | 57 | 5: mov %i7, %g2 |
58 | mov %fp, %g3 | 58 | mov %fp, %g3 |
59 | save %sp, -128, %sp | 59 | save %sp, -176, %sp |
60 | mov %g2, %l0 | 60 | mov %g2, %l0 |
61 | ba,pt %xcc, ftrace_graph_caller | 61 | ba,pt %xcc, ftrace_graph_caller |
62 | mov %g3, %l1 | 62 | mov %g3, %l1 |
@@ -85,7 +85,7 @@ ftrace_caller: | |||
85 | lduw [%g1 + %lo(function_trace_stop)], %g1 | 85 | lduw [%g1 + %lo(function_trace_stop)], %g1 |
86 | brnz,pn %g1, ftrace_stub | 86 | brnz,pn %g1, ftrace_stub |
87 | mov %fp, %g3 | 87 | mov %fp, %g3 |
88 | save %sp, -128, %sp | 88 | save %sp, -176, %sp |
89 | mov %g2, %o1 | 89 | mov %g2, %o1 |
90 | mov %g2, %l0 | 90 | mov %g2, %l0 |
91 | mov %g3, %l1 | 91 | mov %g3, %l1 |
@@ -120,7 +120,7 @@ ENTRY(ftrace_graph_caller) | |||
120 | END(ftrace_graph_caller) | 120 | END(ftrace_graph_caller) |
121 | 121 | ||
122 | ENTRY(return_to_handler) | 122 | ENTRY(return_to_handler) |
123 | save %sp, -128, %sp | 123 | save %sp, -176, %sp |
124 | call ftrace_return_to_handler | 124 | call ftrace_return_to_handler |
125 | mov %fp, %o0 | 125 | mov %fp, %o0 |
126 | jmpl %o0 + 8, %g0 | 126 | jmpl %o0 + 8, %g0 |