Userspace with a syscall

This commit is contained in:
Mathieu Maret 2021-11-03 23:54:36 +01:00
parent a02167ad88
commit 4ad5b58787
7 changed files with 123 additions and 6 deletions

View File

@ -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.cs = BUILD_SEGMENT_REG_VALUE(3, FALSE, SEG_UCODE); // Code
uctx->regs.ds = BUILD_SEGMENT_REG_VALUE(3, FALSE, SEG_UDATA); // Data 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.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_ss = BUILD_SEGMENT_REG_VALUE(3, FALSE, SEG_UDATA); // User Stack
uctx->cpl3_esp = startSP; uctx->cpl3_esp = startSP;

View File

@ -1,3 +1,4 @@
#include "assert.h"
#include "swintr.h" #include "swintr.h"
#include "irq.h" #include "irq.h"
#include "idt.h" #include "idt.h"
@ -8,9 +9,10 @@ int syscallSetup(){
uint32_t flags, ret; uint32_t flags, ret;
disable_IRQs(flags); 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); restore_IRQs(flags);
assert(ret == 0);
return ret; return ret;
} }

View File

@ -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 */}) #define cpu_state_detect_kernel_stack_overflow(ctxt, stkbottom, stksize) ({/* nop */})
#endif #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, int syscallGet3args(const struct cpu_state *user_ctxt,
/* out */ unsigned int *arg1, /* out */ unsigned int *arg1,
/* out */ unsigned int *arg2, /* out */ unsigned int *arg2,

View File

@ -19,6 +19,7 @@
#include "serial.h" #include "serial.h"
#include "stack.h" #include "stack.h"
#include "stdarg.h" #include "stdarg.h"
#include "swintr.h"
#ifdef RUN_TEST #ifdef RUN_TEST
#include "test.h" #include "test.h"
#endif #endif
@ -172,6 +173,7 @@ void kmain(unsigned long magic, unsigned long addr)
threadSetup(_stack_bottom, (_stack_top - _stack_bottom + 1)); threadSetup(_stack_bottom, (_stack_top - _stack_bottom + 1));
threadCreate("idle ", idleThread, NULL); threadCreate("idle ", idleThread, NULL);
processSetup(); processSetup();
syscallSetup();
irqSetRoutine(IRQ_TIMER, pit_handler); irqSetRoutine(IRQ_TIMER, pit_handler);

View File

