import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / mips / kernel / entry.S
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1994 - 2000, 2001 by Ralf Baechle
7  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8  * Copyright (C) 2001 MIPS Technologies, Inc.
9  */
10 #include <linux/config.h>
11 #include <linux/init.h>
12 #include <linux/sys.h>
13
14 #include <asm/addrspace.h>
15 #include <asm/asm.h>
16 #include <asm/cacheops.h>
17 #include <asm/current.h>
18 #include <asm/errno.h>
19 #include <asm/mipsregs.h>
20 #include <asm/page.h>
21 #include <asm/pgtable-bits.h>
22 #include <asm/stackframe.h>
23 #include <asm/processor.h>
24 #include <asm/regdef.h>
25 #include <asm/fpregdef.h>
26 #include <asm/unistd.h>
27 #include <asm/isadep.h>
28
29
30                 .text
31                 .align  5
32                 .set    push
33                 .set    reorder
34 FEXPORT(ret_from_irq)
35 FEXPORT(ret_from_exception)
36                 lw      t0, PT_STATUS(sp)       # returning to kernel mode?
37                 andi    t0, t0, KU_USER
38                 beqz    t0, restore_all
39
40 FEXPORT(ret_from_sys_call)              # here to prevent code duplication
41 ret_from_schedule:
42                 mfc0    t0, CP0_STATUS  # need_resched and signals atomic test
43                 ori     t0, t0, 1
44                 xori    t0, t0, 1
45                 mtc0    t0, CP0_STATUS
46                 SSNOP; SSNOP; SSNOP
47
48                 lw      v0, TASK_NEED_RESCHED($28)
49                 lw      v1, TASK_SIGPENDING($28)
50                 bnez    v0, reschedule
51                 bnez    v1, signal_return
52 restore_all:    .set    noat
53                 RESTORE_ALL_AND_RET
54                 .set    at
55
56 /* Put this behind restore_all for the sake of the branch prediction.  */
57 signal_return:
58                 .type   signal_return, @function
59
60                 mfc0    t0, CP0_STATUS
61                 ori     t0, t0, 1
62                 mtc0    t0, CP0_STATUS
63
64                 move    a0, zero
65                 move    a1, sp
66                 jal     do_signal
67                 b       restore_all
68
69 reschedule:
70                 jal     schedule
71                 b       ret_from_schedule
72
73 /*
74  * Common spurious interrupt handler.
75  */
76                 .text
77                 .align  5
78 LEAF(spurious_interrupt)
79                 /*
80                  * Someone tried to fool us by sending an interrupt but we
81                  * couldn't find a cause for it.
82                  */
83                 lui     t1,%hi(irq_err_count)
84                 lw      t0,%lo(irq_err_count)(t1)
85                 addiu   t0,1
86                 sw      t0,%lo(irq_err_count)(t1)
87                 j       ret_from_irq
88 END(spurious_interrupt)
89
90                 __INIT
91
92                 .set    reorder
93
94 NESTED(except_vec1_generic, 0, sp)
95                 PANIC("Exception vector 1 called")
96 END(except_vec1_generic)
97
98                 /*
99                  * General exception vector.  Used for all CPUs except R4000
100                  * and R4400 SC and MC versions.
101                  */
102 NESTED(except_vec3_generic, 0, sp)
103 #if R5432_CP0_INTERRUPT_WAR
104                 mfc0    k0, CP0_INDEX
105 #endif
106                 mfc0    k1, CP0_CAUSE
107                 la      k0, exception_handlers
108                 andi    k1, k1, 0x7c
109                 addu    k0, k0, k1
110                 lw      k0, (k0)
111                 jr      k0
112 END(except_vec3_generic)
113                 .set    at
114
115                 /* General exception vector R4000 version. */
116 NESTED(except_vec3_r4000, 0, sp)
117                 .set    push
118                 .set    mips3
119                 .set    noat
120                 mfc0    k1, CP0_CAUSE
121                 li      k0, 31<<2
122                 andi    k1, k1, 0x7c
123                 .set    noreorder
124                 beq     k1, k0, handle_vced
125                  li     k0, 14<<2
126                 beq     k1, k0, handle_vcei
127                  la     k0, exception_handlers
128                 .set    reorder
129                 addu    k0, k0, k1
130                 lw      k0, (k0)
131                 jr      k0
132
133                 /*
134                  * Big shit, we now may have two dirty primary cache lines for
135                  * the same physical address.  We can savely invalidate the
136                  * line pointed to by c0_badvaddr because after return from
137                  * this exception handler the load / store will be re-executed.
138                  */
139 handle_vced:
140                 mfc0    k0, CP0_BADVADDR
141                 li      k1, -4
142                 and     k0, k1
143                 mtc0    zero, CP0_TAGLO
144                 cache   Index_Store_Tag_D,(k0)
145                 cache   Hit_Writeback_Inv_SD,(k0)
146 #ifdef CONFIG_PROC_FS
147                 lui     k0, %hi(vced_count)
148                 lw      k1, %lo(vced_count)(k0)
149                 addiu   k1, 1
150                 sw      k1, %lo(vced_count)(k0)
151 #endif
152                 eret
153
154 handle_vcei:
155                 mfc0    k0, CP0_BADVADDR
156                 cache   Hit_Writeback_Inv_SD, (k0)      # also cleans pi
157 #ifdef CONFIG_PROC_FS
158                 lui     k0, %hi(vcei_count)
159                 lw      k1, %lo(vcei_count)(k0)
160                 addiu   k1, 1
161                 sw      k1, %lo(vcei_count)(k0)
162 #endif
163                 eret
164                 .set    pop
165 END(except_vec3_r4000)
166
167                 __FINIT
168
169 /*
170  * Build a default exception handler for the exceptions that don't need
171  * special handlers.  If you didn't know yet - I *like* playing games with
172  * the C preprocessor ...
173  */
174 #define __BUILD_clear_none(exception)
175 #define __BUILD_clear_sti(exception)                                    \
176                 STI
177 #define __BUILD_clear_cli(exception)                                    \
178                 CLI
179 #define __BUILD_clear_fpe(exception)                                    \
180                 cfc1    a1,fcr31;                                       \
181                 li      a2,~(0x3f<<12);                                 \
182                 and     a2,a1;                                          \
183                 ctc1    a2,fcr31;                                       \
184                 STI
185 #define __BUILD_clear_ade(exception)                                    \
186                 .set    reorder;                                        \
187                 MFC0    t0,CP0_BADVADDR;                                \
188                 .set    noreorder;                                      \
189                 REG_S   t0,PT_BVADDR(sp);                               \
190                 KMODE
191 #define __BUILD_silent(exception)
192
193 #define fmt "Got %s at %08lx.\n"
194
195 #define __BUILD_verbose(exception)                                      \
196                 la      a1,8f;                                          \
197                 TEXT    (#exception);                                   \
198                 REG_L   a2,PT_EPC(sp);                                  \
199                 PRINT(fmt)
200 #define __BUILD_count(exception)                                        \
201                 .set    reorder;                                        \
202                 lw      t0,exception_count_##exception;                 \
203                 .set    noreorder;                                      \
204                 addiu   t0, 1;                                          \
205                 sw      t0,exception_count_##exception;                 \
206                 .data;                                                  \
207 EXPORT(exception_count_##exception);                                    \
208                 .word   0;                                              \
209                 .previous;
210 #define BUILD_HANDLER(exception,handler,clear,verbose)                  \
211                 .align  5;                                              \
212 NESTED(handle_##exception, PT_SIZE, sp);                                \
213                 .set    noat;                                           \
214                 SAVE_ALL;                                               \
215 FEXPORT(handle_##exception##_int);                                      \
216                 __BUILD_clear_##clear(exception);                       \
217                 .set    at;                                             \
218                 __BUILD_##verbose(exception);                           \
219                 jal     do_##handler;                                   \
220                  move   a0, sp;                                         \
221                 j       ret_from_exception;                             \
222                  nop;                                                   \
223 END(handle_##exception)
224
225                 BUILD_HANDLER(adel,ade,ade,silent)              /* #4  */
226                 BUILD_HANDLER(ades,ade,ade,silent)              /* #5  */
227                 BUILD_HANDLER(ibe,be,cli,silent)                /* #6  */
228                 BUILD_HANDLER(dbe,be,cli,silent)                /* #7  */
229                 BUILD_HANDLER(bp,bp,sti,silent)                 /* #9  */
230                 BUILD_HANDLER(ri,ri,sti,silent)                 /* #10 */
231                 BUILD_HANDLER(cpu,cpu,sti,silent)               /* #11 */
232                 BUILD_HANDLER(ov,ov,sti,silent)                 /* #12 */
233                 BUILD_HANDLER(tr,tr,sti,silent)                 /* #13 */
234                 BUILD_HANDLER(fpe,fpe,fpe,silent)               /* #15 */
235                 BUILD_HANDLER(mdmx,mdmx,sti,silent)             /* #22 */
236                 BUILD_HANDLER(watch,watch,sti,silent)           /* #23 */
237                 BUILD_HANDLER(mcheck,mcheck,cli,silent)         /* #24 */
238                 BUILD_HANDLER(reserved,reserved,sti,silent)     /* others */
239
240                 .set    pop
241
242 /*
243  * Table of syscalls
244  */
245                 .data
246                 .align  PTRLOG
247 EXPORT(sys_call_table)
248 #define SYS(call, narg) PTR call
249
250                 /* Reserved space for all SVR4 syscalls. */
251                 .space  (1000)*PTRSIZE
252
253 #ifdef CONFIG_BINFMT_IRIX
254                 /* 32bit IRIX5 system calls. */
255 #include "irix5sys.h"
256 #else
257                 .space  (1000)*PTRSIZE          /* No IRIX syscalls */
258 #endif
259
260                 /* Reserved space for all the BSD43 and POSIX syscalls. */
261                 .space  (2000)*PTRSIZE
262
263                 /* Linux flavoured syscalls. */
264 #include "syscalls.h"
265
266 /*
267  * Number of arguments of each syscall
268  */
269 EXPORT(sys_narg_table)
270 #undef SYS
271 #define SYS(call, narg) .byte narg
272
273                 /* Reserved space for all SVR4 flavoured syscalls. */
274                 .space  (1000)
275
276 #ifdef CONFIG_BINFMT_IRIX
277                 /* 32bit IRIX5 system calls. */
278 #include "irix5sys.h"
279 #else
280                 .space  (1000)                  /* No IRIX syscalls */
281 #endif
282
283                 /* Reserved space for all the BSD43 and POSIX syscalls. */
284                 .space  (2000)
285
286                 /* Linux flavoured syscalls. */
287 #include "syscalls.h"