revert between 56095 -> 55830 in arch
[AROS.git] / arch / arm-native / kernel / intr.c
blobf49b48f8f3fddbcb67e514fa6806d5c4780800b9
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 DREGS(x)
26 #define DIRQ(x)
27 #define D(x)
29 /* linker exports */
30 extern void *__intvecs_start, *__intvecs_end;
31 extern void __arm_halt(void);
33 void ictl_enable_irq(uint8_t irq, struct KernelBase *KernelBase)
35 if (__arm_arosintern.ARMI_IRQEnable)
36 __arm_arosintern.ARMI_IRQEnable(irq);
39 void ictl_disable_irq(uint8_t irq, struct KernelBase *KernelBase)
41 if (__arm_arosintern.ARMI_IRQDisable)
42 __arm_arosintern.ARMI_IRQDisable(irq);
45 asm (
46 ".globl __arm_halt \n"
47 ".type __arm_halt,%function \n"
48 "__arm_halt: \n"
49 " b __arm_halt \n"
53 ** UNDEF INSTRUCTION EXCEPTION
54 return addr = lr
55 entered in UND mode.
58 asm (
59 ".set MODE_SYSTEM, 0x1f \n"
61 ".globl __vectorhand_undef \n"
62 ".type __vectorhand_undef,%function \n"
63 "__vectorhand_undef: \n"
64 VECTCOMMON_START
65 " bl handle_undef \n"
66 VECTCOMMON_END
69 void handle_undef(regs_t *regs)
71 bug("[Kernel] Trap ARM Undef Exception\n");
72 bug("[Kernel] exception #4 (Illegal instruction)\n");
73 bug("[Kernel] at 0x%p\n", regs->pc);
75 if (krnRunExceptionHandlers(KernelBase, 4, regs))
76 return;
78 D(bug("[Kernel] exception handler(s) returned\n"));
80 if (core_Trap(4, regs))
82 D(bug("[Kernel] trap handler(s) returned\n"));
83 return;
86 bug("[Kernel] UNHANDLED EXCEPTION #4\n");
88 cpu_DumpRegs(regs);
90 __arm_halt();
94 ** RESET HANDLER
95 no return address,
96 entered in SVC mode.
99 asm (
100 ".globl __vectorhand_reset \n"
101 ".type __vectorhand_reset,%function \n"
102 "__vectorhand_reset: \n"
103 " mov sp, #0x1000 - 16 \n" // re-use bootstrap tmp stack
104 " sub r0, sp, #" STR(BOOT_STACK_SIZE)"\n" // get the boottag's
105 " sub r0, r0, #" STR(BOOT_TAGS_SIZE) "\n"
106 " mov fp, #0 \n" // clear fp
108 " ldr pc, 2f \n" // jump into kernel resource
109 "1: b 1b \n"
110 "2: .word kernel_cstart \n"
114 /* ** SWI HANDLER ** */
116 /** SWI handled in syscall.c */
119 ** IRQ HANDLER
120 return address = lr - 4
121 entered in IRQ mode.
124 asm (
125 ".set MODE_IRQ, 0x12 \n"
126 ".set MODE_SUPERVISOR, 0x13 \n"
127 ".set MODE_SYSTEM, 0x1f \n"
129 ".globl __vectorhand_irq \n"
130 ".type __vectorhand_irq,%function \n"
131 "__vectorhand_irq: \n"
132 " sub lr, lr, #4 \n" // adjust lr_irq
133 VECTCOMMON_START
134 " bl handle_irq \n"
135 " mov r0, sp \n"
136 " ldr r1, [r0, #16*4] \n" // load the spr register
137 " and r1, r1, #31 \n" // mask processor mode
138 " cmp r1, #0x10 \n" // will we go back to user mode?
139 " cmpne r1, #0x1f \n" // or system mode (falls we use it)
140 " bne 1f \n" // no? don't call core_ExitInterrupt!
141 " mov fp, #0 \n" // clear fp
142 " bl core_ExitInterrupt \n"
143 "1: \n"
144 VECTCOMMON_END
147 void handle_irq(regs_t *regs)
149 DIRQ(bug("[Kernel] ## IRQ ##\n"));
151 DREGS(cpu_DumpRegs(regs));
153 if (__arm_arosintern.ARMI_IRQProcess)
154 __arm_arosintern.ARMI_IRQProcess();
156 DIRQ(bug("[Kernel] IRQ processing finished\n"));
158 return;
162 ** FIQ HANDLER
163 return address = lr -4
164 entered in FIQ mode.
167 __attribute__ ((interrupt ("FIQ"))) void __vectorhand_fiq(void)
169 DIRQ(bug("[Kernel] ## FIQ ##\n"));
171 if (__arm_arosintern.ARMI_FIQProcess)
172 __arm_arosintern.ARMI_FIQProcess();
174 DIRQ(bug("[Kernel] FIQ processing finished\n"));
176 return;
180 ** DATA ABORT EXCEPTION
181 return address = lr - 8
182 entered in ABT mode.
185 asm (
186 ".set MODE_SYSTEM, 0x1f \n"
188 ".globl __vectorhand_dataabort \n"
189 ".type __vectorhand_dataabort,%function \n"
190 "__vectorhand_dataabort: \n"
191 " sub lr, lr, #8 \n" // adjust lr_irq
192 VECTCOMMON_START
193 " bl handle_dataabort \n"
194 VECTCOMMON_END
197 void handle_dataabort(regs_t *regs)
199 register unsigned int far;
201 // Read fault address register
202 asm volatile("mrc p15, 0, %[far], c6, c0, 0": [far] "=r" (far) );
204 bug("[Kernel] Trap ARM Data Abort Exception\n");
205 bug("[Kernel] exception #2 (Bus Error)\n");
206 bug("[Kernel] attempt to access 0x%p from 0x%p\n", far, regs->pc);
208 cpu_DumpRegs(regs);
210 if (krnRunExceptionHandlers(KernelBase, 2, regs))
211 return;
213 D(bug("[Kernel] exception handler(s) returned\n"));
215 if (core_Trap(2, regs))
217 D(bug("[Kernel] trap handler(s) returned\n"));
218 return;
221 bug("[Kernel] UNHANDLED EXCEPTION #2\n");
223 cpu_DumpRegs(regs);
225 __arm_halt();
229 ** PREFETCH ABORT EXCEPTION
230 return address = lr - 4
231 entered in ABT mode.
234 asm (
235 ".set MODE_SYSTEM, 0x1f \n"
237 ".globl __vectorhand_prefetchabort \n"
238 ".type __vectorhand_prefetchabort,%function \n"
239 "__vectorhand_prefetchabort: \n"
240 " sub lr, lr, #4 \n" // adjust lr_irq
241 VECTCOMMON_START
243 " bl handle_prefetchabort \n"
245 VECTCOMMON_END
248 void handle_prefetchabort(regs_t *regs)
250 bug("[Kernel] Trap ARM Prefetch Abort Exception\n");
251 bug("[Kernel] exception #3 (Address Error)\n");
252 bug("[Kernel] at 0x%p\n", regs->pc);
254 cpu_DumpRegs(regs);
256 if (krnRunExceptionHandlers(KernelBase, 3, regs))
257 return;
259 D(bug("[Kernel] exception handler(s) returned\n"));
261 if (core_Trap(3, regs))
263 D(bug("[Kernel] trap handler(s) returned\n"));
264 return;
267 bug("[Kernel] UNHANDLED EXCEPTION #3\n");
269 cpu_DumpRegs(regs);
271 __arm_halt();
275 /* ** SETUP ** */
277 void arm_flush_cache(uint32_t addr, uint32_t length)
279 while (length)
281 __asm__ __volatile__("mcr p15, 0, %0, c7, c14, 1"::"r"(addr));
282 addr += 32;
283 length -= 32;
285 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
288 void arm_icache_invalidate(uint32_t addr, uint32_t length)
290 while (length)
292 __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 1"::"r"(addr));
293 addr += 32;
294 length -= 32;
296 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
300 Beware! Here be dragons!
302 This function copies our vector table to address 0. We do that in *two* steps:
303 Fist we copy four bytes from source to address 0 using ASM, because gcc will
304 not allow to dereference null pointer. THen the rest of the table is copied.
306 void copy_vectors(const void * src, int length)
308 char *d = (char *)4;
309 const char *s = (const char *)src + 4;
311 asm volatile("str %1, [%0]"::"r"(0), "r"(*(ULONG*)src));
313 while(length--)
315 *d++ = *s++;
319 void core_SetupIntr(void)
321 bug("[Kernel] Initializing cpu vectors\n");
323 /* Copy vectors into place */
324 copy_vectors(&__intvecs_start,
325 (unsigned int)&__intvecs_end -
326 (unsigned int)&__intvecs_start);
328 arm_flush_cache(0, 1024);
329 arm_icache_invalidate(0, 1024);
331 D(bug("[Kernel] Copied %d bytes from 0x%p to 0x00000000\n", (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start, &__intvecs_start));
334 unsigned int x = 0;
335 bug("[Kernel]: Vector dump-:");
336 for (x=0; x < (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start; x++) {
337 if ((x%16) == 0)
339 bug("\n[Kernel]: %08x:", x);
341 bug(" %02x", *((volatile UBYTE *)x));
343 bug("\n");
346 if (__arm_arosintern.ARMI_IRQInit)
347 __arm_arosintern.ARMI_IRQInit();