source: mainline/kernel/arch/mips32/src/start.S@ 6d8a63a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6d8a63a was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 8.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 <abi/asmtool.h>
30#include <arch/asm/regname.h>
31#include <arch/mm/page.h>
32#include <arch/asm/boot.h>
33#include <arch/stack.h>
34#include <arch/istate_struct.h>
35
36.text
37
38.set noat
39.set noreorder
40
41/*
42 * Which status bits are thread-local:
43 * KSU(UM), EXL, ERL, IE
44 */
45#define REG_SAVE_MASK 0x1f
46
47/*
48 * The fake ABI prologue is never executed and may not be part of the
49 * procedure's body. Instead, it should be immediately preceding the procedure's
50 * body. Its only purpose is to trick the stack trace walker into thinking that
51 * the exception is more or less just a normal function call.
52 */
53.macro FAKE_ABI_PROLOGUE
54 sub $sp, ISTATE_SIZE
55 sw $ra, ISTATE_OFFSET_EPC($sp)
56.endm
57
58/*
59 * Save registers to space defined by \r
60 * We will change status: Disable ERL, EXL, UM, IE
61 * These changes will be automatically reversed in REGISTER_LOAD
62 * %sp is NOT saved as part of these registers
63 */
64.macro REGISTERS_STORE_AND_EXC_RESET r
65 sw $at, ISTATE_OFFSET_AT(\r)
66 sw $v0, ISTATE_OFFSET_V0(\r)
67 sw $v1, ISTATE_OFFSET_V1(\r)
68 sw $a0, ISTATE_OFFSET_A0(\r)
69 sw $a1, ISTATE_OFFSET_A1(\r)
70 sw $a2, ISTATE_OFFSET_A2(\r)
71 sw $a3, ISTATE_OFFSET_A3(\r)
72 sw $t0, ISTATE_OFFSET_T0(\r)
73 sw $t1, ISTATE_OFFSET_T1(\r)
74 sw $t2, ISTATE_OFFSET_T2(\r)
75 sw $t3, ISTATE_OFFSET_T3(\r)
76 sw $t4, ISTATE_OFFSET_T4(\r)
77 sw $t5, ISTATE_OFFSET_T5(\r)
78 sw $t6, ISTATE_OFFSET_T6(\r)
79 sw $t7, ISTATE_OFFSET_T7(\r)
80 sw $t8, ISTATE_OFFSET_T8(\r)
81 sw $t9, ISTATE_OFFSET_T9(\r)
82 sw $s0, ISTATE_OFFSET_S0(\r)
83 sw $s1, ISTATE_OFFSET_S1(\r)
84 sw $s2, ISTATE_OFFSET_S2(\r)
85 sw $s3, ISTATE_OFFSET_S3(\r)
86 sw $s4, ISTATE_OFFSET_S4(\r)
87 sw $s5, ISTATE_OFFSET_S5(\r)
88 sw $s6, ISTATE_OFFSET_S6(\r)
89 sw $s7, ISTATE_OFFSET_S7(\r)
90 sw $s8, ISTATE_OFFSET_S8(\r)
91
92 mflo $at
93 sw $at, ISTATE_OFFSET_LO(\r)
94 mfhi $at
95 sw $at, ISTATE_OFFSET_HI(\r)
96
97 sw $gp, ISTATE_OFFSET_GP(\r)
98 sw $ra, ISTATE_OFFSET_RA(\r)
99 sw $k0, ISTATE_OFFSET_KT0(\r)
100 sw $k1, ISTATE_OFFSET_KT1(\r)
101
102 mfc0 $t0, $status
103 mfc0 $t1, $epc
104
105 /* save only KSU, EXL, ERL, IE */
106 and $t2, $t0, REG_SAVE_MASK
107
108 /* clear KSU, EXL, ERL, IE */
109 li $t3, ~(REG_SAVE_MASK)
110 and $t0, $t0, $t3
111
112 sw $t2, ISTATE_OFFSET_STATUS(\r)
113 sw $t1, ISTATE_OFFSET_EPC(\r)
114 mtc0 $t0, $status
115.endm
116
117.macro REGISTERS_LOAD r
118 /*
119 * Update only UM, EXR, IE from status, the rest
120 * is controlled by OS and not bound to task.
121 */
122 mfc0 $t0, $status
123 lw $t1, ISTATE_OFFSET_STATUS(\r)
124
125 /* mask UM, EXL, ERL, IE */
126 li $t2, ~REG_SAVE_MASK
127 and $t0, $t0, $t2
128
129 /* copy UM, EXL, ERL, IE from saved status */
130 or $t0, $t0, $t1
131 mtc0 $t0, $status
132
133 lw $v0, ISTATE_OFFSET_V0(\r)
134 lw $v1, ISTATE_OFFSET_V1(\r)
135 lw $a0, ISTATE_OFFSET_A0(\r)
136 lw $a1, ISTATE_OFFSET_A1(\r)
137 lw $a2, ISTATE_OFFSET_A2(\r)
138 lw $a3, ISTATE_OFFSET_A3(\r)
139 lw $t0, ISTATE_OFFSET_T0(\r)
140 lw $t1, ISTATE_OFFSET_T1(\r)
141 lw $t2, ISTATE_OFFSET_T2(\r)
142 lw $t3, ISTATE_OFFSET_T3(\r)
143 lw $t4, ISTATE_OFFSET_T4(\r)
144 lw $t5, ISTATE_OFFSET_T5(\r)
145 lw $t6, ISTATE_OFFSET_T6(\r)
146 lw $t7, ISTATE_OFFSET_T7(\r)
147 lw $t8, ISTATE_OFFSET_T8(\r)
148 lw $t9, ISTATE_OFFSET_T9(\r)
149
150 lw $gp, ISTATE_OFFSET_GP(\r)
151 lw $ra, ISTATE_OFFSET_RA(\r)
152 lw $k1, ISTATE_OFFSET_KT1(\r)
153
154 lw $at, ISTATE_OFFSET_LO(\r)
155 mtlo $at
156 lw $at, ISTATE_OFFSET_HI(\r)
157 mthi $at
158
159 lw $at, ISTATE_OFFSET_EPC(\r)
160 mtc0 $at, $epc
161
162 lw $at, ISTATE_OFFSET_AT(\r)
163 lw $sp, ISTATE_OFFSET_SP(\r)
164.endm
165
166/*
167 * Move kernel stack pointer address to register $k0.
168 * If we are in user mode, load the appropriate stack address.
169 */
170.macro KERNEL_STACK_TO_K0
171 /* if we are in user mode */
172 mfc0 $k0, $status
173 andi $k0, 0x10
174
175 beq $k0, $0, 1f
176 move $k0, $sp
177
178 /* move $k0 pointer to kernel stack */
179 la $k0, supervisor_sp
180
181 /* move $k0 (supervisor_sp) */
182 lw $k0, ($k0)
183
184 1:
185.endm
186
187.org 0x0
188SYMBOL(kernel_image_start)
189 /* load temporary stack */
190 lui $sp, %hi(end_stack)
191 ori $sp, $sp, %lo(end_stack)
192
193 /* not sure about this, but might be needed for PIC code */
194 lui $gp, 0x8000
195
196 /* $a1 contains physical address of bootinfo_t */
197 jal mips32_pre_main
198 addiu $sp, -ABI_STACK_FRAME
199
200 j main_bsp
201 nop
202
203.space TEMP_STACK_SIZE
204end_stack:
205
206SYMBOL(tlb_refill_entry)
207 j tlb_refill_handler
208 nop
209
210SYMBOL(cache_error_entry)
211 j cache_error_handler
212 nop
213
214SYMBOL(exception_entry)
215 j exception_handler
216 nop
217
218 FAKE_ABI_PROLOGUE
219exception_handler:
220 KERNEL_STACK_TO_K0
221
222 sub $k0, ISTATE_SIZE
223 sw $sp, ISTATE_OFFSET_SP($k0)
224 move $sp, $k0
225
226 mfc0 $k0, $cause
227
228 sra $k0, $k0, 0x2 /* cp0_exc_cause() part 1 */
229 andi $k0, $k0, 0x1f /* cp0_exc_cause() part 2 */
230 sub $k0, 8 /* 8 = SYSCALL */
231
232 beqz $k0, syscall_shortcut
233 add $k0, 8 /* revert $k0 back to correct exc number */
234
235 REGISTERS_STORE_AND_EXC_RESET $sp
236
237 move $a1, $sp
238 move $a0, $k0
239 jal exc_dispatch /* exc_dispatch(excno, register_space) */
240 addiu $sp, -ABI_STACK_FRAME
241 addiu $sp, ABI_STACK_FRAME
242
243 REGISTERS_LOAD $sp
244 /* the $sp is automatically restored to former value */
245 eret
246
247/** Syscall entry
248 *
249 * Registers:
250 *
251 * @param $v0 Syscall number.
252 * @param $a0 1st argument.
253 * @param $a1 2nd argument.
254 * @param $a2 3rd argument.
255 * @param $a3 4th argument.
256 * @param $t0 5th argument.
257 * @param $t1 6th argument.
258 *
259 * @return The return value will be stored in $v0.
260 *
261 */
262syscall_shortcut:
263 mfc0 $t3, $epc
264 mfc0 $t2, $status
265 sw $t3, ISTATE_OFFSET_EPC($sp) /* save EPC */
266 sw $k1, ISTATE_OFFSET_KT1($sp) /* save $k1 not saved on context switch */
267
268 and $t4, $t2, REG_SAVE_MASK /* save only KSU, EXL, ERL, IE */
269 li $t5, ~(0x1f)
270 and $t2, $t2, $t5 /* clear KSU, EXL, ERL */
271 ori $t2, $t2, 0x1 /* set IE */
272
273 sw $t4, ISTATE_OFFSET_STATUS($sp)
274 mtc0 $t2, $status
275
276 /*
277 * Call the higher level system call handler.
278 *
279 */
280 sw $t0, ISTATE_OFFSET_T0($sp) /* save the 5th argument on the stack */
281 sw $t1, ISTATE_OFFSET_T1($sp) /* save the 6th argument on the stack */
282
283 jal syscall_handler
284 sw $v0, ISTATE_OFFSET_V0($sp) /* save the syscall number on the stack */
285
286 /* restore status */
287 mfc0 $t2, $status
288 lw $t3, ISTATE_OFFSET_STATUS($sp)
289
290 /*
291 * Change back to EXL = 1 (from last exception), otherwise
292 * an interrupt could rewrite the CP0 - EPC.
293 *
294 */
295 li $t4, ~REG_SAVE_MASK /* mask UM, EXL, ERL, IE */
296 and $t2, $t2, $t4
297 or $t2, $t2, $t3 /* copy saved UM, EXL, ERL, IE */
298 mtc0 $t2, $status
299
300 /* restore epc + 4 */
301 lw $t2, ISTATE_OFFSET_EPC($sp)
302 lw $k1, ISTATE_OFFSET_KT1($sp)
303 addi $t2, $t2, 4
304 mtc0 $t2, $epc
305
306 lw $sp, ISTATE_OFFSET_SP($sp) /* restore $sp */
307 eret
308
309 FAKE_ABI_PROLOGUE
310tlb_refill_handler:
311 KERNEL_STACK_TO_K0
312 sub $k0, ISTATE_SIZE
313 REGISTERS_STORE_AND_EXC_RESET $k0
314 sw $sp, ISTATE_OFFSET_SP($k0)
315 move $sp, $k0
316
317 move $a0, $sp
318 jal tlb_refill
319 addiu $sp, -ABI_STACK_FRAME
320 addiu $sp, ABI_STACK_FRAME
321
322 REGISTERS_LOAD $sp
323 eret
324
325 FAKE_ABI_PROLOGUE
326cache_error_handler:
327 KERNEL_STACK_TO_K0
328 sub $k0, ISTATE_SIZE
329 REGISTERS_STORE_AND_EXC_RESET $k0
330 sw $sp, ISTATE_OFFSET_SP($k0)
331 move $sp, $k0
332
333 move $a0, $sp
334 jal cache_error
335 addiu $sp, -ABI_STACK_FRAME
336 addiu $sp, ABI_STACK_FRAME
337
338 REGISTERS_LOAD $sp
339 eret
340
341FUNCTION_BEGIN(userspace_asm)
342 move $sp, $a0
343 move $v0, $a1
344 move $t9, $a2 /* set up correct entry into PIC code */
345 xor $a0, $a0, $a0 /* $a0 is defined to hold pcb_ptr */
346 /* set it to 0 */
347 eret
348FUNCTION_END(userspace_asm)
Note: See TracBrowser for help on using the repository browser.