Use new ARM instructions for interrupts, exceptions and system calls.
[AROS.git] / arch / arm-native / kernel / intr.c
blob65fb7d19c20b526cc6a663e91e3dbc1bff2137b7
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[14]);
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("[KRN] ## IRQ ##\n"));
151 DREGS(cpu_DumpRegs(regs));
153 if (__arm_arosintern.ARMI_IRQProcess)
154 __arm_arosintern.ARMI_IRQProcess();
156 DIRQ(bug("[KRN] 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("[KRN] ## FIQ ##\n"));
171 DIRQ(bug("[KRN] FIQ processing finished\n"));
173 return;
177 ** DATA ABORT EXCEPTION
178 return address = lr - 8
179 entered in ABT mode.
182 asm (
183 ".set MODE_SYSTEM, 0x1f \n"
185 ".globl __vectorhand_dataabort \n"
186 ".type __vectorhand_dataabort,%function \n"
187 "__vectorhand_dataabort: \n"
188 " sub lr, lr, #8 \n" // adjust lr_irq
189 VECTCOMMON_START
190 " bl handle_dataabort \n"
191 VECTCOMMON_END
194 void handle_dataabort(regs_t *regs)
196 register unsigned int far;
198 // Read fault address register
199 asm volatile("mrc p15, 0, %[far], c6, c0, 0": [far] "=r" (far) );
201 bug("[Kernel] Trap ARM Data Abort Exception\n");
202 bug("[Kernel] exception #2 (Bus Error)\n");
203 bug("[Kernel] attempt to access 0x%p from 0x%p\n", far, regs->lr);
205 cpu_DumpRegs(regs);
207 if (krnRunExceptionHandlers(KernelBase, 2, regs))
208 return;
210 D(bug("[Kernel] exception handler(s) returned\n"));
212 if (core_Trap(2, regs))
214 D(bug("[Kernel] trap handler(s) returned\n"));
215 return;
218 bug("[Kernel] UNHANDLED EXCEPTION #2\n");
220 cpu_DumpRegs(regs);
222 __arm_halt();
226 ** PREFETCH ABORT EXCEPTION
227 return address = lr - 4
228 entered in ABT mode.
231 asm (
232 ".set MODE_SYSTEM, 0x1f \n"
234 ".globl __vectorhand_prefetchabort \n"
235 ".type __vectorhand_prefetchabort,%function \n"
236 "__vectorhand_prefetchabort: \n"
237 " sub lr, lr, #4 \n" // adjust lr_irq
238 VECTCOMMON_START
240 " bl handle_prefetchabort \n"
242 VECTCOMMON_END
245 void handle_prefetchabort(regs_t *regs)
247 bug("[Kernel] Trap ARM Prefetch Abort Exception\n");
248 bug("[Kernel] exception #3 (Address Error)\n");
249 bug("[Kernel] at 0x%p\n", regs->lr);
251 cpu_DumpRegs(regs);
253 if (krnRunExceptionHandlers(KernelBase, 3, regs))
254 return;
256 D(bug("[Kernel] exception handler(s) returned\n"));
258 if (core_Trap(3, regs))
260 D(bug("[Kernel] trap handler(s) returned\n"));
261 return;
264 bug("[Kernel] UNHANDLED EXCEPTION #3\n");
266 cpu_DumpRegs(regs);
268 __arm_halt();
272 /* ** SETUP ** */
274 void arm_flush_cache(uint32_t addr, uint32_t length)
276 while (length)
278 __asm__ __volatile__("mcr p15, 0, %0, c7, c14, 1"::"r"(addr));
279 addr += 32;
280 length -= 32;
282 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
285 void arm_icache_invalidate(uint32_t addr, uint32_t length)
287 while (length)
289 __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 1"::"r"(addr));
290 addr += 32;
291 length -= 32;
293 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
296 void core_SetupIntr(void)
298 int irq;
299 bug("[KRN] Initializing cpu vectors\n");
301 /* Copy vectors into place */
302 memcpy(0, &__intvecs_start,
303 (unsigned int)&__intvecs_end -
304 (unsigned int)&__intvecs_start);
306 arm_flush_cache(0, 1024);
307 arm_icache_invalidate(0, 1024);
309 D(bug("[KRN] Copied %d bytes from 0x%p to 0x00000000\n", (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start, &__intvecs_start));
312 unsigned int x = 0;
313 bug("[KRN]: Vector dump-:");
314 for (x=0; x < (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start; x++) {
315 if ((x%16) == 0)
317 bug("\n[KRN]: %08x:", x);
319 bug(" %02x", *((volatile UBYTE *)x));
321 bug("\n");
324 if (__arm_arosintern.ARMI_IRQInit)
325 __arm_arosintern.ARMI_IRQInit();