1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
4 * 2019/9/20 - ROBIN KRENS
9 * |----------------------------|
11 * |--------------------|-------|
13 * | THEOS_CREATE | 2 |
14 * | THEOS_DESTROY | 3 |
15 * | THEOS_SWITCH | 4 |
18 * | THEOS_UPTIME | 7 |
19 * | THEOS_OMNIGOD | 8 |
21 * | THEOS_MAGIC | 99 |
22 * |----------------------------|
24 * TODO: include in header enum
31 #include <sys/robsys.h>
33 #include <sys/process.h>
35 #include <lib/stdio.h>
36 #include <lib/string.h>
37 #include <lib/regfunc.h>
38 #include <lib/tinyprintf.h>
51 static int sys_uptime() {
53 int uptime = *RTC_CNTL;
57 /* Context switch routine, saves stack pointer of
58 * the current process, loads the stack pointer
61 * Other registers and flags (i.e. PSR, PC are popped
62 * by exit of this system call.
63 * Precondition: Usage of PSP */
64 int sys_switch(process_t * currp, process_t * newp) {
66 uint32_t tmp_stackptr = 0xFFFFFFFF;
67 asm volatile("mrs %0, psp" : "=r" (tmp_stackptr));
68 currp->stackptr = tmp_stackptr;
70 asm volatile("msr psp, %0" : : "r" (newp->stackptr) ); // load new pointer
71 uint32_t chk_stackptr;
72 asm volatile("mrs %0, psp" : "=r" (chk_stackptr));
73 //asm volatile("isb");
74 //printf("OLD: %x\n", currp->stackptr);
75 //printf("NEW: %x\n", newp->stackptr);
76 //printf("CHK: %x\n", chk_stackptr);
82 int sys_init(process_t * p) {
84 asm volatile("msr psp, %0" : : "r" (p->stackptr));
88 static int sys_stub() {
95 * This is a so-called first interrupt handler
96 * The naked attribute makes sure the compiler doesn't
97 * places registers on the stack */
100 * SVC is similar to an exception or interrupt
101 * A stack frame is pushed on entry and popped
102 * on exit BY PROCESSOR. Please see in-function command */
104 __attribute__ ((naked))
105 void * _svc_handler(void) {
107 uint32_t * callee_sp;
109 /* Test whether system call was invoked from supervisor (use MSP) or
110 * user (use PSP) mode */
114 "mrseq %0, msp" "\n\t"
115 "mrsne %0, psp" "\n\t"
117 "push {r4-r11}" : "=r" (callee_sp));
119 /* An exception (or interrupt) before entering this handler
120 * places the following on the stack
127 * LR <- Not a real LR, A certain 'mask'
128 * PC <- placed at callee_sp[6], see description below
129 * PSR <- Status of processor before call
131 * PC contains the return address that will continue after this SVC handler
132 * is finised. The previous address (the svc # call) is at PC - 2, the
133 * first byte contains the svc number.
136 uint8_t svc_nr = ((char *) callee_sp[6])[-2];
141 sys_init((process_t *) callee_sp[0]);
143 "ldr r0, =0xFFFFFFFD" "\n\t"
148 sys_switch((process_t *) callee_sp[0], (process_t *) callee_sp[1]);
150 // "ldr r0, =0xFFFFFFFD" "\n\t"
151 // "mov lr, r0" "\n\t"
166 //printf("SYSTEM CALL NR: %d\n", svc_nr);
167 /* Check arguments, placed in r0, r1, r2
168 * (can get more if you save the stack) */
169 //uint32_t arg1 = callee_sp[0];
170 //uint32_t arg2 = callee_sp[1];
171 //uint32_t arg3 = callee_sp[2];
172 //printf("ARGUMENTS: %x, %x, %x\n", arg1, arg2, arg3);
174 /* Return value in r0 for callee */
177 asm volatile ("pop {r4-r11}");
178 /* exception return, 0xFFFFFFFX (<-- last value is flag
179 * and gives the processor information to return to what */
180 asm volatile ("pop {lr}");
181 asm volatile ("bx lr");
186 void syscall_init() {
187 /* SVC is located at position 11 in the interrupt vector table */
188 ivt_set_gate(11, _svc_handler, 0);