* |----------------------------|
* | SYSTEM CALL | # |
* |--------------------|-------|
- * | THEOS_getenv | |
- * | THEOS_killenv | |
- * | THEOS_setenv | |
- * | THEOS_newenv | |
- * | THEOS_cputs | |
- * | THEOS_omnigod | |
- * | THEOS_brk | |
- * | THEOS_time | |
- * | THEOS_magic | |
+ * | THEOS_INIT | 1 |
+ * | THEOS_CREATE | 2 |
+ * | THEOS_DESTROY | 3 |
+ * | THEOS_SWITCH | 4 |
+ * | THEOS_GETC | 5 |
+ * | THEOS_CPUTS | 6 |
+ * | THEOS_UPTIME | 7 |
+ * | THEOS_OMNIGOD | 8 |
+ * | THEOS_TIME | 9 |
+ * | 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
+};
-/* the function gets called for
- * */
-__attribute__ ((naked))
-void * __svc_handler__(int x) {
- uint8_t svc_nr;
-
- asm volatile (
- "tst lr, #4" "\n\t"
- "ite eq" "\n\t"
- "mrseq r0, msp" "\n\t"
- "mrsne r0, psp" "\n\t"
- "ldr r0, [r0, #24]" "\n\t"
- "ldrb %0, [r0, #-2]" : "=r" (svc_nr) );
+static int sys_uptime() {
- printf("SYSTEM CALL NR: %d", svc_nr);
+ int uptime = *RTC_CNTL;
+ return uptime;
+}
- for(;;);
+/* 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);
- volatile uint32_t * sp;
-
- asm volatile (
- "tst lr, #4" "\n\t"
- "ite eq" "\n\t"
- "mrseq %0, msp" "\n\t"
- "mrsne r0, psp" : "=r" (sp) );
+ return 0;
+}
- for (int i = 0; (sp + i) < 0x20010000; i++) {
- printf("ADDRESS: %p, VALUE: %x\n", (sp + i), *(sp + i));
- }
+int sys_init(process_t * p) {
- for (;;);
- //asm ("mov %0, pc" : "=r" (link_register));
- //printf("%x\n", link_register);
-
- volatile uint32_t * svc_number = (uint32_t *) 0x20022222;
- *svc_number = sp[-6];
- // = sp[6];
- //uint8_t tmp = link_register[-2];
- printf("SVC nr: %x", *svc_number);
- //printf("%d, %d, %d, %d, %d, %d\n", msp[6], msp[0], msp[1], msp[2], msp[3], msp[4]);
-
- for (;;);
- //return NULL;
+ asm volatile("msr psp, %0" : : "r" (p->stackptr));
return 0;
-
}
-void syscall(unsigned int * args) {
+static int sys_stub() {
- uint32_t svc_number = 99;
- printf("SYSCALL NR: %x", svc_number);
-
- for(;;);
- /* switch(SYSCALL_NO) {
- case THEOS_cputs:
- kernel_cputs(a1, a2);
- break;
- default:
- for (;;);
- } */
+ return 0;
}
-void syscall_init() {
-
-
- /* SVC is located at position 11 in the interrupt vector table */
-// extern void * _syscall;
- extern void * hardfault;
+/*
+ * This is a so-called first interrupt handler
+ * The naked attribute makes sure the compiler doesn't
+ * places registers on the stack */
- ivt_set_gate(11, __svc_handler__, 0);
+/*
+ * 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 * callee_sp;
-static void kernel_cputs(char * s, size_t l) {
+ /* Test whether system call was invoked from supervisor (use MSP) or
+ * user (use PSP) mode */
+ asm volatile (
+ "tst lr, #4" "\n\t"
+ "ite eq" "\n\t"
+ "mrseq %0, msp" "\n\t"
+ "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 <- args[0]
+ * R1 <- args[1]
+ * R2
+ * R3
+ * R12
+ * 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 *) callee_sp[6])[-2];
+ int ret = -1;
+
+ 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;
+ }
- // TODO
-}
+ //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);
+ /* Return value in r0 for callee */
+ callee_sp[0] = ret;
-void kernel_omnigod() {
+ 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");
- /* */
}
+void syscall_init() {
+ /* SVC is located at position 11 in the interrupt vector table */
+ ivt_set_gate(11, _svc_handler, 0);
+}