aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze/kernel')
-rw-r--r--arch/microblaze/kernel/Makefile7
-rw-r--r--arch/microblaze/kernel/cpu/mb.c1
-rw-r--r--arch/microblaze/kernel/entry-nommu.S28
-rw-r--r--arch/microblaze/kernel/entry.S607
-rw-r--r--arch/microblaze/kernel/exceptions.c9
-rw-r--r--arch/microblaze/kernel/head.S4
-rw-r--r--arch/microblaze/kernel/hw_exception_handler.S4
-rw-r--r--arch/microblaze/kernel/irq.c16
-rw-r--r--arch/microblaze/kernel/kgdb.c147
-rw-r--r--arch/microblaze/kernel/misc.S2
-rw-r--r--arch/microblaze/kernel/of_device.c112
-rw-r--r--arch/microblaze/kernel/of_platform.c200
-rw-r--r--arch/microblaze/kernel/process.c7
-rw-r--r--arch/microblaze/kernel/prom_parse.c877
-rw-r--r--arch/microblaze/kernel/ptrace.c17
-rw-r--r--arch/microblaze/kernel/reset.c12
-rw-r--r--arch/microblaze/kernel/setup.c6
-rw-r--r--arch/microblaze/kernel/stacktrace.c44
-rw-r--r--arch/microblaze/kernel/timer.c24
-rw-r--r--arch/microblaze/kernel/traps.c91
-rw-r--r--arch/microblaze/kernel/unwind.c318
-rw-r--r--arch/microblaze/kernel/vmlinux.lds.S16
22 files changed, 857 insertions, 1692 deletions
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index e51bc1520825..f0cb5c26c81c 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -15,9 +15,9 @@ endif
15extra-y := head.o vmlinux.lds 15extra-y := head.o vmlinux.lds
16 16
17obj-y += dma.o exceptions.o \ 17obj-y += dma.o exceptions.o \
18 hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ 18 hw_exception_handler.o init_task.o intc.o irq.o \
19 of_platform.o process.o prom.o prom_parse.o ptrace.o \ 19 process.o prom.o prom_parse.o ptrace.o \
20 setup.o signal.o sys_microblaze.o timer.o traps.o reset.o 20 reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o
21 21
22obj-y += cpu/ 22obj-y += cpu/
23 23
@@ -28,5 +28,6 @@ obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
28obj-$(CONFIG_MMU) += misc.o 28obj-$(CONFIG_MMU) += misc.o
29obj-$(CONFIG_STACKTRACE) += stacktrace.o 29obj-$(CONFIG_STACKTRACE) += stacktrace.o
30obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o 30obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o
31obj-$(CONFIG_KGDB) += kgdb.o
31 32
32obj-y += entry$(MMU).o 33obj-y += entry$(MMU).o
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index 4216eb1eaa32..7086e3564281 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -126,6 +126,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
126 cpuinfo.pvr_user1, 126 cpuinfo.pvr_user1,
127 cpuinfo.pvr_user2); 127 cpuinfo.pvr_user2);
128 128
129 count += seq_printf(m, "Page size:\t%lu\n", PAGE_SIZE);
129 return 0; 130 return 0;
130} 131}
131 132
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
index 8cc18cd2cce6..ca84368570b6 100644
--- a/arch/microblaze/kernel/entry-nommu.S
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -588,3 +588,31 @@ sys_rt_sigsuspend_wrapper:
588#include "syscall_table.S" 588#include "syscall_table.S"
589 589
590syscall_table_size=(.-sys_call_table) 590syscall_table_size=(.-sys_call_table)
591
592type_SYSCALL:
593 .ascii "SYSCALL\0"
594type_IRQ:
595 .ascii "IRQ\0"
596type_IRQ_PREEMPT:
597 .ascii "IRQ (PREEMPTED)\0"
598type_SYSCALL_PREEMPT:
599 .ascii " SYSCALL (PREEMPTED)\0"
600
601 /*
602 * Trap decoding for stack unwinder
603 * Tuples are (start addr, end addr, string)
604 * If return address lies on [start addr, end addr],
605 * unwinder displays 'string'
606 */
607
608 .align 4
609.global microblaze_trap_handlers
610microblaze_trap_handlers:
611 /* Exact matches come first */
612 .word ret_to_user ; .word ret_to_user ; .word type_SYSCALL
613 .word ret_from_intr; .word ret_from_intr ; .word type_IRQ
614 /* Fuzzy matches go here */
615 .word ret_from_intr; .word no_intr_resched; .word type_IRQ_PREEMPT
616 .word work_pending ; .word no_work_pending; .word type_SYSCALL_PREEMPT
617 /* End of table */
618 .word 0 ; .word 0 ; .word 0
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index c0ede25c5b99..304882e56459 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -48,128 +48,107 @@
48 */ 48 */
49#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 49#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
50 .macro clear_bip 50 .macro clear_bip
51 msrclr r11, MSR_BIP 51 msrclr r0, MSR_BIP
52 nop
53 .endm 52 .endm
54 53
55 .macro set_bip 54 .macro set_bip
56 msrset r11, MSR_BIP 55 msrset r0, MSR_BIP
57 nop
58 .endm 56 .endm
59 57
60 .macro clear_eip 58 .macro clear_eip
61 msrclr r11, MSR_EIP 59 msrclr r0, MSR_EIP
62 nop
63 .endm 60 .endm
64 61
65 .macro set_ee 62 .macro set_ee
66 msrset r11, MSR_EE 63 msrset r0, MSR_EE
67 nop
68 .endm 64 .endm
69 65
70 .macro disable_irq 66 .macro disable_irq
71 msrclr r11, MSR_IE 67 msrclr r0, MSR_IE
72 nop
73 .endm 68 .endm
74 69
75 .macro enable_irq 70 .macro enable_irq
76 msrset r11, MSR_IE 71 msrset r0, MSR_IE
77 nop
78 .endm 72 .endm
79 73
80 .macro set_ums 74 .macro set_ums
81 msrset r11, MSR_UMS 75 msrset r0, MSR_UMS
82 nop 76 msrclr r0, MSR_VMS
83 msrclr r11, MSR_VMS
84 nop
85 .endm 77 .endm
86 78
87 .macro set_vms 79 .macro set_vms
88 msrclr r11, MSR_UMS 80 msrclr r0, MSR_UMS
89 nop 81 msrset r0, MSR_VMS
90 msrset r11, MSR_VMS 82 .endm
91 nop 83
84 .macro clear_ums
85 msrclr r0, MSR_UMS
92 .endm 86 .endm
93 87
94 .macro clear_vms_ums 88 .macro clear_vms_ums
95 msrclr r11, MSR_VMS 89 msrclr r0, MSR_VMS | MSR_UMS
96 nop
97 msrclr r11, MSR_UMS
98 nop
99 .endm 90 .endm
100#else 91#else
101 .macro clear_bip 92 .macro clear_bip
102 mfs r11, rmsr 93 mfs r11, rmsr
103 nop
104 andi r11, r11, ~MSR_BIP 94 andi r11, r11, ~MSR_BIP
105 mts rmsr, r11 95 mts rmsr, r11
106 nop
107 .endm 96 .endm
108 97
109 .macro set_bip 98 .macro set_bip
110 mfs r11, rmsr 99 mfs r11, rmsr
111 nop
112 ori r11, r11, MSR_BIP 100 ori r11, r11, MSR_BIP
113 mts rmsr, r11 101 mts rmsr, r11
114 nop
115 .endm 102 .endm
116 103
117 .macro clear_eip 104 .macro clear_eip
118 mfs r11, rmsr 105 mfs r11, rmsr
119 nop
120 andi r11, r11, ~MSR_EIP 106 andi r11, r11, ~MSR_EIP
121 mts rmsr, r11 107 mts rmsr, r11
122 nop
123 .endm 108 .endm
124 109
125 .macro set_ee 110 .macro set_ee
126 mfs r11, rmsr 111 mfs r11, rmsr
127 nop
128 ori r11, r11, MSR_EE 112 ori r11, r11, MSR_EE
129 mts rmsr, r11 113 mts rmsr, r11
130 nop
131 .endm 114 .endm
132 115
133 .macro disable_irq 116 .macro disable_irq
134 mfs r11, rmsr 117 mfs r11, rmsr
135 nop
136 andi r11, r11, ~MSR_IE 118 andi r11, r11, ~MSR_IE
137 mts rmsr, r11 119 mts rmsr, r11
138 nop
139 .endm 120 .endm
140 121
141 .macro enable_irq 122 .macro enable_irq
142 mfs r11, rmsr 123 mfs r11, rmsr
143 nop
144 ori r11, r11, MSR_IE 124 ori r11, r11, MSR_IE
145 mts rmsr, r11 125 mts rmsr, r11
146 nop
147 .endm 126 .endm
148 127
149 .macro set_ums 128 .macro set_ums
150 mfs r11, rmsr 129 mfs r11, rmsr
151 nop
152 ori r11, r11, MSR_VMS 130 ori r11, r11, MSR_VMS
153 andni r11, r11, MSR_UMS 131 andni r11, r11, MSR_UMS
154 mts rmsr, r11 132 mts rmsr, r11
155 nop
156 .endm 133 .endm
157 134
158 .macro set_vms 135 .macro set_vms
159 mfs r11, rmsr 136 mfs r11, rmsr
160 nop
161 ori r11, r11, MSR_VMS 137 ori r11, r11, MSR_VMS
162 andni r11, r11, MSR_UMS 138 andni r11, r11, MSR_UMS
163 mts rmsr, r11 139 mts rmsr, r11
164 nop 140 .endm
141
142 .macro clear_ums
143 mfs r11, rmsr
144 andni r11, r11, MSR_UMS
145 mts rmsr,r11
165 .endm 146 .endm
166 147
167 .macro clear_vms_ums 148 .macro clear_vms_ums
168 mfs r11, rmsr 149 mfs r11, rmsr
169 nop
170 andni r11, r11, (MSR_VMS|MSR_UMS) 150 andni r11, r11, (MSR_VMS|MSR_UMS)
171 mts rmsr,r11 151 mts rmsr,r11
172 nop
173 .endm 152 .endm
174#endif 153#endif
175 154
@@ -180,18 +159,22 @@
180 159
181/* turn on virtual protected mode save */ 160/* turn on virtual protected mode save */
182#define VM_ON \ 161#define VM_ON \
183 set_ums; \ 162 set_ums; \
184 rted r0, 2f; \ 163 rted r0, 2f; \
1852: nop; 164 nop; \
1652:
186 166
187/* turn off virtual protected mode save and user mode save*/ 167/* turn off virtual protected mode save and user mode save*/
188#define VM_OFF \ 168#define VM_OFF \
189 clear_vms_ums; \ 169 clear_vms_ums; \
190 rted r0, TOPHYS(1f); \ 170 rted r0, TOPHYS(1f); \
1911: nop; 171 nop; \
1721:
192 173
193#define SAVE_REGS \ 174#define SAVE_REGS \
194 swi r2, r1, PTO+PT_R2; /* Save SDA */ \ 175 swi r2, r1, PTO+PT_R2; /* Save SDA */ \
176 swi r3, r1, PTO+PT_R3; \
177 swi r4, r1, PTO+PT_R4; \
195 swi r5, r1, PTO+PT_R5; \ 178 swi r5, r1, PTO+PT_R5; \
196 swi r6, r1, PTO+PT_R6; \ 179 swi r6, r1, PTO+PT_R6; \
197 swi r7, r1, PTO+PT_R7; \ 180 swi r7, r1, PTO+PT_R7; \
@@ -218,14 +201,14 @@
218 swi r30, r1, PTO+PT_R30; \ 201 swi r30, r1, PTO+PT_R30; \
219 swi r31, r1, PTO+PT_R31; /* Save current task reg */ \ 202 swi r31, r1, PTO+PT_R31; /* Save current task reg */ \
220 mfs r11, rmsr; /* save MSR */ \ 203 mfs r11, rmsr; /* save MSR */ \
221 nop; \
222 swi r11, r1, PTO+PT_MSR; 204 swi r11, r1, PTO+PT_MSR;
223 205
224#define RESTORE_REGS \ 206#define RESTORE_REGS \
225 lwi r11, r1, PTO+PT_MSR; \ 207 lwi r11, r1, PTO+PT_MSR; \
226 mts rmsr , r11; \ 208 mts rmsr , r11; \
227 nop; \
228 lwi r2, r1, PTO+PT_R2; /* restore SDA */ \ 209 lwi r2, r1, PTO+PT_R2; /* restore SDA */ \
210 lwi r3, r1, PTO+PT_R3; \
211 lwi r4, r1, PTO+PT_R4; \
229 lwi r5, r1, PTO+PT_R5; \ 212 lwi r5, r1, PTO+PT_R5; \
230 lwi r6, r1, PTO+PT_R6; \ 213 lwi r6, r1, PTO+PT_R6; \
231 lwi r7, r1, PTO+PT_R7; \ 214 lwi r7, r1, PTO+PT_R7; \
@@ -252,6 +235,39 @@
252 lwi r30, r1, PTO+PT_R30; \ 235 lwi r30, r1, PTO+PT_R30; \
253 lwi r31, r1, PTO+PT_R31; /* Restore cur task reg */ 236 lwi r31, r1, PTO+PT_R31; /* Restore cur task reg */
254 237
238#define SAVE_STATE \
239 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */ \
240 /* See if already in kernel mode.*/ \
241 mfs r1, rmsr; \
242 andi r1, r1, MSR_UMS; \
243 bnei r1, 1f; \
244 /* Kernel-mode state save. */ \
245 /* Reload kernel stack-ptr. */ \
246 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); \
247 /* FIXME: I can add these two lines to one */ \
248 /* tophys(r1,r1); */ \
249 /* addik r1, r1, -STATE_SAVE_SIZE; */ \
250 addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
251 SAVE_REGS \
252 brid 2f; \
253 swi r1, r1, PTO+PT_MODE; \
2541: /* User-mode state save. */ \
255 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
256 tophys(r1,r1); \
257 lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ \
258 /* MS these three instructions can be added to one */ \
259 /* addik r1, r1, THREAD_SIZE; */ \
260 /* tophys(r1,r1); */ \
261 /* addik r1, r1, -STATE_SAVE_SIZE; */ \
262 addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
263 SAVE_REGS \
264 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \
265 swi r11, r1, PTO+PT_R1; /* Store user SP. */ \
266 swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ \
267 /* MS: I am clearing UMS even in case when I come from kernel space */ \
268 clear_ums; \
2692: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
270
255.text 271.text
256 272
257/* 273/*
@@ -267,45 +283,23 @@
267 * are masked. This is nice, means we don't have to CLI before state save 283 * are masked. This is nice, means we don't have to CLI before state save
268 */ 284 */
269C_ENTRY(_user_exception): 285C_ENTRY(_user_exception):
270 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
271 addi r14, r14, 4 /* return address is 4 byte after call */ 286 addi r14, r14, 4 /* return address is 4 byte after call */
272 swi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */ 287 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
273
274 lwi r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/
275 beqi r11, 1f; /* Jump ahead if coming from user */
276/* Kernel-mode state save. */
277 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
278 tophys(r1,r11);
279 swi r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */
280 lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
281
282 addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
283 SAVE_REGS
284
285 addi r11, r0, 1; /* Was in kernel-mode. */
286 swi r11, r1, PTO+PT_MODE; /* pt_regs -> kernel mode */
287 brid 2f;
288 nop; /* Fill delay slot */
289 288
290/* User-mode state save. */
2911:
292 lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
293 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ 289 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
294 tophys(r1,r1); 290 tophys(r1,r1);
295 lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ 291 lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */
296/* calculate kernel stack pointer from task struct 8k */ 292 /* MS these three instructions can be added to one */
297 addik r1, r1, THREAD_SIZE; 293 /* addik r1, r1, THREAD_SIZE; */
298 tophys(r1,r1); 294 /* tophys(r1,r1); */
299 295 /* addik r1, r1, -STATE_SAVE_SIZE; */
300 addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ 296 addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
301 SAVE_REGS 297 SAVE_REGS
302 298
303 swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */
304 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 299 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
305 swi r11, r1, PTO+PT_R1; /* Store user SP. */ 300 swi r11, r1, PTO+PT_R1; /* Store user SP. */
306 addi r11, r0, 1; 301 clear_ums;
307 swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode. */ 302 lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
3082: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
309 /* Save away the syscall number. */ 303 /* Save away the syscall number. */
310 swi r12, r1, PTO+PT_R0; 304 swi r12, r1, PTO+PT_R0;
311 tovirt(r1,r1) 305 tovirt(r1,r1)
@@ -316,10 +310,8 @@ C_ENTRY(_user_exception):
316 * register should point to the location where 310 * register should point to the location where
317 * the called function should return. [note that MAKE_SYS_CALL uses label 1] */ 311 * the called function should return. [note that MAKE_SYS_CALL uses label 1] */
318 312
319 # Step into virtual mode. 313 /* Step into virtual mode */
320 set_vms; 314 rtbd r0, 3f
321 addik r11, r0, 3f
322 rtid r11, 0
323 nop 315 nop
3243: 3163:
325 lwi r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */ 317 lwi r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */
@@ -363,24 +355,17 @@ C_ENTRY(_user_exception):
363 # Find and jump into the syscall handler. 355 # Find and jump into the syscall handler.
364 lwi r12, r12, sys_call_table 356 lwi r12, r12, sys_call_table
365 /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 357 /* where the trap should return need -8 to adjust for rtsd r15, 8 */
366 la r15, r0, ret_from_trap-8 358 addi r15, r0, ret_from_trap-8
367 bra r12 359 bra r12
368 360
369 /* The syscall number is invalid, return an error. */ 361 /* The syscall number is invalid, return an error. */
3705: 3625:
363 rtsd r15, 8; /* looks like a normal subroutine return */
371 addi r3, r0, -ENOSYS; 364 addi r3, r0, -ENOSYS;
372 rtsd r15,8; /* looks like a normal subroutine return */
373 or r0, r0, r0
374
375 365
376/* Entry point used to return from a syscall/trap */ 366/* Entry point used to return from a syscall/trap */
377/* We re-enable BIP bit before state restore */ 367/* We re-enable BIP bit before state restore */
378C_ENTRY(ret_from_trap): 368C_ENTRY(ret_from_trap):
379 set_bip; /* Ints masked for state restore*/
380 lwi r11, r1, PTO+PT_MODE;
381/* See if returning to kernel mode, if so, skip resched &c. */
382 bnei r11, 2f;
383
384 swi r3, r1, PTO + PT_R3 369 swi r3, r1, PTO + PT_R3
385 swi r4, r1, PTO + PT_R4 370 swi r4, r1, PTO + PT_R4
386 371
@@ -413,32 +398,19 @@ C_ENTRY(ret_from_trap):
413 andi r11, r11, _TIF_SIGPENDING; 398 andi r11, r11, _TIF_SIGPENDING;
414 beqi r11, 1f; /* Signals to handle, handle them */ 399 beqi r11, 1f; /* Signals to handle, handle them */
415 400
416 la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ 401 addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
417 addi r7, r0, 1; /* Arg 3: int in_syscall */ 402 addi r7, r0, 1; /* Arg 3: int in_syscall */
418 bralid r15, do_signal; /* Handle any signals */ 403 bralid r15, do_signal; /* Handle any signals */
419 add r6, r0, r0; /* Arg 2: sigset_t *oldset */ 404 add r6, r0, r0; /* Arg 2: sigset_t *oldset */
420 405
421/* Finally, return to user state. */ 406/* Finally, return to user state. */
4221: 4071: set_bip; /* Ints masked for state restore */
423 lwi r3, r1, PTO + PT_R3; /* restore syscall result */
424 lwi r4, r1, PTO + PT_R4;
425
426 swi r0, r0, PER_CPU(KM); /* Now officially in user state. */
427 swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 408 swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
428 VM_OFF; 409 VM_OFF;
429 tophys(r1,r1); 410 tophys(r1,r1);
430 RESTORE_REGS; 411 RESTORE_REGS;
431 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ 412 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */
432 lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */ 413 lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
433 bri 6f;
434
435/* Return to kernel state. */
4362: VM_OFF;
437 tophys(r1,r1);
438 RESTORE_REGS;
439 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */
440 tovirt(r1,r1);
4416:
442TRAP_return: /* Make global symbol for debugging */ 414TRAP_return: /* Make global symbol for debugging */
443 rtbd r14, 0; /* Instructions to return from an IRQ */ 415 rtbd r14, 0; /* Instructions to return from an IRQ */
444 nop; 416 nop;
@@ -450,12 +422,11 @@ TRAP_return: /* Make global symbol for debugging */
450C_ENTRY(sys_fork_wrapper): 422C_ENTRY(sys_fork_wrapper):
451 addi r5, r0, SIGCHLD /* Arg 0: flags */ 423 addi r5, r0, SIGCHLD /* Arg 0: flags */
452 lwi r6, r1, PTO+PT_R1 /* Arg 1: child SP (use parent's) */ 424 lwi r6, r1, PTO+PT_R1 /* Arg 1: child SP (use parent's) */
453 la r7, r1, PTO /* Arg 2: parent context */ 425 addik r7, r1, PTO /* Arg 2: parent context */
454 add r8. r0, r0 /* Arg 3: (unused) */ 426 add r8. r0, r0 /* Arg 3: (unused) */
455 add r9, r0, r0; /* Arg 4: (unused) */ 427 add r9, r0, r0; /* Arg 4: (unused) */
456 add r10, r0, r0; /* Arg 5: (unused) */
457 brid do_fork /* Do real work (tail-call) */ 428 brid do_fork /* Do real work (tail-call) */
458 nop; 429 add r10, r0, r0; /* Arg 5: (unused) */
459 430
460/* This the initial entry point for a new child thread, with an appropriate 431/* This the initial entry point for a new child thread, with an appropriate
461 stack in place that makes it look the the child is in the middle of an 432 stack in place that makes it look the the child is in the middle of an
@@ -466,35 +437,31 @@ C_ENTRY(ret_from_fork):
466 bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ 437 bralid r15, schedule_tail; /* ...which is schedule_tail's arg */
467 add r3, r5, r0; /* switch_thread returns the prev task */ 438 add r3, r5, r0; /* switch_thread returns the prev task */
468 /* ( in the delay slot ) */ 439 /* ( in the delay slot ) */
469 add r3, r0, r0; /* Child's fork call should return 0. */
470 brid ret_from_trap; /* Do normal trap return */ 440 brid ret_from_trap; /* Do normal trap return */
471 nop; 441 add r3, r0, r0; /* Child's fork call should return 0. */
472 442
473C_ENTRY(sys_vfork): 443C_ENTRY(sys_vfork):
474 brid microblaze_vfork /* Do real work (tail-call) */ 444 brid microblaze_vfork /* Do real work (tail-call) */
475 la r5, r1, PTO 445 addik r5, r1, PTO
476 446
477C_ENTRY(sys_clone): 447C_ENTRY(sys_clone):
478 bnei r6, 1f; /* See if child SP arg (arg 1) is 0. */ 448 bnei r6, 1f; /* See if child SP arg (arg 1) is 0. */
479 lwi r6, r1, PTO+PT_R1; /* If so, use paret's stack ptr */ 449 lwi r6, r1, PTO + PT_R1; /* If so, use paret's stack ptr */
4801: la r7, r1, PTO; /* Arg 2: parent context */ 4501: addik r7, r1, PTO; /* Arg 2: parent context */
481 add r8, r0, r0; /* Arg 3: (unused) */ 451 add r8, r0, r0; /* Arg 3: (unused) */
482 add r9, r0, r0; /* Arg 4: (unused) */ 452 add r9, r0, r0; /* Arg 4: (unused) */
483 add r10, r0, r0; /* Arg 5: (unused) */
484 brid do_fork /* Do real work (tail-call) */ 453 brid do_fork /* Do real work (tail-call) */
485 nop; 454 add r10, r0, r0; /* Arg 5: (unused) */
486 455
487C_ENTRY(sys_execve): 456C_ENTRY(sys_execve):
488 la r8, r1, PTO; /* add user context as 4th arg */
489 brid microblaze_execve; /* Do real work (tail-call).*/ 457 brid microblaze_execve; /* Do real work (tail-call).*/
490 nop; 458 addik r8, r1, PTO; /* add user context as 4th arg */
491 459
492C_ENTRY(sys_rt_sigreturn_wrapper): 460C_ENTRY(sys_rt_sigreturn_wrapper):
493 swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ 461 swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
494 swi r4, r1, PTO+PT_R4; 462 swi r4, r1, PTO+PT_R4;
495 la r5, r1, PTO; /* add user context as 1st arg */
496 brlid r15, sys_rt_sigreturn /* Do real work */ 463 brlid r15, sys_rt_sigreturn /* Do real work */
497 nop; 464 addik r5, r1, PTO; /* add user context as 1st arg */
498 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ 465 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
499 lwi r4, r1, PTO+PT_R4; 466 lwi r4, r1, PTO+PT_R4;
500 bri ret_from_trap /* fall through will not work here due to align */ 467 bri ret_from_trap /* fall through will not work here due to align */
@@ -503,83 +470,23 @@ C_ENTRY(sys_rt_sigreturn_wrapper):
503/* 470/*
504 * HW EXCEPTION rutine start 471 * HW EXCEPTION rutine start
505 */ 472 */
506
507#define SAVE_STATE \
508 swi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */ \
509 set_bip; /*equalize initial state for all possible entries*/\
510 clear_eip; \
511 enable_irq; \
512 set_ee; \
513 /* See if already in kernel mode.*/ \
514 lwi r11, r0, TOPHYS(PER_CPU(KM)); \
515 beqi r11, 1f; /* Jump ahead if coming from user */\
516 /* Kernel-mode state save. */ \
517 /* Reload kernel stack-ptr. */ \
518 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \
519 tophys(r1,r11); \
520 swi r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */ \
521 lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\
522 addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */\
523 /* store return registers separately because \
524 * this macros is use for others exceptions */ \
525 swi r3, r1, PTO + PT_R3; \
526 swi r4, r1, PTO + PT_R4; \
527 SAVE_REGS \
528 /* PC, before IRQ/trap - this is one instruction above */ \
529 swi r17, r1, PTO+PT_PC; \
530 \
531 addi r11, r0, 1; /* Was in kernel-mode. */ \
532 swi r11, r1, PTO+PT_MODE; \
533 brid 2f; \
534 nop; /* Fill delay slot */ \
5351: /* User-mode state save. */ \
536 lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\
537 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
538 tophys(r1,r1); \
539 lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ \
540 addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */\
541 tophys(r1,r1); \
542 \
543 addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */\
544 /* store return registers separately because this macros \
545 * is use for others exceptions */ \
546 swi r3, r1, PTO + PT_R3; \
547 swi r4, r1, PTO + PT_R4; \
548 SAVE_REGS \
549 /* PC, before IRQ/trap - this is one instruction above FIXME*/ \
550 swi r17, r1, PTO+PT_PC; \
551 \
552 swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */ \
553 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \
554 swi r11, r1, PTO+PT_R1; /* Store user SP. */ \
555 addi r11, r0, 1; \
556 swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode.*/\
5572: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); \
558 /* Save away the syscall number. */ \
559 swi r0, r1, PTO+PT_R0; \
560 tovirt(r1,r1)
561
562C_ENTRY(full_exception_trap): 473C_ENTRY(full_exception_trap):
563 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
564 /* adjust exception address for privileged instruction 474 /* adjust exception address for privileged instruction
565 * for finding where is it */ 475 * for finding where is it */
566 addik r17, r17, -4 476 addik r17, r17, -4
567 SAVE_STATE /* Save registers */ 477 SAVE_STATE /* Save registers */
478 /* PC, before IRQ/trap - this is one instruction above */
479 swi r17, r1, PTO+PT_PC;
480 tovirt(r1,r1)
568 /* FIXME this can be store directly in PT_ESR reg. 481 /* FIXME this can be store directly in PT_ESR reg.
569 * I tested it but there is a fault */ 482 * I tested it but there is a fault */
570 /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 483 /* where the trap should return need -8 to adjust for rtsd r15, 8 */
571 la r15, r0, ret_from_exc - 8 484 addik r15, r0, ret_from_exc - 8
572 la r5, r1, PTO /* parameter struct pt_regs * regs */
573 mfs r6, resr 485 mfs r6, resr
574 nop
575 mfs r7, rfsr; /* save FSR */ 486 mfs r7, rfsr; /* save FSR */
576 nop
577 mts rfsr, r0; /* Clear sticky fsr */ 487 mts rfsr, r0; /* Clear sticky fsr */
578 nop 488 rted r0, full_exception
579 la r12, r0, full_exception 489 addik r5, r1, PTO /* parameter struct pt_regs * regs */
580 set_vms;
581 rtbd r12, 0;
582 nop;
583 490
584/* 491/*
585 * Unaligned data trap. 492 * Unaligned data trap.
@@ -592,19 +499,27 @@ C_ENTRY(full_exception_trap):
592 * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S" 499 * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S"
593 */ 500 */
594C_ENTRY(unaligned_data_trap): 501C_ENTRY(unaligned_data_trap):
595 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ 502 /* MS: I have to save r11 value and then restore it because
503 * set_bit, clear_eip, set_ee use r11 as temp register if MSR
504 * instructions are not used. We don't need to do if MSR instructions
505 * are used and they use r0 instead of r11.
506 * I am using ENTRY_SP which should be primary used only for stack
507 * pointer saving. */
508 swi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
509 set_bip; /* equalize initial state for all possible entries */
510 clear_eip;
511 set_ee;
512 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
596 SAVE_STATE /* Save registers.*/ 513 SAVE_STATE /* Save registers.*/
514 /* PC, before IRQ/trap - this is one instruction above */
515 swi r17, r1, PTO+PT_PC;
516 tovirt(r1,r1)
597 /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 517 /* where the trap should return need -8 to adjust for rtsd r15, 8 */
598 la r15, r0, ret_from_exc-8 518 addik r15, r0, ret_from_exc-8
599 mfs r3, resr /* ESR */ 519 mfs r3, resr /* ESR */
600 nop
601 mfs r4, rear /* EAR */ 520 mfs r4, rear /* EAR */
602 nop 521 rtbd r0, _unaligned_data_exception
603 la r7, r1, PTO /* parameter struct pt_regs * regs */ 522 addik r7, r1, PTO /* parameter struct pt_regs * regs */
604 la r12, r0, _unaligned_data_exception
605 set_vms;
606 rtbd r12, 0; /* interrupts enabled */
607 nop;
608 523
609/* 524/*
610 * Page fault traps. 525 * Page fault traps.
@@ -625,38 +540,32 @@ C_ENTRY(unaligned_data_trap):
625 */ 540 */
626/* data and intruction trap - which is choose is resolved int fault.c */ 541/* data and intruction trap - which is choose is resolved int fault.c */
627C_ENTRY(page_fault_data_trap): 542C_ENTRY(page_fault_data_trap):
628 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
629 SAVE_STATE /* Save registers.*/ 543 SAVE_STATE /* Save registers.*/
544 /* PC, before IRQ/trap - this is one instruction above */
545 swi r17, r1, PTO+PT_PC;
546 tovirt(r1,r1)
630 /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 547 /* where the trap should return need -8 to adjust for rtsd r15, 8 */
631 la r15, r0, ret_from_exc-8 548 addik r15, r0, ret_from_exc-8
632 la r5, r1, PTO /* parameter struct pt_regs * regs */
633 mfs r6, rear /* parameter unsigned long address */ 549 mfs r6, rear /* parameter unsigned long address */
634 nop
635 mfs r7, resr /* parameter unsigned long error_code */ 550 mfs r7, resr /* parameter unsigned long error_code */
636 nop 551 rted r0, do_page_fault
637 la r12, r0, do_page_fault 552 addik r5, r1, PTO /* parameter struct pt_regs * regs */
638 set_vms;
639 rtbd r12, 0; /* interrupts enabled */
640 nop;
641 553
642C_ENTRY(page_fault_instr_trap): 554C_ENTRY(page_fault_instr_trap):
643 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
644 SAVE_STATE /* Save registers.*/ 555 SAVE_STATE /* Save registers.*/
556 /* PC, before IRQ/trap - this is one instruction above */
557 swi r17, r1, PTO+PT_PC;
558 tovirt(r1,r1)
645 /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 559 /* where the trap should return need -8 to adjust for rtsd r15, 8 */
646 la r15, r0, ret_from_exc-8 560 addik r15, r0, ret_from_exc-8
647 la r5, r1, PTO /* parameter struct pt_regs * regs */
648 mfs r6, rear /* parameter unsigned long address */ 561 mfs r6, rear /* parameter unsigned long address */
649 nop
650 ori r7, r0, 0 /* parameter unsigned long error_code */ 562 ori r7, r0, 0 /* parameter unsigned long error_code */
651 la r12, r0, do_page_fault 563 rted r0, do_page_fault
652 set_vms; 564 addik r5, r1, PTO /* parameter struct pt_regs * regs */
653 rtbd r12, 0; /* interrupts enabled */
654 nop;
655 565
656/* Entry point used to return from an exception. */ 566/* Entry point used to return from an exception. */
657C_ENTRY(ret_from_exc): 567C_ENTRY(ret_from_exc):
658 set_bip; /* Ints masked for state restore*/ 568 lwi r11, r1, PTO + PT_MODE;
659 lwi r11, r1, PTO+PT_MODE;
660 bnei r11, 2f; /* See if returning to kernel mode, */ 569 bnei r11, 2f; /* See if returning to kernel mode, */
661 /* ... if so, skip resched &c. */ 570 /* ... if so, skip resched &c. */
662 571
@@ -687,32 +596,27 @@ C_ENTRY(ret_from_exc):
687 * traps), but signal handlers may want to examine or change the 596 * traps), but signal handlers may want to examine or change the
688 * complete register state. Here we save anything not saved by 597 * complete register state. Here we save anything not saved by
689 * the normal entry sequence, so that it may be safely restored 598 * the normal entry sequence, so that it may be safely restored
690 * (in a possibly modified form) after do_signal returns. 599 * (in a possibly modified form) after do_signal returns. */
691 * store return registers separately because this macros is use 600 addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
692 * for others exceptions */
693 la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
694 addi r7, r0, 0; /* Arg 3: int in_syscall */ 601 addi r7, r0, 0; /* Arg 3: int in_syscall */
695 bralid r15, do_signal; /* Handle any signals */ 602 bralid r15, do_signal; /* Handle any signals */
696 add r6, r0, r0; /* Arg 2: sigset_t *oldset */ 603 add r6, r0, r0; /* Arg 2: sigset_t *oldset */
697 604
698/* Finally, return to user state. */ 605/* Finally, return to user state. */
6991: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ 6061: set_bip; /* Ints masked for state restore */
700 swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 607 swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
701 VM_OFF; 608 VM_OFF;
702 tophys(r1,r1); 609 tophys(r1,r1);
703 610
704 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
705 lwi r4, r1, PTO+PT_R4;
706 RESTORE_REGS; 611 RESTORE_REGS;
707 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ 612 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */
708 613
709 lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */ 614 lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
710 bri 6f; 615 bri 6f;
711/* Return to kernel state. */ 616/* Return to kernel state. */
7122: VM_OFF; 6172: set_bip; /* Ints masked for state restore */
618 VM_OFF;
713 tophys(r1,r1); 619 tophys(r1,r1);
714 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
715 lwi r4, r1, PTO+PT_R4;
716 RESTORE_REGS; 620 RESTORE_REGS;
717 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ 621 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */
718 622
@@ -736,36 +640,23 @@ C_ENTRY(_interrupt):
736/* MS: we are in physical address */ 640/* MS: we are in physical address */
737/* Save registers, switch to proper stack, convert SP to virtual.*/ 641/* Save registers, switch to proper stack, convert SP to virtual.*/
738 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) 642 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
739 swi r11, r0, TOPHYS(PER_CPU(R11_SAVE));
740 /* MS: See if already in kernel mode. */ 643 /* MS: See if already in kernel mode. */
741 lwi r11, r0, TOPHYS(PER_CPU(KM)); 644 mfs r1, rmsr
742 beqi r11, 1f; /* MS: Jump ahead if coming from user */ 645 nop
646 andi r1, r1, MSR_UMS
647 bnei r1, 1f
743 648
744/* Kernel-mode state save. */ 649/* Kernel-mode state save. */
745 or r11, r1, r0 650 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
746 tophys(r1,r11); /* MS: I have in r1 physical address where stack is */ 651 tophys(r1,r1); /* MS: I have in r1 physical address where stack is */
747/* MS: Save original SP - position PT_R1 to next stack frame 4 *1 - 152*/
748 swi r11, r1, (PT_R1 - PT_SIZE);
749/* MS: restore r11 because of saving in SAVE_REGS */
750 lwi r11, r0, TOPHYS(PER_CPU(R11_SAVE));
751 /* save registers */ 652 /* save registers */
752/* MS: Make room on the stack -> activation record */ 653/* MS: Make room on the stack -> activation record */
753 addik r1, r1, -STATE_SAVE_SIZE; 654 addik r1, r1, -STATE_SAVE_SIZE;
754/* MS: store return registers separately because
755 * this macros is use for others exceptions */
756 swi r3, r1, PTO + PT_R3;
757 swi r4, r1, PTO + PT_R4;
758 SAVE_REGS 655 SAVE_REGS
759 /* MS: store mode */
760 addi r11, r0, 1; /* MS: Was in kernel-mode. */
761 swi r11, r1, PTO + PT_MODE; /* MS: and save it */
762 brid 2f; 656 brid 2f;
763 nop; /* MS: Fill delay slot */ 657 swi r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */
764
7651: 6581:
766/* User-mode state save. */ 659/* User-mode state save. */
767/* MS: restore r11 -> FIXME move before SAVE_REG */
768 lwi r11, r0, TOPHYS(PER_CPU(R11_SAVE));
769 /* MS: get the saved current */ 660 /* MS: get the saved current */
770 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 661 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
771 tophys(r1,r1); 662 tophys(r1,r1);
@@ -774,27 +665,18 @@ C_ENTRY(_interrupt):
774 tophys(r1,r1); 665 tophys(r1,r1);
775 /* save registers */ 666 /* save registers */
776 addik r1, r1, -STATE_SAVE_SIZE; 667 addik r1, r1, -STATE_SAVE_SIZE;
777 swi r3, r1, PTO+PT_R3;
778 swi r4, r1, PTO+PT_R4;
779 SAVE_REGS 668 SAVE_REGS
780 /* calculate mode */ 669 /* calculate mode */
781 swi r0, r1, PTO + PT_MODE; 670 swi r0, r1, PTO + PT_MODE;
782 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 671 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
783 swi r11, r1, PTO+PT_R1; 672 swi r11, r1, PTO+PT_R1;
784 /* setup kernel mode to KM */ 673 clear_ums;
785 addi r11, r0, 1;
786 swi r11, r0, TOPHYS(PER_CPU(KM));
787
7882: 6742:
789 lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 675 lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
790 swi r0, r1, PTO + PT_R0;
791 tovirt(r1,r1) 676 tovirt(r1,r1)
792 la r5, r1, PTO; 677 addik r15, r0, irq_call;
793 set_vms; 678irq_call:rtbd r0, do_IRQ;
794 la r11, r0, do_IRQ; 679 addik r5, r1, PTO;
795 la r15, r0, irq_call;
796irq_call:rtbd r11, 0;
797 nop;
798 680
799/* MS: we are in virtual mode */ 681/* MS: we are in virtual mode */
800ret_from_irq: 682ret_from_irq:
@@ -815,7 +697,7 @@ ret_from_irq:
815 beqid r11, no_intr_resched 697 beqid r11, no_intr_resched
816/* Handle a signal return; Pending signals should be in r18. */ 698/* Handle a signal return; Pending signals should be in r18. */
817 addi r7, r0, 0; /* Arg 3: int in_syscall */ 699 addi r7, r0, 0; /* Arg 3: int in_syscall */
818 la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ 700 addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
819 bralid r15, do_signal; /* Handle any signals */ 701 bralid r15, do_signal; /* Handle any signals */
820 add r6, r0, r0; /* Arg 2: sigset_t *oldset */ 702 add r6, r0, r0; /* Arg 2: sigset_t *oldset */
821 703
@@ -823,12 +705,9 @@ ret_from_irq:
823no_intr_resched: 705no_intr_resched:
824 /* Disable interrupts, we are now committed to the state restore */ 706 /* Disable interrupts, we are now committed to the state restore */
825 disable_irq 707 disable_irq
826 swi r0, r0, PER_CPU(KM); /* MS: Now officially in user state. */
827 swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); 708 swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE);
828 VM_OFF; 709 VM_OFF;
829 tophys(r1,r1); 710 tophys(r1,r1);
830 lwi r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */
831 lwi r4, r1, PTO + PT_R4;
832 RESTORE_REGS 711 RESTORE_REGS
833 addik r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */ 712 addik r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
834 lwi r1, r1, PT_R1 - PT_SIZE; 713 lwi r1, r1, PT_R1 - PT_SIZE;
@@ -857,8 +736,6 @@ restore:
857#endif 736#endif
858 VM_OFF /* MS: turn off MMU */ 737 VM_OFF /* MS: turn off MMU */
859 tophys(r1,r1) 738 tophys(r1,r1)
860 lwi r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */
861 lwi r4, r1, PTO + PT_R4;
862 RESTORE_REGS 739 RESTORE_REGS
863 addik r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */ 740 addik r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
864 tovirt(r1,r1); 741 tovirt(r1,r1);
@@ -868,86 +745,91 @@ IRQ_return: /* MS: Make global symbol for debugging */
868 nop 745 nop
869 746
870/* 747/*
871 * `Debug' trap 748 * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18
872 * We enter dbtrap in "BIP" (breakpoint) mode. 749 * and call handling function with saved pt_regs
873 * So we exit the breakpoint mode with an 'rtbd' and proceed with the
874 * original dbtrap.
875 * however, wait to save state first
876 */ 750 */
877C_ENTRY(_debug_exception): 751C_ENTRY(_debug_exception):
878 /* BIP bit is set on entry, no interrupts can occur */ 752 /* BIP bit is set on entry, no interrupts can occur */
879 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) 753 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
880 754
881 swi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */ 755 mfs r1, rmsr
882 set_bip; /*equalize initial state for all possible entries*/ 756 nop
883 clear_eip; 757 andi r1, r1, MSR_UMS
884 enable_irq; 758 bnei r1, 1f
885 lwi r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/ 759/* MS: Kernel-mode state save - kgdb */
886 beqi r11, 1f; /* Jump ahead if coming from user */ 760 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
887 /* Kernel-mode state save. */
888 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
889 tophys(r1,r11);
890 swi r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */
891 lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
892 761
893 addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ 762 /* BIP bit is set on entry, no interrupts can occur */
894 swi r3, r1, PTO + PT_R3; 763 addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
895 swi r4, r1, PTO + PT_R4;
896 SAVE_REGS; 764 SAVE_REGS;
765 /* save all regs to pt_reg structure */
766 swi r0, r1, PTO+PT_R0; /* R0 must be saved too */
767 swi r14, r1, PTO+PT_R14 /* rewrite saved R14 value */
768 swi r16, r1, PTO+PT_R16
769 swi r16, r1, PTO+PT_PC; /* PC and r16 are the same */
770 swi r17, r1, PTO+PT_R17
771 /* save special purpose registers to pt_regs */
772 mfs r11, rear;
773 swi r11, r1, PTO+PT_EAR;
774 mfs r11, resr;
775 swi r11, r1, PTO+PT_ESR;
776 mfs r11, rfsr;
777 swi r11, r1, PTO+PT_FSR;
778
779 /* stack pointer is in physical address at it is decrease
780 * by STATE_SAVE_SIZE but we need to get correct R1 value */
781 addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE;
782 swi r11, r1, PTO+PT_R1
783 /* MS: r31 - current pointer isn't changed */
784 tovirt(r1,r1)
785#ifdef CONFIG_KGDB
786 addi r5, r1, PTO /* pass pt_reg address as the first arg */
787 la r15, r0, dbtrap_call; /* return address */
788 rtbd r0, microblaze_kgdb_break
789 nop;
790#endif
791 /* MS: Place handler for brki from kernel space if KGDB is OFF.
792 * It is very unlikely that another brki instruction is called. */
793 bri 0
897 794
898 addi r11, r0, 1; /* Was in kernel-mode. */ 795/* MS: User-mode state save - gdb */
899 swi r11, r1, PTO + PT_MODE; 7961: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
900 brid 2f;
901 nop; /* Fill delay slot */
9021: /* User-mode state save. */
903 lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */
904 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
905 tophys(r1,r1); 797 tophys(r1,r1);
906 lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ 798 lwi r1, r1, TS_THREAD_INFO; /* get the thread info */
907 addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */ 799 addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */
908 tophys(r1,r1); 800 tophys(r1,r1);
909 801
910 addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ 802 addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
911 swi r3, r1, PTO + PT_R3;
912 swi r4, r1, PTO + PT_R4;
913 SAVE_REGS; 803 SAVE_REGS;
914 804 swi r17, r1, PTO+PT_R17;
915 swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */ 805 swi r16, r1, PTO+PT_R16;
806 swi r16, r1, PTO+PT_PC; /* Save LP */
807 swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */
916 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 808 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
917 swi r11, r1, PTO+PT_R1; /* Store user SP. */ 809 swi r11, r1, PTO+PT_R1; /* Store user SP. */
918 addi r11, r0, 1; 810 lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
919 swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode. */
9202: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
921 /* Save away the syscall number. */
922 swi r0, r1, PTO+PT_R0;
923 tovirt(r1,r1) 811 tovirt(r1,r1)
924
925 addi r5, r0, SIGTRAP /* send the trap signal */
926 add r6, r0, CURRENT_TASK; /* Get current task ptr into r11 */
927 addk r7, r0, r0 /* 3rd param zero */
928
929 set_vms; 812 set_vms;
930 la r11, r0, send_sig; 813 addik r5, r1, PTO;
931 la r15, r0, dbtrap_call; 814 addik r15, r0, dbtrap_call;
932dbtrap_call: rtbd r11, 0; 815dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
933 nop; 816 rtbd r0, sw_exception
817 nop
934 818
935 set_bip; /* Ints masked for state restore*/ 819 /* MS: The first instruction for the second part of the gdb/kgdb */
936 lwi r11, r1, PTO+PT_MODE; 820 set_bip; /* Ints masked for state restore */
821 lwi r11, r1, PTO + PT_MODE;
937 bnei r11, 2f; 822 bnei r11, 2f;
938 823/* MS: Return to user space - gdb */
939 /* Get current task ptr into r11 */ 824 /* Get current task ptr into r11 */
940 lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 825 lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
941 lwi r11, r11, TI_FLAGS; /* get flags in thread info */ 826 lwi r11, r11, TI_FLAGS; /* get flags in thread info */
942 andi r11, r11, _TIF_NEED_RESCHED; 827 andi r11, r11, _TIF_NEED_RESCHED;
943 beqi r11, 5f; 828 beqi r11, 5f;
944 829
945/* Call the scheduler before returning from a syscall/trap. */ 830 /* Call the scheduler before returning from a syscall/trap. */
946
947 bralid r15, schedule; /* Call scheduler */ 831 bralid r15, schedule; /* Call scheduler */
948 nop; /* delay slot */ 832 nop; /* delay slot */
949 /* XXX Is PT_DTRACE handling needed here? */
950 /* XXX m68knommu also checks TASK_STATE & TASK_COUNTER here. */
951 833
952 /* Maybe handle a signal */ 834 /* Maybe handle a signal */
9535: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 8355: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
@@ -955,54 +837,40 @@ dbtrap_call: rtbd r11, 0;
955 andi r11, r11, _TIF_SIGPENDING; 837 andi r11, r11, _TIF_SIGPENDING;
956 beqi r11, 1f; /* Signals to handle, handle them */ 838 beqi r11, 1f; /* Signals to handle, handle them */
957 839
958/* Handle a signal return; Pending signals should be in r18. */ 840 addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
959 /* Not all registers are saved by the normal trap/interrupt entry
960 points (for instance, call-saved registers (because the normal
961 C-compiler calling sequence in the kernel makes sure they're
962 preserved), and call-clobbered registers in the case of
963 traps), but signal handlers may want to examine or change the
964 complete register state. Here we save anything not saved by
965 the normal entry sequence, so that it may be safely restored
966 (in a possibly modified form) after do_signal returns. */
967
968 la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
969 addi r7, r0, 0; /* Arg 3: int in_syscall */ 841 addi r7, r0, 0; /* Arg 3: int in_syscall */
970 bralid r15, do_signal; /* Handle any signals */ 842 bralid r15, do_signal; /* Handle any signals */
971 add r6, r0, r0; /* Arg 2: sigset_t *oldset */ 843 add r6, r0, r0; /* Arg 2: sigset_t *oldset */
972 844
973
974/* Finally, return to user state. */ 845/* Finally, return to user state. */
9751: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ 8461: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
976 swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
977 VM_OFF; 847 VM_OFF;
978 tophys(r1,r1); 848 tophys(r1,r1);
979 849 /* MS: Restore all regs */
980 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
981 lwi r4, r1, PTO+PT_R4;
982 RESTORE_REGS 850 RESTORE_REGS
983 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ 851 lwi r17, r1, PTO+PT_R17;
984 852 lwi r16, r1, PTO+PT_R16;
985 853 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space */
986 lwi r1, r1, PT_R1 - PT_SIZE; 854 lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
987 /* Restore user stack pointer. */ 855DBTRAP_return_user: /* MS: Make global symbol for debugging */
988 bri 6f; 856 rtbd r16, 0; /* MS: Instructions to return from a debug trap */
857 nop;
989 858
990/* Return to kernel state. */ 859/* MS: Return to kernel state - kgdb */
9912: VM_OFF; 8602: VM_OFF;
992 tophys(r1,r1); 861 tophys(r1,r1);
993 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ 862 /* MS: Restore all regs */
994 lwi r4, r1, PTO+PT_R4;
995 RESTORE_REGS 863 RESTORE_REGS
996 addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ 864 lwi r14, r1, PTO+PT_R14;
997 865 lwi r16, r1, PTO+PT_PC;
866 lwi r17, r1, PTO+PT_R17;
867 addik r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
998 tovirt(r1,r1); 868 tovirt(r1,r1);
9996: 869DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
1000DBTRAP_return: /* Make global symbol for debugging */ 870 rtbd r16, 0; /* MS: Instructions to return from a debug trap */
1001 rtbd r14, 0; /* Instructions to return from an IRQ */
1002 nop; 871 nop;
1003 872
1004 873
1005
1006ENTRY(_switch_to) 874ENTRY(_switch_to)
1007 /* prepare return value */ 875 /* prepare return value */
1008 addk r3, r0, CURRENT_TASK 876 addk r3, r0, CURRENT_TASK
@@ -1037,16 +905,12 @@ ENTRY(_switch_to)
1037 swi r30, r11, CC_R30 905 swi r30, r11, CC_R30
1038 /* special purpose registers */ 906 /* special purpose registers */
1039 mfs r12, rmsr 907 mfs r12, rmsr
1040 nop
1041 swi r12, r11, CC_MSR 908 swi r12, r11, CC_MSR
1042 mfs r12, rear 909 mfs r12, rear
1043 nop
1044 swi r12, r11, CC_EAR 910 swi r12, r11, CC_EAR
1045 mfs r12, resr 911 mfs r12, resr
1046 nop
1047 swi r12, r11, CC_ESR 912 swi r12, r11, CC_ESR
1048 mfs r12, rfsr 913 mfs r12, rfsr
1049 nop
1050 swi r12, r11, CC_FSR 914 swi r12, r11, CC_FSR
1051 915
1052 /* update r31, the current-give me pointer to task which will be next */ 916 /* update r31, the current-give me pointer to task which will be next */
@@ -1085,10 +949,8 @@ ENTRY(_switch_to)
1085 /* special purpose registers */ 949 /* special purpose registers */
1086 lwi r12, r11, CC_FSR 950 lwi r12, r11, CC_FSR
1087 mts rfsr, r12 951 mts rfsr, r12
1088 nop
1089 lwi r12, r11, CC_MSR 952 lwi r12, r11, CC_MSR
1090 mts rmsr, r12 953 mts rmsr, r12
1091 nop
1092 954
1093 rtsd r15, 8 955 rtsd r15, 8
1094 nop 956 nop
@@ -1096,15 +958,6 @@ ENTRY(_switch_to)
1096ENTRY(_reset) 958ENTRY(_reset)
1097 brai 0x70; /* Jump back to FS-boot */ 959 brai 0x70; /* Jump back to FS-boot */
1098 960
1099ENTRY(_break)
1100 mfs r5, rmsr
1101 nop
1102 swi r5, r0, 0x250 + TOPHYS(r0_ram)
1103 mfs r5, resr
1104 nop
1105 swi r5, r0, 0x254 + TOPHYS(r0_ram)
1106 bri 0
1107
1108 /* These are compiled and loaded into high memory, then 961 /* These are compiled and loaded into high memory, then
1109 * copied into place in mach_early_setup */ 962 * copied into place in mach_early_setup */
1110 .section .init.ivt, "ax" 963 .section .init.ivt, "ax"
@@ -1116,14 +969,38 @@ ENTRY(_break)
1116 nop 969 nop
1117 brai TOPHYS(_user_exception); /* syscall handler */ 970 brai TOPHYS(_user_exception); /* syscall handler */
1118 brai TOPHYS(_interrupt); /* Interrupt handler */ 971 brai TOPHYS(_interrupt); /* Interrupt handler */
1119 brai TOPHYS(_break); /* nmi trap handler */ 972 brai TOPHYS(_debug_exception); /* debug trap handler */
1120 brai TOPHYS(_hw_exception_handler); /* HW exception handler */ 973 brai TOPHYS(_hw_exception_handler); /* HW exception handler */
1121 974
1122 .org 0x60
1123 brai TOPHYS(_debug_exception); /* debug trap handler*/
1124
1125.section .rodata,"a" 975.section .rodata,"a"
1126#include "syscall_table.S" 976#include "syscall_table.S"
1127 977
1128syscall_table_size=(.-sys_call_table) 978syscall_table_size=(.-sys_call_table)
1129 979
980type_SYSCALL:
981 .ascii "SYSCALL\0"
982type_IRQ:
983 .ascii "IRQ\0"
984type_IRQ_PREEMPT:
985 .ascii "IRQ (PREEMPTED)\0"
986type_SYSCALL_PREEMPT:
987 .ascii " SYSCALL (PREEMPTED)\0"
988
989 /*
990 * Trap decoding for stack unwinder
991 * Tuples are (start addr, end addr, string)
992 * If return address lies on [start addr, end addr],
993 * unwinder displays 'string'
994 */
995
996 .align 4
997.global microblaze_trap_handlers
998microblaze_trap_handlers:
999 /* Exact matches come first */
1000 .word ret_from_trap; .word ret_from_trap ; .word type_SYSCALL
1001 .word ret_from_irq ; .word ret_from_irq ; .word type_IRQ
1002 /* Fuzzy matches go here */
1003 .word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT
1004 .word ret_from_trap; .word TRAP_return ; .word type_SYSCALL_PREEMPT
1005 /* End of table */
1006 .word 0 ; .word 0 ; .word 0
diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c
index 02cbdfe5aa8d..b98ee8d0c1cd 100644
--- a/arch/microblaze/kernel/exceptions.c
+++ b/arch/microblaze/kernel/exceptions.c
@@ -48,12 +48,17 @@ void die(const char *str, struct pt_regs *fp, long err)
48 do_exit(err); 48 do_exit(err);
49} 49}
50 50
51/* for user application debugging */
52void sw_exception(struct pt_regs *regs)
53{
54 _exception(SIGTRAP, regs, TRAP_BRKPT, regs->r16);
55}
56
51void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) 57void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
52{ 58{
53 siginfo_t info; 59 siginfo_t info;
54 60
55 if (kernel_mode(regs)) { 61 if (kernel_mode(regs)) {
56 debugger(regs);
57 die("Exception in kernel mode", regs, signr); 62 die("Exception in kernel mode", regs, signr);
58 } 63 }
59 info.si_signo = signr; 64 info.si_signo = signr;
@@ -143,7 +148,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
143#ifdef CONFIG_MMU 148#ifdef CONFIG_MMU
144 case MICROBLAZE_PRIVILEGED_EXCEPTION: 149 case MICROBLAZE_PRIVILEGED_EXCEPTION:
145 pr_debug(KERN_WARNING "Privileged exception\n"); 150 pr_debug(KERN_WARNING "Privileged exception\n");
146 /* "brk r0,r0" - used as debug breakpoint */ 151 /* "brk r0,r0" - used as debug breakpoint - old toolchain */
147 if (get_user(code, (unsigned long *)regs->pc) == 0 152 if (get_user(code, (unsigned long *)regs->pc) == 0
148 && code == 0x980c0000) { 153 && code == 0x980c0000) {
149 _exception(SIGTRAP, regs, TRAP_BRKPT, addr); 154 _exception(SIGTRAP, regs, TRAP_BRKPT, addr);
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S
index 1bf739888260..42434008209e 100644
--- a/arch/microblaze/kernel/head.S
+++ b/arch/microblaze/kernel/head.S
@@ -43,10 +43,10 @@
43.global empty_zero_page 43.global empty_zero_page
44.align 12 44.align 12
45empty_zero_page: 45empty_zero_page:
46 .space 4096 46 .space PAGE_SIZE
47.global swapper_pg_dir 47.global swapper_pg_dir
48swapper_pg_dir: 48swapper_pg_dir:
49 .space 4096 49 .space PAGE_SIZE
50 50
51#endif /* CONFIG_MMU */ 51#endif /* CONFIG_MMU */
52 52
diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S
index 995a2123635b..781195438ee6 100644
--- a/arch/microblaze/kernel/hw_exception_handler.S
+++ b/arch/microblaze/kernel/hw_exception_handler.S
@@ -78,9 +78,6 @@
78#include <asm/asm-offsets.h> 78#include <asm/asm-offsets.h>
79 79
80/* Helpful Macros */ 80/* Helpful Macros */
81#ifndef CONFIG_MMU
82#define EX_HANDLER_STACK_SIZ (4*19)
83#endif
84#define NUM_TO_REG(num) r ## num 81#define NUM_TO_REG(num) r ## num
85 82
86#ifdef CONFIG_MMU 83#ifdef CONFIG_MMU
@@ -988,6 +985,7 @@ ex_unaligned_fixup:
988.end _unaligned_data_exception 985.end _unaligned_data_exception
989#endif /* CONFIG_MMU */ 986#endif /* CONFIG_MMU */
990 987
988.global ex_handler_unhandled
991ex_handler_unhandled: 989ex_handler_unhandled:
992/* FIXME add handle function for unhandled exception - dump register */ 990/* FIXME add handle function for unhandled exception - dump register */
993 bri 0 991 bri 0
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index 8f120aca123d..a9345fb4906a 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -17,26 +17,17 @@
17#include <linux/seq_file.h> 17#include <linux/seq_file.h>
18#include <linux/kernel_stat.h> 18#include <linux/kernel_stat.h>
19#include <linux/irq.h> 19#include <linux/irq.h>
20#include <linux/of_irq.h>
20 21
21#include <asm/prom.h> 22#include <asm/prom.h>
22 23
23unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
24{
25 struct of_irq oirq;
26
27 if (of_irq_map_one(dev, index, &oirq))
28 return NO_IRQ;
29
30 return oirq.specifier[0];
31}
32EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
33
34static u32 concurrent_irq; 24static u32 concurrent_irq;
35 25
36void __irq_entry do_IRQ(struct pt_regs *regs) 26void __irq_entry do_IRQ(struct pt_regs *regs)
37{ 27{
38 unsigned int irq; 28 unsigned int irq;
39 struct pt_regs *old_regs = set_irq_regs(regs); 29 struct pt_regs *old_regs = set_irq_regs(regs);
30 trace_hardirqs_off();
40 31
41 irq_enter(); 32 irq_enter();
42 irq = get_irq(regs); 33 irq = get_irq(regs);
@@ -53,6 +44,7 @@ next_irq:
53 44
54 irq_exit(); 45 irq_exit();
55 set_irq_regs(old_regs); 46 set_irq_regs(old_regs);
47 trace_hardirqs_on();
56} 48}
57 49
58int show_interrupts(struct seq_file *p, void *v) 50int show_interrupts(struct seq_file *p, void *v)
@@ -104,7 +96,7 @@ unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)
104EXPORT_SYMBOL_GPL(irq_create_mapping); 96EXPORT_SYMBOL_GPL(irq_create_mapping);
105 97
106unsigned int irq_create_of_mapping(struct device_node *controller, 98unsigned int irq_create_of_mapping(struct device_node *controller,
107 u32 *intspec, unsigned int intsize) 99 const u32 *intspec, unsigned int intsize)
108{ 100{
109 return intspec[0]; 101 return intspec[0];
110} 102}
diff --git a/arch/microblaze/kernel/kgdb.c b/arch/microblaze/kernel/kgdb.c
new file mode 100644
index 000000000000..bfc006b7f2d8
--- /dev/null
+++ b/arch/microblaze/kernel/kgdb.c
@@ -0,0 +1,147 @@
1/*
2 * Microblaze KGDB support
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 */
8
9#include <linux/kgdb.h>
10#include <linux/kdebug.h>
11#include <linux/irq.h>
12#include <linux/io.h>
13#include <asm/cacheflush.h>
14#include <asm/asm-offsets.h>
15#include <asm/pvr.h>
16
17#define GDB_REG 0
18#define GDB_PC 32
19#define GDB_MSR 33
20#define GDB_EAR 34
21#define GDB_ESR 35
22#define GDB_FSR 36
23#define GDB_BTR 37
24#define GDB_PVR 38
25#define GDB_REDR 50
26#define GDB_RPID 51
27#define GDB_RZPR 52
28#define GDB_RTLBX 53
29#define GDB_RTLBSX 54 /* mfs can't read it */
30#define GDB_RTLBLO 55
31#define GDB_RTLBHI 56
32
33/* keep pvr separately because it is unchangeble */
34struct pvr_s pvr;
35
36void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
37{
38 int i;
39 unsigned long *pt_regb = (unsigned long *)regs;
40 int temp;
41 /* registers r0 - r31, pc, msr, ear, esr, fsr + do not save pt_mode */
42 for (i = 0; i < (sizeof(struct pt_regs) / 4) - 1; i++)
43 gdb_regs[i] = pt_regb[i];
44
45 /* Branch target register can't be changed */
46 __asm__ __volatile__ ("mfs %0, rbtr;" : "=r"(temp) : );
47 gdb_regs[GDB_BTR] = temp;
48
49 /* pvr part - we have 11 pvr regs */
50 for (i = 0; i < sizeof(struct pvr_s)/4; i++)
51 gdb_regs[GDB_PVR + i] = pvr.pvr[i];
52
53 /* read special registers - can't be changed */
54 __asm__ __volatile__ ("mfs %0, redr;" : "=r"(temp) : );
55 gdb_regs[GDB_REDR] = temp;
56 __asm__ __volatile__ ("mfs %0, rpid;" : "=r"(temp) : );
57 gdb_regs[GDB_RPID] = temp;
58 __asm__ __volatile__ ("mfs %0, rzpr;" : "=r"(temp) : );
59 gdb_regs[GDB_RZPR] = temp;
60 __asm__ __volatile__ ("mfs %0, rtlbx;" : "=r"(temp) : );
61 gdb_regs[GDB_RTLBX] = temp;
62 __asm__ __volatile__ ("mfs %0, rtlblo;" : "=r"(temp) : );
63 gdb_regs[GDB_RTLBLO] = temp;
64 __asm__ __volatile__ ("mfs %0, rtlbhi;" : "=r"(temp) : );
65 gdb_regs[GDB_RTLBHI] = temp;
66}
67
68void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
69{
70 int i;
71 unsigned long *pt_regb = (unsigned long *)regs;
72
73 /* pt_regs and gdb_regs have the same 37 values.
74 * The rest of gdb_regs are unused and can't be changed.
75 * r0 register value can't be changed too. */
76 for (i = 1; i < (sizeof(struct pt_regs) / 4) - 1; i++)
77 pt_regb[i] = gdb_regs[i];
78}
79
80void microblaze_kgdb_break(struct pt_regs *regs)
81{
82 if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0)
83 return 0;
84
85 /* Jump over the first arch_kgdb_breakpoint which is barrier to
86 * get kgdb work. The same solution is used for powerpc */
87 if (*(u32 *) (regs->pc) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
88 regs->pc += BREAK_INSTR_SIZE;
89}
90
91/* untested */
92void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
93{
94 int i;
95 unsigned long *pt_regb = (unsigned long *)(p->thread.regs);
96
97 /* registers r0 - r31, pc, msr, ear, esr, fsr + do not save pt_mode */
98 for (i = 0; i < (sizeof(struct pt_regs) / 4) - 1; i++)
99 gdb_regs[i] = pt_regb[i];
100
101 /* pvr part - we have 11 pvr regs */
102 for (i = 0; i < sizeof(struct pvr_s)/4; i++)
103 gdb_regs[GDB_PVR + i] = pvr.pvr[i];
104}
105
106void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
107{
108 regs->pc = ip;
109}
110
111int kgdb_arch_handle_exception(int vector, int signo, int err_code,
112 char *remcom_in_buffer, char *remcom_out_buffer,
113 struct pt_regs *regs)
114{
115 char *ptr;
116 unsigned long address;
117 int cpu = smp_processor_id();
118
119 switch (remcom_in_buffer[0]) {
120 case 'c':
121 /* handle the optional parameter */
122 ptr = &remcom_in_buffer[1];
123 if (kgdb_hex2long(&ptr, &address))
124 regs->pc = address;
125
126 return 0;
127 }
128 return -1; /* this means that we do not want to exit from the handler */
129}
130
131int kgdb_arch_init(void)
132{
133 get_pvr(&pvr); /* Fill PVR structure */
134 return 0;
135}
136
137void kgdb_arch_exit(void)
138{
139 /* Nothing to do */
140}
141
142/*
143 * Global data
144 */
145struct kgdb_arch arch_kgdb_ops = {
146 .gdb_bpt_instr = {0xba, 0x0c, 0x00, 0x18}, /* brki r16, 0x18 */
147};
diff --git a/arch/microblaze/kernel/misc.S b/arch/microblaze/kernel/misc.S
index 0fb5fc6c1fc2..206da3da361f 100644
--- a/arch/microblaze/kernel/misc.S
+++ b/arch/microblaze/kernel/misc.S
@@ -76,7 +76,7 @@ early_console_reg_tlb_alloc:
76 * the UARTs nice and early. We use a 4k real==virtual mapping. 76 * the UARTs nice and early. We use a 4k real==virtual mapping.
77 */ 77 */
78 ori r4, r0, MICROBLAZE_TLB_SIZE - 1 78 ori r4, r0, MICROBLAZE_TLB_SIZE - 1
79 mts rtlbx, r4 /* TLB slot 2 */ 79 mts rtlbx, r4 /* TLB slot 63 */
80 80
81 or r4,r5,r0 81 or r4,r5,r0
82 andi r4,r4,0xfffff000 82 andi r4,r4,0xfffff000
diff --git a/arch/microblaze/kernel/of_device.c b/arch/microblaze/kernel/of_device.c
deleted file mode 100644
index b372787886ed..000000000000
--- a/arch/microblaze/kernel/of_device.c
+++ /dev/null
@@ -1,112 +0,0 @@
1#include <linux/string.h>
2#include <linux/kernel.h>
3#include <linux/of.h>
4#include <linux/init.h>
5#include <linux/module.h>
6#include <linux/mod_devicetable.h>
7#include <linux/slab.h>
8#include <linux/of_device.h>
9
10#include <linux/errno.h>
11
12void of_device_make_bus_id(struct of_device *dev)
13{
14 static atomic_t bus_no_reg_magic;
15 struct device_node *node = dev->dev.of_node;
16 const u32 *reg;
17 u64 addr;
18 int magic;
19
20 /*
21 * For MMIO, get the physical address
22 */
23 reg = of_get_property(node, "reg", NULL);
24 if (reg) {
25 addr = of_translate_address(node, reg);
26 if (addr != OF_BAD_ADDR) {
27 dev_set_name(&dev->dev, "%llx.%s",
28 (unsigned long long)addr, node->name);
29 return;
30 }
31 }
32
33 /*
34 * No BusID, use the node name and add a globally incremented
35 * counter (and pray...)
36 */
37 magic = atomic_add_return(1, &bus_no_reg_magic);
38 dev_set_name(&dev->dev, "%s.%d", node->name, magic - 1);
39}
40EXPORT_SYMBOL(of_device_make_bus_id);
41
42struct of_device *of_device_alloc(struct device_node *np,
43 const char *bus_id,
44 struct device *parent)
45{
46 struct of_device *dev;
47
48 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
49 if (!dev)
50 return NULL;
51
52 dev->dev.of_node = of_node_get(np);
53 dev->dev.dma_mask = &dev->archdata.dma_mask;
54 dev->dev.parent = parent;
55 dev->dev.release = of_release_dev;
56
57 if (bus_id)
58 dev_set_name(&dev->dev, bus_id);
59 else
60 of_device_make_bus_id(dev);
61
62 return dev;
63}
64EXPORT_SYMBOL(of_device_alloc);
65
66int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
67{
68 struct of_device *ofdev;
69 const char *compat;
70 int seen = 0, cplen, sl;
71
72 if (!dev)
73 return -ENODEV;
74
75 ofdev = to_of_device(dev);
76
77 if (add_uevent_var(env, "OF_NAME=%s", ofdev->dev.of_node->name))
78 return -ENOMEM;
79
80 if (add_uevent_var(env, "OF_TYPE=%s", ofdev->dev.of_node->type))
81 return -ENOMEM;
82
83 /* Since the compatible field can contain pretty much anything
84 * it's not really legal to split it out with commas. We split it
85 * up using a number of environment variables instead. */
86
87 compat = of_get_property(ofdev->dev.of_node, "compatible", &cplen);
88 while (compat && *compat && cplen > 0) {
89 if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
90 return -ENOMEM;
91
92 sl = strlen(compat) + 1;
93 compat += sl;
94 cplen -= sl;
95 seen++;
96 }
97
98 if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
99 return -ENOMEM;
100
101 /* modalias is trickier, we add it in 2 steps */
102 if (add_uevent_var(env, "MODALIAS="))
103 return -ENOMEM;
104 sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1],
105 sizeof(env->buf) - env->buflen);
106 if (sl >= (sizeof(env->buf) - env->buflen))
107 return -ENOMEM;
108 env->buflen += sl;
109
110 return 0;
111}
112EXPORT_SYMBOL(of_device_uevent);
diff --git a/arch/microblaze/kernel/of_platform.c b/arch/microblaze/kernel/of_platform.c
deleted file mode 100644
index ccf6f4257f4b..000000000000
--- a/arch/microblaze/kernel/of_platform.c
+++ /dev/null
@@ -1,200 +0,0 @@
1/*
2 * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
3 * <benh@kernel.crashing.org>
4 * and Arnd Bergmann, IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#undef DEBUG
14
15#include <linux/string.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/mod_devicetable.h>
20#include <linux/pci.h>
21#include <linux/of.h>
22#include <linux/of_device.h>
23#include <linux/of_platform.h>
24
25#include <linux/errno.h>
26#include <linux/topology.h>
27#include <asm/atomic.h>
28
29struct bus_type of_platform_bus_type = {
30 .uevent = of_device_uevent,
31};
32EXPORT_SYMBOL(of_platform_bus_type);
33
34static int __init of_bus_driver_init(void)
35{
36 return of_bus_type_init(&of_platform_bus_type, "of_platform");
37}
38postcore_initcall(of_bus_driver_init);
39
40struct of_device *of_platform_device_create(struct device_node *np,
41 const char *bus_id,
42 struct device *parent)
43{
44 struct of_device *dev;
45
46 dev = of_device_alloc(np, bus_id, parent);
47 if (!dev)
48 return NULL;
49
50 dev->archdata.dma_mask = 0xffffffffUL;
51 dev->dev.bus = &of_platform_bus_type;
52
53 /* We do not fill the DMA ops for platform devices by default.
54 * This is currently the responsibility of the platform code
55 * to do such, possibly using a device notifier
56 */
57
58 if (of_device_register(dev) != 0) {
59 of_device_free(dev);
60 return NULL;
61 }
62
63 return dev;
64}
65EXPORT_SYMBOL(of_platform_device_create);
66
67/**
68 * of_platform_bus_create - Create an OF device for a bus node and all its
69 * children. Optionally recursively instanciate matching busses.
70 * @bus: device node of the bus to instanciate
71 * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
72 * disallow recursive creation of child busses
73 */
74static int of_platform_bus_create(const struct device_node *bus,
75 const struct of_device_id *matches,
76 struct device *parent)
77{
78 struct device_node *child;
79 struct of_device *dev;
80 int rc = 0;
81
82 for_each_child_of_node(bus, child) {
83 pr_debug(" create child: %s\n", child->full_name);
84 dev = of_platform_device_create(child, NULL, parent);
85 if (dev == NULL)
86 rc = -ENOMEM;
87 else if (!of_match_node(matches, child))
88 continue;
89 if (rc == 0) {
90 pr_debug(" and sub busses\n");
91 rc = of_platform_bus_create(child, matches, &dev->dev);
92 }
93 if (rc) {
94 of_node_put(child);
95 break;
96 }
97 }
98 return rc;
99}
100
101
102/**
103 * of_platform_bus_probe - Probe the device-tree for platform busses
104 * @root: parent of the first level to probe or NULL for the root of the tree
105 * @matches: match table, NULL to use the default
106 * @parent: parent to hook devices from, NULL for toplevel
107 *
108 * Note that children of the provided root are not instanciated as devices
109 * unless the specified root itself matches the bus list and is not NULL.
110 */
111
112int of_platform_bus_probe(struct device_node *root,
113 const struct of_device_id *matches,
114 struct device *parent)
115{
116 struct device_node *child;
117 struct of_device *dev;
118 int rc = 0;
119
120 if (matches == NULL)
121 matches = of_default_bus_ids;
122 if (matches == OF_NO_DEEP_PROBE)
123 return -EINVAL;
124 if (root == NULL)
125 root = of_find_node_by_path("/");
126 else
127 of_node_get(root);
128
129 pr_debug("of_platform_bus_probe()\n");
130 pr_debug(" starting at: %s\n", root->full_name);
131
132 /* Do a self check of bus type, if there's a match, create
133 * children
134 */
135 if (of_match_node(matches, root)) {
136 pr_debug(" root match, create all sub devices\n");
137 dev = of_platform_device_create(root, NULL, parent);
138 if (dev == NULL) {
139 rc = -ENOMEM;
140 goto bail;
141 }
142 pr_debug(" create all sub busses\n");
143 rc = of_platform_bus_create(root, matches, &dev->dev);
144 goto bail;
145 }
146 for_each_child_of_node(root, child) {
147 if (!of_match_node(matches, child))
148 continue;
149
150 pr_debug(" match: %s\n", child->full_name);
151 dev = of_platform_device_create(child, NULL, parent);
152 if (dev == NULL)
153 rc = -ENOMEM;
154 else
155 rc = of_platform_bus_create(child, matches, &dev->dev);
156 if (rc) {
157 of_node_put(child);
158 break;
159 }
160 }
161 bail:
162 of_node_put(root);
163 return rc;
164}
165EXPORT_SYMBOL(of_platform_bus_probe);
166
167static int of_dev_node_match(struct device *dev, void *data)
168{
169 return to_of_device(dev)->dev.of_node == data;
170}
171
172struct of_device *of_find_device_by_node(struct device_node *np)
173{
174 struct device *dev;
175
176 dev = bus_find_device(&of_platform_bus_type,
177 NULL, np, of_dev_node_match);
178 if (dev)
179 return to_of_device(dev);
180 return NULL;
181}
182EXPORT_SYMBOL(of_find_device_by_node);
183
184static int of_dev_phandle_match(struct device *dev, void *data)
185{
186 phandle *ph = data;
187 return to_of_device(dev)->dev.of_node->phandle == *ph;
188}
189
190struct of_device *of_find_device_by_phandle(phandle ph)
191{
192 struct device *dev;
193
194 dev = bus_find_device(&of_platform_bus_type,
195 NULL, &ph, of_dev_phandle_match);
196 if (dev)
197 return to_of_device(dev);
198 return NULL;
199}
200EXPORT_SYMBOL(of_find_device_by_phandle);
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index 09bed44dfcd3..ba7c4b16ed35 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -76,8 +76,11 @@ __setup("hlt", hlt_setup);
76void default_idle(void) 76void default_idle(void)
77{ 77{
78 if (likely(hlt_counter)) { 78 if (likely(hlt_counter)) {
79 while (!need_resched()) 79 local_irq_disable();
80 cpu_relax(); 80 stop_critical_timings();
81 cpu_relax();
82 start_critical_timings();
83 local_irq_enable();
81 } else { 84 } else {
82 clear_thread_flag(TIF_POLLING_NRFLAG); 85 clear_thread_flag(TIF_POLLING_NRFLAG);
83 smp_mb__after_clear_bit(); 86 smp_mb__after_clear_bit();
diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c
index bf7e6c27e318..d33ba17601fa 100644
--- a/arch/microblaze/kernel/prom_parse.c
+++ b/arch/microblaze/kernel/prom_parse.c
@@ -6,219 +6,11 @@
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/ioport.h> 7#include <linux/ioport.h>
8#include <linux/etherdevice.h> 8#include <linux/etherdevice.h>
9#include <linux/of_address.h>
9#include <asm/prom.h> 10#include <asm/prom.h>
10#include <asm/pci-bridge.h> 11#include <asm/pci-bridge.h>
11 12
12#define PRu64 "%llx"
13
14/* Max address size we deal with */
15#define OF_MAX_ADDR_CELLS 4
16#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
17 (ns) > 0)
18
19static struct of_bus *of_match_bus(struct device_node *np);
20static int __of_address_to_resource(struct device_node *dev,
21 const u32 *addrp, u64 size, unsigned int flags,
22 struct resource *r);
23
24/* Debug utility */
25#ifdef DEBUG
26static void of_dump_addr(const char *s, const u32 *addr, int na)
27{
28 printk(KERN_INFO "%s", s);
29 while (na--)
30 printk(KERN_INFO " %08x", *(addr++));
31 printk(KERN_INFO "\n");
32}
33#else
34static void of_dump_addr(const char *s, const u32 *addr, int na) { }
35#endif
36
37/* Callbacks for bus specific translators */
38struct of_bus {
39 const char *name;
40 const char *addresses;
41 int (*match)(struct device_node *parent);
42 void (*count_cells)(struct device_node *child,
43 int *addrc, int *sizec);
44 u64 (*map)(u32 *addr, const u32 *range,
45 int na, int ns, int pna);
46 int (*translate)(u32 *addr, u64 offset, int na);
47 unsigned int (*get_flags)(const u32 *addr);
48};
49
50/*
51 * Default translator (generic bus)
52 */
53
54static void of_bus_default_count_cells(struct device_node *dev,
55 int *addrc, int *sizec)
56{
57 if (addrc)
58 *addrc = of_n_addr_cells(dev);
59 if (sizec)
60 *sizec = of_n_size_cells(dev);
61}
62
63static u64 of_bus_default_map(u32 *addr, const u32 *range,
64 int na, int ns, int pna)
65{
66 u64 cp, s, da;
67
68 cp = of_read_number(range, na);
69 s = of_read_number(range + na + pna, ns);
70 da = of_read_number(addr, na);
71
72 pr_debug("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n",
73 cp, s, da);
74
75 if (da < cp || da >= (cp + s))
76 return OF_BAD_ADDR;
77 return da - cp;
78}
79
80static int of_bus_default_translate(u32 *addr, u64 offset, int na)
81{
82 u64 a = of_read_number(addr, na);
83 memset(addr, 0, na * 4);
84 a += offset;
85 if (na > 1)
86 addr[na - 2] = a >> 32;
87 addr[na - 1] = a & 0xffffffffu;
88
89 return 0;
90}
91
92static unsigned int of_bus_default_get_flags(const u32 *addr)
93{
94 return IORESOURCE_MEM;
95}
96
97#ifdef CONFIG_PCI 13#ifdef CONFIG_PCI
98/*
99 * PCI bus specific translator
100 */
101
102static int of_bus_pci_match(struct device_node *np)
103{
104 /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */
105 return !strcmp(np->type, "pci") || !strcmp(np->type, "vci");
106}
107
108static void of_bus_pci_count_cells(struct device_node *np,
109 int *addrc, int *sizec)
110{
111 if (addrc)
112 *addrc = 3;
113 if (sizec)
114 *sizec = 2;
115}
116
117static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
118{
119 u64 cp, s, da;
120
121 /* Check address type match */
122 if ((addr[0] ^ range[0]) & 0x03000000)
123 return OF_BAD_ADDR;
124
125 /* Read address values, skipping high cell */
126 cp = of_read_number(range + 1, na - 1);
127 s = of_read_number(range + na + pna, ns);
128 da = of_read_number(addr + 1, na - 1);
129
130 pr_debug("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da);
131
132 if (da < cp || da >= (cp + s))
133 return OF_BAD_ADDR;
134 return da - cp;
135}
136
137static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
138{
139 return of_bus_default_translate(addr + 1, offset, na - 1);
140}
141
142static unsigned int of_bus_pci_get_flags(const u32 *addr)
143{
144 unsigned int flags = 0;
145 u32 w = addr[0];
146
147 switch ((w >> 24) & 0x03) {
148 case 0x01:
149 flags |= IORESOURCE_IO;
150 break;
151 case 0x02: /* 32 bits */
152 case 0x03: /* 64 bits */
153 flags |= IORESOURCE_MEM;
154 break;
155 }
156 if (w & 0x40000000)
157 flags |= IORESOURCE_PREFETCH;
158 return flags;
159}
160
161const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
162 unsigned int *flags)
163{
164 const u32 *prop;
165 unsigned int psize;
166 struct device_node *parent;
167 struct of_bus *bus;
168 int onesize, i, na, ns;
169
170 /* Get parent & match bus type */
171 parent = of_get_parent(dev);
172 if (parent == NULL)
173 return NULL;
174 bus = of_match_bus(parent);
175 if (strcmp(bus->name, "pci")) {
176 of_node_put(parent);
177 return NULL;
178 }
179 bus->count_cells(dev, &na, &ns);
180 of_node_put(parent);
181 if (!OF_CHECK_COUNTS(na, ns))
182 return NULL;
183
184 /* Get "reg" or "assigned-addresses" property */
185 prop = of_get_property(dev, bus->addresses, &psize);
186 if (prop == NULL)
187 return NULL;
188 psize /= 4;
189
190 onesize = na + ns;
191 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
192 if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
193 if (size)
194 *size = of_read_number(prop + na, ns);
195 if (flags)
196 *flags = bus->get_flags(prop);
197 return prop;
198 }
199 return NULL;
200}
201EXPORT_SYMBOL(of_get_pci_address);
202
203int of_pci_address_to_resource(struct device_node *dev, int bar,
204 struct resource *r)
205{
206 const u32 *addrp;
207 u64 size;
208 unsigned int flags;
209
210 addrp = of_get_pci_address(dev, bar, &size, &flags);
211 if (addrp == NULL)
212 return -EINVAL;
213 return __of_address_to_resource(dev, addrp, size, flags, r);
214}
215EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
216
217static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
218{
219 return (((pin - 1) + slot) % 4) + 1;
220}
221
222int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) 14int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
223{ 15{
224 struct device_node *dn, *ppnode; 16 struct device_node *dn, *ppnode;
@@ -293,331 +85,6 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
293EXPORT_SYMBOL_GPL(of_irq_map_pci); 85EXPORT_SYMBOL_GPL(of_irq_map_pci);
294#endif /* CONFIG_PCI */ 86#endif /* CONFIG_PCI */
295 87
296/*
297 * ISA bus specific translator
298 */
299
300static int of_bus_isa_match(struct device_node *np)
301{
302 return !strcmp(np->name, "isa");
303}
304
305static void of_bus_isa_count_cells(struct device_node *child,
306 int *addrc, int *sizec)
307{
308 if (addrc)
309 *addrc = 2;
310 if (sizec)
311 *sizec = 1;
312}
313
314static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna)
315{
316 u64 cp, s, da;
317
318 /* Check address type match */
319 if ((addr[0] ^ range[0]) & 0x00000001)
320 return OF_BAD_ADDR;
321
322 /* Read address values, skipping high cell */
323 cp = of_read_number(range + 1, na - 1);
324 s = of_read_number(range + na + pna, ns);
325 da = of_read_number(addr + 1, na - 1);
326
327 pr_debug("OF: ISA map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da);
328
329 if (da < cp || da >= (cp + s))
330 return OF_BAD_ADDR;
331 return da - cp;
332}
333
334static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
335{
336 return of_bus_default_translate(addr + 1, offset, na - 1);
337}
338
339static unsigned int of_bus_isa_get_flags(const u32 *addr)
340{
341 unsigned int flags = 0;
342 u32 w = addr[0];
343
344 if (w & 1)
345 flags |= IORESOURCE_IO;
346 else
347 flags |= IORESOURCE_MEM;
348 return flags;
349}
350
351/*
352 * Array of bus specific translators
353 */
354
355static struct of_bus of_busses[] = {
356#ifdef CONFIG_PCI
357 /* PCI */
358 {
359 .name = "pci",
360 .addresses = "assigned-addresses",
361 .match = of_bus_pci_match,
362 .count_cells = of_bus_pci_count_cells,
363 .map = of_bus_pci_map,
364 .translate = of_bus_pci_translate,
365 .get_flags = of_bus_pci_get_flags,
366 },
367#endif /* CONFIG_PCI */
368 /* ISA */
369 {
370 .name = "isa",
371 .addresses = "reg",
372 .match = of_bus_isa_match,
373 .count_cells = of_bus_isa_count_cells,
374 .map = of_bus_isa_map,
375 .translate = of_bus_isa_translate,
376 .get_flags = of_bus_isa_get_flags,
377 },
378 /* Default */
379 {
380 .name = "default",
381 .addresses = "reg",
382 .match = NULL,
383 .count_cells = of_bus_default_count_cells,
384 .map = of_bus_default_map,
385 .translate = of_bus_default_translate,
386 .get_flags = of_bus_default_get_flags,
387 },
388};
389
390static struct of_bus *of_match_bus(struct device_node *np)
391{
392 int i;
393
394 for (i = 0; i < ARRAY_SIZE(of_busses); i++)
395 if (!of_busses[i].match || of_busses[i].match(np))
396 return &of_busses[i];
397 BUG();
398 return NULL;
399}
400
401static int of_translate_one(struct device_node *parent, struct of_bus *bus,
402 struct of_bus *pbus, u32 *addr,
403 int na, int ns, int pna)
404{
405 const u32 *ranges;
406 unsigned int rlen;
407 int rone;
408 u64 offset = OF_BAD_ADDR;
409
410 /* Normally, an absence of a "ranges" property means we are
411 * crossing a non-translatable boundary, and thus the addresses
412 * below the current not cannot be converted to CPU physical ones.
413 * Unfortunately, while this is very clear in the spec, it's not
414 * what Apple understood, and they do have things like /uni-n or
415 * /ht nodes with no "ranges" property and a lot of perfectly
416 * useable mapped devices below them. Thus we treat the absence of
417 * "ranges" as equivalent to an empty "ranges" property which means
418 * a 1:1 translation at that level. It's up to the caller not to try
419 * to translate addresses that aren't supposed to be translated in
420 * the first place. --BenH.
421 */
422 ranges = of_get_property(parent, "ranges", (int *) &rlen);
423 if (ranges == NULL || rlen == 0) {
424 offset = of_read_number(addr, na);
425 memset(addr, 0, pna * 4);
426 pr_debug("OF: no ranges, 1:1 translation\n");
427 goto finish;
428 }
429
430 pr_debug("OF: walking ranges...\n");
431
432 /* Now walk through the ranges */
433 rlen /= 4;
434 rone = na + pna + ns;
435 for (; rlen >= rone; rlen -= rone, ranges += rone) {
436 offset = bus->map(addr, ranges, na, ns, pna);
437 if (offset != OF_BAD_ADDR)
438 break;
439 }
440 if (offset == OF_BAD_ADDR) {
441 pr_debug("OF: not found !\n");
442 return 1;
443 }
444 memcpy(addr, ranges + na, 4 * pna);
445
446 finish:
447 of_dump_addr("OF: parent translation for:", addr, pna);
448 pr_debug("OF: with offset: "PRu64"\n", offset);
449
450 /* Translate it into parent bus space */
451 return pbus->translate(addr, offset, pna);
452}
453
454/*
455 * Translate an address from the device-tree into a CPU physical address,
456 * this walks up the tree and applies the various bus mappings on the
457 * way.
458 *
459 * Note: We consider that crossing any level with #size-cells == 0 to mean
460 * that translation is impossible (that is we are not dealing with a value
461 * that can be mapped to a cpu physical address). This is not really specified
462 * that way, but this is traditionally the way IBM at least do things
463 */
464u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
465{
466 struct device_node *parent = NULL;
467 struct of_bus *bus, *pbus;
468 u32 addr[OF_MAX_ADDR_CELLS];
469 int na, ns, pna, pns;
470 u64 result = OF_BAD_ADDR;
471
472 pr_debug("OF: ** translation for device %s **\n", dev->full_name);
473
474 /* Increase refcount at current level */
475 of_node_get(dev);
476
477 /* Get parent & match bus type */
478 parent = of_get_parent(dev);
479 if (parent == NULL)
480 goto bail;
481 bus = of_match_bus(parent);
482
483 /* Cound address cells & copy address locally */
484 bus->count_cells(dev, &na, &ns);
485 if (!OF_CHECK_COUNTS(na, ns)) {
486 printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
487 dev->full_name);
488 goto bail;
489 }
490 memcpy(addr, in_addr, na * 4);
491
492 pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n",
493 bus->name, na, ns, parent->full_name);
494 of_dump_addr("OF: translating address:", addr, na);
495
496 /* Translate */
497 for (;;) {
498 /* Switch to parent bus */
499 of_node_put(dev);
500 dev = parent;
501 parent = of_get_parent(dev);
502
503 /* If root, we have finished */
504 if (parent == NULL) {
505 pr_debug("OF: reached root node\n");
506 result = of_read_number(addr, na);
507 break;
508 }
509
510 /* Get new parent bus and counts */
511 pbus = of_match_bus(parent);
512 pbus->count_cells(dev, &pna, &pns);
513 if (!OF_CHECK_COUNTS(pna, pns)) {
514 printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
515 dev->full_name);
516 break;
517 }
518
519 pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
520 pbus->name, pna, pns, parent->full_name);
521
522 /* Apply bus translation */
523 if (of_translate_one(dev, bus, pbus, addr, na, ns, pna))
524 break;
525
526 /* Complete the move up one level */
527 na = pna;
528 ns = pns;
529 bus = pbus;
530
531 of_dump_addr("OF: one level translation:", addr, na);
532 }
533 bail:
534 of_node_put(parent);
535 of_node_put(dev);
536
537 return result;
538}
539EXPORT_SYMBOL(of_translate_address);
540
541const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
542 unsigned int *flags)
543{
544 const u32 *prop;
545 unsigned int psize;
546 struct device_node *parent;
547 struct of_bus *bus;
548 int onesize, i, na, ns;
549
550 /* Get parent & match bus type */
551 parent = of_get_parent(dev);
552 if (parent == NULL)
553 return NULL;
554 bus = of_match_bus(parent);
555 bus->count_cells(dev, &na, &ns);
556 of_node_put(parent);
557 if (!OF_CHECK_COUNTS(na, ns))
558 return NULL;
559
560 /* Get "reg" or "assigned-addresses" property */
561 prop = of_get_property(dev, bus->addresses, (int *) &psize);
562 if (prop == NULL)
563 return NULL;
564 psize /= 4;
565
566 onesize = na + ns;
567 for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
568 if (i == index) {
569 if (size)
570 *size = of_read_number(prop + na, ns);
571 if (flags)
572 *flags = bus->get_flags(prop);
573 return prop;
574 }
575 return NULL;
576}
577EXPORT_SYMBOL(of_get_address);
578
579static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
580 u64 size, unsigned int flags,
581 struct resource *r)
582{
583 u64 taddr;
584
585 if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
586 return -EINVAL;
587 taddr = of_translate_address(dev, addrp);
588 if (taddr == OF_BAD_ADDR)
589 return -EINVAL;
590 memset(r, 0, sizeof(struct resource));
591 if (flags & IORESOURCE_IO) {
592 unsigned long port;
593 port = -1; /* pci_address_to_pio(taddr); */
594 if (port == (unsigned long)-1)
595 return -EINVAL;
596 r->start = port;
597 r->end = port + size - 1;
598 } else {
599 r->start = taddr;
600 r->end = taddr + size - 1;
601 }
602 r->flags = flags;
603 r->name = dev->name;
604 return 0;
605}
606
607int of_address_to_resource(struct device_node *dev, int index,
608 struct resource *r)
609{
610 const u32 *addrp;
611 u64 size;
612 unsigned int flags;
613
614 addrp = of_get_address(dev, index, &size, &flags);
615 if (addrp == NULL)
616 return -EINVAL;
617 return __of_address_to_resource(dev, addrp, size, flags, r);
618}
619EXPORT_SYMBOL_GPL(of_address_to_resource);
620
621void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, 88void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
622 unsigned long *busno, unsigned long *phys, unsigned long *size) 89 unsigned long *busno, unsigned long *phys, unsigned long *size)
623{ 90{
@@ -644,308 +111,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
644 *size = of_read_number(dma_window, cells); 111 *size = of_read_number(dma_window, cells);
645} 112}
646 113
647/*
648 * Interrupt remapper
649 */
650
651static unsigned int of_irq_workarounds;
652static struct device_node *of_irq_dflt_pic;
653
654static struct device_node *of_irq_find_parent(struct device_node *child)
655{
656 struct device_node *p;
657 const phandle *parp;
658
659 if (!of_node_get(child))
660 return NULL;
661
662 do {
663 parp = of_get_property(child, "interrupt-parent", NULL);
664 if (parp == NULL)
665 p = of_get_parent(child);
666 else {
667 if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
668 p = of_node_get(of_irq_dflt_pic);
669 else
670 p = of_find_node_by_phandle(*parp);
671 }
672 of_node_put(child);
673 child = p;
674 } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
675
676 return p;
677}
678
679/* This doesn't need to be called if you don't have any special workaround
680 * flags to pass
681 */
682void of_irq_map_init(unsigned int flags)
683{
684 of_irq_workarounds = flags;
685
686 /* OldWorld, don't bother looking at other things */
687 if (flags & OF_IMAP_OLDWORLD_MAC)
688 return;
689
690 /* If we don't have phandles, let's try to locate a default interrupt
691 * controller (happens when booting with BootX). We do a first match
692 * here, hopefully, that only ever happens on machines with one
693 * controller.
694 */
695 if (flags & OF_IMAP_NO_PHANDLE) {
696 struct device_node *np;
697
698 for (np = NULL; (np = of_find_all_nodes(np)) != NULL;) {
699 if (of_get_property(np, "interrupt-controller", NULL)
700 == NULL)
701 continue;
702 /* Skip /chosen/interrupt-controller */
703 if (strcmp(np->name, "chosen") == 0)
704 continue;
705 /* It seems like at least one person on this planet
706 * wants to use BootX on a machine with an AppleKiwi
707 * controller which happens to pretend to be an
708 * interrupt controller too.
709 */
710 if (strcmp(np->name, "AppleKiwi") == 0)
711 continue;
712 /* I think we found one ! */
713 of_irq_dflt_pic = np;
714 break;
715 }
716 }
717
718}
719
720int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
721 const u32 *addr, struct of_irq *out_irq)
722{
723 struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
724 const u32 *tmp, *imap, *imask;
725 u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
726 int imaplen, match, i;
727
728 pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],"
729 "ointsize=%d\n",
730 parent->full_name, intspec[0], intspec[1], ointsize);
731
732 ipar = of_node_get(parent);
733
734 /* First get the #interrupt-cells property of the current cursor
735 * that tells us how to interpret the passed-in intspec. If there
736 * is none, we are nice and just walk up the tree
737 */
738 do {
739 tmp = of_get_property(ipar, "#interrupt-cells", NULL);
740 if (tmp != NULL) {
741 intsize = *tmp;
742 break;
743 }
744 tnode = ipar;
745 ipar = of_irq_find_parent(ipar);
746 of_node_put(tnode);
747 } while (ipar);
748 if (ipar == NULL) {
749 pr_debug(" -> no parent found !\n");
750 goto fail;
751 }
752
753 pr_debug("of_irq_map_raw: ipar=%s, size=%d\n",
754 ipar->full_name, intsize);
755
756 if (ointsize != intsize)
757 return -EINVAL;
758
759 /* Look for this #address-cells. We have to implement the old linux
760 * trick of looking for the parent here as some device-trees rely on it
761 */
762 old = of_node_get(ipar);
763 do {
764 tmp = of_get_property(old, "#address-cells", NULL);
765 tnode = of_get_parent(old);
766 of_node_put(old);
767 old = tnode;
768 } while (old && tmp == NULL);
769 of_node_put(old);
770 old = NULL;
771 addrsize = (tmp == NULL) ? 2 : *tmp;
772
773 pr_debug(" -> addrsize=%d\n", addrsize);
774
775 /* Now start the actual "proper" walk of the interrupt tree */
776 while (ipar != NULL) {
777 /* Now check if cursor is an interrupt-controller and if it is
778 * then we are done
779 */
780 if (of_get_property(ipar, "interrupt-controller", NULL) !=
781 NULL) {
782 pr_debug(" -> got it !\n");
783 memcpy(out_irq->specifier, intspec,
784 intsize * sizeof(u32));
785 out_irq->size = intsize;
786 out_irq->controller = ipar;
787 of_node_put(old);
788 return 0;
789 }
790
791 /* Now look for an interrupt-map */
792 imap = of_get_property(ipar, "interrupt-map", &imaplen);
793 /* No interrupt map, check for an interrupt parent */
794 if (imap == NULL) {
795 pr_debug(" -> no map, getting parent\n");
796 newpar = of_irq_find_parent(ipar);
797 goto skiplevel;
798 }
799 imaplen /= sizeof(u32);
800
801 /* Look for a mask */
802 imask = of_get_property(ipar, "interrupt-map-mask", NULL);
803
804 /* If we were passed no "reg" property and we attempt to parse
805 * an interrupt-map, then #address-cells must be 0.
806 * Fail if it's not.
807 */
808 if (addr == NULL && addrsize != 0) {
809 pr_debug(" -> no reg passed in when needed !\n");
810 goto fail;
811 }
812
813 /* Parse interrupt-map */
814 match = 0;
815 while (imaplen > (addrsize + intsize + 1) && !match) {
816 /* Compare specifiers */
817 match = 1;
818 for (i = 0; i < addrsize && match; ++i) {
819 u32 mask = imask ? imask[i] : 0xffffffffu;
820 match = ((addr[i] ^ imap[i]) & mask) == 0;
821 }
822 for (; i < (addrsize + intsize) && match; ++i) {
823 u32 mask = imask ? imask[i] : 0xffffffffu;
824 match =
825 ((intspec[i-addrsize] ^ imap[i])
826 & mask) == 0;
827 }
828 imap += addrsize + intsize;
829 imaplen -= addrsize + intsize;
830
831 pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
832
833 /* Get the interrupt parent */
834 if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
835 newpar = of_node_get(of_irq_dflt_pic);
836 else
837 newpar =
838 of_find_node_by_phandle((phandle)*imap);
839 imap++;
840 --imaplen;
841
842 /* Check if not found */
843 if (newpar == NULL) {
844 pr_debug(" -> imap parent not found !\n");
845 goto fail;
846 }
847
848 /* Get #interrupt-cells and #address-cells of new
849 * parent
850 */
851 tmp = of_get_property(newpar, "#interrupt-cells", NULL);
852 if (tmp == NULL) {
853 pr_debug(" -> parent lacks "
854 "#interrupt-cells!\n");
855 goto fail;
856 }
857 newintsize = *tmp;
858 tmp = of_get_property(newpar, "#address-cells", NULL);
859 newaddrsize = (tmp == NULL) ? 0 : *tmp;
860
861 pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
862 newintsize, newaddrsize);
863
864 /* Check for malformed properties */
865 if (imaplen < (newaddrsize + newintsize))
866 goto fail;
867
868 imap += newaddrsize + newintsize;
869 imaplen -= newaddrsize + newintsize;
870
871 pr_debug(" -> imaplen=%d\n", imaplen);
872 }
873 if (!match)
874 goto fail;
875
876 of_node_put(old);
877 old = of_node_get(newpar);
878 addrsize = newaddrsize;
879 intsize = newintsize;
880 intspec = imap - intsize;
881 addr = intspec - addrsize;
882
883skiplevel:
884 /* Iterate again with new parent */
885 pr_debug(" -> new parent: %s\n",
886 newpar ? newpar->full_name : "<>");
887 of_node_put(ipar);
888 ipar = newpar;
889 newpar = NULL;
890 }
891fail:
892 of_node_put(ipar);
893 of_node_put(old);
894 of_node_put(newpar);
895
896 return -EINVAL;
897}
898EXPORT_SYMBOL_GPL(of_irq_map_raw);
899
900int of_irq_map_one(struct device_node *device,
901 int index, struct of_irq *out_irq)
902{
903 struct device_node *p;
904 const u32 *intspec, *tmp, *addr;
905 u32 intsize, intlen;
906 int res;
907
908 pr_debug("of_irq_map_one: dev=%s, index=%d\n",
909 device->full_name, index);
910
911 /* Get the interrupts property */
912 intspec = of_get_property(device, "interrupts", (int *) &intlen);
913 if (intspec == NULL)
914 return -EINVAL;
915 intlen /= sizeof(u32);
916
917 pr_debug(" intspec=%d intlen=%d\n", *intspec, intlen);
918
919 /* Get the reg property (if any) */
920 addr = of_get_property(device, "reg", NULL);
921
922 /* Look for the interrupt parent. */
923 p = of_irq_find_parent(device);
924 if (p == NULL)
925 return -EINVAL;
926
927 /* Get size of interrupt specifier */
928 tmp = of_get_property(p, "#interrupt-cells", NULL);
929 if (tmp == NULL) {
930 of_node_put(p);
931 return -EINVAL;
932 }
933 intsize = *tmp;
934
935 pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
936
937 /* Check index */
938 if ((index + 1) * intsize > intlen)
939 return -EINVAL;
940
941 /* Get new specifier and map it */
942 res = of_irq_map_raw(p, intspec + index * intsize, intsize,
943 addr, out_irq);
944 of_node_put(p);
945 return res;
946}
947EXPORT_SYMBOL_GPL(of_irq_map_one);
948
949/** 114/**
950 * Search the device tree for the best MAC address to use. 'mac-address' is 115 * Search the device tree for the best MAC address to use. 'mac-address' is
951 * checked first, because that is supposed to contain to "most recent" MAC 116 * checked first, because that is supposed to contain to "most recent" MAC
@@ -983,43 +148,3 @@ const void *of_get_mac_address(struct device_node *np)
983 return NULL; 148 return NULL;
984} 149}
985EXPORT_SYMBOL(of_get_mac_address); 150EXPORT_SYMBOL(of_get_mac_address);
986
987int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
988{
989 struct of_irq out_irq;
990 int irq;
991 int res;
992
993 res = of_irq_map_one(dev, index, &out_irq);
994
995 /* Get irq for the device */
996 if (res) {
997 pr_debug("IRQ not found... code = %d", res);
998 return NO_IRQ;
999 }
1000 /* Assuming single interrupt controller... */
1001 irq = out_irq.specifier[0];
1002
1003 pr_debug("IRQ found = %d", irq);
1004
1005 /* Only dereference the resource if both the
1006 * resource and the irq are valid. */
1007 if (r && irq != NO_IRQ) {
1008 r->start = r->end = irq;
1009 r->flags = IORESOURCE_IRQ;
1010 }
1011
1012 return irq;
1013}
1014EXPORT_SYMBOL_GPL(of_irq_to_resource);
1015
1016void __iomem *of_iomap(struct device_node *np, int index)
1017{
1018 struct resource res;
1019
1020 if (of_address_to_resource(np, index, &res))
1021 return NULL;
1022
1023 return ioremap(res.start, 1 + res.end - res.start);
1024}
1025EXPORT_SYMBOL(of_iomap);
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index a4a7770c6140..dc03ffc8174a 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -38,6 +38,8 @@
38#include <asm/processor.h> 38#include <asm/processor.h>
39#include <linux/uaccess.h> 39#include <linux/uaccess.h>
40#include <asm/asm-offsets.h> 40#include <asm/asm-offsets.h>
41#include <asm/cacheflush.h>
42#include <asm/io.h>
41 43
42/* Returns the address where the register at REG_OFFS in P is stashed away. */ 44/* Returns the address where the register at REG_OFFS in P is stashed away. */
43static microblaze_reg_t *reg_save_addr(unsigned reg_offs, 45static microblaze_reg_t *reg_save_addr(unsigned reg_offs,
@@ -101,8 +103,21 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
101 microblaze_reg_t *reg_addr = reg_save_addr(addr, child); 103 microblaze_reg_t *reg_addr = reg_save_addr(addr, child);
102 if (request == PTRACE_PEEKUSR) 104 if (request == PTRACE_PEEKUSR)
103 val = *reg_addr; 105 val = *reg_addr;
104 else 106 else {
107#if 1
105 *reg_addr = data; 108 *reg_addr = data;
109#else
110 /* MS potential problem on WB system
111 * Be aware that reg_addr is virtual address
112 * virt_to_phys conversion is necessary.
113 * This could be sensible solution.
114 */
115 u32 paddr = virt_to_phys((u32)reg_addr);
116 invalidate_icache_range(paddr, paddr + 4);
117 *reg_addr = data;
118 flush_dcache_range(paddr, paddr + 4);
119#endif
120 }
106 } else 121 } else
107 rval = -EIO; 122 rval = -EIO;
108 123
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c
index a1721a33042e..bd8ccab5ceff 100644
--- a/arch/microblaze/kernel/reset.c
+++ b/arch/microblaze/kernel/reset.c
@@ -24,8 +24,8 @@ static int of_reset_gpio_handle(void)
24 int ret; /* variable which stored handle reset gpio pin */ 24 int ret; /* variable which stored handle reset gpio pin */
25 struct device_node *root; /* root node */ 25 struct device_node *root; /* root node */
26 struct device_node *gpio; /* gpio node */ 26 struct device_node *gpio; /* gpio node */
27 struct of_gpio_chip *of_gc = NULL; 27 struct gpio_chip *gc;
28 enum of_gpio_flags flags ; 28 u32 flags;
29 const void *gpio_spec; 29 const void *gpio_spec;
30 30
31 /* find out root node */ 31 /* find out root node */
@@ -39,19 +39,19 @@ static int of_reset_gpio_handle(void)
39 goto err0; 39 goto err0;
40 } 40 }
41 41
42 of_gc = gpio->data; 42 gc = of_node_to_gpiochip(gpio);
43 if (!of_gc) { 43 if (!gc) {
44 pr_debug("%s: gpio controller %s isn't registered\n", 44 pr_debug("%s: gpio controller %s isn't registered\n",
45 root->full_name, gpio->full_name); 45 root->full_name, gpio->full_name);
46 ret = -ENODEV; 46 ret = -ENODEV;
47 goto err1; 47 goto err1;
48 } 48 }
49 49
50 ret = of_gc->xlate(of_gc, root, gpio_spec, &flags); 50 ret = gc->of_xlate(gc, root, gpio_spec, &flags);
51 if (ret < 0) 51 if (ret < 0)
52 goto err1; 52 goto err1;
53 53
54 ret += of_gc->gc.base; 54 ret += gc->base;
55err1: 55err1:
56 of_node_put(gpio); 56 of_node_put(gpio);
57err0: 57err0:
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 17c98dbcec88..f5f768842354 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -213,15 +213,9 @@ static struct notifier_block dflt_plat_bus_notifier = {
213 .priority = INT_MAX, 213 .priority = INT_MAX,
214}; 214};
215 215
216static struct notifier_block dflt_of_bus_notifier = {
217 .notifier_call = dflt_bus_notify,
218 .priority = INT_MAX,
219};
220
221static int __init setup_bus_notifier(void) 216static int __init setup_bus_notifier(void)
222{ 217{
223 bus_register_notifier(&platform_bus_type, &dflt_plat_bus_notifier); 218 bus_register_notifier(&platform_bus_type, &dflt_plat_bus_notifier);
224 bus_register_notifier(&of_platform_bus_type, &dflt_of_bus_notifier);
225 219
226 return 0; 220 return 0;
227} 221}
diff --git a/arch/microblaze/kernel/stacktrace.c b/arch/microblaze/kernel/stacktrace.c
index 123692f22647..84bc6686102c 100644
--- a/arch/microblaze/kernel/stacktrace.c
+++ b/arch/microblaze/kernel/stacktrace.c
@@ -14,52 +14,18 @@
14#include <linux/thread_info.h> 14#include <linux/thread_info.h>
15#include <linux/ptrace.h> 15#include <linux/ptrace.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <asm/unwind.h>
17 18
18/* FIXME initial support */
19void save_stack_trace(struct stack_trace *trace) 19void save_stack_trace(struct stack_trace *trace)
20{ 20{
21 unsigned long *sp; 21 /* Exclude our helper functions from the trace*/
22 unsigned long addr; 22 trace->skip += 2;
23 asm("addik %0, r1, 0" : "=r" (sp)); 23 microblaze_unwind(NULL, trace);
24
25 while (!kstack_end(sp)) {
26 addr = *sp++;
27 if (__kernel_text_address(addr)) {
28 if (trace->skip > 0)
29 trace->skip--;
30 else
31 trace->entries[trace->nr_entries++] = addr;
32
33 if (trace->nr_entries >= trace->max_entries)
34 break;
35 }
36 }
37} 24}
38EXPORT_SYMBOL_GPL(save_stack_trace); 25EXPORT_SYMBOL_GPL(save_stack_trace);
39 26
40void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 27void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
41{ 28{
42 unsigned int *sp; 29 microblaze_unwind(tsk, trace);
43 unsigned long addr;
44
45 struct thread_info *ti = task_thread_info(tsk);
46
47 if (tsk == current)
48 asm("addik %0, r1, 0" : "=r" (sp));
49 else
50 sp = (unsigned int *)ti->cpu_context.r1;
51
52 while (!kstack_end(sp)) {
53 addr = *sp++;
54 if (__kernel_text_address(addr)) {
55 if (trace->skip > 0)
56 trace->skip--;
57 else
58 trace->entries[trace->nr_entries++] = addr;
59
60 if (trace->nr_entries >= trace->max_entries)
61 break;
62 }
63 }
64} 30}
65EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 31EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index ed61b2f17719..b1380ae93ae1 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -28,6 +28,7 @@
28#include <asm/prom.h> 28#include <asm/prom.h>
29#include <asm/irq.h> 29#include <asm/irq.h>
30#include <asm/system.h> 30#include <asm/system.h>
31#include <linux/cnt32_to_63.h>
31 32
32#ifdef CONFIG_SELFMOD_TIMER 33#ifdef CONFIG_SELFMOD_TIMER
33#include <asm/selfmod.h> 34#include <asm/selfmod.h>
@@ -135,7 +136,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode,
135static struct clock_event_device clockevent_microblaze_timer = { 136static struct clock_event_device clockevent_microblaze_timer = {
136 .name = "microblaze_clockevent", 137 .name = "microblaze_clockevent",
137 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, 138 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
138 .shift = 24, 139 .shift = 8,
139 .rating = 300, 140 .rating = 300,
140 .set_next_event = microblaze_timer_set_next_event, 141 .set_next_event = microblaze_timer_set_next_event,
141 .set_mode = microblaze_timer_set_mode, 142 .set_mode = microblaze_timer_set_mode,
@@ -195,7 +196,7 @@ static cycle_t microblaze_cc_read(const struct cyclecounter *cc)
195static struct cyclecounter microblaze_cc = { 196static struct cyclecounter microblaze_cc = {
196 .read = microblaze_cc_read, 197 .read = microblaze_cc_read,
197 .mask = CLOCKSOURCE_MASK(32), 198 .mask = CLOCKSOURCE_MASK(32),
198 .shift = 24, 199 .shift = 8,
199}; 200};
200 201
201int __init init_microblaze_timecounter(void) 202int __init init_microblaze_timecounter(void)
@@ -213,7 +214,7 @@ static struct clocksource clocksource_microblaze = {
213 .rating = 300, 214 .rating = 300,
214 .read = microblaze_read, 215 .read = microblaze_read,
215 .mask = CLOCKSOURCE_MASK(32), 216 .mask = CLOCKSOURCE_MASK(32),
216 .shift = 24, /* I can shift it */ 217 .shift = 8, /* I can shift it */
217 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 218 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
218}; 219};
219 220
@@ -235,6 +236,12 @@ static int __init microblaze_clocksource_init(void)
235 return 0; 236 return 0;
236} 237}
237 238
239/*
240 * We have to protect accesses before timer initialization
241 * and return 0 for sched_clock function below.
242 */
243static int timer_initialized;
244
238void __init time_init(void) 245void __init time_init(void)
239{ 246{
240 u32 irq, i = 0; 247 u32 irq, i = 0;
@@ -289,4 +296,15 @@ void __init time_init(void)
289#endif 296#endif
290 microblaze_clocksource_init(); 297 microblaze_clocksource_init();
291 microblaze_clockevent_init(); 298 microblaze_clockevent_init();
299 timer_initialized = 1;
300}
301
302unsigned long long notrace sched_clock(void)
303{
304 if (timer_initialized) {
305 struct clocksource *cs = &clocksource_microblaze;
306 cycle_t cyc = cnt32_to_63(cs->read(NULL));
307 return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
308 }
309 return 0;
292} 310}
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c
index 75e49202a5ed..ba034d421ec2 100644
--- a/arch/microblaze/kernel/traps.c
+++ b/arch/microblaze/kernel/traps.c
@@ -16,13 +16,14 @@
16 16
17#include <asm/exceptions.h> 17#include <asm/exceptions.h>
18#include <asm/system.h> 18#include <asm/system.h>
19#include <asm/unwind.h>
19 20
20void trap_init(void) 21void trap_init(void)
21{ 22{
22 __enable_hw_exceptions(); 23 __enable_hw_exceptions();
23} 24}
24 25
25static unsigned long kstack_depth_to_print = 24; 26static unsigned long kstack_depth_to_print; /* 0 == entire stack */
26 27
27static int __init kstack_setup(char *s) 28static int __init kstack_setup(char *s)
28{ 29{
@@ -30,31 +31,47 @@ static int __init kstack_setup(char *s)
30} 31}
31__setup("kstack=", kstack_setup); 32__setup("kstack=", kstack_setup);
32 33
33void show_trace(struct task_struct *task, unsigned long *stack) 34void show_stack(struct task_struct *task, unsigned long *sp)
34{ 35{
35 unsigned long addr; 36 unsigned long words_to_show;
36 37 u32 fp = (u32) sp;
37 if (!stack) 38
38 stack = (unsigned long *)&stack; 39 if (fp == 0) {
40 if (task) {
41 fp = ((struct thread_info *)
42 (task->stack))->cpu_context.r1;
43 } else {
44 /* Pick up caller of dump_stack() */
45 fp = (u32)&sp - 8;
46 }
47 }
39 48
40 printk(KERN_NOTICE "Call Trace: "); 49 words_to_show = (THREAD_SIZE - (fp & (THREAD_SIZE - 1))) >> 2;
41#ifdef CONFIG_KALLSYMS 50 if (kstack_depth_to_print && (words_to_show > kstack_depth_to_print))
42 printk(KERN_NOTICE "\n"); 51 words_to_show = kstack_depth_to_print;
43#endif 52
44 while (!kstack_end(stack)) { 53 pr_info("Kernel Stack:\n");
45 addr = *stack++; 54
46 /* 55 /*
47 * If the address is either in the text segment of the 56 * Make the first line an 'odd' size if necessary to get
48 * kernel, or in the region which contains vmalloc'ed 57 * remaining lines to start at an address multiple of 0x10
49 * memory, it *may* be the address of a calling 58 */
50 * routine; if so, print it so that someone tracing 59 if (fp & 0xF) {
51 * down the cause of the crash will be able to figure 60 unsigned long line1_words = (0x10 - (fp & 0xF)) >> 2;
52 * out the call path that was taken. 61 if (line1_words < words_to_show) {
53 */ 62 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 32,
54 if (kernel_text_address(addr)) 63 4, (void *)fp, line1_words << 2, 0);
55 print_ip_sym(addr); 64 fp += line1_words << 2;
65 words_to_show -= line1_words;
66 }
56 } 67 }
57 printk(KERN_NOTICE "\n"); 68 print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 32, 4, (void *)fp,
69 words_to_show << 2, 0);
70 printk(KERN_INFO "\n\n");
71
72 pr_info("Call Trace:\n");
73 microblaze_unwind(task, NULL);
74 pr_info("\n");
58 75
59 if (!task) 76 if (!task)
60 task = current; 77 task = current;
@@ -62,34 +79,6 @@ void show_trace(struct task_struct *task, unsigned long *stack)
62 debug_show_held_locks(task); 79 debug_show_held_locks(task);
63} 80}
64 81
65void show_stack(struct task_struct *task, unsigned long *sp)
66{
67 unsigned long *stack;
68 int i;
69
70 if (sp == NULL) {
71 if (task)
72 sp = (unsigned long *) ((struct thread_info *)
73 (task->stack))->cpu_context.r1;
74 else
75 sp = (unsigned long *)&sp;
76 }
77
78 stack = sp;
79
80 printk(KERN_INFO "\nStack:\n ");
81
82 for (i = 0; i < kstack_depth_to_print; i++) {
83 if (kstack_end(sp))
84 break;
85 if (i && ((i % 8) == 0))
86 printk("\n ");
87 printk("%08lx ", *sp++);
88 }
89 printk("\n");
90 show_trace(task, stack);
91}
92
93void dump_stack(void) 82void dump_stack(void)
94{ 83{
95 show_stack(NULL, NULL); 84 show_stack(NULL, NULL);
diff --git a/arch/microblaze/kernel/unwind.c b/arch/microblaze/kernel/unwind.c
new file mode 100644
index 000000000000..fefac5c33586
--- /dev/null
+++ b/arch/microblaze/kernel/unwind.c
@@ -0,0 +1,318 @@
1/*
2 * Backtrace support for Microblaze
3 *
4 * Copyright (C) 2010 Digital Design Corporation
5 *
6 * Based on arch/sh/kernel/cpu/sh5/unwind.c code which is:
7 * Copyright (C) 2004 Paul Mundt
8 * Copyright (C) 2004 Richard Curnow
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file "COPYING" in the main directory of this archive
12 * for more details.
13 */
14
15/* #define DEBUG 1 */
16#include <linux/kallsyms.h>
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/stacktrace.h>
20#include <linux/types.h>
21#include <linux/errno.h>
22#include <linux/module.h>
23#include <linux/io.h>
24#include <asm/sections.h>
25#include <asm/exceptions.h>
26#include <asm/unwind.h>
27
28struct stack_trace;
29
30/*
31 * On Microblaze, finding the previous stack frame is a little tricky.
32 * At this writing (3/2010), Microblaze does not support CONFIG_FRAME_POINTERS,
33 * and even if it did, gcc (4.1.2) does not store the frame pointer at
34 * a consistent offset within each frame. To determine frame size, it is
35 * necessary to search for the assembly instruction that creates or reclaims
36 * the frame and extract the size from it.
37 *
38 * Microblaze stores the stack pointer in r1, and creates a frame via
39 *
40 * addik r1, r1, -FRAME_SIZE
41 *
42 * The frame is reclaimed via
43 *
44 * addik r1, r1, FRAME_SIZE
45 *
46 * Frame creation occurs at or near the top of a function.
47 * Depending on the compiler, reclaim may occur at the end, or before
48 * a mid-function return.
49 *
50 * A stack frame is usually not created in a leaf function.
51 *
52 */
53
54/**
55 * get_frame_size - Extract the stack adjustment from an
56 * "addik r1, r1, adjust" instruction
57 * @instr : Microblaze instruction
58 *
59 * Return - Number of stack bytes the instruction reserves or reclaims
60 */
61inline long get_frame_size(unsigned long instr)
62{
63 return abs((s16)(instr & 0xFFFF));
64}
65
66/**
67 * find_frame_creation - Search backward to find the instruction that creates
68 * the stack frame (hopefully, for the same function the
69 * initial PC is in).
70 * @pc : Program counter at which to begin the search
71 *
72 * Return - PC at which stack frame creation occurs
73 * NULL if this cannot be found, i.e. a leaf function
74 */
75static unsigned long *find_frame_creation(unsigned long *pc)
76{
77 int i;
78
79 /* NOTE: Distance to search is arbitrary
80 * 250 works well for most things,
81 * 750 picks up things like tcp_recvmsg(),
82 * 1000 needed for fat_fill_super()
83 */
84 for (i = 0; i < 1000; i++, pc--) {
85 unsigned long instr;
86 s16 frame_size;
87
88 if (!kernel_text_address((unsigned long) pc))
89 return NULL;
90
91 instr = *pc;
92
93 /* addik r1, r1, foo ? */
94 if ((instr & 0xFFFF0000) != 0x30210000)
95 continue; /* No */
96
97 frame_size = get_frame_size(instr);
98 if ((frame_size < 8) || (frame_size & 3)) {
99 pr_debug(" Invalid frame size %d at 0x%p\n",
100 frame_size, pc);
101 return NULL;
102 }
103
104 pr_debug(" Found frame creation at 0x%p, size %d\n", pc,
105 frame_size);
106 return pc;
107 }
108
109 return NULL;
110}
111
112/**
113 * lookup_prev_stack_frame - Find the stack frame of the previous function.
114 * @fp : Frame (stack) pointer for current function
115 * @pc : Program counter within current function
116 * @leaf_return : r15 value within current function. If the current function
117 * is a leaf, this is the caller's return address.
118 * @pprev_fp : On exit, set to frame (stack) pointer for previous function
119 * @pprev_pc : On exit, set to current function caller's return address
120 *
121 * Return - 0 on success, -EINVAL if the previous frame cannot be found
122 */
123static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
124 unsigned long leaf_return,
125 unsigned long *pprev_fp,
126 unsigned long *pprev_pc)
127{
128 unsigned long *prologue = NULL;
129
130 /* _switch_to is a special leaf function */
131 if (pc != (unsigned long) &_switch_to)
132 prologue = find_frame_creation((unsigned long *)pc);
133
134 if (prologue) {
135 long frame_size = get_frame_size(*prologue);
136
137 *pprev_fp = fp + frame_size;
138 *pprev_pc = *(unsigned long *)fp;
139 } else {
140 if (!leaf_return)
141 return -EINVAL;
142 *pprev_pc = leaf_return;
143 *pprev_fp = fp;
144 }
145
146 /* NOTE: don't check kernel_text_address here, to allow display
147 * of userland return address
148 */
149 return (!*pprev_pc || (*pprev_pc & 3)) ? -EINVAL : 0;
150}
151
152static void microblaze_unwind_inner(struct task_struct *task,
153 unsigned long pc, unsigned long fp,
154 unsigned long leaf_return,
155 struct stack_trace *trace);
156
157/**
158 * unwind_trap - Unwind through a system trap, that stored previous state
159 * on the stack.
160 */
161#ifdef CONFIG_MMU
162static inline void unwind_trap(struct task_struct *task, unsigned long pc,
163 unsigned long fp, struct stack_trace *trace)
164{
165 /* To be implemented */
166}
167#else
168static inline void unwind_trap(struct task_struct *task, unsigned long pc,
169 unsigned long fp, struct stack_trace *trace)
170{
171 const struct pt_regs *regs = (const struct pt_regs *) fp;
172 microblaze_unwind_inner(task, regs->pc, regs->r1, regs->r15, trace);
173}
174#endif
175
176/**
177 * microblaze_unwind_inner - Unwind the stack from the specified point
178 * @task : Task whose stack we are to unwind (may be NULL)
179 * @pc : Program counter from which we start unwinding
180 * @fp : Frame (stack) pointer from which we start unwinding
181 * @leaf_return : Value of r15 at pc. If the function is a leaf, this is
182 * the caller's return address.
183 * @trace : Where to store stack backtrace (PC values).
184 * NULL == print backtrace to kernel log
185 */
186void microblaze_unwind_inner(struct task_struct *task,
187 unsigned long pc, unsigned long fp,
188 unsigned long leaf_return,
189 struct stack_trace *trace)
190{
191 int ofs = 0;
192
193 pr_debug(" Unwinding with PC=%p, FP=%p\n", (void *)pc, (void *)fp);
194 if (!pc || !fp || (pc & 3) || (fp & 3)) {
195 pr_debug(" Invalid state for unwind, aborting\n");
196 return;
197 }
198 for (; pc != 0;) {
199 unsigned long next_fp, next_pc = 0;
200 unsigned long return_to = pc + 2 * sizeof(unsigned long);
201 const struct trap_handler_info *handler =
202 &microblaze_trap_handlers;
203
204 /* Is previous function the HW exception handler? */
205 if ((return_to >= (unsigned long)&_hw_exception_handler)
206 &&(return_to < (unsigned long)&ex_handler_unhandled)) {
207 /*
208 * HW exception handler doesn't save all registers,
209 * so we open-code a special case of unwind_trap()
210 */
211#ifndef CONFIG_MMU
212 const struct pt_regs *regs =
213 (const struct pt_regs *) fp;
214#endif
215 pr_info("HW EXCEPTION\n");
216#ifndef CONFIG_MMU
217 microblaze_unwind_inner(task, regs->r17 - 4,
218 fp + EX_HANDLER_STACK_SIZ,
219 regs->r15, trace);
220#endif
221 return;
222 }
223
224 /* Is previous function a trap handler? */
225 for (; handler->start_addr; ++handler) {
226 if ((return_to >= handler->start_addr)
227 && (return_to <= handler->end_addr)) {
228 if (!trace)
229 pr_info("%s\n", handler->trap_name);
230 unwind_trap(task, pc, fp, trace);
231 return;
232 }
233 }
234 pc -= ofs;
235
236 if (trace) {
237#ifdef CONFIG_STACKTRACE
238 if (trace->skip > 0)
239 trace->skip--;
240 else
241 trace->entries[trace->nr_entries++] = pc;
242
243 if (trace->nr_entries >= trace->max_entries)
244 break;
245#endif
246 } else {
247 /* Have we reached userland? */
248 if (unlikely(pc == task_pt_regs(task)->pc)) {
249 pr_info("[<%p>] PID %lu [%s]\n",
250 (void *) pc,
251 (unsigned long) task->pid,
252 task->comm);
253 break;
254 } else
255 print_ip_sym(pc);
256 }
257
258 /* Stop when we reach anything not part of the kernel */
259 if (!kernel_text_address(pc))
260 break;
261
262 if (lookup_prev_stack_frame(fp, pc, leaf_return, &next_fp,
263 &next_pc) == 0) {
264 ofs = sizeof(unsigned long);
265 pc = next_pc & ~3;
266 fp = next_fp;
267 leaf_return = 0;
268 } else {
269 pr_debug(" Failed to find previous stack frame\n");
270 break;
271 }
272
273 pr_debug(" Next PC=%p, next FP=%p\n",
274 (void *)next_pc, (void *)next_fp);
275 }
276}
277
278/**
279 * microblaze_unwind - Stack unwinder for Microblaze (external entry point)
280 * @task : Task whose stack we are to unwind (NULL == current)
281 * @trace : Where to store stack backtrace (PC values).
282 * NULL == print backtrace to kernel log
283 */
284void microblaze_unwind(struct task_struct *task, struct stack_trace *trace)
285{
286 if (task) {
287 if (task == current) {
288 const struct pt_regs *regs = task_pt_regs(task);
289 microblaze_unwind_inner(task, regs->pc, regs->r1,
290 regs->r15, trace);
291 } else {
292 struct thread_info *thread_info =
293 (struct thread_info *)(task->stack);
294 const struct cpu_context *cpu_context =
295 &thread_info->cpu_context;
296
297 microblaze_unwind_inner(task,
298 (unsigned long) &_switch_to,
299 cpu_context->r1,
300 cpu_context->r15, trace);
301 }
302 } else {
303 unsigned long pc, fp;
304
305 __asm__ __volatile__ ("or %0, r1, r0" : "=r" (fp));
306
307 __asm__ __volatile__ (
308 "brlid %0, 0f;"
309 "nop;"
310 "0:"
311 : "=r" (pc)
312 );
313
314 /* Since we are not a leaf function, use leaf_return = 0 */
315 microblaze_unwind_inner(current, pc, fp, 0, trace);
316 }
317}
318
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index db72d7124602..a09f2962fbec 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -10,7 +10,7 @@
10 10
11OUTPUT_FORMAT("elf32-microblaze", "elf32-microblaze", "elf32-microblaze") 11OUTPUT_FORMAT("elf32-microblaze", "elf32-microblaze", "elf32-microblaze")
12OUTPUT_ARCH(microblaze) 12OUTPUT_ARCH(microblaze)
13ENTRY(_start) 13ENTRY(microblaze_start)
14 14
15#include <asm/page.h> 15#include <asm/page.h>
16#include <asm-generic/vmlinux.lds.h> 16#include <asm-generic/vmlinux.lds.h>
@@ -20,7 +20,7 @@ jiffies = jiffies_64 + 4;
20 20
21SECTIONS { 21SECTIONS {
22 . = CONFIG_KERNEL_START; 22 . = CONFIG_KERNEL_START;
23 _start = CONFIG_KERNEL_BASE_ADDR; 23 microblaze_start = CONFIG_KERNEL_BASE_ADDR;
24 .text : AT(ADDR(.text) - LOAD_OFFSET) { 24 .text : AT(ADDR(.text) - LOAD_OFFSET) {
25 _text = . ; 25 _text = . ;
26 _stext = . ; 26 _stext = . ;
@@ -55,7 +55,7 @@ SECTIONS {
55 */ 55 */
56 .sdata2 : AT(ADDR(.sdata2) - LOAD_OFFSET) { 56 .sdata2 : AT(ADDR(.sdata2) - LOAD_OFFSET) {
57 _ssrw = .; 57 _ssrw = .;
58 . = ALIGN(4096); /* page aligned when MMU used - origin 0x8 */ 58 . = ALIGN(PAGE_SIZE); /* page aligned when MMU used */
59 *(.sdata2) 59 *(.sdata2)
60 . = ALIGN(8); 60 . = ALIGN(8);
61 _essrw = .; 61 _essrw = .;
@@ -70,7 +70,7 @@ SECTIONS {
70 /* Reserve some low RAM for r0 based memory references */ 70 /* Reserve some low RAM for r0 based memory references */
71 . = ALIGN(0x4) ; 71 . = ALIGN(0x4) ;
72 r0_ram = . ; 72 r0_ram = . ;
73 . = . + 4096; /* a page should be enough */ 73 . = . + PAGE_SIZE; /* a page should be enough */
74 74
75 /* Under the microblaze ABI, .sdata and .sbss must be contiguous */ 75 /* Under the microblaze ABI, .sdata and .sbss must be contiguous */
76 . = ALIGN(8); 76 . = ALIGN(8);
@@ -120,7 +120,7 @@ SECTIONS {
120 120
121 __init_end_before_initramfs = .; 121 __init_end_before_initramfs = .;
122 122
123 .init.ramfs ALIGN(4096) : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { 123 .init.ramfs ALIGN(PAGE_SIZE) : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
124 __initramfs_start = .; 124 __initramfs_start = .;
125 *(.init.ramfs) 125 *(.init.ramfs)
126 __initramfs_end = .; 126 __initramfs_end = .;
@@ -132,11 +132,11 @@ SECTIONS {
132 * so that __init_end == __bss_start. This will make image.elf 132 * so that __init_end == __bss_start. This will make image.elf
133 * consistent with the image.bin 133 * consistent with the image.bin
134 */ 134 */
135 /* . = ALIGN(4096); */ 135 /* . = ALIGN(PAGE_SIZE); */
136 } 136 }
137 __init_end = .; 137 __init_end = .;
138 138
139 .bss ALIGN (4096) : AT(ADDR(.bss) - LOAD_OFFSET) { 139 .bss ALIGN (PAGE_SIZE) : AT(ADDR(.bss) - LOAD_OFFSET) {
140 /* page aligned when MMU used */ 140 /* page aligned when MMU used */
141 __bss_start = . ; 141 __bss_start = . ;
142 *(.bss*) 142 *(.bss*)
@@ -145,7 +145,7 @@ SECTIONS {
145 __bss_stop = . ; 145 __bss_stop = . ;
146 _ebss = . ; 146 _ebss = . ;
147 } 147 }
148 . = ALIGN(4096); 148 . = ALIGN(PAGE_SIZE);
149 _end = .; 149 _end = .;
150 150
151 DISCARDS 151 DISCARDS