Project

General

Profile

Statistics
| Branch: | Revision:

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