tiddy up debug a little
[AROS.git] / arch / arm-native / kernel / intr.c
blob235fb8e74d3102d07e9e625c060510d4a4a70099
1 /*
2 Copyright � 2013-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <inttypes.h>
7 #include <aros/kernel.h>
8 #include <aros/libcall.h>
9 #include <hardware/intbits.h>
10 #include <stddef.h>
11 #include <string.h>
13 #include <proto/exec.h>
14 #include <proto/kernel.h>
16 #include "kernel_cpu.h"
17 #include "kernel_intern.h"
18 #include "kernel_debug.h"
19 #include "kernel_interrupts.h"
20 #include "kernel_intr.h"
22 #define BOOT_STACK_SIZE (256 << 2)
23 #define BOOT_TAGS_SIZE (128 << 3)
25 #define IRQBANK_POINTER(bank) ((bank == 0) ? GPUIRQ_ENBL0 : (bank == 1) ? GPUIRQ_ENBL1 : ARMIRQ_ENBL)
27 #define DREGS(x)
28 #define DIRQ(x)
29 #define D(x)
31 void ictl_enable_irq(uint8_t irq, struct KernelBase *KernelBase)
33 int bank = IRQ_BANK(irq);
34 unsigned int val, reg;
36 reg = IRQBANK_POINTER(bank);
38 DIRQ(bug("[KRN] Enabling irq %d [bank %d, reg 0x%p]\n", irq, bank, reg));
40 val = *((volatile unsigned int *)reg);
41 val |= IRQ_MASK(irq);
42 *((volatile unsigned int *)reg) = val;
45 void ictl_disable_irq(uint8_t irq, struct KernelBase *KernelBase)
47 int bank = IRQ_BANK(irq);
48 unsigned int val, reg;
50 reg = IRQBANK_POINTER(bank);
52 DIRQ(bug("[KRN] Dissabling irq %d [bank %d, reg 0x%p]\n", irq, bank, reg));
54 val = *((volatile unsigned int *)reg);
55 val |= IRQ_MASK(irq);
56 *((volatile unsigned int *)reg) = val;
59 static void arm_halt(void)
61 bug("[Kernel] halting cpu\n");
63 __asm__ __volatile__(
64 "haltloop: \n"
65 " b haltloop \n"
70 ** UNDEF INSTRUCTION EXCEPTION
71 return addr = lr
72 entered in UND mode.
75 asm (
76 ".set MODE_SYSTEM, 0x1f \n"
78 ".globl __vectorhand_undef \n"
79 ".type __vectorhand_undef,%function \n"
80 "__vectorhand_undef: \n"
81 VECTCOMMON_START
82 " cpsid i, #" STR(MODE_SYSTEM)"\n" // switch to system mode, with interrupts disabled..
83 " str sp, [r0, #13*4] \n"
84 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
85 " mov fp, #0 \n" // clear fp
87 " bl handle_undef \n"
89 VECTCOMMON_END
92 void handle_undef(regs_t *regs)
94 bug("[Kernel] Trap ARM Undef Exception\n");
95 bug("[Kernel] exception #4 (Illegal instruction)\n");
96 bug("[Kernel] at 0x%p\n", regs[14]);
98 if (krnRunExceptionHandlers(KernelBase, 4, regs))
99 return;
101 D(bug("[Kernel] exception handler(s) returned\n"));
103 if (core_Trap(4, regs))
105 D(bug("[Kernel] trap handler(s) returned\n"));
106 return;
109 bug("[Kernel] UNHANDLED EXCEPTION #4\n");
111 cpu_DumpRegs(regs);
113 arm_halt();
117 ** RESET HANDLER
118 no return address,
119 entered in SVC mode.
122 asm (
123 ".globl __vectorhand_reset \n"
124 ".type __vectorhand_reset,%function \n"
125 "__vectorhand_reset: \n"
126 " mov sp, #0x1000 - 16 \n" // re-use bootstrap tmp stack
127 " mov r0, sp \n"
128 " sub r0, r0, #" STR(BOOT_STACK_SIZE)"\n" // get the boottag's
129 " sub r0, r0, #" STR(BOOT_TAGS_SIZE) "\n"
130 " mov fp, #0 \n" // clear fp
132 " ldr pc, 2f \n" // jump into kernel resource
133 "1: b 1b \n"
134 "2: .word kernel_cstart \n"
139 /* ** SWI HANDLER ** */
141 /** SWI handled in syscall.c */
144 ** IRQ HANDLER
145 return address = lr - 4
146 entered in IRQ mode.
149 asm (
150 ".set MODE_IRQ, 0x12 \n"
151 ".set MODE_SUPERVISOR, 0x13 \n"
152 ".set MODE_SYSTEM, 0x1f \n"
154 ".globl __vectorhand_irq \n"
155 ".type __vectorhand_irq,%function \n"
156 "__vectorhand_irq: \n"
157 " sub lr, lr, #4 \n" // adjust lr_irq
158 VECTCOMMON_START
159 " cpsid i, #MODE_SYSTEM \n" // switch to system mode, with interrupts disabled..
160 " str sp, [r0, #13*4] \n"
161 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
162 " mov fp, #0 \n" // clear fp
164 " bl handle_irq \n"
166 " cpsid i, #MODE_IRQ \n" // switch to IRQ mode, with interrupts disabled..
167 " mov r0, sp \n"
168 " ldr r1, [r0, #16*4] \n" // load the spr register
169 " and r1, r1, #31 \n" // mask processor mode
170 " cmp r1, #16 \n" // will we go back to user mode?
171 " cmpne r1, #31 \n" // or maybe system mode which is basically privileged user mode?
172 " bne 1f \n" // no? don't call core_ExitInterrupt!
173 " mov fp, #0 \n" // clear fp
174 " bl core_ExitInterrupt \n"
175 "1: \n"
176 VECTCOMMON_END
179 #define IRQ_BANK1 0x00000100
180 #define IRQ_BANK2 0x00000200
182 void handle_irq(regs_t *regs)
184 unsigned int pending, processed, irq;
186 DIRQ(bug("[KRN] ## IRQ ##\n"));
188 DREGS(cpu_DumpRegs(regs));
190 pending = *((volatile unsigned int *)(ARMIRQ_PEND));
191 DIRQ(bug("[KRN] PendingARM %08x\n", pending));
192 if (!(pending & IRQ_BANK1))
194 processed = 0;
195 for (irq = (2 << 5); irq < ((2 << 5) + 32); irq++)
197 if (pending & (1 << (irq - (2 << 5))))
199 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq));
200 krnRunIRQHandlers(KernelBase, irq);
201 processed |= (1 << (irq - (2 << 5)));
205 else
207 processed = IRQ_BANK1;
209 if (processed) *((volatile unsigned int *)(ARMIRQ_PEND)) = (pending & ~processed);
211 pending = *((volatile unsigned int *)(GPUIRQ_PEND0));
212 DIRQ(bug("[KRN] Pending0 %08x\n", pending));
213 if (!(pending & IRQ_BANK2))
215 processed = 0;
216 for (irq = (0 << 5); irq < ((0 << 5) + 32); irq++)
218 if (pending & (1 << (irq - (0 << 5))))
220 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq));
221 krnRunIRQHandlers(KernelBase, irq);
222 processed |= (1 << (irq - (0 << 5)));
226 else
228 processed = IRQ_BANK2;
230 if (processed) *((volatile unsigned int *)(GPUIRQ_PEND0)) = (pending & ~processed);
232 pending = *((volatile unsigned int *)(GPUIRQ_PEND1));
233 DIRQ(bug("[KRN] Pending1 %08x\n", pending));
234 processed = 0;
235 for (irq = (1 << 5); irq < ((1 << 5) + 32); irq++)
237 if (pending & (1 << (irq - (1 << 5))))
239 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq));
240 krnRunIRQHandlers(KernelBase, irq);
241 processed |= (1 << (irq - (1 << 5)));
244 if (processed) *((volatile unsigned int *)(GPUIRQ_PEND1)) = (pending & ~processed);
246 DIRQ(bug("[KRN] IRQ processing finished\n"));
248 return;
252 ** FIQ HANDLER
253 return address = lr -4
254 entered in FIQ mode.
257 __attribute__ ((interrupt ("FIQ"))) void __vectorhand_fiq(void)
259 DIRQ(bug("[KRN] ## FIQ ##\n"));
261 return;
266 ** DATA ABORT EXCEPTION
267 return address = lr - 8
268 entered in ABT mode.
271 asm (
272 ".set MODE_SYSTEM, 0x1f \n"
274 ".globl __vectorhand_dataabort \n"
275 ".type __vectorhand_dataabort,%function \n"
276 "__vectorhand_dataabort: \n"
277 " sub lr, lr, #8 \n" // adjust lr_irq
278 VECTCOMMON_START
279 " cpsid i, #MODE_SYSTEM \n" // switch to system mode, with interrupts disabled..
280 " str sp, [r0, #13*4] \n"
281 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
282 " mov fp, #0 \n" // clear fp
284 " bl handle_dataabort \n"
286 VECTCOMMON_END
289 void handle_dataabort(regs_t *regs)
291 register unsigned int far;
293 // Read fault address register
294 asm volatile("mrc p15, 0, %[far], c6, c0, 0": [far] "=r" (far) );
296 bug("[Kernel] Trap ARM Data Abort Exception\n");
297 bug("[Kernel] exception #2 (Bus Error)\n");
298 bug("[Kernel] attempt to access 0x%p from 0x%p\n", far, regs[14]);
300 if (krnRunExceptionHandlers(KernelBase, 2, regs))
301 return;
303 D(bug("[Kernel] exception handler(s) returned\n"));
305 if (core_Trap(2, regs))
307 D(bug("[Kernel] trap handler(s) returned\n"));
308 return;
311 bug("[Kernel] UNHANDLED EXCEPTION #2\n");
313 cpu_DumpRegs(regs);
315 arm_halt();
319 ** PREFETCH ABORT EXCEPTION
320 return address = lr - 4
321 entered in ABT mode.
324 asm (
325 ".set MODE_SYSTEM, 0x1f \n"
327 ".globl __vectorhand_prefetchabort \n"
328 ".type __vectorhand_prefetchabort,%function \n"
329 "__vectorhand_prefetchabort: \n"
330 " sub lr, lr, #4 \n" // adjust lr_irq
331 VECTCOMMON_START
332 " cpsid i, #MODE_SYSTEM \n" // switch to system mode, with interrupts disabled..
333 " str sp, [r0, #13*4] \n"
334 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
335 " mov fp, #0 \n" // clear fp
337 " bl handle_prefetchabort \n"
339 VECTCOMMON_END
342 void handle_prefetchabort(regs_t *regs)
344 bug("[Kernel] Trap ARM Prefetch Abort Exception\n");
345 bug("[Kernel] exception #3 (Address Error)\n");
346 bug("[Kernel] at 0x%p\n", regs[14]);
348 if (krnRunExceptionHandlers(KernelBase, 3, regs))
349 return;
351 D(bug("[Kernel] exception handler(s) returned\n"));
353 if (core_Trap(3, regs))
355 D(bug("[Kernel] trap handler(s) returned\n"));
356 return;
359 bug("[Kernel] UNHANDLED EXCEPTION #3\n");
361 cpu_DumpRegs(regs);
363 arm_halt();
367 /* ** SETUP ** */
369 /* linker exports */
370 extern void *__intvecs_start, *__intvecs_end;
372 void arm_flush_cache(uint32_t addr, uint32_t length)
374 while (length)
376 __asm__ __volatile__("mcr p15, 0, %0, c7, c14, 1"::"r"(addr));
377 addr += 32;
378 length -= 32;
380 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
383 void arm_icache_invalidate(uint32_t addr, uint32_t length)
385 while (length)
387 __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 1"::"r"(addr));
388 addr += 32;
389 length -= 32;
391 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
394 void core_SetupIntr(void)
396 int irq;
397 bug("[KRN] Initializing cpu vectors\n");
399 /* Copy vectors into place */
400 memcpy(0, &__intvecs_start,
401 (unsigned int)&__intvecs_end -
402 (unsigned int)&__intvecs_start);
404 arm_flush_cache(0, 1024);
405 arm_icache_invalidate(0, 1024);
407 D(bug("[KRN] Copied %d bytes from 0x%p to 0x00000000\n", (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start, &__intvecs_start));
410 unsigned int x = 0;
411 bug("[KRN]: Vector dump-:");
412 for (x=0; x < (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start; x++) {
413 if ((x%16) == 0)
415 bug("\n[KRN]: %08x:", x);
417 bug(" %02x", *((volatile UBYTE *)x));
419 bug("\n");
422 D(bug("[KRN] Disabling IRQs\n"));
423 *(volatile unsigned int *)ARMIRQ_DIBL = ~0;
424 *(volatile unsigned int *)GPUIRQ_DIBL0 = ~0;
425 *(volatile unsigned int *)GPUIRQ_DIBL1 = ~0;