2 Copyright � 2013-2015, The AROS Development Team. All rights reserved.
7 #include <aros/kernel.h>
8 #include <aros/libcall.h>
9 #include <hardware/intbits.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)
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
);
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
);
56 *((volatile unsigned int *)reg
) = val
;
60 ** UNDEF INSTRUCTION EXCEPTION
66 ".set MODE_SYSTEM, 0x1f \n"
68 ".globl __vectorhand_undef \n"
69 ".type __vectorhand_undef,%function \n"
70 "__vectorhand_undef: \n"
72 " cpsid i, #" STR(MODE_SYSTEM
)"\n" // switch to system mode, with interrupts disabled..
73 " str sp, [r0, #13*4] \n"
74 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
75 " mov fp, #0 \n" // clear fp
82 void handle_undef(regs_t
*regs
)
84 bug("[Kernel] Trap ARM Undef Exception -> Exception #4 (Illegal instruction)\n");
86 if (krnRunExceptionHandlers(KernelBase
, 4, regs
))
89 if (core_Trap(4, regs
))
91 bug("[Kernel] Trap handler returned\n");
95 bug("[Kernel] UNHANDLED EXCEPTION #4\n");
98 asm volatile ("mov r0, r0\n");
108 ".globl __vectorhand_reset \n"
109 ".type __vectorhand_reset,%function \n"
110 "__vectorhand_reset: \n"
111 " mov sp, #0x1000 - 16 \n" // re-use bootstrap tmp stack
113 " sub r0, r0, #" STR(BOOT_STACK_SIZE
)"\n" // get the boottag's
114 " sub r0, r0, #" STR(BOOT_TAGS_SIZE
) "\n"
115 " mov fp, #0 \n" // clear fp
117 " ldr pc, 2f \n" // jump into kernel resource
119 "2: .word kernel_cstart \n"
124 /* ** SWI HANDLER ** */
126 /** SWI handled in syscall.c */
130 return address = lr - 4
135 ".set MODE_IRQ, 0x12 \n"
136 ".set MODE_SUPERVISOR, 0x13 \n"
137 ".set MODE_SYSTEM, 0x1f \n"
139 ".globl __vectorhand_irq \n"
140 ".type __vectorhand_irq,%function \n"
141 "__vectorhand_irq: \n"
142 " sub lr, lr, #4 \n" // adjust lr_irq
144 " cpsid i, #MODE_SYSTEM \n" // switch to system mode, with interrupts disabled..
145 " str sp, [r0, #13*4] \n"
146 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
147 " mov fp, #0 \n" // clear fp
151 " cpsid i, #MODE_IRQ \n" // switch to IRQ mode, with interrupts disabled..
153 " mov fp, #0 \n" // clear fp
154 " bl core_ExitInterrupt \n"
158 #define IRQ_BANK1 0x00000100
159 #define IRQ_BANK2 0x00000200
161 void handle_irq(regs_t
*regs
)
163 unsigned int pending
, processed
, irq
;
165 DIRQ(bug("[KRN] ## IRQ ##\n"));
167 DREGS(cpu_DumpRegs(regs
));
169 pending
= *((volatile unsigned int *)(ARMIRQ_PEND
));
170 DIRQ(bug("[KRN] PendingARM %08x\n", pending
));
171 if (!(pending
& IRQ_BANK1
))
174 for (irq
= (2 << 5); irq
< ((2 << 5) + 32); irq
++)
176 if (pending
& (1 << (irq
- (2 << 5))))
178 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq
));
179 krnRunIRQHandlers(KernelBase
, irq
);
180 processed
|= (1 << (irq
- (2 << 5)));
186 processed
= IRQ_BANK1
;
188 if (processed
) *((volatile unsigned int *)(ARMIRQ_PEND
)) = (pending
& ~processed
);
190 pending
= *((volatile unsigned int *)(GPUIRQ_PEND0
));
191 DIRQ(bug("[KRN] Pending0 %08x\n", pending
));
192 if (!(pending
& IRQ_BANK2
))
195 for (irq
= (0 << 5); irq
< ((0 << 5) + 32); irq
++)
197 if (pending
& (1 << (irq
- (0 << 5))))
199 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq
));
200 krnRunIRQHandlers(KernelBase
, irq
);
201 processed
|= (1 << (irq
- (0 << 5)));
207 processed
= IRQ_BANK2
;
209 if (processed
) *((volatile unsigned int *)(GPUIRQ_PEND0
)) = (pending
& ~processed
);
211 pending
= *((volatile unsigned int *)(GPUIRQ_PEND1
));
212 DIRQ(bug("[KRN] Pending1 %08x\n", pending
));
214 for (irq
= (1 << 5); irq
< ((1 << 5) + 32); irq
++)
216 if (pending
& (1 << (irq
- (1 << 5))))
218 DIRQ(bug("[KRN] Handling IRQ %d ..\n", irq
));
219 krnRunIRQHandlers(KernelBase
, irq
);
220 processed
|= (1 << (irq
- (1 << 5)));
223 if (processed
) *((volatile unsigned int *)(GPUIRQ_PEND1
)) = (pending
& ~processed
);
225 DIRQ(bug("[KRN] IRQ processing finished\n"));
232 return address = lr -4
236 __attribute__ ((interrupt ("FIQ"))) void __vectorhand_fiq(void)
238 DIRQ(bug("[KRN] ## FIQ ##\n"));
245 ** DATA ABORT EXCEPTION
246 return address = lr - 8
251 ".set MODE_SYSTEM, 0x1f \n"
253 ".globl __vectorhand_dataabort \n"
254 ".type __vectorhand_dataabort,%function \n"
255 "__vectorhand_dataabort: \n"
256 " sub lr, lr, #8 \n" // adjust lr_irq
258 " cpsid i, #MODE_SYSTEM \n" // switch to system mode, with interrupts disabled..
259 " str sp, [r0, #13*4] \n"
260 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
261 " mov fp, #0 \n" // clear fp
263 " bl handle_dataabort \n"
268 void handle_dataabort(regs_t
*regs
)
270 register unsigned int far
;
272 // Read fault address register
273 asm volatile("mrc p15, 0, %[far], c6, c0, 0": [far
] "=r" (far
) );
275 bug("[Kernel] Trap ARM Data Abort Exception -> Exception #2 (Bus Error)\n");
276 bug("[Kernel] attempt to access 0x%p\n", far
);
278 if (krnRunExceptionHandlers(KernelBase
, 2, regs
))
281 if (core_Trap(2, regs
))
283 bug("[Kernel] Trap handler returned\n");
287 bug("[Kernel] UNHANDLED EXCEPTION #2\n");
290 asm volatile ("mov r0, r0\n");
294 ** PREFETCH ABORT EXCEPTION
295 return address = lr - 4
300 ".set MODE_SYSTEM, 0x1f \n"
302 ".globl __vectorhand_prefetchabort \n"
303 ".type __vectorhand_prefetchabort,%function \n"
304 "__vectorhand_prefetchabort: \n"
305 " sub lr, lr, #4 \n" // adjust lr_irq
307 " cpsid i, #MODE_SYSTEM \n" // switch to system mode, with interrupts disabled..
308 " str sp, [r0, #13*4] \n"
309 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
310 " mov fp, #0 \n" // clear fp
312 " bl handle_prefetchabort \n"
317 void handle_prefetchabort(regs_t
*regs
)
319 bug("[Kernel] Trap ARM Prefetch Abort Exception -> Exception #3 (Address Error)\n");
321 if (krnRunExceptionHandlers(KernelBase
, 3, regs
))
324 if (core_Trap(3, regs
))
326 bug("[Kernel] Trap handler returned\n");
330 bug("[Kernel] UNHANDLED EXCEPTION #3\n");
333 asm volatile ("mov r0, r0\n");
340 extern void *__intvecs_start
, *__intvecs_end
;
342 void arm_flush_cache(uint32_t addr
, uint32_t length
)
346 __asm__
__volatile__("mcr p15, 0, %0, c7, c14, 1"::"r"(addr
));
350 __asm__
__volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr
));
353 void arm_icache_invalidate(uint32_t addr
, uint32_t length
)
357 __asm__
__volatile__("mcr p15, 0, %0, c7, c5, 1"::"r"(addr
));
361 __asm__
__volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr
));
364 void core_SetupIntr(void)
367 bug("[KRN] Initializing cpu vectors\n");
369 /* Copy vectors into place */
370 memcpy(0, &__intvecs_start
,
371 (unsigned int)&__intvecs_end
-
372 (unsigned int)&__intvecs_start
);
374 arm_flush_cache(0, 1024);
375 arm_icache_invalidate(0, 1024);
377 D(bug("[KRN] Copied %d bytes from 0x%p to 0x00000000\n", (unsigned int)&__intvecs_end
- (unsigned int)&__intvecs_start
, &__intvecs_start
));
381 bug("[KRN]: Vector dump-:");
382 for (x
=0; x
< (unsigned int)&__intvecs_end
- (unsigned int)&__intvecs_start
; x
++) {
385 bug("\n[KRN]: %08x:", x
);
387 bug(" %02x", *((volatile UBYTE
*)x
));
392 D(bug("[KRN] Disabling IRQs\n"));
393 *(volatile unsigned int *)ARMIRQ_DIBL
= ~0;
394 *(volatile unsigned int *)GPUIRQ_DIBL0
= ~0;
395 *(volatile unsigned int *)GPUIRQ_DIBL1
= ~0;