Use existing core_Cause definition. use syscalls to perform krnCli/Sti.
[AROS.git] / arch / arm-raspi / kernel / syscall.c
blob976ba0d4ec648240eb09fe4b3dcbd534a0ee0778
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"
20 #include "kernel_intr.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 #define DREGS(x)
32 /* r0 = passed to function, r1/r2 = temp */
36 __vectorhand_swi:
38 warning : this code will be changes to stoe spsr_svc, and lr_svc onto the system mode stack
39 and then switch into that mode - and at the end jump back into svc mode, before returning from the exception
41 asm (
42 ".set MODE_SUPERVISOR, 0x13 \n"
43 ".set MODE_SYSTEM, 0x1f \n"
45 ".globl __vectorhand_swi \n"
46 ".type __vectorhand_swi,%function \n"
47 "__vectorhand_swi: \n"
48 " sub sp, sp, #5*4 \n" // make space to store callers cpsr, pc, lr, sp, and ip
49 " stmfd sp!, {r0-r11} \n" // store untouched registers to pass to c handler ..
50 " mov r0, sp \n" // r0 = registers r0-r12 on the stack
51 " mrs r2, spsr \n" // store spsr above registers
52 " str r2, [sp, #16*4] \n"
53 " str lr, [sp, #15*4] \n" // store the lr as the callers pc
54 " str ip, [sp, #13*4] \n" // store callers stack pointer ..
55 " ldr r1, [ip, #-8] \n" // store lr passed in via the callers stack
56 " str r1, [sp, #14*4] \n"
57 " ldr ip, [ip, #-4] \n" // store callers ip
58 " str ip, [sp, #12*4] \n"
59 " ldr r1, [sp, #1*4] \n" // restore r1 ..
60 " ldr r2, [sp, #2*4] \n" // .. and r2 ..
61 " mov fp, #0 \n" // clear fp(??)
62 " bl handle_syscall \n"
63 " ldr r0, [sp, #13*4] \n" // get task_sp
64 " ldr r1, [sp, #12*4] \n" // get task_ip
65 " str r1, [r0, #-4] \n" // push task_lp into task_sp
66 " ldr r1, [sp, #14*4] \n" // get task_lr
67 " str r1, [r0, #-8] \n" // push task_lr into task_sp
68 " ldr lr, [sp, #15*4] \n" // put task_pc into lr
69 " ldr r2, [sp, #16*4] \n" // restore task_cpsr
70 " msr spsr_c, r2 \n"
71 " add sp, sp, #1*4 \n" // skip r0 (contains our return value = task_sp)
72 " ldmfd sp!, {r1-r11} \n" // restore remaining task_registers
73 " add sp, sp, #5*4 \n" // correct the stack pointer ..
74 " movs pc, lr \n" // ..and return
77 void handle_syscall(void *regs)
79 register unsigned int addr;
80 register unsigned int swi_no;
81 struct ExceptionContext *ctx;
82 struct Task *thisTask;
84 /* We determine the SWI number by reading in the return address
85 from the link register, subtract the instruction from it and
86 obtain the value from there. we also use this to check if
87 we have been called from outwith the kernel's code (illegal!)
90 addr = ((uint32_t *)regs)[15];
91 addr -= 4;
92 swi_no = *((unsigned int *)addr) & 0x00ffffff;
94 D(bug("[KRN] ## SWI %d @ 0x%p\n", swi_no, addr));
96 if (((char*)addr < &__text_start) || ((char*)addr >= &__text_end))
98 D(bug("[KRN] ## SWI : ILLEGAL ACCESS!\n"));
99 return;
101 if (swi_no <= 0x0a || swi_no == 0x100)
103 if ((thisTask = SysBase->ThisTask) != NULL)
105 D(bug("[KRN] SWI invoked in '%s'", thisTask->tc_Node.ln_Name));
106 if ((ctx = thisTask->tc_UnionETask.tc_ETask->et_RegFrame) != NULL)
108 int i;
110 D(bug(", ExceptionContext @ 0x%p", ctx));
111 DREGS(bug("\n"));
112 for (i = 0; i < 12; i++)
114 ctx->r[i] = ((uint32_t *)regs)[i];
115 DREGS(bug("[KRN] r%02d: 0x%08x\n", i, ctx->r[i]));
117 ctx->ip = ((uint32_t *)regs)[12];
118 DREGS(bug("[KRN] (ip) r12: 0x%08x\n", ctx->ip));
119 ctx->sp = ((uint32_t *)regs)[13];
120 DREGS(bug("[KRN] (sp) r13: 0x%08x\n", ctx->sp));
121 ctx->lr = ((uint32_t *)regs)[14];
122 DREGS(bug("[KRN] (lr) r14: 0x%08x\n", ctx->lr));
123 ctx->pc = ((uint32_t *)regs)[15];
124 DREGS(bug("[KRN] (pc) r15: 0x%08x\n", ctx->pc));
125 ctx->cpsr = ((uint32_t *)regs)[16];
126 DREGS(bug("[KRN] cpsr: 0x%08x", ctx->cpsr));
127 thisTask->tc_SPReg = ctx->sp;
129 D(bug("\n"));
132 switch (swi_no)
134 case SC_CLI:
136 D(bug("[KRN] ## CLI...\n"));
137 if (ctx) ctx->cpsr |= 0x80;
138 ((uint32_t *)regs)[16] |= 0x80;
139 break;
142 case SC_STI:
144 D(bug("[KRN] ## STI...\n"));
145 if (ctx) ctx->cpsr &= ~0x80;
146 ((uint32_t *)regs)[16] &= ~0x80;
147 break;
150 case SC_SUPERSTATE:
152 D(bug("[KRN] ## SUPERSTATE...\n"));
153 break;
156 case SC_ISSUPERSTATE:
158 D(bug("[KRN] ## ISSUPERSTATE...\n"));
159 break;
162 case SC_RTAS:
164 break;
167 case SC_INVALIDATED:
169 break;
172 case SC_REBOOT:
174 D(bug("[KRN] ## REBOOT...\n"));
175 asm volatile ("mov pc, #0\n"); // Jump to the reset vector..
176 break;
178 default:
179 core_SysCall(swi_no, regs);
180 break;
183 else
185 D(bug("[KRN] ## SWI : ILLEGAL SWI!\n"));
186 return;
189 D(bug("[KRN] ## SWI returning ..\n"));