diff --git a/arch/x86/cpu_context.c b/arch/x86/cpu_context.c index b7a6fd6..eedd0f4 100644 --- a/arch/x86/cpu_context.c +++ b/arch/x86/cpu_context.c @@ -335,7 +335,7 @@ int cpu_ustate_init(struct cpu_state **ctx, uaddr_t startPC, uint32_t arg1, uint uctx->regs.cs = BUILD_SEGMENT_REG_VALUE(3, FALSE, SEG_UCODE); // Code uctx->regs.ds = BUILD_SEGMENT_REG_VALUE(3, FALSE, SEG_UDATA); // Data uctx->regs.es = BUILD_SEGMENT_REG_VALUE(3, FALSE, SEG_UDATA); // Data - uctx->regs.cpl0_ss = BUILD_SEGMENT_REG_VALUE(3, FALSE, SEG_UDATA); // Kernel Stack + uctx->regs.cpl0_ss = BUILD_SEGMENT_REG_VALUE(0, FALSE, SEG_KDATA); // Kernel Stack uctx->cpl3_ss = BUILD_SEGMENT_REG_VALUE(3, FALSE, SEG_UDATA); // User Stack uctx->cpl3_esp = startSP; diff --git a/arch/x86/swintr.c b/arch/x86/swintr.c index d16d3e8..44d28fc 100644 --- a/arch/x86/swintr.c +++ b/arch/x86/swintr.c @@ -1,3 +1,4 @@ +#include "assert.h" #include "swintr.h" #include "irq.h" #include "idt.h" @@ -8,9 +9,10 @@ int syscallSetup(){ uint32_t flags, ret; disable_IRQs(flags); - ret = idt_set_handler(SYSCALL_INTR_NB, (vaddr_t)syscallHandler, 3); + ret = idt_set_handler(SYSCALL_INTR_NB, (vaddr_t)syscallHandler, 3); restore_IRQs(flags); + assert(ret == 0); return ret; } diff --git a/core/cpu_context.h b/core/cpu_context.h index 840179f..724b067 100644 --- a/core/cpu_context.h +++ b/core/cpu_context.h @@ -201,6 +201,9 @@ void cpu_state_detect_kernel_stack_overflow(const struct cpu_state *ctxt, #define cpu_state_detect_kernel_stack_overflow(ctxt, stkbottom, stksize) ({/* nop */}) #endif +int cpu_ustate_init(struct cpu_state **ctx, uaddr_t startPC, uint32_t arg1, uint32_t arg2, + uaddr_t startSP, vaddr_t kernelStackBottom, size_t kernelStackSize); + int syscallGet3args(const struct cpu_state *user_ctxt, /* out */ unsigned int *arg1, /* out */ unsigned int *arg2, diff --git a/core/main.c b/core/main.c index f261810..62f4f19 100644 --- a/core/main.c +++ b/core/main.c @@ -19,6 +19,7 @@ #include "serial.h" #include "stack.h" #include "stdarg.h" +#include "swintr.h" #ifdef RUN_TEST #include "test.h" #endif @@ -172,6 +173,7 @@ void kmain(unsigned long magic, unsigned long addr) threadSetup(_stack_bottom, (_stack_top - _stack_bottom + 1)); threadCreate("idle ", idleThread, NULL); processSetup(); + syscallSetup(); irqSetRoutine(IRQ_TIMER, pit_handler); diff --git a/core/thread.c b/core/thread.c index 0aa406d..4bd8f6d 100644 --- a/core/thread.c +++ b/core/thread.c @@ -6,6 +6,7 @@ #include "list.h" #include "mmuContext.h" #include "time.h" +#include "types.h" #include "vga.h" static struct thread *currentThread; @@ -59,15 +60,15 @@ struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, v return NULL; thread->stackAddr = (vaddr_t)malloc(THREAD_DEFAULT_STACK_SIZE); - if (!thread->stackAddr) + if (!thread->stackAddr){ + free(thread); return NULL; + } #ifdef DEBUG printf("Alloc stack at 0x%x struct at 0x%x\n", thread->stackAddr, thread); #endif thread->stackSize = THREAD_DEFAULT_STACK_SIZE; - if (!thread->stackAddr) - goto free_mem; if (name) strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH); @@ -91,12 +92,53 @@ free_mem: return NULL; } +struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t startPc, + uint32_t arg1, uint32_t arg2, uaddr_t startSP) +{ + struct thread *thread = malloc(sizeof(struct thread)); + + if (thread == NULL) + return NULL; + + thread->stackAddr = (vaddr_t)malloc(THREAD_DEFAULT_STACK_SIZE); + if (!thread->stackAddr) { + free(thread); + return NULL; + } + thread->stackSize = THREAD_DEFAULT_STACK_SIZE; + + if (name) + strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH); + else + strzcpy(thread->name, "[UNKNOW]", THREAD_NAME_MAX_LENGTH); + + if (cpu_ustate_init(&thread->cpuState, startPc, arg1, arg2, startSP, thread->stackAddr, + thread->stackSize)) { + goto free_mem; + } + + if(processAddThread(proc, thread)) + goto free_mem; + + thread->state = READY; + uint32_t flags; + disable_IRQs(flags); + list_add_tail(currentThread, thread); + restore_IRQs(flags); + return thread; +free_mem: + free((void *)thread->stackAddr); + free((void *)thread); + return NULL; +} + void threadDelete(struct thread *thread) { uint32_t flags; disable_IRQs(flags); list_delete(currentThread, thread); restore_IRQs(flags); + assert(thread->state == EXITING); if (thread->squattedContext) { threadChangeCurrentContext(NULL); @@ -135,6 +177,7 @@ struct cpu_state *threadSwitch(struct cpu_state *prevCpu) currentThread->cpuState = prevCpu; if (nextThread != currentThread) { currentThread->state = READY; +// printf(" Switch from %s to %s\n", currentThread->name, nextThread->name); currentThread = nextThread; currentThread->state = RUNNING; threadPrepareContext(nextThread); @@ -145,6 +188,17 @@ struct cpu_state *threadSwitch(struct cpu_state *prevCpu) return nextThread->cpuState; } +int threadCount() +{ + struct thread *nextThread; + int idx; + uint32_t flags; + disable_IRQs(flags); + list_foreach(currentThread, nextThread, idx){ + } + return idx; +} + int threadOnJieffiesTick() { struct thread *nextThread; @@ -224,7 +278,7 @@ int threadYield() if (current->state == RUNNING) current->state = READY; - +// printf(" Yield from %s to %s\n", currentThread->name, next->name); currentThread = next; currentThread->state = RUNNING; threadPrepareContext(next); diff --git a/core/thread.h b/core/thread.h index ce76c2b..0997676 100644 --- a/core/thread.h +++ b/core/thread.h @@ -72,6 +72,8 @@ int threadSetup(vaddr_t mainStack, size_t mainStackSize); void threadExit(); struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, void *args); +struct thread *threadCreateUser(const char *name, struct process *proc, uaddr_t startPc, + uint32_t arg1, uint32_t arg2, uaddr_t startSP); void threadDelete(struct thread *thread); struct thread *threadSelectNext(); @@ -85,3 +87,4 @@ int threadOnJieffiesTick(); struct thread *getCurrentThread(); int threadAddThread(struct thread *th); int threadChangeCurrentContext(struct mmu_context *ctx); +int threadCount(); diff --git a/tests/test.c b/tests/test.c index 4544a77..a1117f8 100644 --- a/tests/test.c +++ b/tests/test.c @@ -3,6 +3,7 @@ #include "ata.h" #include "assert.h" #include "cpu_context.h" +#include "kernel.h" #include "klibc.h" #include "thread.h" #include "list.h" @@ -13,6 +14,8 @@ #include "serial.h" #include "stack.h" #include "synchro.h" +#include "syscall.h" +#include "swintr.h" #include "time.h" void testMemcpyPerf() @@ -213,6 +216,7 @@ static void reclaim_stack(void *stack_vaddr) static void exit_hello12(void *stack_vaddr) { + printf("Stopping hello\n"); cpu_context_exit_to(ctxt_main, (cpu_kstate_function_arg1_t *)reclaim_stack, (vaddr_t)stack_vaddr); } @@ -348,6 +352,7 @@ void testKthread() threadCreate("mtest1", mutThread, "mut1"); threadCreate("mtest2", mutThread, "mut2"); threadCreate("mtest3", mutThread, "mut3"); + threadMsleep(2000); } void testATAThread(){ @@ -382,6 +387,29 @@ static void testMMUContext() mmuContextUnref(new); } +static void userProgramm() +{ + int ret; + + asm volatile("movl %1,%%eax \n" + "movl %2,%%ebx \n" + "movl %3,%%ecx \n" + "movl %4,%%edx \n" + "int %5\n" + "movl %%eax, %0" + : "=g"(ret) + : "g"(SYSCALL_ID_WRITE), "g"(0), "g"(0), "g"(0), "i"(SYSCALL_INTR_NB) + : "eax", "ebx", "ecx", "edx"); + asm volatile("movl %1,%%eax \n" + "movl %2,%%ebx \n" + "movl %3,%%ecx \n" + "movl %4,%%edx \n" + "int %5\n" + "movl %%eax, %0" + : "=g"(ret) + : "g"(SYSCALL_ID_EXIT), "g"(0), "g"(0), "g"(0), "i"(SYSCALL_INTR_NB) + : "eax", "ebx", "ecx", "edx"); +} static void testProcess(){ struct process *proc= processCreate("TESTPROCESS"); @@ -397,6 +425,29 @@ static void testProcess(){ processUnref(proc); printf("Next process list should be empty\n"); processListPrint(); + printf("Running user space app\n"); + struct process *proc2= processCreate("TESTPROCESS2"); + + threadChangeCurrentContext(processGetMMUContext(proc2)); + uaddr_t stackTop = 0xfffffffc; + uaddr_t stackBottom = ALIGN_DOWN(stackTop, PAGE_SIZE); + paddr_t stackPhy = allocPhyPage(1); + assert(pageMap(stackBottom, stackPhy, PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ) == 0); + unrefPhyPage(stackPhy); + + uaddr_t mem = PAGING_BASE_USER_ADDRESS; + paddr_t memPhy = allocPhyPage(1); + assert(pageMap(mem, memPhy, PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ) == 0); + unrefPhyPage(memPhy); + + memcpy((void *)mem, userProgramm, PAGE_SIZE); + + threadCreateUser("UserProg", proc2, mem, 0, 0, stackTop); + threadYield(); + processUnref(proc2); + threadChangeCurrentContext(NULL); + + printf("Running user space app DONE\n"); } void run_test(void) @@ -436,7 +487,9 @@ void run_test(void) printf("Testing backtrace\n"); test_backtrace(); testCoroutine(); + int nbThread = threadCount(); testKthread(); + assert(nbThread + 1 == threadCount());//For sleep Thread testMMUContext(); testProcess(); memGetStat(&afterFreemem, &afterUsedmem);