Call core_ExitInterrupt only when going back to user mode. Going back to
[AROS.git] / arch / arm-native / kernel / intr.c
blobbc4e5083e25e3acdc27305c502b7cdc7f1bfea17
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 " cpsid i, #" STR(MODE_SYSTEM)"\n" // switch to system mode, with interrupts disabled..
66 " str sp, [r0, #13*4] \n"
67 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
68 " mov fp, #0 \n" // clear fp
70 " bl handle_undef \n"
72 VECTCOMMON_END
75 void handle_undef(regs_t *regs)
77 bug("[Kernel] Trap ARM Undef Exception\n");
78 bug("[Kernel] exception #4 (Illegal instruction)\n");
79 bug("[Kernel] at 0x%p\n", regs[14]);
81 if (krnRunExceptionHandlers(KernelBase, 4, regs))
82 return;
84 D(bug("[Kernel] exception handler(s) returned\n"));
86 if (core_Trap(4, regs))
88 D(bug("[Kernel] trap handler(s) returned\n"));
89 return;
92 bug("[Kernel] UNHANDLED EXCEPTION #4\n");
94 cpu_DumpRegs(regs);
96 __arm_halt();
100 ** RESET HANDLER
101 no return address,
102 entered in SVC mode.
105 asm (
106 ".globl __vectorhand_reset \n"
107 ".type __vectorhand_reset,%function \n"
108 "__vectorhand_reset: \n"
109 " mov sp, #0x1000 - 16 \n" // re-use bootstrap tmp stack
110 " mov r0, sp \n"
111 " sub r0, r0, #" STR(BOOT_STACK_SIZE)"\n" // get the boottag's
112 " sub r0, r0, #" STR(BOOT_TAGS_SIZE) "\n"
113 " mov fp, #0 \n" // clear fp
115 " ldr pc, 2f \n" // jump into kernel resource
116 "1: b 1b \n"
117 "2: .word kernel_cstart \n"
121 /* ** SWI HANDLER ** */
123 /** SWI handled in syscall.c */
126 ** IRQ HANDLER
127 return address = lr - 4
128 entered in IRQ mode.
131 asm (
132 ".set MODE_IRQ, 0x12 \n"
133 ".set MODE_SUPERVISOR, 0x13 \n"
134 ".set MODE_SYSTEM, 0x1f \n"
136 ".globl __vectorhand_irq \n"
137 ".type __vectorhand_irq,%function \n"
138 "__vectorhand_irq: \n"
139 " sub lr, lr, #4 \n" // adjust lr_irq
140 VECTCOMMON_START
141 " cpsid i, #MODE_SYSTEM \n" // switch to system mode, with interrupts disabled..
142 " str sp, [r0, #13*4] \n"
143 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
144 " mov fp, #0 \n" // clear fp
146 " bl handle_irq \n"
148 " cpsid i, #MODE_IRQ \n" // switch to IRQ mode, with interrupts disabled..
149 " mov r0, sp \n"
150 " ldr r1, [r0, #16*4] \n" // load the spr register
151 " and r1, r1, #31 \n" // mask processor mode
152 " cmp r1, #16 \n" // will we go back to user mode?
153 " bne 1f \n" // no? don't call core_ExitInterrupt!
154 " mov fp, #0 \n" // clear fp
155 " bl core_ExitInterrupt \n"
156 "1: \n"
157 VECTCOMMON_END
160 void handle_irq(regs_t *regs)
162 DIRQ(bug("[KRN] ## IRQ ##\n"));
164 DREGS(cpu_DumpRegs(regs));
166 if (__arm_arosintern.ARMI_IRQProcess)
167 __arm_arosintern.ARMI_IRQProcess();
169 DIRQ(bug("[KRN] IRQ processing finished\n"));
171 return;
175 ** FIQ HANDLER
176 return address = lr -4
177 entered in FIQ mode.
180 __attribute__ ((interrupt ("FIQ"))) void __vectorhand_fiq(void)
182 DIRQ(bug("[KRN] ## FIQ ##\n"));
184 DIRQ(bug("[KRN] FIQ processing finished\n"));
186 return;
190 ** DATA ABORT EXCEPTION
191 return address = lr - 8
192 entered in ABT mode.
195 asm (
196 ".set MODE_SYSTEM, 0x1f \n"
198 ".globl __vectorhand_dataabort \n"
199 ".type __vectorhand_dataabort,%function \n"
200 "__vectorhand_dataabort: \n"
201 " sub lr, lr, #8 \n" // adjust lr_irq
202 VECTCOMMON_START
203 " cpsid i, #MODE_SYSTEM \n" // switch to system mode, with interrupts disabled..
204 " str sp, [r0, #13*4] \n"
205 " str lr, [r0, #14*4] \n" // store lr in ctx_lr
206 " mov fp, #0 \n" // clear fp
208 " bl handle_dataabort \n"
210 VECTCOMMON_END
213 void handle_dataabort(regs_t *regs)
215 register unsigned int far;
217 // Read fault address register
218 asm volatile("mrc p15, 0, %[far], c6, c0, 0": [far] "=r" (far) );
220 bug("[Kernel] Trap ARM Data Abort Exception\n");
221 bug("[Kernel] exception #2 (Bus Error)\n");
222 bug("[Kernel] attempt to access 0x%p from 0x%p\n", far, regs->lr);
224 cpu_DumpRegs(regs);
226 if (krnRunExceptionHandlers(KernelBase, 2, regs))
227 return;
229 D(bug("[Kernel] exception handler(s) returned\n"));
231 if (core_Trap(2, regs))
233 D(bug("[Kernel] trap handler(s) returned\n"));
234 return;
237 bug("[Kernel] UNHANDLED EXCEPTION #2\n");
239 cpu_DumpRegs(regs);
241 __arm_halt();
245 ** PREFETCH ABORT EXCEPTION
246 return address = lr - 4
247 entered in ABT mode.
250 asm (
251 ".set MODE_SYSTEM, 0x1f \n"
253 ".globl __vectorhand_prefetchabort \n"
254 ".type __vectorhand_prefetchabort,%function \n"
255 "__vectorhand_prefetchabort: \n"
256 " sub lr, lr, #4 \n" // adjust lr_irq
257 VECTCOMMON_START
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_prefetchabort \n"
265 VECTCOMMON_END
268 void handle_prefetchabort(regs_t *regs)
270 bug("[Kernel] Trap ARM Prefetch Abort Exception\n");
271 bug("[Kernel] exception #3 (Address Error)\n");
272 bug("[Kernel] at 0x%p\n", regs->lr);
274 cpu_DumpRegs(regs);
276 if (krnRunExceptionHandlers(KernelBase, 3, regs))
277 return;
279 D(bug("[Kernel] exception handler(s) returned\n"));
281 if (core_Trap(3, regs))
283 D(bug("[Kernel] trap handler(s) returned\n"));
284 return;
287 bug("[Kernel] UNHANDLED EXCEPTION #3\n");
289 cpu_DumpRegs(regs);
291 __arm_halt();
295 /* ** SETUP ** */
297 void arm_flush_cache(uint32_t addr, uint32_t length)
299 while (length)
301 __asm__ __volatile__("mcr p15, 0, %0, c7, c14, 1"::"r"(addr));
302 addr += 32;
303 length -= 32;
305 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
308 void arm_icache_invalidate(uint32_t addr, uint32_t length)
310 while (length)
312 __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 1"::"r"(addr));
313 addr += 32;
314 length -= 32;
316 __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(addr));
319 void core_SetupIntr(void)
321 int irq;
322 bug("[KRN] Initializing cpu vectors\n");
324 /* Copy vectors into place */
325 memcpy(0, &__intvecs_start,
326 (unsigned int)&__intvecs_end -
327 (unsigned int)&__intvecs_start);
329 arm_flush_cache(0, 1024);
330 arm_icache_invalidate(0, 1024);
332 D(bug("[KRN] Copied %d bytes from 0x%p to 0x00000000\n", (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start, &__intvecs_start));
335 unsigned int x = 0;
336 bug("[KRN]: Vector dump-:");
337 for (x=0; x < (unsigned int)&__intvecs_end - (unsigned int)&__intvecs_start; x++) {
338 if ((x%16) == 0)
340 bug("\n[KRN]: %08x:", x);
342 bug(" %02x", *((volatile UBYTE *)x));
344 bug("\n");
347 if (__arm_arosintern.ARMI_IRQInit)
348 __arm_arosintern.ARMI_IRQInit();