/* [<][>][^][v][top][bottom][index][help] */
1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3 * The President and Fellows of Harvard College.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <kern/mips/regdefs.h>
31 #include <mips/specialreg.h>
32
33 /*
34 * Entry points for exceptions.
35 *
36 * MIPS-1 (r2000/r3000) style exception handling, with the "rfe"
37 * instruction rather than "eret", and the three sets of status bits.
38 */
39
40
41 /*
42 * Do not allow the assembler to use $1 (at), because we need to be
43 * able to save it.
44 */
45 .set noat
46 .set noreorder
47
48 /*
49 * UTLB exception handler.
50 *
51 * This code is copied to address 0x80000000, where the MIPS processor
52 * automatically invokes it.
53 *
54 * To avoid colliding with the other exception code, it must not
55 * exceed 128 bytes (32 instructions).
56 *
57 * This is the special entry point for the fast-path TLB refill for
58 * faults in the user address space. We don't implement fast-path TLB
59 * refill by default. Note that if you do, you either need to make
60 * sure the refill code doesn't fault or write extra code in
61 * common_exception to tidy up after such faults.
62 */
63
64 .text
65 .globl mips_utlb_handler
66 .type mips_utlb_handler,@function
67 .ent mips_utlb_handler
68 mips_utlb_handler:
69 j common_exception /* Don't need to do anything special */
70 nop /* Delay slot */
71 .globl mips_utlb_end
72 mips_utlb_end:
73 .end mips_utlb_handler
74
75 /*
76 * General exception handler.
77 *
78 * This code is copied to address 0x80000080, where
79 * the MIPS processor automatically invokes it.
80 */
81
82 .text
83 .globl mips_general_handler
84 .type mips_general_handler,@function
85 .ent mips_general_handler
86 mips_general_handler:
87 j common_exception /* Don't need to do anything special */
88 nop /* Delay slot */
89 .globl mips_general_end
90 mips_general_end:
91 .end mips_general_handler
92
93 /* This keeps gdb from conflating common_exception and mips_general_end */
94 nop /* padding */
95
96
97 /*
98 * Shared exception code for both handlers.
99 */
100
101 .text
102 .type common_exception,@function
103 .ent common_exception
104 common_exception:
105 mfc0 k0, c0_status /* Get status register */
106 andi k0, k0, CST_KUp /* Check the we-were-in-user-mode bit */
107 beq k0, $0, 1f /* If clear, from kernel, already have stack */
108 nop /* delay slot */
109
110 /* Coming from user mode - find kernel stack */
111 mfc0 k1, c0_context /* we keep the CPU number here */
112 srl k1, k1, CTX_PTBASESHIFT /* shift it to get just the CPU number */
113 sll k1, k1, 2 /* shift it back to make an array index */
114 lui k0, %hi(cpustacks) /* get base address of cpustacks[] */
115 addu k0, k0, k1 /* index it */
116 move k1, sp /* Save previous stack pointer in k1 */
117 b 2f /* Skip to common code */
118 lw sp, %lo(cpustacks)(k0) /* Load kernel stack pointer (in delay slot) */
119 1:
120 /* Coming from kernel mode - just save previous stuff */
121 move k1, sp /* Save previous stack in k1 (delay slot) */
122 2:
123 /*
124 * At this point:
125 * Interrupts are off. (The processor did this for us.)
126 * k0 contains the value for curthread, to go into s7.
127 * k1 contains the old stack pointer.
128 * sp points into the kernel stack.
129 * All other registers are untouched.
130 */
131
132 /*
133 * Allocate stack space for 37 words to hold the trap frame,
134 * plus four more words for a minimal argument block, plus
135 * one more for proper (64-bit) stack alignment.
136 */
137 addi sp, sp, -168
138
139 /*
140 * Save general registers.
141 * We exclude k0/k1, which the kernel is free to clobber (and which
142 * we already have clobbered), and $0, whose value is fixed.
143 *
144 * The order here must match mips/include/trapframe.h.
145 *
146 * gdb disassembles this code to try to figure out what registers
147 * are where, and it isn't very bright. So in order to make gdb be
148 * able to trace the stack back through here, we play some silly
149 * games.
150 *
151 * In particular:
152 * (1) We store the return address register into the epc slot,
153 * which makes gdb think it's the return address slot. Then
154 * we store the real epc value over that.
155 * (2) We store the current sp into the sp slot, which makes gdb
156 * think it's the stack pointer slot. Then we store the real
157 * value.
158 * (3) gdb also assumes that saved registers in a function are
159 * saved in order. This is why we put epc where it is, and
160 * handle the real value of ra afterwards.
161 * (4) Because gdb will think we're saving k0 and k1, we need to
162 * leave slots for them in the trap frame, even though the
163 * stuff we save there is useless.
164 *
165 * This logic has not been tested against a recent gdb and has
166 * probably bitrotted. Someone(TM) should figure out what gdb
167 * currently expects -- or maybe even patch gdb to understand a
168 * better form of this that doesn't waste so many cycles.
169 */
170 sw ra, 160(sp) /* dummy for gdb */
171 sw s8, 156(sp) /* save s8 */
172 sw sp, 152(sp) /* dummy for gdb */
173 sw gp, 148(sp) /* save gp */
174 sw k1, 144(sp) /* dummy for gdb */
175 sw k0, 140(sp) /* dummy for gdb */
176
177 sw k1, 152(sp) /* real saved sp */
178 nop /* delay slot for store */
179
180 mfc0 k1, c0_epc /* Copr.0 reg 13 == PC for exception */
181 sw k1, 160(sp) /* real saved PC */
182
183 sw t9, 136(sp)
184 sw t8, 132(sp)
185 sw s7, 128(sp)
186 sw s6, 124(sp)
187 sw s5, 120(sp)
188 sw s4, 116(sp)
189 sw s3, 112(sp)
190 sw s2, 108(sp)
191 sw s1, 104(sp)
192 sw s0, 100(sp)
193 sw t7, 96(sp)
194 sw t6, 92(sp)
195 sw t5, 88(sp)
196 sw t4, 84(sp)
197 sw t3, 80(sp)
198 sw t2, 76(sp)
199 sw t1, 72(sp)
200 sw t0, 68(sp)
201 sw a3, 64(sp)
202 sw a2, 60(sp)
203 sw a1, 56(sp)
204 sw a0, 52(sp)
205 sw v1, 48(sp)
206 sw v0, 44(sp)
207 sw AT, 40(sp)
208
209 sw ra, 36(sp)
210
211 /*
212 * Save special registers.
213 */
214 mfhi t0
215 mflo t1
216 sw t0, 32(sp)
217 sw t1, 28(sp)
218
219 /*
220 * Save remaining exception context information.
221 */
222
223 mfc0 t2, c0_status /* Copr.0 reg 11 == status */
224 sw t2, 20(sp)
225 mfc0 t3, c0_vaddr /* Copr.0 reg 8 == faulting vaddr */
226 sw t3, 16(sp)
227 mfc0 t4, c0_cause
228 sw t4, 24(sp) /* Copr.0 reg 13 == exception cause */
229
230 /*
231 * Pretend to save $0 for gdb's benefit.
232 */
233 sw $0, 12(sp)
234
235 /*
236 * Load the curthread register if coming from user mode.
237 */
238 andi k0, t2, CST_KUp /* Check the we-were-in-user-mode bit */
239 beq k0, $0, 3f /* If clear, were in kernel, skip ahead */
240 nop /* delay slot */
241
242 mfc0 k1, c0_context /* we keep the CPU number here */
243 srl k1, k1, CTX_PTBASESHIFT /* shift it to get just the CPU number */
244 sll k1, k1, 2 /* shift it back to make an array index */
245 lui k0, %hi(cputhreads) /* get base address of cputhreads[] */
246 addu k0, k0, k1 /* index it */
247 lw s7, %lo(cputhreads)(k0) /* Load curthread value */
248 3:
249
250 /*
251 * Load the kernel GP value.
252 */
253 la gp, _gp
254
255 /*
256 * Prepare to call mips_trap(struct trapframe *)
257 */
258
259 addiu a0, sp, 16 /* set argument - pointer to the trapframe */
260 jal mips_trap /* call it */
261 nop /* delay slot */
262
263 /* Something must be here or gdb doesn't find the stack frame. */
264 nop
265
266 /*
267 * Now restore stuff and return from the exception.
268 * Interrupts should be off.
269 */
270 exception_return:
271
272 /* 16(sp) no need to restore tf_vaddr */
273 lw t0, 20(sp) /* load status register value into t0 */
274 nop /* load delay slot */
275 mtc0 t0, c0_status /* store it back to coprocessor 0 */
276 /* 24(sp) no need to restore tf_cause */
277
278 /* restore special registers */
279 lw t1, 28(sp)
280 lw t0, 32(sp)
281 mtlo t1
282 mthi t0
283
284 /* load the general registers */
285 lw ra, 36(sp)
286
287 lw AT, 40(sp)
288 lw v0, 44(sp)
289 lw v1, 48(sp)
290 lw a0, 52(sp)
291 lw a1, 56(sp)
292 lw a2, 60(sp)
293 lw a3, 64(sp)
294 lw t0, 68(sp)
295 lw t1, 72(sp)
296 lw t2, 76(sp)
297 lw t3, 80(sp)
298 lw t4, 84(sp)
299 lw t5, 88(sp)
300 lw t6, 92(sp)
301 lw t7, 96(sp)
302 lw s0, 100(sp)
303 lw s1, 104(sp)
304 lw s2, 108(sp)
305 lw s3, 112(sp)
306 lw s4, 116(sp)
307 lw s5, 120(sp)
308 lw s6, 124(sp)
309 lw s7, 128(sp)
310 lw t8, 132(sp)
311 lw t9, 136(sp)
312
313 /* 140(sp) "saved" k0 was dummy garbage anyway */
314 /* 144(sp) "saved" k1 was dummy garbage anyway */
315
316 lw gp, 148(sp) /* restore gp */
317 /* 152(sp) stack pointer - below */
318 lw s8, 156(sp) /* restore s8 */
319 lw k0, 160(sp) /* fetch exception return PC into k0 */
320
321 lw sp, 152(sp) /* fetch saved sp (must be last) */
322
323 /* done */
324 jr k0 /* jump back */
325 rfe /* in delay slot */
326 .end common_exception
327
328 /*
329 * Code to enter user mode for the first time.
330 * Does not return.
331 *
332 * This is called from mips_usermode().
333 * Interrupts on this processor should be off.
334 */
335
336 .text
337 .globl asm_usermode
338 .type asm_usermode,@function
339 .ent asm_usermode
340 asm_usermode:
341 /*
342 * a0 is the address of a trapframe to use for exception "return".
343 * It's allocated on our stack.
344 *
345 * Move it to the stack pointer - we don't need the actual stack
346 * position any more. (When we come back from usermode, cpustacks[]
347 * will be used to reinitialize our stack pointer, and that was
348 * set by mips_usermode.)
349 *
350 * Then just jump to the exception return code above.
351 */
352
353 j exception_return
354 addiu sp, a0, -16 /* in delay slot */
355 .end asm_usermode