@ -6,6 +6,7 @@
#include "list.h" #include "list.h"
#include "mmuContext.h" #include "mmuContext.h"
#include "time.h" #include "time.h"
#include "types.h"
#include "vga.h" #include "vga.h"
static struct thread *currentThread; static struct thread *currentThread;
@ -59,15 +60,15 @@ struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, v
return NULL; return NULL;
thread->stackAddr = (vaddr_t)malloc(THREAD_DEFAULT_STACK_SIZE); thread->stackAddr = (vaddr_t)malloc(THREAD_DEFAULT_STACK_SIZE);
if (!thread->stackAddr) if (!thread->stackAddr){
free(thread);
return NULL; return NULL;
}
#ifdef DEBUG #ifdef DEBUG
printf("Alloc stack at 0x%x struct at 0x%x\n", thread->stackAddr, thread); printf("Alloc stack at 0x%x struct at 0x%x\n", thread->stackAddr, thread);
#endif #endif
thread->stackSize = THREAD_DEFAULT_STACK_SIZE; thread->stackSize = THREAD_DEFAULT_STACK_SIZE;
if (!thread->stackAddr)
goto free_mem;
if (name) if (name)
strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH); strzcpy(thread->name, name, THREAD_NAME_MAX_LENGTH);
@ -91,12 +92,53 @@ free_mem:
return NULL; 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) void threadDelete(struct thread *thread)
{ {
uint32_t flags; uint32_t flags;
disable_IRQs(flags); disable_IRQs(flags);
list_delete(currentThread, thread); list_delete(currentThread, thread);
restore_IRQs(flags); restore_IRQs(flags);
assert(thread->state == EXITING);
if (thread->squattedContext) { if (thread->squattedContext) {
threadChangeCurrentContext(NULL); threadChangeCurrentContext(NULL);
@ -135,6 +177,7 @@ struct cpu_state *threadSwitch(struct cpu_state *prevCpu)
currentThread->cpuState = prevCpu; currentThread->cpuState = prevCpu;
if (nextThread != currentThread) { if (nextThread != currentThread) {
currentThread->state = READY; currentThread->state = READY;
// printf(" Switch from %s to %s\n", currentThread->name, nextThread->name);
currentThread = nextThread; currentThread = nextThread;
currentThread->state = RUNNING; currentThread->state = RUNNING;
threadPrepareContext(nextThread); threadPrepareContext(nextThread);
@ -145,6 +188,17 @@ struct cpu_state *threadSwitch(struct cpu_state *prevCpu)
return nextThread->cpuState; 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() int threadOnJieffiesTick()
{ {
struct thread *nextThread; struct thread *nextThread;
@ -224,7 +278,7 @@ int threadYield()
if (current->state == RUNNING) if (current->state == RUNNING)
current->state = READY; current->state = READY;
// printf(" Yield from %s to %s\n", currentThread->name, next->name);
currentThread = next; currentThread = next;
currentThread->state = RUNNING; currentThread->state = RUNNING;
threadPrepareContext(next); threadPrepareContext(next);

View File

@ -72,6 +72,8 @@ int threadSetup(vaddr_t mainStack, size_t mainStackSize);
void threadExit(); void threadExit();
struct thread *threadCreate(const char *name, cpu_kstate_function_arg1_t func, void *args); 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); void threadDelete(struct thread *thread);
struct thread *threadSelectNext(); struct thread *threadSelectNext();
@ -85,3 +87,4 @@ int threadOnJieffiesTick();
struct thread *getCurrentThread(); struct thread *getCurrentThread();
int threadAddThread(struct thread *th); int threadAddThread(struct thread *th);
int threadChangeCurrentContext(struct mmu_context *ctx); int threadChangeCurrentContext(struct mmu_context *ctx);
int threadCount();

View File

@ -3,6 +3,7 @@
#include "ata.h" #include "ata.h"
#include "assert.h" #include "assert.h"
#include "cpu_context.h" #include "cpu_context.h"
#include "kernel.h"
#include "klibc.h" #include "klibc.h"
#include "thread.h" #include "thread.h"
#include "list.h" #include "list.h"
@ -13,6 +14,8 @@
#include "serial.h" #include "serial.h"
#include "stack.h" #include "stack.h"
#include "synchro.h" #include "synchro.h"
#include "syscall.h"
#include "swintr.h"
#include "time.h" #include "time.h"
void testMemcpyPerf() void testMemcpyPerf()
@ -213,6 +216,7 @@ static void reclaim_stack(void *stack_vaddr)
static void exit_hello12(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, cpu_context_exit_to(ctxt_main, (cpu_kstate_function_arg1_t *)reclaim_stack,
(vaddr_t)stack_vaddr); (vaddr_t)stack_vaddr);
} }
@ -348,6 +352,7 @@ void testKthread()
threadCreate("mtest1", mutThread, "mut1"); threadCreate("mtest1", mutThread, "mut1");
threadCreate("mtest2", mutThread, "mut2"); threadCreate("mtest2", mutThread, "mut2");
threadCreate("mtest3", mutThread, "mut3"); threadCreate("mtest3", mutThread, "mut3");
threadMsleep(2000);
} }
void testATAThread(){ void testATAThread(){
@ -382,6 +387,29 @@ static void testMMUContext()
mmuContextUnref(new); 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(){ static void testProcess(){
struct process *proc= processCreate("TESTPROCESS"); struct process *proc= processCreate("TESTPROCESS");
@ -397,6 +425,29 @@ static void testProcess(){
processUnref(proc); processUnref(proc);
printf("Next process list should be empty\n"); printf("Next process list should be empty\n");
processListPrint(); 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) void run_test(void)
@ -436,7 +487,9 @@ void run_test(void)
printf("Testing backtrace\n"); printf("Testing backtrace\n");
test_backtrace(); test_backtrace();
testCoroutine(); testCoroutine();
int nbThread = threadCount();
testKthread(); testKthread();
assert(nbThread + 1 == threadCount());//For sleep Thread
testMMUContext(); testMMUContext();
testProcess(); testProcess();
memGetStat(&afterFreemem, &afterUsedmem); memGetStat(&afterFreemem, &afterUsedmem);