scoutos / prex-0.9.0 / bsp / hal / ppc / arch / locore.S @ 03e9c04a
History | View | Annotate | Download (10.5 KB)
1 | 03e9c04a | Brad Neuman | /*- |
---|---|---|---|
2 | * Copyright (c) 2009, Kohsuke Ohtani |
||
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 | * 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 author nor the names of any co-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 AUTHOR 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 AUTHOR 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 | /* |
||
31 | * locore.S - low level platform support |
||
32 | */ |
||
33 | |||
34 | /* |
||
35 | * Memo: SPRG usage |
||
36 | * SPRG0 - kernel stack pointer |
||
37 | * SPRG1 - saved stack pointer |
||
38 | * SPRG2 - interrupt nest counter |
||
39 | * SPRG3 - scratch pad |
||
40 | */ |
||
41 | |||
42 | #include <conf/config.h> |
||
43 | #include <machine/asm.h> |
||
44 | #include <machine/syspage.h> |
||
45 | #include <machine/memory.h> |
||
46 | #include <sys/errno.h> |
||
47 | #include <context.h> |
||
48 | #include <trap.h> |
||
49 | #include <cpu.h> |
||
50 | |||
51 | .section ".text","ax" |
||
52 | |||
53 | #define ABS_JUMP(target) \ |
||
54 | lis r12, (target)@ha ; \ |
||
55 | ori r12, r12, (target)@l ; \ |
||
56 | mtctr r12 ;\ |
||
57 | bctr |
||
58 | |||
59 | /* |
||
60 | * Macro to save all registers. |
||
61 | */ |
||
62 | #define SAVE_ALL \ |
||
63 | subi r1, r1, CTXREGS; \ |
||
64 | stw r0, REG_R0(r1); \ |
||
65 | stw r2, REG_R2(r1); \ |
||
66 | stw r3, REG_R3(r1); \ |
||
67 | stw r4, REG_R4(r1); \ |
||
68 | stw r5, REG_R5(r1); \ |
||
69 | stw r6, REG_R6(r1); \ |
||
70 | stw r7, REG_R7(r1); \ |
||
71 | stw r8, REG_R8(r1); \ |
||
72 | stw r9, REG_R9(r1); \ |
||
73 | stw r10, REG_R10(r1); \ |
||
74 | stw r11, REG_R11(r1); \ |
||
75 | stw r12, REG_R12(r1); \ |
||
76 | stw r13, REG_R13(r1); \ |
||
77 | stw r14, REG_R14(r1); \ |
||
78 | stw r15, REG_R15(r1); \ |
||
79 | stw r16, REG_R16(r1); \ |
||
80 | stw r17, REG_R17(r1); \ |
||
81 | stw r18, REG_R18(r1); \ |
||
82 | stw r19, REG_R19(r1); \ |
||
83 | stw r20, REG_R20(r1); \ |
||
84 | stw r21, REG_R21(r1); \ |
||
85 | stw r22, REG_R22(r1); \ |
||
86 | stw r23, REG_R23(r1); \ |
||
87 | stw r24, REG_R24(r1); \ |
||
88 | stw r25, REG_R25(r1); \ |
||
89 | stw r26, REG_R26(r1); \ |
||
90 | stw r27, REG_R27(r1); \ |
||
91 | stw r28, REG_R28(r1); \ |
||
92 | stw r29, REG_R29(r1); \ |
||
93 | stw r30, REG_R30(r1); \ |
||
94 | stw r31, REG_R31(r1); \ |
||
95 | mfsprg1 r10; /* Get saved sp */ \ |
||
96 | stw r10, REG_R1(r1); \ |
||
97 | mfspr r10, SPR_SRR0; \ |
||
98 | stw r10, REG_SRR0(r1); \ |
||
99 | mfspr r10, SPR_SRR1; \ |
||
100 | stw r10, REG_SRR1(r1); \ |
||
101 | mfspr r10, SPR_LR; \ |
||
102 | stw r10, REG_LR(r1); \ |
||
103 | mfspr r10, SPR_CTR; \ |
||
104 | stw r10, REG_CTR(r1); \ |
||
105 | mfspr r10, SPR_XER; \ |
||
106 | stw r10, REG_XER(r1); \ |
||
107 | mfspr r10, SPR_LR; \ |
||
108 | stw r10, REG_LR(r1); \ |
||
109 | mfcr r10; \ |
||
110 | stw r10, REG_CR(r1); |
||
111 | |||
112 | /* |
||
113 | * Macro to restore all registers. |
||
114 | */ |
||
115 | #define RESTORE_ALL \ |
||
116 | lwz r10, REG_SRR0(r1); \ |
||
117 | mtspr SPR_SRR0, r10; \ |
||
118 | lwz r10, REG_SRR1(r1); \ |
||
119 | mtspr SPR_SRR1, r10; \ |
||
120 | lwz r10, REG_LR(r1); \ |
||
121 | mtspr SPR_LR, r10; \ |
||
122 | lwz r10, REG_XER(r1); \ |
||
123 | mtspr SPR_XER, r10; \ |
||
124 | lwz r10, REG_CTR(r1); \ |
||
125 | mtspr SPR_CTR, r10; \ |
||
126 | lwz r10, REG_LR(r1); \ |
||
127 | mtspr SPR_LR, r10; \ |
||
128 | lwz r10, REG_CR(r1); \ |
||
129 | mtcr r10; \ |
||
130 | lwz r10, REG_R1(r1); \ |
||
131 | mtsprg1 r10; /* Restore saved sp */ \ |
||
132 | lwz r0, REG_R0(r1); \ |
||
133 | lwz r2, REG_R2(r1); \ |
||
134 | lwz r3, REG_R3(r1); \ |
||
135 | lwz r4, REG_R4(r1); \ |
||
136 | lwz r5, REG_R5(r1); \ |
||
137 | lwz r6, REG_R6(r1); \ |
||
138 | lwz r7, REG_R7(r1); \ |
||
139 | lwz r8, REG_R8(r1); \ |
||
140 | lwz r9, REG_R9(r1); \ |
||
141 | lwz r10, REG_R10(r1); \ |
||
142 | lwz r11, REG_R11(r1); \ |
||
143 | lwz r12, REG_R12(r1); \ |
||
144 | lwz r13, REG_R13(r1); \ |
||
145 | lwz r14, REG_R14(r1); \ |
||
146 | lwz r15, REG_R15(r1); \ |
||
147 | lwz r16, REG_R16(r1); \ |
||
148 | lwz r17, REG_R17(r1); \ |
||
149 | lwz r18, REG_R18(r1); \ |
||
150 | lwz r19, REG_R19(r1); \ |
||
151 | lwz r20, REG_R20(r1); \ |
||
152 | lwz r21, REG_R21(r1); \ |
||
153 | lwz r22, REG_R22(r1); \ |
||
154 | lwz r23, REG_R23(r1); \ |
||
155 | lwz r24, REG_R24(r1); \ |
||
156 | lwz r25, REG_R25(r1); \ |
||
157 | lwz r26, REG_R26(r1); \ |
||
158 | lwz r27, REG_R27(r1); \ |
||
159 | lwz r28, REG_R28(r1); \ |
||
160 | lwz r29, REG_R29(r1); \ |
||
161 | lwz r30, REG_R30(r1); \ |
||
162 | lwz r31, REG_R31(r1); |
||
163 | |||
164 | /* |
||
165 | * Macro to build an exception entry. |
||
166 | * We assume interrupts are disabled. |
||
167 | */ |
||
168 | #define EXCEPTION_ENTRY(offset, name, id, xfer) \ |
||
169 | .skip offset - (. - exception_vector); \ |
||
170 | exception_##name: \ |
||
171 | mtsprg1 r1; /* sprg1: current sp */ \ |
||
172 | mtsprg3 r10; /* sprg3: saved r10 */ \ |
||
173 | mfcr r10; /* r10: saved cr */ \ |
||
174 | mfsrr1 r1; /* Get msr */ \ |
||
175 | mtcr r1; \ |
||
176 | bt 17, 1f; /* Exception from user mode? */ \ |
||
177 | mfsprg1 r1; /* Kernel mode => restore orignal sp */ \ |
||
178 | b 2f; \ |
||
179 | 1: mfsprg0 r1; /* User mode => Load kernel stack */ \ |
||
180 | 2: mtcr r10; /* Restore cr */ \ |
||
181 | mfsprg3 r10; /* Restore r10 */ \ |
||
182 | SAVE_ALL ; \ |
||
183 | li r10, id; \ |
||
184 | ABS_JUMP(xfer); |
||
185 | |||
186 | #define INTR_ENTRY(offset, name, id) \ |
||
187 | EXCEPTION_ENTRY(offset, name, id, interrupt_common) |
||
188 | |||
189 | #define TRAP_ENTRY(offset, name, id) \ |
||
190 | EXCEPTION_ENTRY(offset, name, id, trap_common) |
||
191 | |||
192 | /* |
||
193 | * Macro to build a system call entry. |
||
194 | */ |
||
195 | #define SYSC_ENTRY(offset, name, id) \ |
||
196 | .skip offset - (. - exception_vector); \ |
||
197 | exception_##name: \ |
||
198 | mtsprg1 r1; /* sprg1: current sp */ \ |
||
199 | mfsprg0 r1; /* Load kernel stack */ \ |
||
200 | SAVE_ALL ; \ |
||
201 | li r10, id; \ |
||
202 | ABS_JUMP(syscall_entry); |
||
203 | |||
204 | /* |
||
205 | * Exception vectors |
||
206 | */ |
||
207 | .globl exception_vector |
||
208 | exception_vector: |
||
209 | .long 0 |
||
210 | |||
211 | .skip 0x100 - (. - exception_vector); \ |
||
212 | ENTRY(system_reset) |
||
213 | ABS_JUMP(kernel_start) |
||
214 | |||
215 | TRAP_ENTRY(0x200, machine_check ,TRAP_MACHINE_CHECK) |
||
216 | TRAP_ENTRY(0x300, dsi ,TRAP_DSI) |
||
217 | TRAP_ENTRY(0x400, isi ,TRAP_ISI) |
||
218 | INTR_ENTRY(0x500, external_intr ,TRAP_EXT_INTERRUPT) |
||
219 | TRAP_ENTRY(0x600, alignment ,TRAP_ALIGNMENT) |
||
220 | TRAP_ENTRY(0x700, program ,TRAP_PROGRAM) |
||
221 | TRAP_ENTRY(0x800, fp_unavailable ,TRAP_FP_UNAVAILABLE) |
||
222 | INTR_ENTRY(0x900, decrementer ,TRAP_DECREMENTER) |
||
223 | SYSC_ENTRY(0xc00, syscall ,TRAP_SYSTEM_CALL) |
||
224 | TRAP_ENTRY(0xd00, trace ,TRAP_TRACE) |
||
225 | TRAP_ENTRY(0xe00, fp_assist ,TRAP_FP_ASSIST) |
||
226 | |||
227 | .globl exception_vector_end |
||
228 | exception_vector_end: |
||
229 | |||
230 | |||
231 | /* |
||
232 | * Kernel start point |
||
233 | */ |
||
234 | ENTRY(kernel_start) |
||
235 | /* |
||
236 | * Setup CPU registers. |
||
237 | */ |
||
238 | li r3, MSR_IP /* Establish default MSR value */ |
||
239 | mtmsr r3 |
||
240 | |||
241 | li r3, 0 /* Init interrupt nest count */ |
||
242 | mtspr SPR_SPRG2, r3 |
||
243 | |||
244 | li r3, 0 /* Reset timebase */ |
||
245 | mttbl r3 |
||
246 | mttbu r3 |
||
247 | mttbl r3 |
||
248 | |||
249 | /* |
||
250 | * Init boot stack |
||
251 | */ |
||
252 | lis r1, BOOTSTKTOP@ha |
||
253 | addi r1, r1, BOOTSTKTOP@l |
||
254 | subi r1, r1, 16 |
||
255 | |||
256 | mtspr SPR_SPRG0, r1 /* Keep kernel stack */ |
||
257 | |||
258 | /* |
||
259 | * Clear kernel BSS |
||
260 | */ |
||
261 | lis r3, __bss@ha |
||
262 | addi r3, r3, __bss@l |
||
263 | lis r4, __end@ha |
||
264 | addi r4, r4, __end@l |
||
265 | li r0, 0 |
||
266 | 1: |
||
267 | stwu r0, 4(r3) |
||
268 | cmplw cr0, r3, r4 |
||
269 | blt 1b |
||
270 | |||
271 | /* |
||
272 | * Call kernel main routine |
||
273 | */ |
||
274 | b main |
||
275 | /* NOTREACHED */ |
||
276 | |||
277 | |||
278 | /* |
||
279 | * Common entry for interrupts. |
||
280 | * r3 - trap id |
||
281 | */ |
||
282 | ENTRY(interrupt_common) |
||
283 | stw r10, CTX_TRAPNO(r1) |
||
284 | |||
285 | mfsprg2 r28 /* r28: current IRQ nesting level */ |
||
286 | addi r3, r28, 1 /* Increment IRQ nesting level */ |
||
287 | mtsprg2 r3 |
||
288 | |||
289 | mfmsr r29 /* r29: current msr value */ |
||
290 | isync |
||
291 | mr r30, r1 /* r30: trap frame */ |
||
292 | subi r1, r1, STKFRAME_LEN /* Adjust stack frame for C routine */ |
||
293 | |||
294 | cmpwi cr0, r28, 0 /* Outermost interrupt? */ |
||
295 | bne 1f |
||
296 | bl sched_lock /* If outermost, lock scheduler */ |
||
297 | 1: |
||
298 | mr r3, r30 |
||
299 | bl interrupt_handler /* Call main interrupt handler */ |
||
300 | |||
301 | mtsprg2 r28 /* Restore IRQ nesting level */ |
||
302 | cmpwi cr0, r28, 0 /* Outermost interrupt? */ |
||
303 | bne interrupt_ret |
||
304 | bl sched_unlock /* Try to preempt */ |
||
305 | |||
306 | mtcr r29 /* Exception from user mode? */ |
||
307 | bf 17, interrupt_ret /* Exit if it's from kernel mode */ |
||
308 | |||
309 | mfmsr r27 /* Enable IRQ */ |
||
310 | andi. r4, r27, ~MSR_EE@l |
||
311 | mtmsr r4 |
||
312 | bl exception_deliver /* Check exception */ |
||
313 | mtmsr r27 /* Disable IRQ */ |
||
314 | interrupt_ret: |
||
315 | mr r1, r30 /* Restore stack */ |
||
316 | RESTORE_ALL |
||
317 | mfsprg1 r1 /* restore original sp */ |
||
318 | rfi |
||
319 | |||
320 | /* |
||
321 | * System call entry |
||
322 | */ |
||
323 | .global syscall_ret |
||
324 | ENTRY(syscall_entry) |
||
325 | stw r10, CTX_TRAPNO(r1) |
||
326 | |||
327 | mfmsr r29 /* r29: current msr value */ |
||
328 | mr r30, r1 /* r30: trap frame */ |
||
329 | subi r1, r1, STKFRAME_LEN /* Adjust stack frame for C routine */ |
||
330 | |||
331 | mfmsr r27 /* Enable IRQ */ |
||
332 | andi. r27, r27, ~MSR_EE@l |
||
333 | mtmsr r27 |
||
334 | |||
335 | mr r26, r0 /* r26: saved syscall number */ |
||
336 | mr r7, r0 |
||
337 | bl syscall_handler /* System call dispatcher */ |
||
338 | |||
339 | cmpwi cr0, r26, 0 /* exception_return? */ |
||
340 | beq 1f /* Skip storing error if so */ |
||
341 | stw r3, REG_R3(30) /* Set return value */ |
||
342 | 1: |
||
343 | bl exception_deliver /* Check exception */ |
||
344 | mr r1, r30 /* Restore stack */ |
||
345 | syscall_ret: |
||
346 | mfmsr r27 /* Disable IRQ */ |
||
347 | ori r27, r27, MSR_EE@l |
||
348 | mtmsr r27 |
||
349 | RESTORE_ALL |
||
350 | mfsprg1 r1 /* Restore original sp */ |
||
351 | rfi |
||
352 | |||
353 | /* |
||
354 | * Common entry for exceptions. |
||
355 | * r3 - trap id |
||
356 | */ |
||
357 | ENTRY(trap_common) |
||
358 | stw r10, CTX_TRAPNO(r1) |
||
359 | |||
360 | mfsprg2 r3 /* increment nest counter */ |
||
361 | addi r3, r3, 1 |
||
362 | mtsprg2 r3 |
||
363 | |||
364 | mr r3, r1 |
||
365 | subi r1, r1, STKFRAME_LEN |
||
366 | bl trap_handler |
||
367 | addi r1, r1, STKFRAME_LEN |
||
368 | |||
369 | mfsprg2 r3 /* decrement nest counter */ |
||
370 | addi r3, r3, -1 |
||
371 | mtsprg2 r3 |
||
372 | |||
373 | RESTORE_ALL |
||
374 | mfsprg1 r1 /* restore original sp */ |
||
375 | rfi |
||
376 | |||
377 | /* |
||
378 | * Switch register context. |
||
379 | * r3 = previous kern_regs, r4 = next kern_regs |
||
380 | * Interrupts must be disabled by caller. |
||
381 | * |
||
382 | * syntax - void cpu_switch(kern_regs *prev, kern_regs *next) |
||
383 | * |
||
384 | * Note: GCC uses r0-r12 as scratch registers |
||
385 | */ |
||
386 | ENTRY(cpu_switch) |
||
387 | isync |
||
388 | stw r13, 0x00(r3) |
||
389 | stw r14, 0x04(r3) |
||
390 | stw r15, 0x08(r3) |
||
391 | stw r16, 0x0c(r3) |
||
392 | stw r17, 0x10(r3) |
||
393 | stw r18, 0x14(r3) |
||
394 | stw r19, 0x18(r3) |
||
395 | stw r20, 0x1c(r3) |
||
396 | stw r21, 0x20(r3) |
||
397 | stw r22, 0x24(r3) |
||
398 | stw r23, 0x28(r3) |
||
399 | stw r24, 0x2c(r3) |
||
400 | stw r25, 0x30(r3) |
||
401 | stw r26, 0x34(r3) |
||
402 | stw r27, 0x38(r3) |
||
403 | stw r28, 0x3c(r3) |
||
404 | stw r29, 0x40(r3) |
||
405 | stw r30, 0x44(r3) |
||
406 | stw r31, 0x48(r3) |
||
407 | stw r2, 0x4c(r3) |
||
408 | stw r1, 0x50(r3) |
||
409 | mflr r5 |
||
410 | stw r5, 0x54(r3) |
||
411 | mfcr r5 |
||
412 | stw r5, 0x58(r3) |
||
413 | mfsprg0 r5 /* Save kernel stack */ |
||
414 | stw r5, 0x5c(r3) |
||
415 | |||
416 | lwz r13, 0x00(r4) |
||
417 | lwz r14, 0x04(r4) |
||
418 | lwz r15, 0x08(r4) |
||
419 | lwz r16, 0x0c(r4) |
||
420 | lwz r17, 0x10(r4) |
||
421 | lwz r18, 0x14(r4) |
||
422 | lwz r19, 0x18(r4) |
||
423 | lwz r20, 0x1c(r4) |
||
424 | lwz r21, 0x20(r4) |
||
425 | lwz r22, 0x24(r4) |
||
426 | lwz r23, 0x28(r4) |
||
427 | lwz r24, 0x2c(r4) |
||
428 | lwz r25, 0x30(r4) |
||
429 | lwz r26, 0x34(r4) |
||
430 | lwz r27, 0x38(r4) |
||
431 | lwz r28, 0x3c(r4) |
||
432 | lwz r29, 0x40(r4) |
||
433 | lwz r30, 0x44(r4) |
||
434 | lwz r31, 0x48(r4) |
||
435 | lwz r2, 0x4c(r4) |
||
436 | lwz r1, 0x50(r4) |
||
437 | lwz r5, 0x54(r4) |
||
438 | mtlr r5 |
||
439 | lwz r5, 0x58(r4) |
||
440 | mtcr r5 |
||
441 | lwz r5, 0x5c(r4) |
||
442 | mtsprg0 r5 /* Restore kernel stack */ |
||
443 | isync |
||
444 | blr |
||
445 | |||
446 | /* |
||
447 | * void sploff(void); |
||
448 | */ |
||
449 | ENTRY(sploff) |
||
450 | mfmsr r3 |
||
451 | andi. r4, r3, ~MSR_EE@l |
||
452 | mtmsr r4 |
||
453 | blr |
||
454 | |||
455 | /* |
||
456 | * void splon(void); |
||
457 | */ |
||
458 | ENTRY(splon) |
||
459 | mfmsr r3 |
||
460 | ori r4, r3, MSR_EE@l |
||
461 | mtmsr r4 |
||
462 | blr |