diff options
Diffstat (limited to 'arch/cris/kernel')
-rw-r--r-- | arch/cris/kernel/Makefile | 3 | ||||
-rw-r--r-- | arch/cris/kernel/crisksyms.c | 21 | ||||
-rw-r--r-- | arch/cris/kernel/irq.c | 263 | ||||
-rw-r--r-- | arch/cris/kernel/module.c | 39 | ||||
-rw-r--r-- | arch/cris/kernel/process.c | 40 | ||||
-rw-r--r-- | arch/cris/kernel/profile.c | 73 | ||||
-rw-r--r-- | arch/cris/kernel/ptrace.c | 37 | ||||
-rw-r--r-- | arch/cris/kernel/setup.c | 26 | ||||
-rw-r--r-- | arch/cris/kernel/time.c | 18 | ||||
-rw-r--r-- | arch/cris/kernel/traps.c | 64 |
10 files changed, 251 insertions, 333 deletions
diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile index 1546a0e74047..c8e8ea570989 100644 --- a/arch/cris/kernel/Makefile +++ b/arch/cris/kernel/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile,v 1.10 2004/05/14 10:18:12 starvik Exp $ | 1 | # $Id: Makefile,v 1.12 2004/10/19 13:07:43 starvik Exp $ |
2 | # | 2 | # |
3 | # Makefile for the linux kernel. | 3 | # Makefile for the linux kernel. |
4 | # | 4 | # |
@@ -10,6 +10,7 @@ obj-y := process.o traps.o irq.o ptrace.o setup.o \ | |||
10 | 10 | ||
11 | obj-$(CONFIG_MODULES) += crisksyms.o | 11 | obj-$(CONFIG_MODULES) += crisksyms.o |
12 | obj-$(CONFIG_MODULES) += module.o | 12 | obj-$(CONFIG_MODULES) += module.o |
13 | obj-$(CONFIG_SYSTEM_PROFILER) += profile.o | ||
13 | 14 | ||
14 | clean: | 15 | clean: |
15 | 16 | ||
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c index 7141bbecd7e4..85833d704ebb 100644 --- a/arch/cris/kernel/crisksyms.c +++ b/arch/cris/kernel/crisksyms.c | |||
@@ -27,13 +27,13 @@ extern void __Udiv(void); | |||
27 | extern void __Umod(void); | 27 | extern void __Umod(void); |
28 | extern void __Div(void); | 28 | extern void __Div(void); |
29 | extern void __Mod(void); | 29 | extern void __Mod(void); |
30 | extern void __ashldi3(void); | ||
30 | extern void __ashrdi3(void); | 31 | extern void __ashrdi3(void); |
31 | extern void iounmap(void *addr); | 32 | extern void __lshrdi3(void); |
33 | extern void iounmap(volatile void * __iomem); | ||
32 | 34 | ||
33 | /* Platform dependent support */ | 35 | /* Platform dependent support */ |
34 | EXPORT_SYMBOL(dump_thread); | 36 | EXPORT_SYMBOL(dump_thread); |
35 | EXPORT_SYMBOL(enable_irq); | ||
36 | EXPORT_SYMBOL(disable_irq); | ||
37 | EXPORT_SYMBOL(kernel_thread); | 37 | EXPORT_SYMBOL(kernel_thread); |
38 | EXPORT_SYMBOL(get_cmos_time); | 38 | EXPORT_SYMBOL(get_cmos_time); |
39 | EXPORT_SYMBOL(loops_per_usec); | 39 | EXPORT_SYMBOL(loops_per_usec); |
@@ -57,7 +57,9 @@ EXPORT_SYMBOL(__Udiv); | |||
57 | EXPORT_SYMBOL(__Umod); | 57 | EXPORT_SYMBOL(__Umod); |
58 | EXPORT_SYMBOL(__Div); | 58 | EXPORT_SYMBOL(__Div); |
59 | EXPORT_SYMBOL(__Mod); | 59 | EXPORT_SYMBOL(__Mod); |
60 | EXPORT_SYMBOL(__ashldi3); | ||
60 | EXPORT_SYMBOL(__ashrdi3); | 61 | EXPORT_SYMBOL(__ashrdi3); |
62 | EXPORT_SYMBOL(__lshrdi3); | ||
61 | 63 | ||
62 | /* Memory functions */ | 64 | /* Memory functions */ |
63 | EXPORT_SYMBOL(__ioremap); | 65 | EXPORT_SYMBOL(__ioremap); |
@@ -69,23 +71,10 @@ EXPORT_SYMBOL(__down); | |||
69 | EXPORT_SYMBOL(__down_interruptible); | 71 | EXPORT_SYMBOL(__down_interruptible); |
70 | EXPORT_SYMBOL(__down_trylock); | 72 | EXPORT_SYMBOL(__down_trylock); |
71 | 73 | ||
72 | /* Export shadow registers for the CPU I/O pins */ | ||
73 | EXPORT_SYMBOL(genconfig_shadow); | ||
74 | EXPORT_SYMBOL(port_pa_data_shadow); | ||
75 | EXPORT_SYMBOL(port_pa_dir_shadow); | ||
76 | EXPORT_SYMBOL(port_pb_data_shadow); | ||
77 | EXPORT_SYMBOL(port_pb_dir_shadow); | ||
78 | EXPORT_SYMBOL(port_pb_config_shadow); | ||
79 | EXPORT_SYMBOL(port_g_data_shadow); | ||
80 | |||
81 | /* Userspace access functions */ | 74 | /* Userspace access functions */ |
82 | EXPORT_SYMBOL(__copy_user_zeroing); | 75 | EXPORT_SYMBOL(__copy_user_zeroing); |
83 | EXPORT_SYMBOL(__copy_user); | 76 | EXPORT_SYMBOL(__copy_user); |
84 | 77 | ||
85 | /* Cache flush functions */ | ||
86 | EXPORT_SYMBOL(flush_etrax_cache); | ||
87 | EXPORT_SYMBOL(prepare_rx_descriptor); | ||
88 | |||
89 | #undef memcpy | 78 | #undef memcpy |
90 | #undef memset | 79 | #undef memset |
91 | extern void * memset(void *, int, __kernel_size_t); | 80 | extern void * memset(void *, int, __kernel_size_t); |
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index d848b9407457..30deaf1b728a 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c | |||
@@ -12,8 +12,6 @@ | |||
12 | * shouldn't result in any weird surprises, and installing new handlers | 12 | * shouldn't result in any weird surprises, and installing new handlers |
13 | * should be easier. | 13 | * should be easier. |
14 | * | 14 | * |
15 | * Notice Linux/CRIS: these routines do not care about SMP | ||
16 | * | ||
17 | */ | 15 | */ |
18 | 16 | ||
19 | /* | 17 | /* |
@@ -24,6 +22,7 @@ | |||
24 | #include <linux/config.h> | 22 | #include <linux/config.h> |
25 | #include <linux/module.h> | 23 | #include <linux/module.h> |
26 | #include <linux/ptrace.h> | 24 | #include <linux/ptrace.h> |
25 | #include <linux/irq.h> | ||
27 | 26 | ||
28 | #include <linux/kernel_stat.h> | 27 | #include <linux/kernel_stat.h> |
29 | #include <linux/signal.h> | 28 | #include <linux/signal.h> |
@@ -36,84 +35,56 @@ | |||
36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
37 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
38 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
39 | #include <linux/bitops.h> | 38 | #include <linux/spinlock.h> |
40 | 39 | ||
41 | #include <asm/io.h> | 40 | #include <asm/io.h> |
42 | 41 | ||
43 | /* Defined in arch specific irq.c */ | 42 | void ack_bad_irq(unsigned int irq) |
44 | extern void arch_setup_irq(int irq); | ||
45 | extern void arch_free_irq(int irq); | ||
46 | |||
47 | void | ||
48 | disable_irq(unsigned int irq_nr) | ||
49 | { | ||
50 | unsigned long flags; | ||
51 | |||
52 | local_save_flags(flags); | ||
53 | local_irq_disable(); | ||
54 | mask_irq(irq_nr); | ||
55 | local_irq_restore(flags); | ||
56 | } | ||
57 | |||
58 | void | ||
59 | enable_irq(unsigned int irq_nr) | ||
60 | { | 43 | { |
61 | unsigned long flags; | 44 | printk("unexpected IRQ trap at vector %02x\n", irq); |
62 | local_save_flags(flags); | ||
63 | local_irq_disable(); | ||
64 | unmask_irq(irq_nr); | ||
65 | local_irq_restore(flags); | ||
66 | } | 45 | } |
67 | 46 | ||
68 | unsigned long | ||
69 | probe_irq_on() | ||
70 | { | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | EXPORT_SYMBOL(probe_irq_on); | ||
75 | |||
76 | int | ||
77 | probe_irq_off(unsigned long x) | ||
78 | { | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | EXPORT_SYMBOL(probe_irq_off); | ||
83 | |||
84 | /* | ||
85 | * Initial irq handlers. | ||
86 | */ | ||
87 | |||
88 | static struct irqaction *irq_action[NR_IRQS]; | ||
89 | |||
90 | int show_interrupts(struct seq_file *p, void *v) | 47 | int show_interrupts(struct seq_file *p, void *v) |
91 | { | 48 | { |
92 | int i = *(loff_t *) v; | 49 | int i = *(loff_t *) v, j; |
93 | struct irqaction * action; | 50 | struct irqaction * action; |
94 | unsigned long flags; | 51 | unsigned long flags; |
95 | 52 | ||
53 | if (i == 0) { | ||
54 | seq_printf(p, " "); | ||
55 | for (j=0; j<NR_CPUS; j++) | ||
56 | if (cpu_online(j)) | ||
57 | seq_printf(p, "CPU%d ",j); | ||
58 | seq_putc(p, '\n'); | ||
59 | } | ||
60 | |||
96 | if (i < NR_IRQS) { | 61 | if (i < NR_IRQS) { |
97 | local_irq_save(flags); | 62 | spin_lock_irqsave(&irq_desc[i].lock, flags); |
98 | action = irq_action[i]; | 63 | action = irq_desc[i].action; |
99 | if (!action) | 64 | if (!action) |
100 | goto skip; | 65 | goto skip; |
101 | seq_printf(p, "%2d: %10u %c %s", | 66 | seq_printf(p, "%3d: ",i); |
102 | i, kstat_this_cpu.irqs[i], | 67 | #ifndef CONFIG_SMP |
103 | (action->flags & SA_INTERRUPT) ? '+' : ' ', | 68 | seq_printf(p, "%10u ", kstat_irqs(i)); |
104 | action->name); | 69 | #else |
105 | for (action = action->next; action; action = action->next) { | 70 | for (j = 0; j < NR_CPUS; j++) |
106 | seq_printf(p, ",%s %s", | 71 | if (cpu_online(j)) |
107 | (action->flags & SA_INTERRUPT) ? " +" : "", | 72 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); |
108 | action->name); | 73 | #endif |
109 | } | 74 | seq_printf(p, " %14s", irq_desc[i].handler->typename); |
75 | seq_printf(p, " %s", action->name); | ||
76 | |||
77 | for (action=action->next; action; action = action->next) | ||
78 | seq_printf(p, ", %s", action->name); | ||
79 | |||
110 | seq_putc(p, '\n'); | 80 | seq_putc(p, '\n'); |
111 | skip: | 81 | skip: |
112 | local_irq_restore(flags); | 82 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); |
113 | } | 83 | } |
114 | return 0; | 84 | return 0; |
115 | } | 85 | } |
116 | 86 | ||
87 | |||
117 | /* called by the assembler IRQ entry functions defined in irq.h | 88 | /* called by the assembler IRQ entry functions defined in irq.h |
118 | * to dispatch the interrupts to registred handlers | 89 | * to dispatch the interrupts to registred handlers |
119 | * interrupts are disabled upon entry - depending on if the | 90 | * interrupts are disabled upon entry - depending on if the |
@@ -123,164 +94,17 @@ skip: | |||
123 | 94 | ||
124 | asmlinkage void do_IRQ(int irq, struct pt_regs * regs) | 95 | asmlinkage void do_IRQ(int irq, struct pt_regs * regs) |
125 | { | 96 | { |
126 | struct irqaction *action; | 97 | unsigned long sp; |
127 | int do_random, cpu; | 98 | irq_enter(); |
128 | int ret, retval = 0; | 99 | sp = rdsp(); |
129 | 100 | if (unlikely((sp & (PAGE_SIZE - 1)) < (PAGE_SIZE/8))) { | |
130 | cpu = smp_processor_id(); | 101 | printk("do_IRQ: stack overflow: %lX\n", sp); |
131 | irq_enter(); | 102 | show_stack(NULL, (unsigned long *)sp); |
132 | kstat_cpu(cpu).irqs[irq - FIRST_IRQ]++; | ||
133 | action = irq_action[irq - FIRST_IRQ]; | ||
134 | |||
135 | if (action) { | ||
136 | if (!(action->flags & SA_INTERRUPT)) | ||
137 | local_irq_enable(); | ||
138 | do_random = 0; | ||
139 | do { | ||
140 | ret = action->handler(irq, action->dev_id, regs); | ||
141 | if (ret == IRQ_HANDLED) | ||
142 | do_random |= action->flags; | ||
143 | retval |= ret; | ||
144 | action = action->next; | ||
145 | } while (action); | ||
146 | |||
147 | if (retval != 1) { | ||
148 | if (retval) { | ||
149 | printk("irq event %d: bogus retval mask %x\n", | ||
150 | irq, retval); | ||
151 | } else { | ||
152 | printk("irq %d: nobody cared\n", irq); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | if (do_random & SA_SAMPLE_RANDOM) | ||
157 | add_interrupt_randomness(irq); | ||
158 | local_irq_disable(); | ||
159 | } | ||
160 | irq_exit(); | ||
161 | } | ||
162 | |||
163 | /* this function links in a handler into the chain of handlers for the | ||
164 | given irq, and if the irq has never been registred, the appropriate | ||
165 | handler is entered into the interrupt vector | ||
166 | */ | ||
167 | |||
168 | int setup_irq(int irq, struct irqaction * new) | ||
169 | { | ||
170 | int shared = 0; | ||
171 | struct irqaction *old, **p; | ||
172 | unsigned long flags; | ||
173 | |||
174 | p = irq_action + irq - FIRST_IRQ; | ||
175 | if ((old = *p) != NULL) { | ||
176 | /* Can't share interrupts unless both agree to */ | ||
177 | if (!(old->flags & new->flags & SA_SHIRQ)) | ||
178 | return -EBUSY; | ||
179 | |||
180 | /* Can't share interrupts unless both are same type */ | ||
181 | if ((old->flags ^ new->flags) & SA_INTERRUPT) | ||
182 | return -EBUSY; | ||
183 | |||
184 | /* add new interrupt at end of irq queue */ | ||
185 | do { | ||
186 | p = &old->next; | ||
187 | old = *p; | ||
188 | } while (old); | ||
189 | shared = 1; | ||
190 | } | ||
191 | |||
192 | if (new->flags & SA_SAMPLE_RANDOM) | ||
193 | rand_initialize_irq(irq); | ||
194 | |||
195 | local_save_flags(flags); | ||
196 | local_irq_disable(); | ||
197 | *p = new; | ||
198 | |||
199 | if (!shared) { | ||
200 | /* if the irq wasn't registred before, enter it into the vector table | ||
201 | and unmask it physically | ||
202 | */ | ||
203 | arch_setup_irq(irq); | ||
204 | unmask_irq(irq); | ||
205 | } | ||
206 | |||
207 | local_irq_restore(flags); | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | /* this function is called by a driver to register an irq handler | ||
212 | Valid flags: | ||
213 | SA_INTERRUPT -> it's a fast interrupt, handler called with irq disabled and | ||
214 | no signal checking etc is performed upon exit | ||
215 | SA_SHIRQ -> the interrupt can be shared between different handlers, the handler | ||
216 | is required to check if the irq was "aimed" at it explicitely | ||
217 | SA_RANDOM -> the interrupt will add to the random generators entropy | ||
218 | */ | ||
219 | |||
220 | int request_irq(unsigned int irq, | ||
221 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
222 | unsigned long irqflags, | ||
223 | const char * devname, | ||
224 | void *dev_id) | ||
225 | { | ||
226 | int retval; | ||
227 | struct irqaction * action; | ||
228 | |||
229 | if(!handler) | ||
230 | return -EINVAL; | ||
231 | |||
232 | /* allocate and fill in a handler structure and setup the irq */ | ||
233 | |||
234 | action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); | ||
235 | if (!action) | ||
236 | return -ENOMEM; | ||
237 | |||
238 | action->handler = handler; | ||
239 | action->flags = irqflags; | ||
240 | cpus_clear(action->mask); | ||
241 | action->name = devname; | ||
242 | action->next = NULL; | ||
243 | action->dev_id = dev_id; | ||
244 | |||
245 | retval = setup_irq(irq, action); | ||
246 | |||
247 | if (retval) | ||
248 | kfree(action); | ||
249 | return retval; | ||
250 | } | ||
251 | |||
252 | EXPORT_SYMBOL(request_irq); | ||
253 | |||
254 | void free_irq(unsigned int irq, void *dev_id) | ||
255 | { | ||
256 | struct irqaction * action, **p; | ||
257 | unsigned long flags; | ||
258 | |||
259 | if (irq >= NR_IRQS) { | ||
260 | printk("Trying to free IRQ%d\n",irq); | ||
261 | return; | ||
262 | } | 103 | } |
263 | for (p = irq - FIRST_IRQ + irq_action; (action = *p) != NULL; p = &action->next) { | 104 | __do_IRQ(irq, regs); |
264 | if (action->dev_id != dev_id) | 105 | irq_exit(); |
265 | continue; | ||
266 | |||
267 | /* Found it - now free it */ | ||
268 | local_save_flags(flags); | ||
269 | local_irq_disable(); | ||
270 | *p = action->next; | ||
271 | if (!irq_action[irq - FIRST_IRQ]) { | ||
272 | mask_irq(irq); | ||
273 | arch_free_irq(irq); | ||
274 | } | ||
275 | local_irq_restore(flags); | ||
276 | kfree(action); | ||
277 | return; | ||
278 | } | ||
279 | printk("Trying to free free IRQ%d\n",irq); | ||
280 | } | 106 | } |
281 | 107 | ||
282 | EXPORT_SYMBOL(free_irq); | ||
283 | |||
284 | void weird_irq(void) | 108 | void weird_irq(void) |
285 | { | 109 | { |
286 | local_irq_disable(); | 110 | local_irq_disable(); |
@@ -288,10 +112,3 @@ void weird_irq(void) | |||
288 | while(1); | 112 | while(1); |
289 | } | 113 | } |
290 | 114 | ||
291 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) | ||
292 | /* Used by other archs to show/control IRQ steering during SMP */ | ||
293 | void __init | ||
294 | init_irq_proc(void) | ||
295 | { | ||
296 | } | ||
297 | #endif | ||
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c index f1d3e784f30c..11b867df8617 100644 --- a/arch/cris/kernel/module.c +++ b/arch/cris/kernel/module.c | |||
@@ -32,7 +32,7 @@ void *module_alloc(unsigned long size) | |||
32 | { | 32 | { |
33 | if (size == 0) | 33 | if (size == 0) |
34 | return NULL; | 34 | return NULL; |
35 | return vmalloc(size); | 35 | return vmalloc_exec(size); |
36 | } | 36 | } |
37 | 37 | ||
38 | 38 | ||
@@ -59,26 +59,8 @@ int apply_relocate(Elf32_Shdr *sechdrs, | |||
59 | unsigned int relsec, | 59 | unsigned int relsec, |
60 | struct module *me) | 60 | struct module *me) |
61 | { | 61 | { |
62 | unsigned int i; | 62 | printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name); |
63 | Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; | 63 | return -ENOEXEC; |
64 | Elf32_Sym *sym; | ||
65 | uint32_t *location; | ||
66 | |||
67 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
68 | sechdrs[relsec].sh_info); | ||
69 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
70 | /* This is where to make the change */ | ||
71 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset | ||
72 | + rel[i].r_offset; | ||
73 | /* This is the symbol it is referring to. Note that all | ||
74 | undefined symbols have been resolved. */ | ||
75 | sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
76 | + ELF32_R_SYM(rel[i].r_info); | ||
77 | |||
78 | /* We add the value into the location given */ | ||
79 | *location += sym->st_value; | ||
80 | } | ||
81 | return 0; | ||
82 | } | 64 | } |
83 | 65 | ||
84 | int apply_relocate_add(Elf32_Shdr *sechdrs, | 66 | int apply_relocate_add(Elf32_Shdr *sechdrs, |
@@ -90,7 +72,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, | |||
90 | unsigned int i; | 72 | unsigned int i; |
91 | Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; | 73 | Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; |
92 | 74 | ||
93 | DEBUGP ("Applying relocate section %u to %u\n", relsec, | 75 | DEBUGP ("Applying add relocate section %u to %u\n", relsec, |
94 | sechdrs[relsec].sh_info); | 76 | sechdrs[relsec].sh_info); |
95 | 77 | ||
96 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) { | 78 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) { |
@@ -103,7 +85,18 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, | |||
103 | Elf32_Sym *sym | 85 | Elf32_Sym *sym |
104 | = ((Elf32_Sym *)sechdrs[symindex].sh_addr | 86 | = ((Elf32_Sym *)sechdrs[symindex].sh_addr |
105 | + ELF32_R_SYM (rela[i].r_info)); | 87 | + ELF32_R_SYM (rela[i].r_info)); |
106 | *loc = sym->st_value + rela[i].r_addend; | 88 | switch (ELF32_R_TYPE(rela[i].r_info)) { |
89 | case R_CRIS_32: | ||
90 | *loc = sym->st_value + rela[i].r_addend; | ||
91 | break; | ||
92 | case R_CRIS_32_PCREL: | ||
93 | *loc = sym->st_value - (unsigned)loc + rela[i].r_addend - 4; | ||
94 | break; | ||
95 | default: | ||
96 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
97 | me->name, ELF32_R_TYPE(rela[i].r_info)); | ||
98 | return -ENOEXEC; | ||
99 | } | ||
107 | } | 100 | } |
108 | 101 | ||
109 | return 0; | 102 | return 0; |
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 9f7cad7c7849..949a0e40e03c 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: process.c,v 1.17 2004/04/05 13:53:48 starvik Exp $ | 1 | /* $Id: process.c,v 1.21 2005/03/04 08:16:17 starvik Exp $ |
2 | * | 2 | * |
3 | * linux/arch/cris/kernel/process.c | 3 | * linux/arch/cris/kernel/process.c |
4 | * | 4 | * |
@@ -8,6 +8,18 @@ | |||
8 | * Authors: Bjorn Wesen (bjornw@axis.com) | 8 | * Authors: Bjorn Wesen (bjornw@axis.com) |
9 | * | 9 | * |
10 | * $Log: process.c,v $ | 10 | * $Log: process.c,v $ |
11 | * Revision 1.21 2005/03/04 08:16:17 starvik | ||
12 | * Merge of Linux 2.6.11. | ||
13 | * | ||
14 | * Revision 1.20 2005/01/18 05:57:22 starvik | ||
15 | * Renamed hlt_counter to cris_hlt_counter and made it global. | ||
16 | * | ||
17 | * Revision 1.19 2004/10/19 13:07:43 starvik | ||
18 | * Merge of Linux 2.6.9 | ||
19 | * | ||
20 | * Revision 1.18 2004/08/16 12:37:23 starvik | ||
21 | * Merge of Linux 2.6.8 | ||
22 | * | ||
11 | * Revision 1.17 2004/04/05 13:53:48 starvik | 23 | * Revision 1.17 2004/04/05 13:53:48 starvik |
12 | * Merge of Linux 2.6.5 | 24 | * Merge of Linux 2.6.5 |
13 | * | 25 | * |
@@ -113,6 +125,7 @@ | |||
113 | #include <linux/user.h> | 125 | #include <linux/user.h> |
114 | #include <linux/elfcore.h> | 126 | #include <linux/elfcore.h> |
115 | #include <linux/mqueue.h> | 127 | #include <linux/mqueue.h> |
128 | #include <linux/reboot.h> | ||
116 | 129 | ||
117 | //#define DEBUG | 130 | //#define DEBUG |
118 | 131 | ||
@@ -160,18 +173,18 @@ EXPORT_SYMBOL(init_task); | |||
160 | * region by enable_hlt/disable_hlt. | 173 | * region by enable_hlt/disable_hlt. |
161 | */ | 174 | */ |
162 | 175 | ||
163 | static int hlt_counter=0; | 176 | int cris_hlt_counter=0; |
164 | 177 | ||
165 | void disable_hlt(void) | 178 | void disable_hlt(void) |
166 | { | 179 | { |
167 | hlt_counter++; | 180 | cris_hlt_counter++; |
168 | } | 181 | } |
169 | 182 | ||
170 | EXPORT_SYMBOL(disable_hlt); | 183 | EXPORT_SYMBOL(disable_hlt); |
171 | 184 | ||
172 | void enable_hlt(void) | 185 | void enable_hlt(void) |
173 | { | 186 | { |
174 | hlt_counter--; | 187 | cris_hlt_counter--; |
175 | } | 188 | } |
176 | 189 | ||
177 | EXPORT_SYMBOL(enable_hlt); | 190 | EXPORT_SYMBOL(enable_hlt); |
@@ -194,27 +207,28 @@ void cpu_idle (void) | |||
194 | /* endless idle loop with no priority at all */ | 207 | /* endless idle loop with no priority at all */ |
195 | while (1) { | 208 | while (1) { |
196 | while (!need_resched()) { | 209 | while (!need_resched()) { |
197 | void (*idle)(void) = pm_idle; | 210 | void (*idle)(void); |
198 | 211 | /* | |
212 | * Mark this as an RCU critical section so that | ||
213 | * synchronize_kernel() in the unload path waits | ||
214 | * for our completion. | ||
215 | */ | ||
216 | idle = pm_idle; | ||
199 | if (!idle) | 217 | if (!idle) |
200 | idle = default_idle; | 218 | idle = default_idle; |
201 | |||
202 | idle(); | 219 | idle(); |
203 | } | 220 | } |
204 | schedule(); | 221 | schedule(); |
205 | } | 222 | } |
206 | |||
207 | } | 223 | } |
208 | 224 | ||
209 | void hard_reset_now (void); | 225 | void hard_reset_now (void); |
210 | 226 | ||
211 | void machine_restart(void) | 227 | void machine_restart(char *cmd) |
212 | { | 228 | { |
213 | hard_reset_now(); | 229 | hard_reset_now(); |
214 | } | 230 | } |
215 | 231 | ||
216 | EXPORT_SYMBOL(machine_restart); | ||
217 | |||
218 | /* | 232 | /* |
219 | * Similar to machine_power_off, but don't shut off power. Add code | 233 | * Similar to machine_power_off, but don't shut off power. Add code |
220 | * here to freeze the system for e.g. post-mortem debug purpose when | 234 | * here to freeze the system for e.g. post-mortem debug purpose when |
@@ -225,16 +239,12 @@ void machine_halt(void) | |||
225 | { | 239 | { |
226 | } | 240 | } |
227 | 241 | ||
228 | EXPORT_SYMBOL(machine_halt); | ||
229 | |||
230 | /* If or when software power-off is implemented, add code here. */ | 242 | /* If or when software power-off is implemented, add code here. */ |
231 | 243 | ||
232 | void machine_power_off(void) | 244 | void machine_power_off(void) |
233 | { | 245 | { |
234 | } | 246 | } |
235 | 247 | ||
236 | EXPORT_SYMBOL(machine_power_off); | ||
237 | |||
238 | /* | 248 | /* |
239 | * When a process does an "exec", machine state like FPU and debug | 249 | * When a process does an "exec", machine state like FPU and debug |
240 | * registers need to be reset. This is a hook function for that. | 250 | * registers need to be reset. This is a hook function for that. |
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c new file mode 100644 index 000000000000..69c52189f044 --- /dev/null +++ b/arch/cris/kernel/profile.c | |||
@@ -0,0 +1,73 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/proc_fs.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <asm/ptrace.h> | ||
7 | #include <asm/uaccess.h> | ||
8 | |||
9 | #define SAMPLE_BUFFER_SIZE 8192 | ||
10 | |||
11 | static char* sample_buffer; | ||
12 | static char* sample_buffer_pos; | ||
13 | static int prof_running = 0; | ||
14 | |||
15 | void | ||
16 | cris_profile_sample(struct pt_regs* regs) | ||
17 | { | ||
18 | if (!prof_running) | ||
19 | return; | ||
20 | if (user_mode(regs)) | ||
21 | *(unsigned int*)sample_buffer_pos = current->pid; | ||
22 | else | ||
23 | *(unsigned int*)sample_buffer_pos = 0; | ||
24 | *(unsigned int*)(sample_buffer_pos + 4) = instruction_pointer(regs); | ||
25 | sample_buffer_pos += 8; | ||
26 | if (sample_buffer_pos == sample_buffer + SAMPLE_BUFFER_SIZE) | ||
27 | sample_buffer_pos = sample_buffer; | ||
28 | } | ||
29 | |||
30 | static ssize_t | ||
31 | read_cris_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos) | ||
32 | { | ||
33 | unsigned long p = *ppos; | ||
34 | if (p > SAMPLE_BUFFER_SIZE) | ||
35 | return 0; | ||
36 | if (p + count > SAMPLE_BUFFER_SIZE) | ||
37 | count = SAMPLE_BUFFER_SIZE - p; | ||
38 | if (copy_to_user(buf, sample_buffer + p,count)) | ||
39 | return -EFAULT; | ||
40 | memset(sample_buffer + p, 0, count); | ||
41 | *ppos += count; | ||
42 | return count; | ||
43 | } | ||
44 | |||
45 | static ssize_t | ||
46 | write_cris_profile(struct file *file, const char __user *buf, | ||
47 | size_t count, loff_t *ppos) | ||
48 | { | ||
49 | sample_buffer_pos = sample_buffer; | ||
50 | memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE); | ||
51 | } | ||
52 | |||
53 | static struct file_operations cris_proc_profile_operations = { | ||
54 | .read = read_cris_profile, | ||
55 | .write = write_cris_profile, | ||
56 | }; | ||
57 | |||
58 | static int | ||
59 | __init init_cris_profile(void) | ||
60 | { | ||
61 | struct proc_dir_entry *entry; | ||
62 | sample_buffer = (char*)kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL); | ||
63 | sample_buffer_pos = sample_buffer; | ||
64 | entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL); | ||
65 | if (entry) { | ||
66 | entry->proc_fops = &cris_proc_profile_operations; | ||
67 | entry->size = SAMPLE_BUFFER_SIZE; | ||
68 | } | ||
69 | prof_running = 1; | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | __initcall(init_cris_profile); | ||
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c index e85a2fdd9acf..2b6363cbe985 100644 --- a/arch/cris/kernel/ptrace.c +++ b/arch/cris/kernel/ptrace.c | |||
@@ -8,6 +8,12 @@ | |||
8 | * Authors: Bjorn Wesen | 8 | * Authors: Bjorn Wesen |
9 | * | 9 | * |
10 | * $Log: ptrace.c,v $ | 10 | * $Log: ptrace.c,v $ |
11 | * Revision 1.10 2004/09/22 11:50:01 orjanf | ||
12 | * * Moved get_reg/put_reg to arch-specific files. | ||
13 | * * Added functions to access debug registers (CRISv32). | ||
14 | * * Added support for PTRACE_SINGLESTEP (CRISv32). | ||
15 | * * Added S flag to CCS_MASK (CRISv32). | ||
16 | * | ||
11 | * Revision 1.9 2003/07/04 12:56:11 tobiasa | 17 | * Revision 1.9 2003/07/04 12:56:11 tobiasa |
12 | * Moved arch-specific code to arch-specific files. | 18 | * Moved arch-specific code to arch-specific files. |
13 | * | 19 | * |
@@ -72,37 +78,6 @@ | |||
72 | #include <asm/system.h> | 78 | #include <asm/system.h> |
73 | #include <asm/processor.h> | 79 | #include <asm/processor.h> |
74 | 80 | ||
75 | /* | ||
76 | * Get contents of register REGNO in task TASK. | ||
77 | */ | ||
78 | inline long get_reg(struct task_struct *task, unsigned int regno) | ||
79 | { | ||
80 | /* USP is a special case, it's not in the pt_regs struct but | ||
81 | * in the tasks thread struct | ||
82 | */ | ||
83 | |||
84 | if (regno == PT_USP) | ||
85 | return task->thread.usp; | ||
86 | else if (regno < PT_MAX) | ||
87 | return ((unsigned long *)user_regs(task->thread_info))[regno]; | ||
88 | else | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Write contents of register REGNO in task TASK. | ||
94 | */ | ||
95 | inline int put_reg(struct task_struct *task, unsigned int regno, | ||
96 | unsigned long data) | ||
97 | { | ||
98 | if (regno == PT_USP) | ||
99 | task->thread.usp = data; | ||
100 | else if (regno < PT_MAX) | ||
101 | ((unsigned long *)user_regs(task->thread_info))[regno] = data; | ||
102 | else | ||
103 | return -1; | ||
104 | return 0; | ||
105 | } | ||
106 | 81 | ||
107 | /* notification of userspace execution resumption | 82 | /* notification of userspace execution resumption |
108 | * - triggered by current->work.notify_resume | 83 | * - triggered by current->work.notify_resume |
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c index 6ec2671078bf..d11206e467ab 100644 --- a/arch/cris/kernel/setup.c +++ b/arch/cris/kernel/setup.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/pgtable.h> | 17 | #include <asm/pgtable.h> |
18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
19 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
20 | #include <linux/utsname.h> | ||
20 | 21 | ||
21 | #include <asm/setup.h> | 22 | #include <asm/setup.h> |
22 | 23 | ||
@@ -29,7 +30,7 @@ struct screen_info screen_info; | |||
29 | extern int root_mountflags; | 30 | extern int root_mountflags; |
30 | extern char _etext, _edata, _end; | 31 | extern char _etext, _edata, _end; |
31 | 32 | ||
32 | static char command_line[COMMAND_LINE_SIZE] = { 0, }; | 33 | char cris_command_line[COMMAND_LINE_SIZE] = { 0, }; |
33 | 34 | ||
34 | extern const unsigned long text_start, edata; /* set by the linker script */ | 35 | extern const unsigned long text_start, edata; /* set by the linker script */ |
35 | extern unsigned long dram_start, dram_end; | 36 | extern unsigned long dram_start, dram_end; |
@@ -147,34 +148,35 @@ setup_arch(char **cmdline_p) | |||
147 | 148 | ||
148 | paging_init(); | 149 | paging_init(); |
149 | 150 | ||
150 | /* We don't use a command line yet, so just re-initialize it without | 151 | *cmdline_p = cris_command_line; |
151 | saving anything that might be there. */ | ||
152 | |||
153 | *cmdline_p = command_line; | ||
154 | 152 | ||
155 | #ifdef CONFIG_ETRAX_CMDLINE | 153 | #ifdef CONFIG_ETRAX_CMDLINE |
156 | strlcpy(command_line, CONFIG_ETRAX_CMDLINE, COMMAND_LINE_SIZE); | 154 | if (!strcmp(cris_command_line, "")) { |
157 | command_line[COMMAND_LINE_SIZE - 1] = '\0'; | 155 | strlcpy(cris_command_line, CONFIG_ETRAX_CMDLINE, COMMAND_LINE_SIZE); |
156 | cris_command_line[COMMAND_LINE_SIZE - 1] = '\0'; | ||
157 | } | ||
158 | #endif | ||
158 | 159 | ||
159 | /* Save command line for future references. */ | 160 | /* Save command line for future references. */ |
160 | memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); | 161 | memcpy(saved_command_line, cris_command_line, COMMAND_LINE_SIZE); |
161 | saved_command_line[COMMAND_LINE_SIZE - 1] = '\0'; | 162 | saved_command_line[COMMAND_LINE_SIZE - 1] = '\0'; |
162 | #endif | ||
163 | 163 | ||
164 | /* give credit for the CRIS port */ | 164 | /* give credit for the CRIS port */ |
165 | show_etrax_copyright(); | 165 | show_etrax_copyright(); |
166 | |||
167 | /* Setup utsname */ | ||
168 | strcpy(system_utsname.machine, cris_machine_name); | ||
166 | } | 169 | } |
167 | 170 | ||
168 | static void *c_start(struct seq_file *m, loff_t *pos) | 171 | static void *c_start(struct seq_file *m, loff_t *pos) |
169 | { | 172 | { |
170 | /* We only got one CPU... */ | 173 | return *pos < NR_CPUS ? (void *)(int)(*pos + 1): NULL; |
171 | return *pos < 1 ? (void *)1 : NULL; | ||
172 | } | 174 | } |
173 | 175 | ||
174 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | 176 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) |
175 | { | 177 | { |
176 | ++*pos; | 178 | ++*pos; |
177 | return NULL; | 179 | return c_start(m, pos); |
178 | } | 180 | } |
179 | 181 | ||
180 | static void c_stop(struct seq_file *m, void *v) | 182 | static void c_stop(struct seq_file *m, void *v) |
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c index 6c28b0e7f7b4..fa2d4323da25 100644 --- a/arch/cris/kernel/time.c +++ b/arch/cris/kernel/time.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: time.c,v 1.14 2004/06/01 05:38:11 starvik Exp $ | 1 | /* $Id: time.c,v 1.18 2005/03/04 08:16:17 starvik Exp $ |
2 | * | 2 | * |
3 | * linux/arch/cris/kernel/time.c | 3 | * linux/arch/cris/kernel/time.c |
4 | * | 4 | * |
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/bcd.h> | 30 | #include <linux/bcd.h> |
31 | #include <linux/timex.h> | 31 | #include <linux/timex.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/profile.h> | ||
33 | 34 | ||
34 | u64 jiffies_64 = INITIAL_JIFFIES; | 35 | u64 jiffies_64 = INITIAL_JIFFIES; |
35 | 36 | ||
@@ -214,6 +215,21 @@ update_xtime_from_cmos(void) | |||
214 | } | 215 | } |
215 | } | 216 | } |
216 | 217 | ||
218 | extern void cris_profile_sample(struct pt_regs* regs); | ||
219 | |||
220 | void | ||
221 | cris_do_profile(struct pt_regs* regs) | ||
222 | { | ||
223 | |||
224 | #if CONFIG_SYSTEM_PROFILER | ||
225 | cris_profile_sample(regs); | ||
226 | #endif | ||
227 | |||
228 | #if CONFIG_PROFILING | ||
229 | profile_tick(CPU_PROFILING, regs); | ||
230 | #endif | ||
231 | } | ||
232 | |||
217 | /* | 233 | /* |
218 | * Scheduler clock - returns current time in nanosec units. | 234 | * Scheduler clock - returns current time in nanosec units. |
219 | */ | 235 | */ |
diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c index d4dfa050e3a5..520d92205fed 100644 --- a/arch/cris/kernel/traps.c +++ b/arch/cris/kernel/traps.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: traps.c,v 1.9 2004/05/11 12:28:26 starvik Exp $ | 1 | /* $Id: traps.c,v 1.11 2005/01/24 16:03:19 orjanf Exp $ |
2 | * | 2 | * |
3 | * linux/arch/cris/traps.c | 3 | * linux/arch/cris/traps.c |
4 | * | 4 | * |
@@ -20,13 +20,15 @@ | |||
20 | 20 | ||
21 | static int kstack_depth_to_print = 24; | 21 | static int kstack_depth_to_print = 24; |
22 | 22 | ||
23 | extern int raw_printk(const char *fmt, ...); | ||
24 | |||
23 | void show_trace(unsigned long * stack) | 25 | void show_trace(unsigned long * stack) |
24 | { | 26 | { |
25 | unsigned long addr, module_start, module_end; | 27 | unsigned long addr, module_start, module_end; |
26 | extern char _stext, _etext; | 28 | extern char _stext, _etext; |
27 | int i; | 29 | int i; |
28 | 30 | ||
29 | printk("\nCall Trace: "); | 31 | raw_printk("\nCall Trace: "); |
30 | 32 | ||
31 | i = 1; | 33 | i = 1; |
32 | module_start = VMALLOC_START; | 34 | module_start = VMALLOC_START; |
@@ -37,7 +39,7 @@ void show_trace(unsigned long * stack) | |||
37 | /* This message matches "failing address" marked | 39 | /* This message matches "failing address" marked |
38 | s390 in ksymoops, so lines containing it will | 40 | s390 in ksymoops, so lines containing it will |
39 | not be filtered out by ksymoops. */ | 41 | not be filtered out by ksymoops. */ |
40 | printk ("Failing address 0x%lx\n", (unsigned long)stack); | 42 | raw_printk ("Failing address 0x%lx\n", (unsigned long)stack); |
41 | break; | 43 | break; |
42 | } | 44 | } |
43 | stack++; | 45 | stack++; |
@@ -54,8 +56,8 @@ void show_trace(unsigned long * stack) | |||
54 | (addr <= (unsigned long) &_etext)) || | 56 | (addr <= (unsigned long) &_etext)) || |
55 | ((addr >= module_start) && (addr <= module_end))) { | 57 | ((addr >= module_start) && (addr <= module_end))) { |
56 | if (i && ((i % 8) == 0)) | 58 | if (i && ((i % 8) == 0)) |
57 | printk("\n "); | 59 | raw_printk("\n "); |
58 | printk("[<%08lx>] ", addr); | 60 | raw_printk("[<%08lx>] ", addr); |
59 | i++; | 61 | i++; |
60 | } | 62 | } |
61 | } | 63 | } |
@@ -96,25 +98,59 @@ show_stack(struct task_struct *task, unsigned long *sp) | |||
96 | 98 | ||
97 | stack = sp; | 99 | stack = sp; |
98 | 100 | ||
99 | printk("\nStack from %08lx:\n ", (unsigned long)stack); | 101 | raw_printk("\nStack from %08lx:\n ", (unsigned long)stack); |
100 | for(i = 0; i < kstack_depth_to_print; i++) { | 102 | for(i = 0; i < kstack_depth_to_print; i++) { |
101 | if (((long) stack & (THREAD_SIZE-1)) == 0) | 103 | if (((long) stack & (THREAD_SIZE-1)) == 0) |
102 | break; | 104 | break; |
103 | if (i && ((i % 8) == 0)) | 105 | if (i && ((i % 8) == 0)) |
104 | printk("\n "); | 106 | raw_printk("\n "); |
105 | if (__get_user (addr, stack)) { | 107 | if (__get_user (addr, stack)) { |
106 | /* This message matches "failing address" marked | 108 | /* This message matches "failing address" marked |
107 | s390 in ksymoops, so lines containing it will | 109 | s390 in ksymoops, so lines containing it will |
108 | not be filtered out by ksymoops. */ | 110 | not be filtered out by ksymoops. */ |
109 | printk ("Failing address 0x%lx\n", (unsigned long)stack); | 111 | raw_printk ("Failing address 0x%lx\n", (unsigned long)stack); |
110 | break; | 112 | break; |
111 | } | 113 | } |
112 | stack++; | 114 | stack++; |
113 | printk("%08lx ", addr); | 115 | raw_printk("%08lx ", addr); |
114 | } | 116 | } |
115 | show_trace(sp); | 117 | show_trace(sp); |
116 | } | 118 | } |
117 | 119 | ||
120 | static void (*nmi_handler)(struct pt_regs*); | ||
121 | extern void arch_enable_nmi(void); | ||
122 | |||
123 | void set_nmi_handler(void (*handler)(struct pt_regs*)) | ||
124 | { | ||
125 | nmi_handler = handler; | ||
126 | arch_enable_nmi(); | ||
127 | } | ||
128 | |||
129 | void handle_nmi(struct pt_regs* regs) | ||
130 | { | ||
131 | if (nmi_handler) | ||
132 | nmi_handler(regs); | ||
133 | } | ||
134 | |||
135 | #ifdef CONFIG_DEBUG_NMI_OOPS | ||
136 | void oops_nmi_handler(struct pt_regs* regs) | ||
137 | { | ||
138 | stop_watchdog(); | ||
139 | raw_printk("NMI!\n"); | ||
140 | show_registers(regs); | ||
141 | } | ||
142 | |||
143 | static int | ||
144 | __init oops_nmi_register(void) | ||
145 | { | ||
146 | set_nmi_handler(oops_nmi_handler); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | __initcall(oops_nmi_register); | ||
151 | |||
152 | #endif | ||
153 | |||
118 | #if 0 | 154 | #if 0 |
119 | /* displays a short stack trace */ | 155 | /* displays a short stack trace */ |
120 | 156 | ||
@@ -123,9 +159,9 @@ show_stack() | |||
123 | { | 159 | { |
124 | unsigned long *sp = (unsigned long *)rdusp(); | 160 | unsigned long *sp = (unsigned long *)rdusp(); |
125 | int i; | 161 | int i; |
126 | printk("Stack dump [0x%08lx]:\n", (unsigned long)sp); | 162 | raw_printk("Stack dump [0x%08lx]:\n", (unsigned long)sp); |
127 | for(i = 0; i < 16; i++) | 163 | for(i = 0; i < 16; i++) |
128 | printk("sp + %d: 0x%08lx\n", i*4, sp[i]); | 164 | raw_printk("sp + %d: 0x%08lx\n", i*4, sp[i]); |
129 | return 0; | 165 | return 0; |
130 | } | 166 | } |
131 | #endif | 167 | #endif |
@@ -142,3 +178,9 @@ trap_init(void) | |||
142 | { | 178 | { |
143 | /* Nothing needs to be done */ | 179 | /* Nothing needs to be done */ |
144 | } | 180 | } |
181 | |||
182 | void spinning_cpu(void* addr) | ||
183 | { | ||
184 | raw_printk("CPU %d spinning on %X\n", smp_processor_id(), addr); | ||
185 | dump_stack(); | ||
186 | } | ||