added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / ppc-sam440 / kernel / intr.c
blobe23893793cd1bdbbfff4be771fdd5c8a7a599ffe
1 #include <aros/kernel.h>
2 #include <aros/libcall.h>
3 #include <asm/amcc440.h>
4 #include <stddef.h>
6 #include "kernel_intern.h"
7 #include "syscall.h"
9 AROS_LH4(void *, KrnAddIRQHandler,
10 AROS_LHA(uint8_t, irq, D0),
11 AROS_LHA(void *, handler, A0),
12 AROS_LHA(void *, handlerData, A1),
13 AROS_LHA(void *, handlerData2, A2),
14 struct KernelBase *, KernelBase, 7, Kernel)
16 AROS_LIBFUNC_INIT
18 return NULL;
20 AROS_LIBFUNC_EXIT
23 AROS_LH1(void, KrnRemIRQHandler,
24 AROS_LHA(void *, handle, A0),
25 struct KernelBase *, KernelBase, 8, Kernel)
27 AROS_LIBFUNC_INIT
30 AROS_LIBFUNC_EXIT
33 AROS_LH0I(void, KrnCli,
34 struct KernelBase *, KernelBase, 9, Kernel)
36 AROS_LIBFUNC_INIT
38 asm volatile("li %%r3,%0; sc"::"i"(SC_CLI):"memory","r3");
40 AROS_LIBFUNC_EXIT
43 AROS_LH0I(void, KrnSti,
44 struct KernelBase *, KernelBase, 10, Kernel)
46 AROS_LIBFUNC_INIT
48 asm volatile("li %%r3,%0; sc"::"i"(SC_STI):"memory","r3");
50 AROS_LIBFUNC_EXIT
53 AROS_LH0I(void, KrnIsSuper,
54 struct KernelBase *, KernelBase, 12, Kernel)
56 AROS_LIBFUNC_INIT
58 register int retval asm ("r3");
60 asm volatile("sc":"=r"(retval):"0"(SC_ISSUPERSTATE):"memory");
62 return retval;
64 AROS_LIBFUNC_EXIT
67 void *__EXCEPTION_0_Prolog();
68 void *__EXCEPTION_1_Prolog();
69 void *__EXCEPTION_2_Prolog();
70 void *__EXCEPTION_3_Prolog();
71 void *__EXCEPTION_4_Prolog();
72 void *__EXCEPTION_5_Prolog();
73 void *__EXCEPTION_6_Prolog();
74 void *__EXCEPTION_7_Prolog();
75 void *__EXCEPTION_8_Prolog();
76 void *__EXCEPTION_9_Prolog();
77 void *__EXCEPTION_10_Prolog();
78 void *__EXCEPTION_11_Prolog();
79 void *__EXCEPTION_12_Prolog();
80 void *__EXCEPTION_13_Prolog();
81 void *__EXCEPTION_14_Prolog();
82 void *__EXCEPTION_15_Prolog();
84 void intr_init()
86 D(bug("[KRN] Setting up exception handlers\n"));
87 wrspr(IVPR, ((uint32_t)&__EXCEPTION_0_Prolog) & 0xffff0000);
89 wrspr(IVOR0, ((uint32_t)&__EXCEPTION_0_Prolog) & 0x0000fff0);
90 wrspr(IVOR1, ((uint32_t)&__EXCEPTION_1_Prolog) & 0x0000fff0);
91 wrspr(IVOR2, ((uint32_t)&__EXCEPTION_2_Prolog) & 0x0000fff0);
92 wrspr(IVOR3, ((uint32_t)&__EXCEPTION_3_Prolog) & 0x0000fff0);
93 wrspr(IVOR4, ((uint32_t)&__EXCEPTION_4_Prolog) & 0x0000fff0);
94 wrspr(IVOR5, ((uint32_t)&__EXCEPTION_5_Prolog) & 0x0000fff0);
95 wrspr(IVOR6, ((uint32_t)&__EXCEPTION_6_Prolog) & 0x0000fff0);
96 wrspr(IVOR7, ((uint32_t)&__EXCEPTION_7_Prolog) & 0x0000fff0);
97 wrspr(IVOR8, ((uint32_t)&__EXCEPTION_8_Prolog) & 0x0000fff0);
98 wrspr(IVOR9, ((uint32_t)&__EXCEPTION_9_Prolog) & 0x0000fff0);
99 wrspr(IVOR10, ((uint32_t)&__EXCEPTION_10_Prolog) & 0x0000fff0);
100 wrspr(IVOR11, ((uint32_t)&__EXCEPTION_11_Prolog) & 0x0000fff0);
101 wrspr(IVOR12, ((uint32_t)&__EXCEPTION_12_Prolog) & 0x0000fff0);
102 wrspr(IVOR13, ((uint32_t)&__EXCEPTION_13_Prolog) & 0x0000fff0);
103 wrspr(IVOR14, ((uint32_t)&__EXCEPTION_14_Prolog) & 0x0000fff0);
104 wrspr(IVOR15, ((uint32_t)&__EXCEPTION_15_Prolog) & 0x0000fff0);
107 #define _STR(x) #x
108 #define STR(x) _STR(x)
109 #define PUT_INTR_TEMPLATE(num, handler) \
110 asm volatile(".section .aros.init,\"ax\"\n\t.align 5\n\t.globl __EXCEPTION_" STR(num) "_Prolog\n\t.type __EXCEPTION_" STR(num) "_Prolog,@function\n" \
111 "__EXCEPTION_" STR(num) "_Prolog: \n\t" \
112 "mtsprg1 %%r3 \n\t" /* save %r3 */ \
113 "mfcr %%r3 \n\t" /* copy CR to %r3 */ \
114 "mtsprg2 %%r3 \n\t" /* save %r3 */ \
116 "mfsrr1 %%r3 \n\t" /* srr1 (previous MSR) reg into %r3 */ \
117 "andi. %%r3,%%r3,%0 \n\t" /* Was the PR bit set in MSR already? */ \
118 "beq- 1f \n\t" /* No, we were in supervisor mode */ \
120 "mfsprg0 %%r3 \n\t" /* user mode case: SSP into %r3 */ \
121 "b 2f \n" \
122 "1: mr %%r3,%%r1 \n\t" /* Supervisor case: use current stack */ \
123 "2: addi %%r3,%%r3,%1 " \
124 ::"i"(MSR_PR),"i"(-sizeof(regs_t))); \
125 asm volatile("stw %%r0, %[gpr0](%%r3) \n\t" \
126 "stw %%r1, %[gpr1](%%r3) \n\t" \
127 "stw %%r2, %[gpr2](%%r3) \n\t" \
128 "mfsprg1 %%r0 \n\t" \
129 "stw %%r4, %[gpr4](%%r3) \n\t" \
130 "stw %%r0, %[gpr3](%%r3) \n\t" \
131 "stw %%r5, %[gpr5](%%r3) \n\t" \
132 "mfsprg2 %%r2 \n\t" \
133 "mfsrr0 %%r0 \n\t" \
134 "mfsrr1 %%r1 \n\t" \
135 "lis %%r5, " #handler "@ha\n\t" \
136 "la %%r5, " #handler "@l(%%r5)\n\t" \
137 "li %%r4, %[irq] \n\t" \
138 "stw %%r2,%[ccr](%%r3) \n\t" \
139 "stw %%r0,%[srr0](%%r3) \n\t" \
140 "stw %%r1,%[srr1](%%r3) \n\t" \
141 "mfctr %%r0 \n\t" \
142 "mflr %%r1 \n\t" \
143 "mfxer %%r2 \n\t" \
144 "stw %%r0,%[ctr](%%r3) \n\t" \
145 "stw %%r1,%[lr](%%r3) \n\t" \
146 "stw %%r2,%[xer](%%r3) \n\t" \
148 :: \
149 [gpr0]"i"(offsetof(regs_t, gpr[0])), \
150 [gpr1]"i"(offsetof(regs_t, gpr[1])), \
151 [gpr2]"i"(offsetof(regs_t, gpr[2])), \
152 [gpr3]"i"(offsetof(regs_t, gpr[3])), \
153 [gpr4]"i"(offsetof(regs_t, gpr[4])), \
154 [gpr5]"i"(offsetof(regs_t, gpr[5])), \
156 [ccr]"i"(offsetof(regs_t, ccr)), \
157 [srr0]"i"(offsetof(regs_t, srr0)), \
158 [srr1]"i"(offsetof(regs_t, srr1)), \
159 [ctr]"i"(offsetof(regs_t, ctr)), \
160 [lr]"i"(offsetof(regs_t, lr)), \
161 [xer]"i"(offsetof(regs_t, xer)), \
162 [irq]"i"(num) \
163 ); \
164 /* \
165 * Registers %r0 to %r5 are now saved together with CPU state. Go to the \
166 * trampoline code which will care about the rest. Adjust the stack frame pointer now, \
167 * or else it will be destroyed later by C code. \
168 */ \
169 asm volatile("addi %r1,%r3,-16"); \
171 /* \
172 * Go to the trampoline code. Use long call within whole 4GB addresspace in order to \
173 * avoid any trouble in future. \
174 */ \
175 asm volatile( "b __EXCEPTION_Trampoline\n\t");
177 void __attribute__((noreturn)) decrementer_handler(regs_t *ctx, uint8_t exception, void *self)
179 struct KernelBase *KernelBase = getKernelBase();
181 /* Clear the DIS bit - we have received decrementer exception */
182 wrspr(TSR, TSR_DIS);
183 //D(bug("[KRN] Decrementer handler. Context @ %p\n", ctx));
185 core_ExitInterrupt(ctx);
189 void __attribute__((noreturn)) generic_handler(regs_t *ctx, uint8_t exception, void *self)
191 struct KernelBase *KernelBase = getKernelBase();
195 D(bug("[KRN] Exception %d handler. Context @ %p\n", exception, ctx));
196 D(bug("[KRN] SRR0=%08x, SRR1=%08x DEAR=%08x\n",ctx->srr0, ctx->srr1, rdspr(DEAR)));
197 D(bug("[KRN] GPR00=%08x GPR01=%08x GPR02=%08x GPR03=%08x\n",
198 ctx->gpr[0],ctx->gpr[1],ctx->gpr[2],ctx->gpr[3]));
199 D(bug("[KRN] GPR04=%08x GPR05=%08x GPR06=%08x GPR07=%08x\n",
200 ctx->gpr[4],ctx->gpr[5],ctx->gpr[6],ctx->gpr[7]));
201 D(bug("[KRN] GPR08=%08x GPR09=%08x GPR10=%08x GPR11=%08x\n",
202 ctx->gpr[8],ctx->gpr[9],ctx->gpr[10],ctx->gpr[11]));
203 D(bug("[KRN] GPR12=%08x GPR13=%08x GPR14=%08x GPR15=%07x\n",
204 ctx->gpr[12],ctx->gpr[13],ctx->gpr[14],ctx->gpr[15]));
206 D(bug("[KRN] GPR16=%08x GPR17=%08x GPR18=%08x GPR19=%08x\n",
207 ctx->gpr[16],ctx->gpr[17],ctx->gpr[18],ctx->gpr[19]));
208 D(bug("[KRN] GPR20=%08x GPR21=%08x GPR22=%08x GPR23=%08x\n",
209 ctx->gpr[20],ctx->gpr[21],ctx->gpr[22],ctx->gpr[23]));
210 D(bug("[KRN] GPR24=%08x GPR25=%08x GPR26=%08x GPR27=%08x\n",
211 ctx->gpr[24],ctx->gpr[25],ctx->gpr[26],ctx->gpr[27]));
212 D(bug("[KRN] GPR28=%08x GPR29=%08x GPR30=%08x GPR31=%07x\n",
213 ctx->gpr[28],ctx->gpr[29],ctx->gpr[30],ctx->gpr[31]));
215 D(bug("[KRN] **UNHANDLED EXCEPTION** stopping here...\n"));
217 while(1) {
218 wrmsr(rdmsr() | MSR_POW);
221 core_LeaveInterrupt(ctx);
224 void __attribute__((noreturn)) mmu_handler(regs_t *ctx, uint8_t exception, void *self)
226 struct KernelBase *KernelBase = getKernelBase();
228 uint32_t insn = *(uint32_t *)ctx->srr0;
230 /* SysBase access at 4UL? Occurs only with lwz instruction and DEAR=4 */
231 if ((insn & 0xfc000000) == 0x80000000 && rdspr(DEAR) == 4)
233 int reg = (insn & 0x03e00000) >> 21;
235 // D(bug("[KRN] Pagefault exception. Someone tries to get SysBase (%08x) from 0x00000004 into r%d. EVIL EVIL EVIL!\n",
236 // getSysBase(), reg));
238 ctx->gpr[reg] = getSysBase();
239 ctx->srr0 += 4;
241 core_LeaveInterrupt(ctx);
243 else
244 generic_handler(ctx, exception, self);
249 static void __attribute__((used)) __EXCEPTION_Prolog_template()
253 * Create partial context on the stack. It is impossible to save it fully since the
254 * exception handlers have limited size. This code will do as much as possible and then
255 * jump to general trampoline...
258 PUT_INTR_TEMPLATE(0, generic_handler); /* crit */
259 PUT_INTR_TEMPLATE(1, generic_handler);
260 PUT_INTR_TEMPLATE(2, generic_handler);
261 PUT_INTR_TEMPLATE(3, generic_handler);
262 PUT_INTR_TEMPLATE(4, uic_handler);
263 PUT_INTR_TEMPLATE(5, generic_handler);
264 PUT_INTR_TEMPLATE(6, generic_handler);
265 PUT_INTR_TEMPLATE(7, generic_handler);
266 PUT_INTR_TEMPLATE(8, syscall_handler);
267 PUT_INTR_TEMPLATE(9, generic_handler);
268 PUT_INTR_TEMPLATE(10, decrementer_handler);
269 PUT_INTR_TEMPLATE(11, generic_handler);
270 PUT_INTR_TEMPLATE(12, generic_handler); /* crit */
271 PUT_INTR_TEMPLATE(13, mmu_handler);
272 PUT_INTR_TEMPLATE(14, generic_handler);
273 PUT_INTR_TEMPLATE(15, generic_handler); /* crit */
276 static void __attribute__((used)) __EXCEPTION_Trampoline_template()
278 asm volatile(".section .aros.init,\"ax\"\n\t.align 5\n\t.globl __EXCEPTION_Trampoline\n\t.type __EXCEPTION_Trampoline,@function\n"
279 "__EXCEPTION_Trampoline: \n\t"
280 "stw %%r6,%[gpr6](%%r3) \n\t"
281 "stw %%r7,%[gpr7](%%r3) \n\t"
282 "stw %%r8,%[gpr8](%%r3) \n\t"
283 "stw %%r9,%[gpr9](%%r3) \n\t"
284 "stw %%r10,%[gpr10](%%r3) \n\t"
285 "stw %%r11,%[gpr11](%%r3) \n\t"
286 "stw %%r12,%[gpr12](%%r3) \n\t"
287 "stw %%r13,%[gpr13](%%r3) \n\t"
288 "stw %%r14,%[gpr14](%%r3) \n\t"
289 "stw %%r15,%[gpr15](%%r3) \n\t"
290 "stw %%r16,%[gpr16](%%r3) \n\t"
291 "stw %%r17,%[gpr17](%%r3) \n\t"
292 "stw %%r18,%[gpr18](%%r3) \n\t"
293 "stw %%r19,%[gpr19](%%r3) \n\t"
294 "stw %%r20,%[gpr20](%%r3) \n\t"
295 "stw %%r21,%[gpr21](%%r3) \n\t"
296 "stw %%r22,%[gpr22](%%r3) \n\t"
297 "stw %%r23,%[gpr23](%%r3) \n\t"
298 "stw %%r24,%[gpr24](%%r3) \n\t"
299 "stw %%r25,%[gpr25](%%r3) \n\t"
300 "stw %%r26,%[gpr26](%%r3) \n\t"
301 "stw %%r27,%[gpr27](%%r3) \n\t"
302 "stw %%r28,%[gpr28](%%r3) \n\t"
303 "stw %%r29,%[gpr29](%%r3) \n\t"
304 "stw %%r30,%[gpr30](%%r3) \n\t"
305 "stw %%r31,%[gpr31](%%r3) \n\t"
306 "mr %%r28,%%r3 \n\t"
307 "mr %%r29,%%r4 \n\t"
308 "mr %%r30,%%r5 \n\t"
309 "mtsrr0 %%r5 \n\t"
310 "lis %%r9, %[msrval]@ha \n\t"
311 "ori %%r9,%%r9, %[msrval]@l \n\t"
312 "mtsrr1 %%r9 \n\t"
313 "sync; isync; rfi"
315 [gpr6]"i"(offsetof(regs_t, gpr[6])),
316 [gpr7]"i"(offsetof(regs_t, gpr[7])),
317 [gpr8]"i"(offsetof(regs_t, gpr[8])),
318 [gpr9]"i"(offsetof(regs_t, gpr[9])),
319 [gpr10]"i"(offsetof(regs_t, gpr[10])),
320 [gpr11]"i"(offsetof(regs_t, gpr[11])),
321 [gpr12]"i"(offsetof(regs_t, gpr[12])),
322 [gpr13]"i"(offsetof(regs_t, gpr[13])),
323 [gpr14]"i"(offsetof(regs_t, gpr[14])),
324 [gpr15]"i"(offsetof(regs_t, gpr[15])),
325 [gpr16]"i"(offsetof(regs_t, gpr[16])),
326 [gpr17]"i"(offsetof(regs_t, gpr[17])),
327 [gpr18]"i"(offsetof(regs_t, gpr[18])),
328 [gpr19]"i"(offsetof(regs_t, gpr[19])),
329 [gpr20]"i"(offsetof(regs_t, gpr[20])),
330 [gpr21]"i"(offsetof(regs_t, gpr[21])),
331 [gpr22]"i"(offsetof(regs_t, gpr[22])),
332 [gpr23]"i"(offsetof(regs_t, gpr[23])),
333 [gpr24]"i"(offsetof(regs_t, gpr[24])),
334 [gpr25]"i"(offsetof(regs_t, gpr[25])),
335 [gpr26]"i"(offsetof(regs_t, gpr[26])),
336 [gpr27]"i"(offsetof(regs_t, gpr[27])),
337 [gpr28]"i"(offsetof(regs_t, gpr[28])),
338 [gpr29]"i"(offsetof(regs_t, gpr[29])),
339 [gpr30]"i"(offsetof(regs_t, gpr[30])),
340 [gpr31]"i"(offsetof(regs_t, gpr[31])),
341 [msrval]"i"(MSR_ME|MSR_CE)
346 static void __attribute__((used)) __core_LeaveInterrupt()
348 asm volatile(".section .aros.init,\"ax\"\n\t.align 5\n\t.globl core_LeaveInterrupt\n\t.type core_LeaveInterrupt,@function\n"
349 "core_LeaveInterrupt: \n\t"
350 "lwz %%r31,%[gpr31](%%r3) \n\t"
351 "lwz %%r30,%[gpr30](%%r3) \n\t"
352 "lwz %%r29,%[gpr29](%%r3) \n\t"
353 "lwz %%r28,%[gpr28](%%r3) \n\t"
354 "lwz %%r27,%[gpr27](%%r3) \n\t"
355 "lwz %%r26,%[gpr26](%%r3) \n\t"
356 "lwz %%r25,%[gpr25](%%r3) \n\t"
357 "lwz %%r24,%[gpr24](%%r3) \n\t"
358 "lwz %%r23,%[gpr23](%%r3) \n\t"
359 "lwz %%r22,%[gpr22](%%r3) \n\t"
360 "lwz %%r21,%[gpr21](%%r3) \n\t"
361 "lwz %%r20,%[gpr20](%%r3) \n\t"
362 "lwz %%r19,%[gpr19](%%r3) \n\t"
363 "lwz %%r18,%[gpr18](%%r3) \n\t"
364 "lwz %%r17,%[gpr17](%%r3) \n\t"
365 "lwz %%r16,%[gpr16](%%r3) \n\t"
366 "lwz %%r15,%[gpr15](%%r3) \n\t"
367 "lwz %%r14,%[gpr14](%%r3) \n\t"
368 "lwz %%r13,%[gpr13](%%r3) \n\t"
369 "lwz %%r12,%[gpr12](%%r3) \n\t"
371 [gpr12]"i"(offsetof(regs_t, gpr[12])),
372 [gpr13]"i"(offsetof(regs_t, gpr[13])),
373 [gpr14]"i"(offsetof(regs_t, gpr[14])),
374 [gpr15]"i"(offsetof(regs_t, gpr[15])),
375 [gpr16]"i"(offsetof(regs_t, gpr[16])),
376 [gpr17]"i"(offsetof(regs_t, gpr[17])),
377 [gpr18]"i"(offsetof(regs_t, gpr[18])),
378 [gpr19]"i"(offsetof(regs_t, gpr[19])),
379 [gpr20]"i"(offsetof(regs_t, gpr[20])),
380 [gpr21]"i"(offsetof(regs_t, gpr[21])),
381 [gpr22]"i"(offsetof(regs_t, gpr[22])),
382 [gpr23]"i"(offsetof(regs_t, gpr[23])),
383 [gpr24]"i"(offsetof(regs_t, gpr[24])),
384 [gpr25]"i"(offsetof(regs_t, gpr[25])),
385 [gpr26]"i"(offsetof(regs_t, gpr[26])),
386 [gpr27]"i"(offsetof(regs_t, gpr[27])),
387 [gpr28]"i"(offsetof(regs_t, gpr[28])),
388 [gpr29]"i"(offsetof(regs_t, gpr[29])),
389 [gpr30]"i"(offsetof(regs_t, gpr[30])),
390 [gpr31]"i"(offsetof(regs_t, gpr[31]))
393 asm volatile(
394 "lwz %%r11,%[gpr11](%%r3) \n\t"
395 "lwz %%r0,%[srr0](%%r3) \n\t"
396 "mtsrr0 %%r0 \n\t"
397 "lwz %%r0,%[srr1](%%r3) \n\t"
398 "mtsrr1 %%r0 \n\t"
399 "lwz %%r0,%[ctr](%%r3) \n\t"
400 "mtctr %%r0 \n\t"
401 "lwz %%r0,%[lr](%%r3) \n\t"
402 "mtlr %%r0 \n\t"
403 "lwz %%r0,%[xer](%%r3) \n\t"
404 "mtxer %%r0 \n\t"
405 "lwz %%r10,%[gpr10](%%r3) \n\t"
406 "lwz %%r9,%[gpr9](%%r3) \n\t"
407 "lwz %%r8,%[gpr8](%%r3) \n\t"
408 "lwz %%r7,%[gpr7](%%r3) \n\t"
409 "lwz %%r6,%[gpr6](%%r3) \n\t"
410 "lwz %%r5,%[gpr5](%%r3) \n\t"
411 "lwz %%r4,%[gpr4](%%r3) \n\t"
412 "lwz %%r0,%[gpr3](%%r3) \n\t"
413 "mtsprg1 %%r0 \n\t"
414 "lwz %%r2,%[gpr2](%%r3) \n\t"
415 "stwcx. %%r0,0,%%r1 \n\t"
416 "lwz %%r0,%[ccr](%%r3) \n\t"
417 "mtcr %%r0 \n\t"
418 "lwz %%r1,%[gpr1](%%r3) \n\t"
419 "lwz %%r0,%[gpr0](%%r3) \n\t"
420 "mfsprg1 %%r3 \n\t"
421 "sync; isync; rfi"
423 [ccr]"i"(offsetof(regs_t, ccr)), /* */
424 [srr0]"i"(offsetof(regs_t, srr0)), /* */
425 [srr1]"i"(offsetof(regs_t, srr1)),/* */
426 [ctr]"i"(offsetof(regs_t, ctr)),/**/
427 [lr]"i"(offsetof(regs_t, lr)),/**/
428 [xer]"i"(offsetof(regs_t, xer)),
429 [gpr0]"i"(offsetof(regs_t, gpr[0])),
430 [gpr1]"i"(offsetof(regs_t, gpr[1])),
431 [gpr2]"i"(offsetof(regs_t, gpr[2])),
432 [gpr3]"i"(offsetof(regs_t, gpr[3])),
433 [gpr4]"i"(offsetof(regs_t, gpr[4])),
434 [gpr5]"i"(offsetof(regs_t, gpr[5])),
435 [gpr6]"i"(offsetof(regs_t, gpr[6])),
436 [gpr7]"i"(offsetof(regs_t, gpr[7])),
437 [gpr8]"i"(offsetof(regs_t, gpr[8])),
438 [gpr9]"i"(offsetof(regs_t, gpr[9])),
439 [gpr10]"i"(offsetof(regs_t, gpr[10])),
440 [gpr11]"i"(offsetof(regs_t, gpr[11]))