Userspace with a syscall
This commit is contained in:
parent
a02167ad88
commit
4ad5b58787
@ -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;
|
||||||
|
@ -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"
|
||||||
@ -11,6 +12,7 @@ int syscallSetup(){
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
53
tests/test.c
53
tests/test.c
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user