source: mainline/kernel/arch/mips32/src/start.S@ 3e94678

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3e94678 was 0c39b96, checked in by Jakub Jermar <jakub@…>, 15 years ago

If possible, print stack also with the mips32 trap frame and frames preceding
the trap. Currently, the stack tracer handles well only the most friendly cases,
but it stops tracing when the trap frame was inserted from a leaf-optimised
function. This is partly due to the fact that we are using a simplified
disassembling stack tracer and also because the stack trace printed from
panic_common() completely ignores the information available in istate (which
could be of some help).

  • Property mode set to 100644
File size: 9.4 KB
Line 
1#
2# Copyright (c) 2003-2004 Jakub Jermar
3# All rights reserved.
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#
9# - Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# - Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution.
14# - The name of the author may not be used to endorse or promote products
15# derived from this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28
29#include <arch/asm/regname.h>
30#include <arch/mm/page.h>
31#include <arch/asm/boot.h>
32#include <arch/context_offset.h>
33#include <arch/stack.h>
34
35.text
36
37.set noat
38.set noreorder
39.set nomacro
40
41.global kernel_image_start
42.global tlb_refill_entry
43.global cache_error_entry
44.global exception_entry
45.global userspace_asm
46
47/*
48 * Which status bits are thread-local:
49 * KSU(UM), EXL, ERL, IE
50 */
51#define REG_SAVE_MASK 0x1f
52
53#define ISTATE_OFFSET_A0 0
54#define ISTATE_OFFSET_A1 4
55#define ISTATE_OFFSET_A2 8
56#define ISTATE_OFFSET_A3 12
57#define ISTATE_OFFSET_T0 16
58#define ISTATE_OFFSET_T1 20
59#define ISTATE_OFFSET_V0 24
60#define ISTATE_OFFSET_V1 28
61#define ISTATE_OFFSET_AT 32
62#define ISTATE_OFFSET_T2 36
63#define ISTATE_OFFSET_T3 40
64#define ISTATE_OFFSET_T4 44
65#define ISTATE_OFFSET_T5 48
66#define ISTATE_OFFSET_T6 52
67#define ISTATE_OFFSET_T7 56
68#define ISTATE_OFFSET_S0 60
69#define ISTATE_OFFSET_S1 64
70#define ISTATE_OFFSET_S2 68
71#define ISTATE_OFFSET_S3 72
72#define ISTATE_OFFSET_S4 76
73#define ISTATE_OFFSET_S5 80
74#define ISTATE_OFFSET_S6 84
75#define ISTATE_OFFSET_S7 88
76#define ISTATE_OFFSET_T8 92
77#define ISTATE_OFFSET_T9 96
78#define ISTATE_OFFSET_KT0 100
79#define ISTATE_OFFSET_KT1 104
80#define ISTATE_OFFSET_GP 108
81#define ISTATE_OFFSET_SP 112
82#define ISTATE_OFFSET_S8 116
83#define ISTATE_OFFSET_RA 120
84#define ISTATE_OFFSET_LO 124
85#define ISTATE_OFFSET_HI 128
86#define ISTATE_OFFSET_STATUS 132
87#define ISTATE_OFFSET_EPC 136
88#define ISTATE_OFFSET_ALIGNMENT 140
89
90#define ISTATE_SOFT_SIZE 144
91
92/*
93 * The fake ABI prologue is never executed and may not be part of the
94 * procedure's body. Instead, it should be immediately preceding the procedure's
95 * body. Its only purpose is to trick the stack trace walker into thinking that
96 * the exception is more or less just a normal function call.
97 */
98.macro FAKE_ABI_PROLOGUE
99 sub $sp, ISTATE_SOFT_SIZE
100 sw $ra, ISTATE_OFFSET_EPC($sp)
101.endm
102
103/*
104 * Save registers to space defined by \r
105 * We will change status: Disable ERL, EXL, UM, IE
106 * These changes will be automatically reversed in REGISTER_LOAD
107 * %sp is NOT saved as part of these registers
108 */
109.macro REGISTERS_STORE_AND_EXC_RESET r
110 sw $at, ISTATE_OFFSET_AT(\r)
111 sw $v0, ISTATE_OFFSET_V0(\r)
112 sw $v1, ISTATE_OFFSET_V1(\r)
113 sw $a0, ISTATE_OFFSET_A0(\r)
114 sw $a1, ISTATE_OFFSET_A1(\r)
115 sw $a2, ISTATE_OFFSET_A2(\r)
116 sw $a3, ISTATE_OFFSET_A3(\r)
117 sw $t0, ISTATE_OFFSET_T0(\r)
118 sw $t1, ISTATE_OFFSET_T1(\r)
119 sw $t2, ISTATE_OFFSET_T2(\r)
120 sw $t3, ISTATE_OFFSET_T3(\r)
121 sw $t4, ISTATE_OFFSET_T4(\r)
122 sw $t5, ISTATE_OFFSET_T5(\r)
123 sw $t6, ISTATE_OFFSET_T6(\r)
124 sw $t7, ISTATE_OFFSET_T7(\r)
125 sw $t8, ISTATE_OFFSET_T8(\r)
126 sw $t9, ISTATE_OFFSET_T9(\r)
127 sw $s0, ISTATE_OFFSET_S0(\r)
128 sw $s1, ISTATE_OFFSET_S1(\r)
129 sw $s2, ISTATE_OFFSET_S2(\r)
130 sw $s3, ISTATE_OFFSET_S3(\r)
131 sw $s4, ISTATE_OFFSET_S4(\r)
132 sw $s5, ISTATE_OFFSET_S5(\r)
133 sw $s6, ISTATE_OFFSET_S6(\r)
134 sw $s7, ISTATE_OFFSET_S7(\r)
135 sw $s8, ISTATE_OFFSET_S8(\r)
136
137 mflo $at
138 sw $at, ISTATE_OFFSET_LO(\r)
139 mfhi $at
140 sw $at, ISTATE_OFFSET_HI(\r)
141
142 sw $gp, ISTATE_OFFSET_GP(\r)
143 sw $ra, ISTATE_OFFSET_RA(\r)
144 sw $k0, ISTATE_OFFSET_KT0(\r)
145 sw $k1, ISTATE_OFFSET_KT1(\r)
146
147 mfc0 $t0, $status
148 mfc0 $t1, $epc
149
150 /* save only KSU, EXL, ERL, IE */
151 and $t2, $t0, REG_SAVE_MASK
152
153 /* clear KSU, EXL, ERL, IE */
154 li $t3, ~(REG_SAVE_MASK)
155 and $t0, $t0, $t3
156
157 sw $t2, ISTATE_OFFSET_STATUS(\r)
158 sw $t1, ISTATE_OFFSET_EPC(\r)
159 mtc0 $t0, $status
160.endm
161
162.macro REGISTERS_LOAD r
163 /*
164 * Update only UM, EXR, IE from status, the rest
165 * is controlled by OS and not bound to task.
166 */
167 mfc0 $t0, $status
168 lw $t1, ISTATE_OFFSET_STATUS(\r)
169
170 /* mask UM, EXL, ERL, IE */
171 li $t2, ~REG_SAVE_MASK
172 and $t0, $t0, $t2
173
174 /* copy UM, EXL, ERL, IE from saved status */
175 or $t0, $t0, $t1
176 mtc0 $t0, $status
177
178 lw $v0, ISTATE_OFFSET_V0(\r)
179 lw $v1, ISTATE_OFFSET_V1(\r)
180 lw $a0, ISTATE_OFFSET_A0(\r)
181 lw $a1, ISTATE_OFFSET_A1(\r)
182 lw $a2, ISTATE_OFFSET_A2(\r)
183 lw $a3, ISTATE_OFFSET_A3(\r)
184 lw $t0, ISTATE_OFFSET_T0(\r)
185 lw $t1, ISTATE_OFFSET_T1(\r)
186 lw $t2, ISTATE_OFFSET_T2(\r)
187 lw $t3, ISTATE_OFFSET_T3(\r)
188 lw $t4, ISTATE_OFFSET_T4(\r)
189 lw $t5, ISTATE_OFFSET_T5(\r)
190 lw $t6, ISTATE_OFFSET_T6(\r)
191 lw $t7, ISTATE_OFFSET_T7(\r)
192 lw $t8, ISTATE_OFFSET_T8(\r)
193 lw $t9, ISTATE_OFFSET_T9(\r)
194
195 lw $gp, ISTATE_OFFSET_GP(\r)
196 lw $ra, ISTATE_OFFSET_RA(\r)
197 lw $k1, ISTATE_OFFSET_KT1(\r)
198
199 lw $at, ISTATE_OFFSET_LO(\r)
200 mtlo $at
201 lw $at, ISTATE_OFFSET_HI(\r)
202 mthi $at
203
204 lw $at, ISTATE_OFFSET_EPC(\r)
205 mtc0 $at, $epc
206
207 lw $at, ISTATE_OFFSET_AT(\r)
208 lw $sp, ISTATE_OFFSET_SP(\r)
209.endm
210
211/*
212 * Move kernel stack pointer address to register $k0.
213 * If we are in user mode, load the appropriate stack address.
214 */
215.macro KERNEL_STACK_TO_K0
216 /* if we are in user mode */
217 mfc0 $k0, $status
218 andi $k0, 0x10
219
220 beq $k0, $0, 1f
221 move $k0, $sp
222
223 /* move $k0 pointer to kernel stack */
224 lui $k0, %hi(supervisor_sp)
225 ori $k0, $k0, %lo(supervisor_sp)
226
227 /* move $k0 (supervisor_sp) */
228 lw $k0, ($k0)
229
230 1:
231.endm
232
233.org 0x0
234kernel_image_start:
235 /* load temporary stack */
236 lui $sp, %hi(end_stack)
237 ori $sp, $sp, %lo(end_stack)
238
239 /* not sure about this, but might be needed for PIC code */
240 lui $gp, 0x8000
241
242 /* $a1 contains physical address of bootinfo_t */
243 jal arch_pre_main
244 nop
245
246 j main_bsp
247 nop
248
249.space TEMP_STACK_SIZE
250end_stack:
251
252tlb_refill_entry:
253 j tlb_refill_handler
254 nop
255
256cache_error_entry:
257 j cache_error_handler
258 nop
259
260exception_entry:
261 j exception_handler
262 nop
263
264 FAKE_ABI_PROLOGUE
265exception_handler:
266 KERNEL_STACK_TO_K0
267
268 sub $k0, ISTATE_SOFT_SIZE
269 sw $sp, ISTATE_OFFSET_SP($k0)
270 move $sp, $k0
271
272 mfc0 $k0, $cause
273
274 sra $k0, $k0, 0x2 /* cp0_exc_cause() part 1 */
275 andi $k0, $k0, 0x1f /* cp0_exc_cause() part 2 */
276 sub $k0, 8 /* 8 = SYSCALL */
277
278 beqz $k0, syscall_shortcut
279 add $k0, 8 /* revert $k0 back to correct exc number */
280
281 REGISTERS_STORE_AND_EXC_RESET $sp
282
283 move $a1, $sp
284 jal exc_dispatch /* exc_dispatch(excno, register_space) */
285 move $a0, $k0
286
287 REGISTERS_LOAD $sp
288 /* the $sp is automatically restored to former value */
289 eret
290
291/** Syscall entry
292 *
293 * Registers:
294 *
295 * @param $v0 Syscall number.
296 * @param $a0 1st argument.
297 * @param $a1 2nd argument.
298 * @param $a2 3rd argument.
299 * @param $a3 4th argument.
300 * @param $t0 5th argument.
301 * @param $t1 6th argument.
302 *
303 * @return The return value will be stored in $v0.
304 *
305 */
306syscall_shortcut:
307 mfc0 $t3, $epc
308 mfc0 $t2, $status
309 sw $t3, ISTATE_OFFSET_EPC($sp) /* save EPC */
310 sw $k1, ISTATE_OFFSET_KT1($sp) /* save $k1 not saved on context switch */
311
312 and $t4, $t2, REG_SAVE_MASK /* save only KSU, EXL, ERL, IE */
313 li $t5, ~(0x1f)
314 and $t2, $t2, $t5 /* clear KSU, EXL, ERL */
315 ori $t2, $t2, 0x1 /* set IE */
316
317 sw $t4, ISTATE_OFFSET_STATUS($sp)
318 mtc0 $t2, $status
319
320 /*
321 * Call the higher level system call handler.
322 *
323 */
324 sw $t0, ISTATE_OFFSET_T0($sp) /* save the 5th argument on the stack */
325 sw $t1, ISTATE_OFFSET_T1($sp) /* save the 6th argument on the stack */
326 jal syscall_handler
327 sw $v0, ISTATE_OFFSET_V0($sp) /* save the syscall number on the stack */
328
329 /* restore status */
330 mfc0 $t2, $status
331 lw $t3, ISTATE_OFFSET_STATUS($sp)
332
333 /*
334 * Change back to EXL = 1 (from last exception), otherwise
335 * an interrupt could rewrite the CP0 - EPC.
336 *
337 */
338 li $t4, ~REG_SAVE_MASK /* mask UM, EXL, ERL, IE */
339 and $t2, $t2, $t4
340 or $t2, $t2, $t3 /* copy saved UM, EXL, ERL, IE */
341 mtc0 $t2, $status
342
343 /* restore epc + 4 */
344 lw $t2, ISTATE_OFFSET_EPC($sp)
345 lw $k1, ISTATE_OFFSET_KT1($sp)
346 addi $t2, $t2, 4
347 mtc0 $t2, $epc
348
349 lw $sp, ISTATE_OFFSET_SP($sp) /* restore $sp */
350 eret
351
352 FAKE_ABI_PROLOGUE
353tlb_refill_handler:
354 KERNEL_STACK_TO_K0
355 sub $k0, ISTATE_SOFT_SIZE
356 REGISTERS_STORE_AND_EXC_RESET $k0
357 sw $sp, ISTATE_OFFSET_SP($k0)
358 move $sp, $k0
359
360 jal tlb_refill
361 move $a0, $sp
362
363 REGISTERS_LOAD $sp
364 eret
365
366 FAKE_ABI_PROLOGUE
367cache_error_handler:
368 KERNEL_STACK_TO_K0
369 sub $k0, ISTATE_SOFT_SIZE
370 REGISTERS_STORE_AND_EXC_RESET $k0
371 sw $sp, ISTATE_OFFSET_SP($k0)
372 move $sp, $k0
373
374 jal cache_error
375 move $a0, $sp
376
377 REGISTERS_LOAD $sp
378 eret
379
380userspace_asm:
381 move $sp, $a0
382 move $v0, $a1
383 move $t9, $a2 /* set up correct entry into PIC code */
384 xor $a0, $a0, $a0 /* $a0 is defined to hold pcb_ptr */
385 /* set it to 0 */
386 eret
Note: See TracBrowser for help on using the repository browser.