Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[pandora-kernel.git] / arch / microblaze / kernel / entry.S
1 /*
2  * Low-level system-call handling, trap handlers and context-switching
3  *
4  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
5  * Copyright (C) 2008-2009 PetaLogix
6  * Copyright (C) 2003           John Williams <jwilliams@itee.uq.edu.au>
7  * Copyright (C) 2001,2002      NEC Corporation
8  * Copyright (C) 2001,2002      Miles Bader <miles@gnu.org>
9  *
10  * This file is subject to the terms and conditions of the GNU General
11  * Public License. See the file COPYING in the main directory of this
12  * archive for more details.
13  *
14  * Written by Miles Bader <miles@gnu.org>
15  * Heavily modified by John Williams for Microblaze
16  */
17
18 #include <linux/sys.h>
19 #include <linux/linkage.h>
20
21 #include <asm/entry.h>
22 #include <asm/current.h>
23 #include <asm/processor.h>
24 #include <asm/exceptions.h>
25 #include <asm/asm-offsets.h>
26 #include <asm/thread_info.h>
27
28 #include <asm/page.h>
29 #include <asm/unistd.h>
30
31 #include <linux/errno.h>
32 #include <asm/signal.h>
33
34 #undef DEBUG
35
36 /* The size of a state save frame. */
37 #define STATE_SAVE_SIZE         (PT_SIZE + STATE_SAVE_ARG_SPACE)
38
39 /* The offset of the struct pt_regs in a `state save frame' on the stack. */
40 #define PTO     STATE_SAVE_ARG_SPACE /* 24 the space for args */
41
42 #define C_ENTRY(name)   .globl name; .align 4; name
43
44 /*
45  * Various ways of setting and clearing BIP in flags reg.
46  * This is mucky, but necessary using microblaze version that
47  * allows msr ops to write to BIP
48  */
49 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
50         .macro  clear_bip
51         msrclr  r0, MSR_BIP
52         .endm
53
54         .macro  set_bip
55         msrset  r0, MSR_BIP
56         .endm
57
58         .macro  clear_eip
59         msrclr  r0, MSR_EIP
60         .endm
61
62         .macro  set_ee
63         msrset  r0, MSR_EE
64         .endm
65
66         .macro  disable_irq
67         msrclr  r0, MSR_IE
68         .endm
69
70         .macro  enable_irq
71         msrset  r0, MSR_IE
72         .endm
73
74         .macro  set_ums
75         msrset  r0, MSR_UMS
76         msrclr  r0, MSR_VMS
77         .endm
78
79         .macro  set_vms
80         msrclr  r0, MSR_UMS
81         msrset  r0, MSR_VMS
82         .endm
83
84         .macro  clear_ums
85         msrclr  r0, MSR_UMS
86         .endm
87
88         .macro  clear_vms_ums
89         msrclr  r0, MSR_VMS | MSR_UMS
90         .endm
91 #else
92         .macro  clear_bip
93         mfs     r11, rmsr
94         andi    r11, r11, ~MSR_BIP
95         mts     rmsr, r11
96         .endm
97
98         .macro  set_bip
99         mfs     r11, rmsr
100         ori     r11, r11, MSR_BIP
101         mts     rmsr, r11
102         .endm
103
104         .macro  clear_eip
105         mfs     r11, rmsr
106         andi    r11, r11, ~MSR_EIP
107         mts     rmsr, r11
108         .endm
109
110         .macro  set_ee
111         mfs     r11, rmsr
112         ori     r11, r11, MSR_EE
113         mts     rmsr, r11
114         .endm
115
116         .macro  disable_irq
117         mfs     r11, rmsr
118         andi    r11, r11, ~MSR_IE
119         mts     rmsr, r11
120         .endm
121
122         .macro  enable_irq
123         mfs     r11, rmsr
124         ori     r11, r11, MSR_IE
125         mts     rmsr, r11
126         .endm
127
128         .macro set_ums
129         mfs     r11, rmsr
130         ori     r11, r11, MSR_VMS
131         andni   r11, r11, MSR_UMS
132         mts     rmsr, r11
133         .endm
134
135         .macro  set_vms
136         mfs     r11, rmsr
137         ori     r11, r11, MSR_VMS
138         andni   r11, r11, MSR_UMS
139         mts     rmsr, r11
140         .endm
141
142         .macro  clear_ums
143         mfs     r11, rmsr
144         andni   r11, r11, MSR_UMS
145         mts     rmsr,r11
146         .endm
147
148         .macro  clear_vms_ums
149         mfs     r11, rmsr
150         andni   r11, r11, (MSR_VMS|MSR_UMS)
151         mts     rmsr,r11
152         .endm
153 #endif
154
155 /* Define how to call high-level functions. With MMU, virtual mode must be
156  * enabled when calling the high-level function. Clobbers R11.
157  * VM_ON, VM_OFF, DO_JUMP_BIPCLR, DO_CALL
158  */
159
160 /* turn on virtual protected mode save */
161 #define VM_ON           \
162         set_ums;        \
163         rted    r0, 2f; \
164         nop; \
165 2:
166
167 /* turn off virtual protected mode save and user mode save*/
168 #define VM_OFF                  \
169         clear_vms_ums;          \
170         rted    r0, TOPHYS(1f); \
171         nop; \
172 1:
173
174 #define SAVE_REGS \
175         swi     r2, r1, PTO+PT_R2;      /* Save SDA */                  \
176         swi     r3, r1, PTO+PT_R3;                                      \
177         swi     r4, r1, PTO+PT_R4;                                      \
178         swi     r5, r1, PTO+PT_R5;                                      \
179         swi     r6, r1, PTO+PT_R6;                                      \
180         swi     r7, r1, PTO+PT_R7;                                      \
181         swi     r8, r1, PTO+PT_R8;                                      \
182         swi     r9, r1, PTO+PT_R9;                                      \
183         swi     r10, r1, PTO+PT_R10;                                    \
184         swi     r11, r1, PTO+PT_R11;    /* save clobbered regs after rval */\
185         swi     r12, r1, PTO+PT_R12;                                    \
186         swi     r13, r1, PTO+PT_R13;    /* Save SDA2 */                 \
187         swi     r14, r1, PTO+PT_PC;     /* PC, before IRQ/trap */       \
188         swi     r15, r1, PTO+PT_R15;    /* Save LP */                   \
189         swi     r16, r1, PTO+PT_R16;                                    \
190         swi     r17, r1, PTO+PT_R17;                                    \
191         swi     r18, r1, PTO+PT_R18;    /* Save asm scratch reg */      \
192         swi     r19, r1, PTO+PT_R19;                                    \
193         swi     r20, r1, PTO+PT_R20;                                    \
194         swi     r21, r1, PTO+PT_R21;                                    \
195         swi     r22, r1, PTO+PT_R22;                                    \
196         swi     r23, r1, PTO+PT_R23;                                    \
197         swi     r24, r1, PTO+PT_R24;                                    \
198         swi     r25, r1, PTO+PT_R25;                                    \
199         swi     r26, r1, PTO+PT_R26;                                    \
200         swi     r27, r1, PTO+PT_R27;                                    \
201         swi     r28, r1, PTO+PT_R28;                                    \
202         swi     r29, r1, PTO+PT_R29;                                    \
203         swi     r30, r1, PTO+PT_R30;                                    \
204         swi     r31, r1, PTO+PT_R31;    /* Save current task reg */     \
205         mfs     r11, rmsr;              /* save MSR */                  \
206         swi     r11, r1, PTO+PT_MSR;
207
208 #define RESTORE_REGS \
209         lwi     r11, r1, PTO+PT_MSR;                                    \
210         mts     rmsr , r11;                                             \
211         lwi     r2, r1, PTO+PT_R2;      /* restore SDA */               \
212         lwi     r3, r1, PTO+PT_R3;                                      \
213         lwi     r4, r1, PTO+PT_R4;                                      \
214         lwi     r5, r1, PTO+PT_R5;                                      \
215         lwi     r6, r1, PTO+PT_R6;                                      \
216         lwi     r7, r1, PTO+PT_R7;                                      \
217         lwi     r8, r1, PTO+PT_R8;                                      \
218         lwi     r9, r1, PTO+PT_R9;                                      \
219         lwi     r10, r1, PTO+PT_R10;                                    \
220         lwi     r11, r1, PTO+PT_R11;    /* restore clobbered regs after rval */\
221         lwi     r12, r1, PTO+PT_R12;                                    \
222         lwi     r13, r1, PTO+PT_R13;    /* restore SDA2 */              \
223         lwi     r14, r1, PTO+PT_PC;     /* RESTORE_LINK PC, before IRQ/trap */\
224         lwi     r15, r1, PTO+PT_R15;    /* restore LP */                \
225         lwi     r16, r1, PTO+PT_R16;                                    \
226         lwi     r17, r1, PTO+PT_R17;                                    \
227         lwi     r18, r1, PTO+PT_R18;    /* restore asm scratch reg */   \
228         lwi     r19, r1, PTO+PT_R19;                                    \
229         lwi     r20, r1, PTO+PT_R20;                                    \
230         lwi     r21, r1, PTO+PT_R21;                                    \
231         lwi     r22, r1, PTO+PT_R22;                                    \
232         lwi     r23, r1, PTO+PT_R23;                                    \
233         lwi     r24, r1, PTO+PT_R24;                                    \
234         lwi     r25, r1, PTO+PT_R25;                                    \
235         lwi     r26, r1, PTO+PT_R26;                                    \
236         lwi     r27, r1, PTO+PT_R27;                                    \
237         lwi     r28, r1, PTO+PT_R28;                                    \
238         lwi     r29, r1, PTO+PT_R29;                                    \
239         lwi     r30, r1, PTO+PT_R30;                                    \
240         lwi     r31, r1, PTO+PT_R31;    /* Restore cur task reg */
241
242 #define SAVE_STATE      \
243         swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */     \
244         /* See if already in kernel mode.*/                             \
245         mfs     r1, rmsr;                                               \
246         andi    r1, r1, MSR_UMS;                                        \
247         bnei    r1, 1f;                                         \
248         /* Kernel-mode state save.  */                                  \
249         /* Reload kernel stack-ptr. */                                  \
250         lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP));                      \
251         /* FIXME: I can add these two lines to one */                   \
252         /* tophys(r1,r1); */                                            \
253         /* addik        r1, r1, -STATE_SAVE_SIZE; */                    \
254         addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
255         SAVE_REGS                                                       \
256         brid    2f;                                                     \
257         swi     r1, r1, PTO+PT_MODE;                                    \
258 1:      /* User-mode state save.  */                                    \
259         lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
260         tophys(r1,r1);                                                  \
261         lwi     r1, r1, TS_THREAD_INFO; /* get the thread info */       \
262         /* MS these three instructions can be added to one */           \
263         /* addik        r1, r1, THREAD_SIZE; */                         \
264         /* tophys(r1,r1); */                                            \
265         /* addik        r1, r1, -STATE_SAVE_SIZE; */                    \
266         addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
267         SAVE_REGS                                                       \
268         lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));                     \
269         swi     r11, r1, PTO+PT_R1; /* Store user SP.  */               \
270         swi     r0, r1, PTO + PT_MODE; /* Was in user-mode.  */         \
271         /* MS: I am clearing UMS even in case when I come from kernel space */ \
272         clear_ums;                                                      \
273 2:      lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
274
275 .text
276
277 /*
278  * User trap.
279  *
280  * System calls are handled here.
281  *
282  * Syscall protocol:
283  * Syscall number in r12, args in r5-r10
284  * Return value in r3
285  *
286  * Trap entered via brki instruction, so BIP bit is set, and interrupts
287  * are masked. This is nice, means we don't have to CLI before state save
288  */
289 C_ENTRY(_user_exception):
290         swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
291         addi    r14, r14, 4     /* return address is 4 byte after call */
292
293         mfs     r1, rmsr
294         nop
295         andi    r1, r1, MSR_UMS
296         bnei    r1, 1f
297
298 /* Kernel-mode state save - kernel execve */
299         lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
300         tophys(r1,r1);
301
302         addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
303         SAVE_REGS
304
305         swi     r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */
306         brid    2f;
307         nop;                            /* Fill delay slot */
308
309 /* User-mode state save.  */
310 1:
311         lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
312         tophys(r1,r1);
313         lwi     r1, r1, TS_THREAD_INFO; /* get stack from task_struct */
314 /* calculate kernel stack pointer from task struct 8k */
315         addik   r1, r1, THREAD_SIZE;
316         tophys(r1,r1);
317
318         addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
319         SAVE_REGS
320         swi     r0, r1, PTO + PT_R3
321         swi     r0, r1, PTO + PT_R4
322
323         swi     r0, r1, PTO + PT_MODE;                  /* Was in user-mode. */
324         lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
325         swi     r11, r1, PTO+PT_R1;             /* Store user SP.  */
326         clear_ums;
327 2:      lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
328         /* Save away the syscall number.  */
329         swi     r12, r1, PTO+PT_R0;
330         tovirt(r1,r1)
331
332 /* where the trap should return need -8 to adjust for rtsd r15, 8*/
333 /* Jump to the appropriate function for the system call number in r12
334  * (r12 is not preserved), or return an error if r12 is not valid. The LP
335  * register should point to the location where
336  * the called function should return.  [note that MAKE_SYS_CALL uses label 1] */
337
338         /* Step into virtual mode */
339         rtbd    r0, 3f
340         nop
341 3:
342         lwi     r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */
343         lwi     r11, r11, TI_FLAGS       /* get flags in thread info */
344         andi    r11, r11, _TIF_WORK_SYSCALL_MASK
345         beqi    r11, 4f
346
347         addik   r3, r0, -ENOSYS
348         swi     r3, r1, PTO + PT_R3
349         brlid   r15, do_syscall_trace_enter
350         addik   r5, r1, PTO + PT_R0
351
352         # do_syscall_trace_enter returns the new syscall nr.
353         addk    r12, r0, r3
354         lwi     r5, r1, PTO+PT_R5;
355         lwi     r6, r1, PTO+PT_R6;
356         lwi     r7, r1, PTO+PT_R7;
357         lwi     r8, r1, PTO+PT_R8;
358         lwi     r9, r1, PTO+PT_R9;
359         lwi     r10, r1, PTO+PT_R10;
360 4:
361 /* Jump to the appropriate function for the system call number in r12
362  * (r12 is not preserved), or return an error if r12 is not valid.
363  * The LP register should point to the location where the called function
364  * should return.  [note that MAKE_SYS_CALL uses label 1] */
365         /* See if the system call number is valid */
366         addi    r11, r12, -__NR_syscalls;
367         bgei    r11,5f;
368         /* Figure out which function to use for this system call.  */
369         /* Note Microblaze barrel shift is optional, so don't rely on it */
370         add     r12, r12, r12;                  /* convert num -> ptr */
371         add     r12, r12, r12;
372
373 #ifdef DEBUG
374         /* Trac syscalls and stored them to r0_ram */
375         lwi     r3, r12, 0x400 + r0_ram
376         addi    r3, r3, 1
377         swi     r3, r12, 0x400 + r0_ram
378 #endif
379
380         # Find and jump into the syscall handler.
381         lwi     r12, r12, sys_call_table
382         /* where the trap should return need -8 to adjust for rtsd r15, 8 */
383         addi    r15, r0, ret_from_trap-8
384         bra     r12
385
386         /* The syscall number is invalid, return an error.  */
387 5:
388         rtsd    r15, 8;         /* looks like a normal subroutine return */
389         addi    r3, r0, -ENOSYS;
390
391 /* Entry point used to return from a syscall/trap */
392 /* We re-enable BIP bit before state restore */
393 C_ENTRY(ret_from_trap):
394         swi     r3, r1, PTO + PT_R3
395         swi     r4, r1, PTO + PT_R4
396
397         lwi     r11, r1, PTO + PT_MODE;
398 /* See if returning to kernel mode, if so, skip resched &c.  */
399         bnei    r11, 2f;
400         /* We're returning to user mode, so check for various conditions that
401          * trigger rescheduling. */
402         /* FIXME: Restructure all these flag checks. */
403         lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
404         lwi     r11, r11, TI_FLAGS;             /* get flags in thread info */
405         andi    r11, r11, _TIF_WORK_SYSCALL_MASK
406         beqi    r11, 1f
407
408         brlid   r15, do_syscall_trace_leave
409         addik   r5, r1, PTO + PT_R0
410 1:
411         /* We're returning to user mode, so check for various conditions that
412          * trigger rescheduling. */
413         /* get thread info from current task */
414         lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
415         lwi     r11, r11, TI_FLAGS;             /* get flags in thread info */
416         andi    r11, r11, _TIF_NEED_RESCHED;
417         beqi    r11, 5f;
418
419         bralid  r15, schedule;  /* Call scheduler */
420         nop;                            /* delay slot */
421
422         /* Maybe handle a signal */
423 5:      /* get thread info from current task*/
424         lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
425         lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
426         andi    r11, r11, _TIF_SIGPENDING;
427         beqi    r11, 1f;                /* Signals to handle, handle them */
428
429         addik   r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
430         addi    r7, r0, 1;              /* Arg 3: int in_syscall */
431         bralid  r15, do_signal; /* Handle any signals */
432         add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
433
434 /* Finally, return to user state.  */
435 1:      set_bip;                        /*  Ints masked for state restore */
436         swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
437         VM_OFF;
438         tophys(r1,r1);
439         RESTORE_REGS;
440         addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
441         lwi     r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
442         bri     6f;
443
444 /* Return to kernel state.  */
445 2:      set_bip;                        /*  Ints masked for state restore */
446         VM_OFF;
447         tophys(r1,r1);
448         RESTORE_REGS;
449         addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
450         tovirt(r1,r1);
451 6:
452 TRAP_return:            /* Make global symbol for debugging */
453         rtbd    r14, 0; /* Instructions to return from an IRQ */
454         nop;
455
456
457 /* These syscalls need access to the struct pt_regs on the stack, so we
458    implement them in assembly (they're basically all wrappers anyway).  */
459
460 C_ENTRY(sys_fork_wrapper):
461         addi    r5, r0, SIGCHLD                 /* Arg 0: flags */
462         lwi     r6, r1, PTO+PT_R1       /* Arg 1: child SP (use parent's) */
463         addik   r7, r1, PTO                     /* Arg 2: parent context */
464         add     r8. r0, r0                      /* Arg 3: (unused) */
465         add     r9, r0, r0;                     /* Arg 4: (unused) */
466         brid    do_fork         /* Do real work (tail-call) */
467         add     r10, r0, r0;                    /* Arg 5: (unused) */
468
469 /* This the initial entry point for a new child thread, with an appropriate
470    stack in place that makes it look the the child is in the middle of an
471    syscall.  This function is actually `returned to' from switch_thread
472    (copy_thread makes ret_from_fork the return address in each new thread's
473    saved context).  */
474 C_ENTRY(ret_from_fork):
475         bralid  r15, schedule_tail; /* ...which is schedule_tail's arg */
476         add     r3, r5, r0;     /* switch_thread returns the prev task */
477                                 /* ( in the delay slot ) */
478         brid    ret_from_trap;  /* Do normal trap return */
479         add     r3, r0, r0;     /* Child's fork call should return 0. */
480
481 C_ENTRY(sys_vfork):
482         brid    microblaze_vfork        /* Do real work (tail-call) */
483         addik   r5, r1, PTO
484
485 C_ENTRY(sys_clone):
486         bnei    r6, 1f;                 /* See if child SP arg (arg 1) is 0. */
487         lwi     r6, r1, PTO + PT_R1;    /* If so, use paret's stack ptr */
488 1:      addik   r7, r1, PTO;                    /* Arg 2: parent context */
489         add     r8, r0, r0;                     /* Arg 3: (unused) */
490         add     r9, r0, r0;                     /* Arg 4: (unused) */
491         brid    do_fork         /* Do real work (tail-call) */
492         add     r10, r0, r0;                    /* Arg 5: (unused) */
493
494 C_ENTRY(sys_execve):
495         brid    microblaze_execve;      /* Do real work (tail-call).*/
496         addik   r8, r1, PTO;            /* add user context as 4th arg */
497
498 C_ENTRY(sys_rt_sigreturn_wrapper):
499         brid    sys_rt_sigreturn        /* Do real work */
500         addik   r5, r1, PTO;            /* add user context as 1st arg */
501
502 /*
503  * HW EXCEPTION rutine start
504  */
505 C_ENTRY(full_exception_trap):
506         /* adjust exception address for privileged instruction
507          * for finding where is it */
508         addik   r17, r17, -4
509         SAVE_STATE /* Save registers */
510         /* PC, before IRQ/trap - this is one instruction above */
511         swi     r17, r1, PTO+PT_PC;
512         tovirt(r1,r1)
513         /* FIXME this can be store directly in PT_ESR reg.
514          * I tested it but there is a fault */
515         /* where the trap should return need -8 to adjust for rtsd r15, 8 */
516         addik   r15, r0, ret_from_exc - 8
517         mfs     r6, resr
518         mfs     r7, rfsr;               /* save FSR */
519         mts     rfsr, r0;       /* Clear sticky fsr */
520         rted    r0, full_exception
521         addik   r5, r1, PTO              /* parameter struct pt_regs * regs */
522
523 /*
524  * Unaligned data trap.
525  *
526  * Unaligned data trap last on 4k page is handled here.
527  *
528  * Trap entered via exception, so EE bit is set, and interrupts
529  * are masked.  This is nice, means we don't have to CLI before state save
530  *
531  * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S"
532  */
533 C_ENTRY(unaligned_data_trap):
534         /* MS: I have to save r11 value and then restore it because
535          * set_bit, clear_eip, set_ee use r11 as temp register if MSR
536          * instructions are not used. We don't need to do if MSR instructions
537          * are used and they use r0 instead of r11.
538          * I am using ENTRY_SP which should be primary used only for stack
539          * pointer saving. */
540         swi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
541         set_bip;        /* equalize initial state for all possible entries */
542         clear_eip;
543         set_ee;
544         lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
545         SAVE_STATE              /* Save registers.*/
546         /* PC, before IRQ/trap - this is one instruction above */
547         swi     r17, r1, PTO+PT_PC;
548         tovirt(r1,r1)
549         /* where the trap should return need -8 to adjust for rtsd r15, 8 */
550         addik   r15, r0, ret_from_exc-8
551         mfs     r3, resr                /* ESR */
552         mfs     r4, rear                /* EAR */
553         rtbd    r0, _unaligned_data_exception
554         addik   r7, r1, PTO             /* parameter struct pt_regs * regs */
555
556 /*
557  * Page fault traps.
558  *
559  * If the real exception handler (from hw_exception_handler.S) didn't find
560  * the mapping for the process, then we're thrown here to handle such situation.
561  *
562  * Trap entered via exceptions, so EE bit is set, and interrupts
563  * are masked.  This is nice, means we don't have to CLI before state save
564  *
565  * Build a standard exception frame for TLB Access errors.  All TLB exceptions
566  * will bail out to this point if they can't resolve the lightweight TLB fault.
567  *
568  * The C function called is in "arch/microblaze/mm/fault.c", declared as:
569  * void do_page_fault(struct pt_regs *regs,
570  *                              unsigned long address,
571  *                              unsigned long error_code)
572  */
573 /* data and intruction trap - which is choose is resolved int fault.c */
574 C_ENTRY(page_fault_data_trap):
575         SAVE_STATE              /* Save registers.*/
576         /* PC, before IRQ/trap - this is one instruction above */
577         swi     r17, r1, PTO+PT_PC;
578         tovirt(r1,r1)
579         /* where the trap should return need -8 to adjust for rtsd r15, 8 */
580         addik   r15, r0, ret_from_exc-8
581         mfs     r6, rear                /* parameter unsigned long address */
582         mfs     r7, resr                /* parameter unsigned long error_code */
583         rted    r0, do_page_fault
584         addik   r5, r1, PTO             /* parameter struct pt_regs * regs */
585
586 C_ENTRY(page_fault_instr_trap):
587         SAVE_STATE              /* Save registers.*/
588         /* PC, before IRQ/trap - this is one instruction above */
589         swi     r17, r1, PTO+PT_PC;
590         tovirt(r1,r1)
591         /* where the trap should return need -8 to adjust for rtsd r15, 8 */
592         addik   r15, r0, ret_from_exc-8
593         mfs     r6, rear                /* parameter unsigned long address */
594         ori     r7, r0, 0               /* parameter unsigned long error_code */
595         rted    r0, do_page_fault
596         addik   r5, r1, PTO             /* parameter struct pt_regs * regs */
597
598 /* Entry point used to return from an exception.  */
599 C_ENTRY(ret_from_exc):
600         lwi     r11, r1, PTO + PT_MODE;
601         bnei    r11, 2f;                /* See if returning to kernel mode, */
602                                         /* ... if so, skip resched &c.  */
603
604         /* We're returning to user mode, so check for various conditions that
605            trigger rescheduling. */
606         lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
607         lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
608         andi    r11, r11, _TIF_NEED_RESCHED;
609         beqi    r11, 5f;
610
611 /* Call the scheduler before returning from a syscall/trap. */
612         bralid  r15, schedule;  /* Call scheduler */
613         nop;                            /* delay slot */
614
615         /* Maybe handle a signal */
616 5:      lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
617         lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
618         andi    r11, r11, _TIF_SIGPENDING;
619         beqi    r11, 1f;                /* Signals to handle, handle them */
620
621         /*
622          * Handle a signal return; Pending signals should be in r18.
623          *
624          * Not all registers are saved by the normal trap/interrupt entry
625          * points (for instance, call-saved registers (because the normal
626          * C-compiler calling sequence in the kernel makes sure they're
627          * preserved), and call-clobbered registers in the case of
628          * traps), but signal handlers may want to examine or change the
629          * complete register state.  Here we save anything not saved by
630          * the normal entry sequence, so that it may be safely restored
631          * (in a possibly modified form) after do_signal returns. */
632         addik   r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
633         addi    r7, r0, 0;              /* Arg 3: int in_syscall */
634         bralid  r15, do_signal; /* Handle any signals */
635         add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
636
637 /* Finally, return to user state.  */
638 1:      set_bip;                        /* Ints masked for state restore */
639         swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
640         VM_OFF;
641         tophys(r1,r1);
642
643         RESTORE_REGS;
644         addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
645
646         lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
647         bri     6f;
648 /* Return to kernel state.  */
649 2:      set_bip;                        /* Ints masked for state restore */
650         VM_OFF;
651         tophys(r1,r1);
652         RESTORE_REGS;
653         addik   r1, r1, STATE_SAVE_SIZE         /* Clean up stack space.  */
654
655         tovirt(r1,r1);
656 6:
657 EXC_return:             /* Make global symbol for debugging */
658         rtbd    r14, 0; /* Instructions to return from an IRQ */
659         nop;
660
661 /*
662  * HW EXCEPTION rutine end
663  */
664
665 /*
666  * Hardware maskable interrupts.
667  *
668  * The stack-pointer (r1) should have already been saved to the memory
669  * location PER_CPU(ENTRY_SP).
670  */
671 C_ENTRY(_interrupt):
672 /* MS: we are in physical address */
673 /* Save registers, switch to proper stack, convert SP to virtual.*/
674         swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
675         /* MS: See if already in kernel mode. */
676         mfs     r1, rmsr
677         nop
678         andi    r1, r1, MSR_UMS
679         bnei    r1, 1f
680
681 /* Kernel-mode state save. */
682         lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
683         tophys(r1,r1); /* MS: I have in r1 physical address where stack is */
684         /* save registers */
685 /* MS: Make room on the stack -> activation record */
686         addik   r1, r1, -STATE_SAVE_SIZE;
687         SAVE_REGS
688         brid    2f;
689         swi     r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */
690 1:
691 /* User-mode state save. */
692  /* MS: get the saved current */
693         lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
694         tophys(r1,r1);
695         lwi     r1, r1, TS_THREAD_INFO;
696         addik   r1, r1, THREAD_SIZE;
697         tophys(r1,r1);
698         /* save registers */
699         addik   r1, r1, -STATE_SAVE_SIZE;
700         SAVE_REGS
701         /* calculate mode */
702         swi     r0, r1, PTO + PT_MODE;
703         lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
704         swi     r11, r1, PTO+PT_R1;
705         clear_ums;
706 2:
707         lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
708         tovirt(r1,r1)
709         addik   r15, r0, irq_call;
710 irq_call:rtbd   r0, do_IRQ;
711         addik   r5, r1, PTO;
712
713 /* MS: we are in virtual mode */
714 ret_from_irq:
715         lwi     r11, r1, PTO + PT_MODE;
716         bnei    r11, 2f;
717
718         lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
719         lwi     r11, r11, TI_FLAGS; /* MS: get flags from thread info */
720         andi    r11, r11, _TIF_NEED_RESCHED;
721         beqi    r11, 5f
722         bralid  r15, schedule;
723         nop; /* delay slot */
724
725     /* Maybe handle a signal */
726 5:      lwi     r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
727         lwi     r11, r11, TI_FLAGS; /* get flags in thread info */
728         andi    r11, r11, _TIF_SIGPENDING;
729         beqid   r11, no_intr_resched
730 /* Handle a signal return; Pending signals should be in r18. */
731         addi    r7, r0, 0; /* Arg 3: int in_syscall */
732         addik   r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
733         bralid  r15, do_signal; /* Handle any signals */
734         add     r6, r0, r0; /* Arg 2: sigset_t *oldset */
735
736 /* Finally, return to user state. */
737 no_intr_resched:
738     /* Disable interrupts, we are now committed to the state restore */
739         disable_irq
740         swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE);
741         VM_OFF;
742         tophys(r1,r1);
743         RESTORE_REGS
744         addik   r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
745         lwi     r1, r1, PT_R1 - PT_SIZE;
746         bri     6f;
747 /* MS: Return to kernel state. */
748 2:
749 #ifdef CONFIG_PREEMPT
750         lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
751         /* MS: get preempt_count from thread info */
752         lwi     r5, r11, TI_PREEMPT_COUNT;
753         bgti    r5, restore;
754
755         lwi     r5, r11, TI_FLAGS;              /* get flags in thread info */
756         andi    r5, r5, _TIF_NEED_RESCHED;
757         beqi    r5, restore /* if zero jump over */
758
759 preempt:
760         /* interrupts are off that's why I am calling preempt_chedule_irq */
761         bralid  r15, preempt_schedule_irq
762         nop
763         lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
764         lwi     r5, r11, TI_FLAGS;              /* get flags in thread info */
765         andi    r5, r5, _TIF_NEED_RESCHED;
766         bnei    r5, preempt /* if non zero jump to resched */
767 restore:
768 #endif
769         VM_OFF /* MS: turn off MMU */
770         tophys(r1,r1)
771         RESTORE_REGS
772         addik   r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
773         tovirt(r1,r1);
774 6:
775 IRQ_return: /* MS: Make global symbol for debugging */
776         rtid    r14, 0
777         nop
778
779 /*
780  * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18
781  * and call handling function with saved pt_regs
782  */
783 C_ENTRY(_debug_exception):
784         /* BIP bit is set on entry, no interrupts can occur */
785         swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
786
787         mfs     r1, rmsr
788         nop
789         andi    r1, r1, MSR_UMS
790         bnei    r1, 1f
791 /* MS: Kernel-mode state save - kgdb */
792         lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
793
794         /* BIP bit is set on entry, no interrupts can occur */
795         addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
796         SAVE_REGS;
797         /* save all regs to pt_reg structure */
798         swi     r0, r1, PTO+PT_R0;      /* R0 must be saved too */
799         swi     r14, r1, PTO+PT_R14     /* rewrite saved R14 value */
800         swi     r16, r1, PTO+PT_PC; /* PC and r16 are the same */
801         /* save special purpose registers to pt_regs */
802         mfs     r11, rear;
803         swi     r11, r1, PTO+PT_EAR;
804         mfs     r11, resr;
805         swi     r11, r1, PTO+PT_ESR;
806         mfs     r11, rfsr;
807         swi     r11, r1, PTO+PT_FSR;
808
809         /* stack pointer is in physical address at it is decrease
810          * by STATE_SAVE_SIZE but we need to get correct R1 value */
811         addik   r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE;
812         swi     r11, r1, PTO+PT_R1
813         /* MS: r31 - current pointer isn't changed */
814         tovirt(r1,r1)
815 #ifdef CONFIG_KGDB
816         addi    r5, r1, PTO /* pass pt_reg address as the first arg */
817         la      r15, r0, dbtrap_call; /* return address */
818         rtbd    r0, microblaze_kgdb_break
819         nop;
820 #endif
821         /* MS: Place handler for brki from kernel space if KGDB is OFF.
822          * It is very unlikely that another brki instruction is called. */
823         bri 0
824
825 /* MS: User-mode state save - gdb */
826 1:      lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
827         tophys(r1,r1);
828         lwi     r1, r1, TS_THREAD_INFO; /* get the thread info */
829         addik   r1, r1, THREAD_SIZE;    /* calculate kernel stack pointer */
830         tophys(r1,r1);
831
832         addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
833         SAVE_REGS;
834         swi     r16, r1, PTO+PT_PC;     /* Save LP */
835         swi     r0, r1, PTO + PT_MODE; /* Was in user-mode.  */
836         lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
837         swi     r11, r1, PTO+PT_R1; /* Store user SP.  */
838         lwi     CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
839         tovirt(r1,r1)
840         set_vms;
841         addik   r5, r1, PTO;
842         addik   r15, r0, dbtrap_call;
843 dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
844         rtbd    r0, sw_exception
845         nop
846
847         /* MS: The first instruction for the second part of the gdb/kgdb */
848         set_bip; /* Ints masked for state restore */
849         lwi     r11, r1, PTO + PT_MODE;
850         bnei    r11, 2f;
851 /* MS: Return to user space - gdb */
852         /* Get current task ptr into r11 */
853         lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
854         lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
855         andi    r11, r11, _TIF_NEED_RESCHED;
856         beqi    r11, 5f;
857
858         /* Call the scheduler before returning from a syscall/trap. */
859         bralid  r15, schedule;  /* Call scheduler */
860         nop;                            /* delay slot */
861
862         /* Maybe handle a signal */
863 5:      lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
864         lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
865         andi    r11, r11, _TIF_SIGPENDING;
866         beqi    r11, 1f;                /* Signals to handle, handle them */
867
868         addik   r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
869         addi  r7, r0, 0;        /* Arg 3: int in_syscall */
870         bralid  r15, do_signal; /* Handle any signals */
871         add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
872
873 /* Finally, return to user state.  */
874 1:      swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
875         VM_OFF;
876         tophys(r1,r1);
877         /* MS: Restore all regs */
878         RESTORE_REGS
879         addik   r1, r1, STATE_SAVE_SIZE  /* Clean up stack space */
880         lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
881 DBTRAP_return_user: /* MS: Make global symbol for debugging */
882         rtbd    r16, 0; /* MS: Instructions to return from a debug trap */
883         nop;
884
885 /* MS: Return to kernel state - kgdb */
886 2:      VM_OFF;
887         tophys(r1,r1);
888         /* MS: Restore all regs */
889         RESTORE_REGS
890         lwi     r14, r1, PTO+PT_R14;
891         lwi     r16, r1, PTO+PT_PC;
892         addik   r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
893         tovirt(r1,r1);
894 DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
895         rtbd    r16, 0; /* MS: Instructions to return from a debug trap */
896         nop;
897
898
899 ENTRY(_switch_to)
900         /* prepare return value */
901         addk    r3, r0, CURRENT_TASK
902
903         /* save registers in cpu_context */
904         /* use r11 and r12, volatile registers, as temp register */
905         /* give start of cpu_context for previous process */
906         addik   r11, r5, TI_CPU_CONTEXT
907         swi     r1, r11, CC_R1
908         swi     r2, r11, CC_R2
909         /* skip volatile registers.
910          * they are saved on stack when we jumped to _switch_to() */
911         /* dedicated registers */
912         swi     r13, r11, CC_R13
913         swi     r14, r11, CC_R14
914         swi     r15, r11, CC_R15
915         swi     r16, r11, CC_R16
916         swi     r17, r11, CC_R17
917         swi     r18, r11, CC_R18
918         /* save non-volatile registers */
919         swi     r19, r11, CC_R19
920         swi     r20, r11, CC_R20
921         swi     r21, r11, CC_R21
922         swi     r22, r11, CC_R22
923         swi     r23, r11, CC_R23
924         swi     r24, r11, CC_R24
925         swi     r25, r11, CC_R25
926         swi     r26, r11, CC_R26
927         swi     r27, r11, CC_R27
928         swi     r28, r11, CC_R28
929         swi     r29, r11, CC_R29
930         swi     r30, r11, CC_R30
931         /* special purpose registers */
932         mfs     r12, rmsr
933         swi     r12, r11, CC_MSR
934         mfs     r12, rear
935         swi     r12, r11, CC_EAR
936         mfs     r12, resr
937         swi     r12, r11, CC_ESR
938         mfs     r12, rfsr
939         swi     r12, r11, CC_FSR
940
941         /* update r31, the current-give me pointer to task which will be next */
942         lwi     CURRENT_TASK, r6, TI_TASK
943         /* stored it to current_save too */
944         swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE)
945
946         /* get new process' cpu context and restore */
947         /* give me start where start context of next task */
948         addik   r11, r6, TI_CPU_CONTEXT
949
950         /* non-volatile registers */
951         lwi     r30, r11, CC_R30
952         lwi     r29, r11, CC_R29
953         lwi     r28, r11, CC_R28
954         lwi     r27, r11, CC_R27
955         lwi     r26, r11, CC_R26
956         lwi     r25, r11, CC_R25
957         lwi     r24, r11, CC_R24
958         lwi     r23, r11, CC_R23
959         lwi     r22, r11, CC_R22
960         lwi     r21, r11, CC_R21
961         lwi     r20, r11, CC_R20
962         lwi     r19, r11, CC_R19
963         /* dedicated registers */
964         lwi     r18, r11, CC_R18
965         lwi     r17, r11, CC_R17
966         lwi     r16, r11, CC_R16
967         lwi     r15, r11, CC_R15
968         lwi     r14, r11, CC_R14
969         lwi     r13, r11, CC_R13
970         /* skip volatile registers */
971         lwi     r2, r11, CC_R2
972         lwi     r1, r11, CC_R1
973
974         /* special purpose registers */
975         lwi     r12, r11, CC_FSR
976         mts     rfsr, r12
977         lwi     r12, r11, CC_MSR
978         mts     rmsr, r12
979
980         rtsd    r15, 8
981         nop
982
983 ENTRY(_reset)
984         brai    0x70; /* Jump back to FS-boot */
985
986         /* These are compiled and loaded into high memory, then
987          * copied into place in mach_early_setup */
988         .section        .init.ivt, "ax"
989         .org    0x0
990         /* this is very important - here is the reset vector */
991         /* in current MMU branch you don't care what is here - it is
992          * used from bootloader site - but this is correct for FS-BOOT */
993         brai    0x70
994         nop
995         brai    TOPHYS(_user_exception); /* syscall handler */
996         brai    TOPHYS(_interrupt);     /* Interrupt handler */
997         brai    TOPHYS(_debug_exception);       /* debug trap handler */
998         brai    TOPHYS(_hw_exception_handler);  /* HW exception handler */
999
1000 .section .rodata,"a"
1001 #include "syscall_table.S"
1002
1003 syscall_table_size=(.-sys_call_table)
1004
1005 type_SYSCALL:
1006         .ascii "SYSCALL\0"
1007 type_IRQ:
1008         .ascii "IRQ\0"
1009 type_IRQ_PREEMPT:
1010         .ascii "IRQ (PREEMPTED)\0"
1011 type_SYSCALL_PREEMPT:
1012         .ascii " SYSCALL (PREEMPTED)\0"
1013
1014         /*
1015          * Trap decoding for stack unwinder
1016          * Tuples are (start addr, end addr, string)
1017          * If return address lies on [start addr, end addr],
1018          * unwinder displays 'string'
1019          */
1020
1021         .align 4
1022 .global microblaze_trap_handlers
1023 microblaze_trap_handlers:
1024         /* Exact matches come first */
1025         .word ret_from_trap; .word ret_from_trap   ; .word type_SYSCALL
1026         .word ret_from_irq ; .word ret_from_irq    ; .word type_IRQ
1027         /* Fuzzy matches go here */
1028         .word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT
1029         .word ret_from_trap; .word TRAP_return     ; .word type_SYSCALL_PREEMPT
1030         /* End of table */
1031         .word 0               ; .word 0               ; .word 0