2 Copyright © 2013, The AROS Development Team. All rights reserved.
9 #include <aros/kernel.h>
10 #include <aros/libcall.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
;
32 /* r0 = passed to function, r1/r2 = temp */
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
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
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];
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"));
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
)
110 D(bug(", ExceptionContext @ 0x%p", ctx
));
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
;
136 D(bug("[KRN] ## CLI...\n"));
137 if (ctx
) ctx
->cpsr
|= 0x80;
138 ((uint32_t *)regs
)[16] |= 0x80;
144 D(bug("[KRN] ## STI...\n"));
145 if (ctx
) ctx
->cpsr
&= ~0x80;
146 ((uint32_t *)regs
)[16] &= ~0x80;
152 D(bug("[KRN] ## SUPERSTATE...\n"));
156 case SC_ISSUPERSTATE
:
158 D(bug("[KRN] ## ISSUPERSTATE...\n"));
174 D(bug("[KRN] ## REBOOT...\n"));
175 asm volatile ("mov pc, #0\n"); // Jump to the reset vector..
179 core_SysCall(swi_no
, regs
);
185 D(bug("[KRN] ## SWI : ILLEGAL SWI!\n"));
189 D(bug("[KRN] ## SWI returning ..\n"));