poor r0 was neglected when caching the current tasks registers... fix the swi handler...
[AROS.git] / arch / arm-raspi / kernel / syscall.c
blobb0548eb59d7a8e2e03ef04319f6ae07a080c95dc
1 /*
2 Copyright © 2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 1
8 #include <inttypes.h>
9 #include <aros/kernel.h>
10 #include <aros/libcall.h>
11 #include <stddef.h>
12 #include <string.h>
14 #include <proto/exec.h>
15 #include <proto/kernel.h>
17 #include "kernel_cpu.h"
18 #include "kernel_intern.h"
19 #include "kernel_scheduler.h"
21 #include "kernel_syscall.h"
23 extern char * __text_start;
24 extern char * __text_end;
26 #ifndef _CUSTOM
27 #define _CUSTOM NULL
28 #endif
30 /* r0 = passed to function, r1/r2 = temp */
31 asm (".globl __intrhand_swi\n\t"
32 ".type __intrhand_swi,%function\n"
33 "__intrhand_swi:\n"
34 " sub sp, sp, #3*4 \n" // make space to store spsr, stack pointer and link register
35 " stmfd sp!, {r0-r12} \n" // store registers to pass to c handler ..
36 " str lr, [sp, #14*4] \n"
37 " mrs r2, spsr \n" // store spsr above registers
38 " str r2, [sp, #15*4] \n"
39 " mov r0, sp \n" // r0 = registers r0-r12 on the stack
40 " mov r1, r0 \n"
41 " add r1, r1, #16*4 \n" // r1 = orig (callers) stack pointer
42 " str r1, [sp, #13*4] \n"
43 " ldr r1, [sp, #1*4] \n" // restore r1 ..
44 " ldr r2, [sp, #2*4] \n" // .. and r2 ..
45 " mov fp, #0 \n" // clear fp(??)
46 " bl handle_syscall \n"
47 " ldr lr, [sp, #14*4] \n" // restore lr
48 " ldr r2, [sp, #15*4] \n" // restore spsr
49 " msr spsr_c, r2 \n"
50 " ldmfd sp!, {r0-r12} \n" // restore registers
51 " add sp, sp, #12 \n" // correct the stack pointer ..
52 " movs pc, lr \n" // ..and return
55 void core_Cause(unsigned char n, unsigned int mask)
57 D(bug("[KRN] core_Cause(%d, %08x)", n, mask));
59 if (SysBase)
61 struct IntVector *iv = &SysBase->IntVects[n];
63 /* If the SoftInt vector in SysBase is set, call it. It will do the rest for us */
64 if (iv->iv_Code)
65 AROS_INTC3(iv->iv_Code, iv->iv_Data, mask, _CUSTOM);
69 void handle_syscall(void *regs)
71 register unsigned int addr;
72 register unsigned int swi_no;
73 struct ExceptionContext *ctx;
74 struct Task *thisTask;
76 /* We determine the SWI number by reading in the return address
77 from the link register, subtract the instruction from it and
78 obtain the value from there. we also use this to check if
79 we have been called from outwith the kernel's code (illegal!)
82 addr = ((uint32_t *)regs)[14];
83 addr -= 4;
84 swi_no = *((unsigned int *)addr) & 0x00ffffff;
86 D(bug("[KRN] ## SWI %d @ 0x%p\n", swi_no, addr));
88 if (((char*)addr < &__text_start) || ((char*)addr >= &__text_end))
90 D(bug("[KRN] ## SWI : ILLEGAL ACCESS!\n"));
91 return;
93 if (swi_no <= 0x0a || swi_no == 0x100)
95 if ((thisTask = SysBase->ThisTask) != NULL)
97 D(bug("[KRN] SWI invoked in '%s'", thisTask->tc_Node.ln_Name));
98 if ((ctx = thisTask->tc_UnionETask.tc_ETask->et_RegFrame) != NULL)
100 int i;
102 D(bug(", ExceptionContext @ 0x%p\n", ctx));
103 for (i = 0; i < 12; i++)
105 ctx->r[i] = ((uint32_t *)regs)[i];
106 D(bug("[KRN] r%02d: 0x%08x\n", i, ctx->r[i]));
108 ctx->ip = ((uint32_t *)regs)[12];
109 D(bug("[KRN] (ip) r12: 0x%08x\n", ctx->ip));
110 ctx->sp = ((uint32_t *)regs)[13];
111 D(bug("[KRN] (sp) r13: 0x%08x\n", ctx->sp));
112 ctx->lr = ((uint32_t *)regs)[14];
113 D(bug("[KRN] (lr) r14: 0x%08x\n", ctx->lr));
114 ctx->cpsr = ((uint32_t *)regs)[15];;
115 D(bug("[KRN] cpsr: 0x%08x", ctx->cpsr));
116 thisTask->tc_SPReg = ctx->sp;
118 D(bug("\n"));
121 switch (swi_no)
123 case SC_CLI:
125 D(bug("[KRN] ## CLI...\n"));
126 break;
129 case SC_STI:
131 D(bug("[KRN] ## STI...\n"));
132 break;
135 case SC_SUPERSTATE:
137 D(bug("[KRN] ## SUPERSTATE...\n"));
138 break;
141 case SC_ISSUPERSTATE:
143 D(bug("[KRN] ## ISSUPERSTATE...\n"));
144 break;
147 case SC_CAUSE:
149 D(bug("[KRN] ## CAUSE...\n"));
150 //core_Cause(SysBase);
151 break;
154 case SC_DISPATCH:
156 D(bug("[KRN] ## DISPATCH...\n"));
157 core_Dispatch();
158 break;
161 case SC_SWITCH:
163 D(bug("[KRN] ## SWITCH...\n"));
164 core_Switch();
165 break;
168 case SC_SCHEDULE:
170 D(bug("[KRN] ## SCHEDULE...\n"));
171 core_Schedule();
172 break;
175 case SC_RTAS:
177 break;
180 case SC_INVALIDATED:
182 break;
185 case SC_REBOOT:
187 D(bug("[KRN] ## REBOOT...\n"));
188 asm volatile ("mov pc, #0\n"); // Jump to the reset vector..
189 break;
193 else
195 D(bug("[KRN] ## SWI : ILLEGAL SWI!\n"));
196 return;
199 D(bug("[KRN] ## SWI returning ..\n"));