1 #include <aros/kernel.h>
2 #include <aros/libcall.h>
3 #include <asm/amcc440.h>
6 #include "kernel_intern.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
)
23 AROS_LH1(void, KrnRemIRQHandler
,
24 AROS_LHA(void *, handle
, A0
),
25 struct KernelBase
*, KernelBase
, 8, Kernel
)
33 AROS_LH0I(void, KrnCli
,
34 struct KernelBase
*, KernelBase
, 9, Kernel
)
38 asm volatile("li %%r3,%0; sc"::"i"(SC_CLI
):"memory","r3");
43 AROS_LH0I(void, KrnSti
,
44 struct KernelBase
*, KernelBase
, 10, Kernel
)
48 asm volatile("li %%r3,%0; sc"::"i"(SC_STI
):"memory","r3");
53 AROS_LH0I(void, KrnIsSuper
,
54 struct KernelBase
*, KernelBase
, 12, Kernel
)
58 register int retval
asm ("r3");
60 asm volatile("sc":"=r"(retval
):"0"(SC_ISSUPERSTATE
):"memory");
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();
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);
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 */ \
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" \
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" \
144 "stw %%r0,%[ctr](%%r3) \n\t" \
145 "stw %%r1,%[lr](%%r3) \n\t" \
146 "stw %%r2,%[xer](%%r3) \n\t" \
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)), \
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. \
169 asm volatile("addi %r1,%r3,-16"); \
172 * Go to the trampoline code. Use long call within whole 4GB addresspace in order to \
173 * avoid any trouble in future. \
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 */
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"));
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();
241 core_LeaveInterrupt(ctx
);
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"
310 "lis %%r9, %[msrval]@ha \n\t"
311 "ori %%r9,%%r9, %[msrval]@l \n\t"
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]))
394 "lwz %%r11,%[gpr11](%%r3) \n\t"
395 "lwz %%r0,%[srr0](%%r3) \n\t"
397 "lwz %%r0,%[srr1](%%r3) \n\t"
399 "lwz %%r0,%[ctr](%%r3) \n\t"
401 "lwz %%r0,%[lr](%%r3) \n\t"
403 "lwz %%r0,%[xer](%%r3) \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"
414 "lwz %%r2,%[gpr2](%%r3) \n\t"
415 "stwcx. %%r0,0,%%r1 \n\t"
416 "lwz %%r0,%[ccr](%%r3) \n\t"
418 "lwz %%r1,%[gpr1](%%r3) \n\t"
419 "lwz %%r0,%[gpr0](%%r3) \n\t"
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]))