diff --git a/include/errno.h b/include/errno.h index d3d5330..4cba6a4 100644 --- a/include/errno.h +++ b/include/errno.h @@ -2,11 +2,12 @@ #ifndef __ERRNO_H__ #define __ERRNO_H__ -#define EIO 1 -#define EBADF 2 -#define EINVAL 3 -#define EFAULT 4 -#define ENOMEM 5 +#define EIO 0xBAD1 +#define EBADF 0xBAD2 +#define EINVAL 0xBAD3 +#define EFAULT 0xBAD4 +#define ENOMEM 0xBAD5 +#define ENOENT 0xBAD6 #endif /* __ERRNO_H__ */ diff --git a/sbin/init/init.c b/sbin/init/init.c index af14598..7db436b 100644 --- a/sbin/init/init.c +++ b/sbin/init/init.c @@ -1,7 +1,17 @@ +#include +#include int main(int argc, const char *argv[]) { - asm volatile("int3"); + fputs("Init spawning shell\n", stdout); + + SystemSpawn("/bin/shell"); + + //while (1) { } + + while (1) { + asm volatile("int3"); + } } diff --git a/sys/amd64/include/trap.h b/sys/amd64/include/trap.h index ae2583d..9b49b09 100644 --- a/sys/amd64/include/trap.h +++ b/sys/amd64/include/trap.h @@ -61,6 +61,7 @@ typedef struct TrapFrame uint64_t rdx; uint64_t rcx; uint64_t rbx; + uint64_t ds; uint64_t rax; uint64_t vector; diff --git a/sys/amd64/machine.c b/sys/amd64/machine.c index 56ddea1..2819918 100644 --- a/sys/amd64/machine.c +++ b/sys/amd64/machine.c @@ -83,14 +83,14 @@ void Machine_TSSInit() TSS[c]._unused2 = 0; TSS[c]._unused3 = 0; TSS[c]._unused4 = 0; - TSS[c].ist1 = (uint64_t)&df_stack; + TSS[c].ist1 = ((uint64_t)&df_stack) + 4096; TSS[c].ist2 = 0x0; TSS[c].ist3 = 0x0; TSS[c].ist4 = 0x0; TSS[c].ist5 = 0x0; TSS[c].ist6 = 0x0; TSS[c].ist7 = 0x0; - TSS[c].rsp0 = (uint64_t)&df_stack; + TSS[c].rsp0 = ((uint64_t)&df_stack) + 4096; TSS[c].rsp1 = 0; TSS[c].rsp2 = 0; diff --git a/sys/amd64/multiboot.S b/sys/amd64/multiboot.S index 1c291ca..fc2fb64 100644 --- a/sys/amd64/multiboot.S +++ b/sys/amd64/multiboot.S @@ -74,7 +74,7 @@ multiboot_entry: .code32 lmenter: .code64 movw $(0x7000 + '1'), (0xB8010) - movw $0x10, %ax + xorw %ax, %ax movw %ax, %ss movw %ax, %ds movw %ax, %es diff --git a/sys/amd64/thread.c b/sys/amd64/thread.c index adf35ee..640fdaa 100644 --- a/sys/amd64/thread.c +++ b/sys/amd64/thread.c @@ -39,7 +39,8 @@ Thread_SetupKThread(Thread *thr, void (*f)(void *), void *arg) sf->rip = (uint64_t)&ThreadKThreadEntry; sf->rdi = (uint64_t)tf; - tf->ss = SEL_KDS; + tf->ds = 0; + tf->ss = 0; //SEL_KDS; tf->rsp = stacktop; tf->cs = SEL_KCS; tf->rip = (uint64_t)f; diff --git a/sys/amd64/trapentry.S b/sys/amd64/trapentry.S index 8ed602b..981095d 100644 --- a/sys/amd64/trapentry.S +++ b/sys/amd64/trapentry.S @@ -11,6 +11,9 @@ trap\TRAPNUM: pushq %rax pushq $\TRAPNUM pushq %rax + xorq %rax, %rax + movw %ds, %ax + pushq %rax jmp trap_common .endm @@ -18,6 +21,9 @@ trap\TRAPNUM: trap\TRAPNUM: pushq $\TRAPNUM pushq %rax + xorq %rax, %rax + movw %ds, %ax + pushq %rax jmp trap_common .endm @@ -187,6 +193,8 @@ trap_return: popq %rcx popq %rbx popq %rax + movw %ax, %ds + popq %rax addq $16, %rsp // Skip error code and vector number iretq diff --git a/sys/kern/ktime.c b/sys/kern/ktime.c index 08bddca..e41ed25 100644 --- a/sys/kern/ktime.c +++ b/sys/kern/ktime.c @@ -10,7 +10,7 @@ static Spinlock ktimeLock; static uint64_t ktimeLastEpoch; static uint64_t ktimeLastTSC; -static uint64_t ticksPerSecond; +uint64_t ticksPerSecond; static uint64_t ticksPrevTSC; static uint64_t ticksCount; // Stable Value diff --git a/sys/kern/loader.c b/sys/kern/loader.c index 326fca3..78c7c82 100644 --- a/sys/kern/loader.c +++ b/sys/kern/loader.c @@ -37,6 +37,126 @@ Loader_CheckHeader(const Elf64_Ehdr *ehdr) return true; } +bool +Loader_LoadFirst(Thread *thr, VNode *vn, void *buf, uint64_t len) +{ + int i; + const Elf64_Ehdr *ehdr; + const Elf64_Phdr *phdr; + AS *as = thr->space; + + ehdr = (const Elf64_Ehdr *)(buf); + phdr = (const Elf64_Phdr *)(buf + ehdr->e_phoff); + + if (!Loader_CheckHeader(ehdr)) { + kprintf("Not a valid executable!\n"); + return false; + } + + kprintf("%8s %16s %8s %8s\n", "Offset", "VAddr", "FileSize", "MemSize"); + for (i = 0; i < ehdr->e_phnum; i++) + { + ASSERT(phdr[i].p_type != PT_DYNAMIC); + if (phdr[i].p_type == PT_LOAD) { + uint64_t va = phdr[i].p_vaddr; + uint64_t memsz = phdr[i].p_memsz; + kprintf("%08llx %016llx %08llx %08llx\n", phdr[i].p_offset, + phdr[i].p_vaddr, phdr[i].p_filesz, phdr[i].p_memsz); + + // Make sure it is page aligned + va = va & ~(uint64_t)PGMASK; + memsz += phdr[i].p_vaddr - va; + + kprintf("%016llx %08llx\n", va, memsz); + if (!PMap_AllocMap(as, va, phdr[i].p_memsz, PTE_W)) { + // XXX: Cleanup! + ASSERT(false); + return false; + } + } + } + + void *stack = PAlloc_AllocPage(); + PMap_Map(as, (uint64_t)DMVA2PA(stack), 0x70000000, 1, 0); + PMap_LoadAS(as); // Reload CR3 + + for (i = 0; i < ehdr->e_phnum; i++) + { + ASSERT(phdr[i].p_type != PT_DYNAMIC); + if (phdr[i].p_type == PT_LOAD) { + if (phdr[i].p_filesz != 0) { + VFS_Read(vn, (void *)phdr[i].p_vaddr, + phdr[i].p_offset, phdr[i].p_filesz); + } + memset((void *)(phdr[i].p_vaddr + phdr[i].p_filesz), + 0, + (uintptr_t)(phdr[i].p_memsz - phdr[i].p_filesz)); + } + } + + TrapFrame tf; + memset(&tf, 0, sizeof(tf)); + tf.ds = SEL_UDS | 3; + tf.rip = ehdr->e_entry; + tf.cs = SEL_UCS | 3; + tf.rsp = 0x70000000 + PGSIZE; + tf.ss = SEL_UDS | 3; + tf.rflags = RFLAGS_IF; + Trap_Pop(&tf); + + return true; +} + +Handle *Console_OpenHandle(); + +void +Loader_LoadInit() +{ + int status; + void *pg; + VNode *init; + + pg = PAlloc_AllocPage(); + if (!pg) + Panic("Not enough memory!"); + + init = VFS_Lookup("/sbin/init"); + status = VFS_Open(init); + if (status < 0) + Panic("Loading init process failed!"); + status = VFS_Read(init, pg, 0, 1024); + if (status < 0) + Panic("Reading init process failed!"); + + Thread *thr = Thread_Current(); + + // Open stdin/out/err + Handle *handle = Console_OpenHandle(); + Handle_Add(thr, handle); + handle = Console_OpenHandle(); + Handle_Add(thr, handle); + handle = Console_OpenHandle(); + Handle_Add(thr, handle); + + Loader_LoadFirst(thr, init, pg, 1024); + + VFS_Close(init); +} + +void +Loader_EnterUserLevel(void *arg) +{ + TrapFrame tf; + memset(&tf, 0, sizeof(tf)); + tf.ds = SEL_UDS | 3; + tf.rip = (uint64_t)arg; + tf.cs = SEL_UCS | 3; + tf.rsp = 0x70000000 + PGSIZE; + tf.ss = SEL_UDS | 3; + tf.rflags = RFLAGS_IF; + Trap_Pop(&tf); +} + bool Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len) { @@ -94,52 +214,11 @@ Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len) } } - TrapFrame tf; - memset(&tf, 0, sizeof(tf)); - tf.rip = ehdr->e_entry; - tf.cs = SEL_UCS | 3; - tf.rsp = 0x70000000 + PGSIZE; - tf.ss = SEL_UDS | 3; - tf.rflags = RFLAGS_IF; - Trap_Pop(&tf); + Thread_SetupKThread(thr, Loader_EnterUserLevel, (void *)ehdr->e_entry); + + // Restore AS + PMap_LoadAS(Thread_Current()->space); return true; } -// XXX: Cleanup -Handle *Console_OpenHandle(); - -void -Loader_LoadInit() -{ - int status; - void *pg; - VNode *init; - - pg = PAlloc_AllocPage(); - if (!pg) - Panic("Not enough memory!"); - - init = VFS_Lookup("/sbin/init"); - status = VFS_Open(init); - if (status < 0) - Panic("Loading init process failed!"); - status = VFS_Read(init, pg, 0, 1024); - if (status < 0) - Panic("Reading init process failed!"); - - Thread *thr = Thread_Current(); - - // Open stdin/out/err - Handle *handle = Console_OpenHandle(); - Handle_Add(thr, handle); - handle = Console_OpenHandle(); - Handle_Add(thr, handle); - handle = Console_OpenHandle(); - Handle_Add(thr, handle); - - Loader_Load(thr, init, pg, 1024); - - VFS_Close(init); -} - diff --git a/sys/kern/spinlock.c b/sys/kern/spinlock.c index 93fb38f..f329a90 100644 --- a/sys/kern/spinlock.c +++ b/sys/kern/spinlock.c @@ -15,6 +15,8 @@ Spinlock lockListLock = { 0, 0, 0, 0, 0, 0, "SPINLOCK LIST" }; LIST_HEAD(LockListHead, Spinlock) lockList = LIST_HEAD_INITIALIZER(lockList); +extern uint64_t ticksPerSecond; + void Spinlock_Init(Spinlock *lock, const char *name) { @@ -48,6 +50,9 @@ Spinlock_Lock(Spinlock *lock) startTSC = Time_GetTSC(); while (atomic_swap_uint64(&lock->lock, 1) == 1) { + if ((Time_GetTSC() - startTSC) / ticksPerSecond > 1) { + kprintf("Spinlock_Lock(%s): waiting for over a second!\n", lock->name); + } } lock->waitTime += Time_GetTSC() - startTSC; diff --git a/sys/kern/syscall.c b/sys/kern/syscall.c index ab981aa..92d1ae4 100644 --- a/sys/kern/syscall.c +++ b/sys/kern/syscall.c @@ -10,6 +10,10 @@ #include #include #include +#include +#include + +Handle *Console_OpenHandle(); uint64_t Syscall_Time() @@ -32,9 +36,61 @@ Syscall_Exit(uint64_t status) } uint64_t -Syscall_Spawn(uint64_t path) +Syscall_Spawn(uint64_t user_path) { - //Thread *thr = Thread_Create(); + int status; + char path[512]; + void *pg; + VNode *file; + Thread *thr; + + // XXX: Use CopyInStr + status = CopyIn(user_path, &path, sizeof(path)); + if (status != 0) + return status; + + kprintf("Spawn(%s)\n", path); + + pg = PAlloc_AllocPage(); + if (!pg) { + return ENOMEM; + } + + file = VFS_Lookup(path); + if (!file) { + // Free + return ENOENT; + } + + status = VFS_Open(file); + if (status < 0) { + kprintf("Error VFS_Open\n"); + // Release & free + return status; + } + + status = VFS_Read(file, pg, 0, 1024); + if (status < 0) { + kprintf("Error VFS_Read\n"); + // Release & free + return status; + } + + thr = Thread_Create(); + kprintf("SPAWN %lx\n", thr); + + Handle *handle = Console_OpenHandle(); + Handle_Add(thr, handle); + handle = Console_OpenHandle(); + Handle_Add(thr, handle); + handle = Console_OpenHandle(); + Handle_Add(thr, handle); + + //Loader_Load(thr, file, pg, 1024); + + VFS_Close(file); + + //Thread_SetRunnable(thr); return 0; }