* |----------------------------|
* | SYSTEM CALL | # |
* |--------------------|-------|
- * | THEOS_getenv | |
- * | THEOS_killenv | |
- * | THEOS_setenv | |
- * | THEOS_newenv | |
- * | THEOS_cputs | |
- * | THEOS_omnigod | |
- * | THEOS_brk | |
- * | THEOS_time | |
- * | THEOS_magic | |
+ * | THEOS_INIT | 1 |
+ * | THEOS_DESTROY | 2 |
+ * | THEOS_RESCHED | 3 |
+ * | THEOS_GETC | 4 |
+ * | THEOS_CPUTS | 5 |
+ * | THEOS_UPTIME | 6 |
+ * | THEOS_OMNIGOD | 7 |
+ * | THEOS_TIME | 8 |
+ * | THEOS_MAGIC | 99 |
* |----------------------------|
*
* TODO: include in header enum
* */
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/robsys.h>
#include <sys/mmap.h>
+#include <sys/process.h>
#include <lib/stdio.h>
#include <lib/string.h>
#include <lib/regfunc.h>
#include <lib/tinyprintf.h>
+enum {
+ THEOS_INIT = 1,
+ THEOS_CREATE,
+ THEOS_DESTROY,
+ THEOS_SWITCH,
+ THEOS_GETC,
+ THEOS_CPUTS,
+ THEOS_UPTIME
+};
+
+
+static int sys_uptime() {
+
+ int uptime = *RTC_CNTL;
+ return uptime;
+}
+
+/* Context switch routine, saves stack pointer of
+ * the current process, loads the stack pointer
+ * of the next.
+ *
+ * Other registers and flags (i.e. PSR, PC are popped
+ * by exit of this system call.
+ * Precondition: Usage of PSP */
+int sys_switch(process_t * currp, process_t * newp) {
+
+ uint32_t tmp_stackptr = 0xFFFFFFFF;
+ asm volatile("mrs %0, psp" : "=r" (tmp_stackptr));
+ currp->stackptr = tmp_stackptr;
+
+ asm volatile("msr psp, %0" : : "r" (newp->stackptr) ); // load new pointer
+ uint32_t chk_stackptr;
+ asm volatile("mrs %0, psp" : "=r" (chk_stackptr));
+ //asm volatile("isb");
+ printf("OLD: %x\n", currp->stackptr);
+ printf("NEW: %x\n", newp->stackptr);
+ printf("CHK: %x\n", chk_stackptr);
+ //for(;;);
+
+ return 0;
+
+}
+
+int sys_init(process_t * p) {
+
+ asm volatile("msr psp, %0" : : "r" (p->stackptr));
+ return 0;
+}
+
+static int sys_stub() {
+
+ return 0;
+
+}
/*
* This is a so-called first interrupt handler
* The naked attribute makes sure the compiler doesn't
- * places registers on the stack. */
+ * places registers on the stack */
+
+/*
+ * SVC is similar to an exception or interrupt
+ * A stack frame is pushed on entry and popped
+ * on exit BY PROCESSOR. Please see in-function command */
__attribute__ ((naked))
void * _svc_handler(void) {
- uint32_t * current_sp;
+ uint32_t * callee_sp;
/* Test whether system call was invoked from supervisor (use MSP) or
* user (use PSP) mode */
"tst lr, #4" "\n\t"
"ite eq" "\n\t"
"mrseq %0, msp" "\n\t"
- "mrsne %0, psp" : "=r" (current_sp));
+ "mrsne %0, psp" "\n\t"
+ "push {lr}" "\n\t"
+ "push {r4-r11}" : "=r" (callee_sp));
/* An exception (or interrupt) before entering this handler
* places the following on the stack
*
- * R0
- * R1
- * R2
+ * R0 <- args[0]
+ * R1 <- args[1]
+ * R2
* R3
* R12
- * LR
- * PC <- placed at current_sp[6]
- * PSR
+ * LR <- Not a real LR, A certain 'mask'
+ * PC <- placed at callee_sp[6], see description below
+ * PSR <- Status of processor before call
*
* PC contains the return address that will continue after this SVC handler
* is finised. The previous address (the svc # call) is at PC - 2, the
* first byte contains the svc number.
* */
- uint8_t svc_nr = ((char *) current_sp[6])[-2];
-
- printf("SYSTEM CALL NR: %d", svc_nr);
+ uint8_t svc_nr = ((char *) callee_sp[6])[-2];
+ int ret = -1;
- for (;;);
+ switch(svc_nr) {
+ case THEOS_INIT:
+ sys_init((process_t *) callee_sp[0]);
+ asm volatile (
+ "ldr r0, =0xFFFFFFFD" "\n\t"
+ "mov lr, r0" "\n\t"
+ "bx lr");
+ break;
+ case THEOS_SWITCH:
+ sys_switch((process_t *) callee_sp[0], (process_t *) callee_sp[1]);
+ //asm volatile (
+ // "ldr r0, =0xFFFFFFFD" "\n\t"
+ // "mov lr, r0" "\n\t"
+ // "bx lr");
+
+ break;
+ case THEOS_CPUTS:
+ break;
+ case THEOS_GETC:
+ break;
+ case THEOS_UPTIME:
+ ret = sys_uptime();
+ break;
+ default:
+ break;
+ }
-}
+ //printf("SYSTEM CALL NR: %d\n", svc_nr);
+ /* Check arguments, placed in r0, r1, r2
+ * (can get more if you save the stack) */
+ //uint32_t arg1 = callee_sp[0];
+ //uint32_t arg2 = callee_sp[1];
+ //uint32_t arg3 = callee_sp[2];
+ //printf("ARGUMENTS: %x, %x, %x\n", arg1, arg2, arg3);
-void syscall(unsigned int * args) {
+ /* Return value in r0 for callee */
+ callee_sp[0] = ret;
- uint32_t svc_number = 99;
- printf("SYSCALL NR: %x", svc_number);
+ asm volatile ("pop {r4-r11}");
+ /* exception return, 0xFFFFFFFX (<-- last value is flag
+ * and gives the processor information to return to what */
+ asm volatile ("pop {lr}");
+ asm volatile ("bx lr");
- for(;;);
- /* switch(SYSCALL_NO) {
- case THEOS_cputs:
- kernel_cputs(a1, a2);
- break;
- default:
- for (;;);
- } */
}
void syscall_init() {
-
/* SVC is located at position 11 in the interrupt vector table */
ivt_set_gate(11, _svc_handler, 0);
-
}
-static void kernel_cputs(char * s, size_t l) {
-
- // TODO
-}
-
-
-void kernel_omnigod() {
-
- /* */
-
-}
-
-