aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze/kernel/entry.S
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 11:59:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 11:59:22 -0400
commitbbc4fd12a635492ad9d12bb418124fa2d5f0d734 (patch)
treefe245d350db180d499a9e9d6dc84bbb308f33dc2 /arch/microblaze/kernel/entry.S
parent673b864fd76a29031aa0b4b08fc80886d527b3b7 (diff)
parent2d5973cb5ac5d04662f86e19a06a4c52fa4c4ae3 (diff)
Merge branch 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze
* 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze: (49 commits) microblaze: Add KGDB support microblaze: Support brki rX, 0x18 for user application debugging microblaze: Remove nop after MSRCLR/SET, MTS, MFS instructions microblaze: Simplify syscall rutine microblaze: Move PT_MODE saving to delay slot microblaze: Fix _interrupt function microblaze: Fix _user_exception function microblaze: Put together addik instructions microblaze: Use delay slot in syscall macros microblaze: Save kernel mode in delay slot microblaze: Do not mix register saving and mode setting microblaze: Move SAVE_STATE upward microblaze: entry.S: Macro optimization microblaze: Optimize hw exception rutine microblaze: Implement clear_ums macro and fix SAVE_STATE macro microblaze: Remove additional setup for kernel_mode microblaze: Optimize SAVE_STATE macro microblaze: Remove additional loading microblaze: Completely remove working with R11 register microblaze: Do not setup BIP in _debug_exception ...
Diffstat (limited to 'arch/microblaze/kernel/entry.S')
-rw-r--r--arch/microblaze/kernel/entry.S607
1 files changed, 242 insertions, 365 deletions
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