diff --git a/include/context-switch.h b/include/context-switch.h index 70308618e127c776eba309c423f523f0137bff97..b30443c572787e8369fe66108ef4a7ab449de328 100644 --- a/include/context-switch.h +++ b/include/context-switch.h @@ -1,8 +1,10 @@ #ifndef CONTEXT_SWITCH_H #define CONTEXT_SWITCH_H +void SetUpRegs(); + void kerent(); -void kerxit(TD* Active); +void kerxit(int* sp, int* spsr, int RetVal); #endif \ No newline at end of file diff --git a/include/request.h b/include/request.h deleted file mode 100644 index e7d498cf1b4e6ee27c865c38f92a692309e2ba3a..0000000000000000000000000000000000000000 --- a/include/request.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef REQUEST_H -#define REQUEST_H - -typedef struct req { - int n; - void* args[2]; -} Request; - -#endif diff --git a/include/syscall-handler.h b/include/syscall-handler.h index 8aa8983509fc5b694b309f09dd4e3a3caef4bf17..718298a7898afab144b804b0cd785baad1479046 100644 --- a/include/syscall-handler.h +++ b/include/syscall-handler.h @@ -9,9 +9,13 @@ typedef enum syscall { SYS_Exit }Syscall; -void handlerCreate (TD* Active); +void handlerCreate(TD* Active); + +int Activate(KernelStruct* Colonel, TD* Task); + +void Handle(KernelStruct* Colonel); + -int syscallHandler (KernelStruct* Colonel); #endif diff --git a/include/task-descriptor.h b/include/task-descriptor.h index a9e8dda3e4bd093da041668b5e7d21b314fff323..fec11a7be5c3680a55c83a77a14654915cc2ff84 100644 --- a/include/task-descriptor.h +++ b/include/task-descriptor.h @@ -8,7 +8,8 @@ typedef enum taskstate { Active, Ready, Blocked, - Init + Init, + Zombie }State; typedef enum prioritylvl { diff --git a/lib/kernel.c b/lib/kernel.c index e688cee72443cee292533bb86ce0767f5850bd40..2d3bc023ff9a4b672a1783169d5b8f3a565c717f 100644 --- a/lib/kernel.c +++ b/lib/kernel.c @@ -25,6 +25,7 @@ void kernelInit(KernelStruct* Colonel) { Colonel->FirstFree = &(Colonel->Tasks[0]); Colonel->LastFree = &(Colonel->Tasks[MAX_NUM_TD-1]); Colonel->NumTDsAvail = MAX_NUM_TD; + Colonel->Active = NULL; } diff --git a/lib/syscall-handler.c b/lib/syscall-handler.c index ef93eb44296dc5e8287d15d0af2b6cd5da099cad..aef5775d70bd69c25006a1fc7cdd5b378edc87fe 100644 --- a/lib/syscall-handler.c +++ b/lib/syscall-handler.c @@ -4,28 +4,35 @@ -int handlerCreate(KernelStruct* Colonel, TD* Active, int priority, void (*code)()) { +void handlerCreate(KernelStruct* Colonel) { - TD* NewTask = NewTask(priority,Active->TaskID),code); - return pushToScheduler(Colonel, NewTask); } -int handle(TD* Active, Request* req) { - switch(req->n) { +void Handle(KernelStruct* Colonel, int n) { + switch(n) { case SYS_Create: - return handlerCreate(Active, Active->TaskPriority, ???); // TODO + handlerCreate(Colonel); + break; case SYS_MyTid: - return Active->TaskID; + (Colonel->Active)->RetVal = (Colonel->Active)->TaskID; + pushToScheduler(Colonel); + break; case SYS_ParentTid: - if (isTaskAlive(Active->ParentID)) return Active->ParentID; - else return FAILURE; + (Colonel->Active)->RetVal = (Colonel->Active)->ParentID; + pushToScheduler(Colonel); + break; case SYS_Pass: - Active->TaskState = Ready; - return SUCCESS; + pushToScheduler(Colonel); + break; case SYS_Exit: - - + (Colonel->Active)->TaskState = Zombie; + break; } } +int Activate(KernelStruct* Colonel, TD* Task) { + int Request; + return Request; +} + diff --git a/lib/syscall.c b/lib/syscall.c index 0822f65a076302c607e4776dcf7da057c0b16e20..f30d8fbdceec556a9664b628f8ee5bf38c9bf136 100644 --- a/lib/syscall.c +++ b/lib/syscall.c @@ -9,7 +9,6 @@ int Create (int priority, void (*code)()) { ); register int RetVal asm("r0"); return RetVal; - // return TaskID of new Task } int MyTid() { diff --git a/src/context-switch.s b/src/context-switch.s index 3f5b9c3f3703367dcadfb0e1887c886aaa71ba01..dd478e8bb1c779dc54febf4cceceac68b78825ca 100644 --- a/src/context-switch.s +++ b/src/context-switch.s @@ -15,7 +15,7 @@ kerent: msr cpsr_c, #0xDF @or #223 @ push register contents onto users stack - stmfd sp!, {r0-r14} + stmfd sp!, {r4-r12,r14} @ save user's sp mov r3, sp @@ -42,9 +42,9 @@ kerxit: @ when its ready to restart the active task @ args = 0, pretend = 0, frame = 8 @ frame_needed = 1, uses_anonymous_args = 0 - + mov ip, sp @ push kernel's registers - stmfd sp!, {r4-r14} + stmfd sp!, {r3-r12, r14} @ stmfd sp_svc!, {r0-r14} TODO @ switching to system mode msr cpsr_c, #0xDF diff --git a/src/cs.s b/src/cs.s new file mode 100644 index 0000000000000000000000000000000000000000..67dedc8bc09d2f1fc9fa32f6fa77a0b75e2b920d --- /dev/null +++ b/src/cs.s @@ -0,0 +1,86 @@ +.file "context_switch.c" +.text + +.align 2 +.global init_regs +.type init_regs, %function +init_regs: + mov ip, sp + stmfd sp!, {fp, ip, lr} + mov r0, #0 + mov r1, #0 + mov r2, #0 + mov r3, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0 + mov r8, #0 + mov r9, #0 + @mov r10, #0 @ apparently we cannot clear this register @,@? + ldmfd sp, {fp, sp, pc} +@blah +.align 2 +.global init_kernelentry +.type init_kernelentry, %function +init_kernelentry: + mov ip, sp + stmfd sp!, {fp, ip, lr} + ldr r1, =kernelentry + add r1, r1, #0x218000 + mov r2, #0x28 + str r1, [r2] + ldmfd sp, {fp, sp, pc} + +.align 2 +.global kernel_exit +.type kernel_exit, %function +@TODO: find out args etc settings + +kernel_exit: + @ 1. push kregs onto stack + mov ip, sp + stmfd sp!, {r3-r12, r14} + @ Set spsr to saved value + msr spsr, r2 + @ 2. switch to system mode + msr cpsr_c, #0xdf + @ 3. get retval, sp from TD + mov sp, r1 + @ load the pc into r1 + ldmfd sp!, {r1} + @ r0 is already retval + @ 4. pop the registers of the active task + ldmfd sp!, {r4-r12, r14} + @ 6. return to svc state + msr cpsr_c, #0xd3 + @ 8. install the pc of the active task and change modes + movs pc, r1 + @ldmfd sp, {r3-r12, pc} + + +@.align 2 +@.global kernel_entry +@.type kernel_entry, %function +kernelentry: + @ 3. change to system state, sp lr are in user + msr cpsr_c, #0xdf + @ 5. store user's registers values onto user stack + stmfd sp!, {r4-r12, r14} + @ 6. save active user task's sp in r1 + mov r1, sp + @ 7. back to service state + msr cpsr_c, #0xd3 + @ Calculate address of SWI instruction and load it into r0. + ldr r0, [lr,#-4] + @ Mask off top 8 bits of instruction to give SWI number. + bic r0, r0,#0xFF000000 + @ save user's next pc to stack which is stored in lr_svc, set by swi + stmfd r1!, {lr} + @ 8. getting spsr, user's values were set by swi + mrs r2, spsr + @ 9. pop kernel registers from stack, jump to kernel's lr instruction + ldmfd sp!, {r3-r12, r14} + mov sp, ip + mov pc, lr + @ r0: request_type, r1: user sp, r2: user spsr, arguments on user stack \ No newline at end of file diff --git a/src/main.c b/src/main.c index 6232fe9bc9bd99141914099f5cb7ab0852a40919..d812aef5df2cebcb8364fe20af1c13ac8aafb7e0 100644 --- a/src/main.c +++ b/src/main.c @@ -10,20 +10,27 @@ int main(int argc, char const *argv[]) { - KernelStruct Colonel; - Request* Req; - int i, Status; + KernelStruct Colonel; + int i, Status, req; + TD* Next; int* kernelEntry = (int *)(0x8); *kernelEntry = (int)&kerent; + SetUpRegs(); + kerent(); kernelInit(&Colonel); schedulerInit(); - memoryInit(); - + // First User Task Colonel->Active = Create(Prio4, &firstUserTaskChildren); + pushToScheduler(&Colonel); + FOREVER { + Task = getNextTaskScheduler(&Colonel); + req = Activate(&Colonel, Task); + Handle(&Colonel, req); + } return 0; } diff --git a/src/sc.c b/src/sc.c new file mode 100644 index 0000000000000000000000000000000000000000..e3903ab1dcc33816a358e206def59ee9075c60d2 --- /dev/null +++ b/src/sc.c @@ -0,0 +1,72 @@ +#include "task-descriptor.h" +#include "kernel.h" +#include "syscall-handler.h" + + + +void handlerCreate(KernelStruct* Colonel) { + register int Priority asm("r0"); + register void (*Code)() asm ("r1"); + register int* CurSP asm("r3") = (Colonel->Active)->sp; + + asm volatile( + "msr cpsr_c, #0xDF\n\t" + "mov r1, %0\n\t" : "r" (CurSp) + "sub r2, r1, #44\n\t" + "ldmfd r2, {%0, %1}\n\t" : "r" (Priority), "r" (Code) + "msr cpsr_c, #0xD3\n\t" + ); + + TD* NewTask = NewTask(Colonel, (int)priority,(int)code); + if (NewTask == NULL) (Colonel->Active)->RetVal = FAILURE; + else { + (Colonel->Active)->RetVal = NewTask->TaskID; + pushToScheduler(Colonel, NewTask); + } + pushToScheduler(Colonel, Colonel->Active); +} + + +void Handle(KernelStruct* Colonel, int n) { + switch(n) { + case SYS_Create: + handlerCreate(Colonel); + break; + case SYS_MyTid: + (Colonel->Active)->RetVal = (Colonel->Active)->TaskID; + pushToScheduler(Colonel); + break; + case SYS_ParentTid: + (Colonel->Active)->RetVal = (Colonel->Active)->ParentID; + pushToScheduler(Colonel); + break; + case SYS_Pass: + pushToScheduler(Colonel); + break; + case SYS_Exit: + (Colonel->Active)->TaskState = Zombie; + break; + } +} + +int Activate(KernelStruct* Colonel, TD* Task) { + register int Request asm ("r0"); + register int* NewSP asm("r1"); + register int NewSPSR asm("r2"); + + Colonel->Active = Task; + + kerxit(Task->sp, Task0->spsr, Task->RetVal); + + asm volatile ( + "mov %0, r0\n\t" : "r" (Request) // TODO + "mov %1, r1\n\t" : "r" (NewSP) + "mov %2, r2\n\t": "r" (NewSPSR) + }; + + Task->sp = NewSP; + Task->spsr = NewSPSR; + + return Request; +} +