Segment registers and TSS bugfix that caused triple faults. Also includes part of the Spawn system call implementation.
This commit is contained in:
parent
8826ed6396
commit
796a7f0cbb
@ -2,11 +2,12 @@
|
|||||||
#ifndef __ERRNO_H__
|
#ifndef __ERRNO_H__
|
||||||
#define __ERRNO_H__
|
#define __ERRNO_H__
|
||||||
|
|
||||||
#define EIO 1
|
#define EIO 0xBAD1
|
||||||
#define EBADF 2
|
#define EBADF 0xBAD2
|
||||||
#define EINVAL 3
|
#define EINVAL 0xBAD3
|
||||||
#define EFAULT 4
|
#define EFAULT 0xBAD4
|
||||||
#define ENOMEM 5
|
#define ENOMEM 0xBAD5
|
||||||
|
#define ENOENT 0xBAD6
|
||||||
|
|
||||||
#endif /* __ERRNO_H__ */
|
#endif /* __ERRNO_H__ */
|
||||||
|
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <syscall.h>
|
||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ typedef struct TrapFrame
|
|||||||
uint64_t rdx;
|
uint64_t rdx;
|
||||||
uint64_t rcx;
|
uint64_t rcx;
|
||||||
uint64_t rbx;
|
uint64_t rbx;
|
||||||
|
uint64_t ds;
|
||||||
uint64_t rax;
|
uint64_t rax;
|
||||||
|
|
||||||
uint64_t vector;
|
uint64_t vector;
|
||||||
|
@ -83,14 +83,14 @@ void Machine_TSSInit()
|
|||||||
TSS[c]._unused2 = 0;
|
TSS[c]._unused2 = 0;
|
||||||
TSS[c]._unused3 = 0;
|
TSS[c]._unused3 = 0;
|
||||||
TSS[c]._unused4 = 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].ist2 = 0x0;
|
||||||
TSS[c].ist3 = 0x0;
|
TSS[c].ist3 = 0x0;
|
||||||
TSS[c].ist4 = 0x0;
|
TSS[c].ist4 = 0x0;
|
||||||
TSS[c].ist5 = 0x0;
|
TSS[c].ist5 = 0x0;
|
||||||
TSS[c].ist6 = 0x0;
|
TSS[c].ist6 = 0x0;
|
||||||
TSS[c].ist7 = 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].rsp1 = 0;
|
||||||
TSS[c].rsp2 = 0;
|
TSS[c].rsp2 = 0;
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ multiboot_entry: .code32
|
|||||||
|
|
||||||
lmenter: .code64
|
lmenter: .code64
|
||||||
movw $(0x7000 + '1'), (0xB8010)
|
movw $(0x7000 + '1'), (0xB8010)
|
||||||
movw $0x10, %ax
|
xorw %ax, %ax
|
||||||
movw %ax, %ss
|
movw %ax, %ss
|
||||||
movw %ax, %ds
|
movw %ax, %ds
|
||||||
movw %ax, %es
|
movw %ax, %es
|
||||||
|
@ -39,7 +39,8 @@ Thread_SetupKThread(Thread *thr, void (*f)(void *), void *arg)
|
|||||||
sf->rip = (uint64_t)&ThreadKThreadEntry;
|
sf->rip = (uint64_t)&ThreadKThreadEntry;
|
||||||
sf->rdi = (uint64_t)tf;
|
sf->rdi = (uint64_t)tf;
|
||||||
|
|
||||||
tf->ss = SEL_KDS;
|
tf->ds = 0;
|
||||||
|
tf->ss = 0; //SEL_KDS;
|
||||||
tf->rsp = stacktop;
|
tf->rsp = stacktop;
|
||||||
tf->cs = SEL_KCS;
|
tf->cs = SEL_KCS;
|
||||||
tf->rip = (uint64_t)f;
|
tf->rip = (uint64_t)f;
|
||||||
|
@ -11,6 +11,9 @@ trap\TRAPNUM:
|
|||||||
pushq %rax
|
pushq %rax
|
||||||
pushq $\TRAPNUM
|
pushq $\TRAPNUM
|
||||||
pushq %rax
|
pushq %rax
|
||||||
|
xorq %rax, %rax
|
||||||
|
movw %ds, %ax
|
||||||
|
pushq %rax
|
||||||
jmp trap_common
|
jmp trap_common
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
@ -18,6 +21,9 @@ trap\TRAPNUM:
|
|||||||
trap\TRAPNUM:
|
trap\TRAPNUM:
|
||||||
pushq $\TRAPNUM
|
pushq $\TRAPNUM
|
||||||
pushq %rax
|
pushq %rax
|
||||||
|
xorq %rax, %rax
|
||||||
|
movw %ds, %ax
|
||||||
|
pushq %rax
|
||||||
jmp trap_common
|
jmp trap_common
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
@ -187,6 +193,8 @@ trap_return:
|
|||||||
popq %rcx
|
popq %rcx
|
||||||
popq %rbx
|
popq %rbx
|
||||||
popq %rax
|
popq %rax
|
||||||
|
movw %ax, %ds
|
||||||
|
popq %rax
|
||||||
addq $16, %rsp // Skip error code and vector number
|
addq $16, %rsp // Skip error code and vector number
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
static Spinlock ktimeLock;
|
static Spinlock ktimeLock;
|
||||||
static uint64_t ktimeLastEpoch;
|
static uint64_t ktimeLastEpoch;
|
||||||
static uint64_t ktimeLastTSC;
|
static uint64_t ktimeLastTSC;
|
||||||
static uint64_t ticksPerSecond;
|
uint64_t ticksPerSecond;
|
||||||
static uint64_t ticksPrevTSC;
|
static uint64_t ticksPrevTSC;
|
||||||
static uint64_t ticksCount;
|
static uint64_t ticksCount;
|
||||||
// Stable Value
|
// Stable Value
|
||||||
|
@ -37,6 +37,126 @@ Loader_CheckHeader(const Elf64_Ehdr *ehdr)
|
|||||||
return true;
|
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
|
bool
|
||||||
Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len)
|
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;
|
Thread_SetupKThread(thr, Loader_EnterUserLevel, (void *)ehdr->e_entry);
|
||||||
memset(&tf, 0, sizeof(tf));
|
|
||||||
tf.rip = ehdr->e_entry;
|
// Restore AS
|
||||||
tf.cs = SEL_UCS | 3;
|
PMap_LoadAS(Thread_Current()->space);
|
||||||
tf.rsp = 0x70000000 + PGSIZE;
|
|
||||||
tf.ss = SEL_UDS | 3;
|
|
||||||
tf.rflags = RFLAGS_IF;
|
|
||||||
Trap_Pop(&tf);
|
|
||||||
|
|
||||||
return true;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
Spinlock lockListLock = { 0, 0, 0, 0, 0, 0, "SPINLOCK LIST" };
|
Spinlock lockListLock = { 0, 0, 0, 0, 0, 0, "SPINLOCK LIST" };
|
||||||
LIST_HEAD(LockListHead, Spinlock) lockList = LIST_HEAD_INITIALIZER(lockList);
|
LIST_HEAD(LockListHead, Spinlock) lockList = LIST_HEAD_INITIALIZER(lockList);
|
||||||
|
|
||||||
|
extern uint64_t ticksPerSecond;
|
||||||
|
|
||||||
void
|
void
|
||||||
Spinlock_Init(Spinlock *lock, const char *name)
|
Spinlock_Init(Spinlock *lock, const char *name)
|
||||||
{
|
{
|
||||||
@ -48,6 +50,9 @@ Spinlock_Lock(Spinlock *lock)
|
|||||||
startTSC = Time_GetTSC();
|
startTSC = Time_GetTSC();
|
||||||
while (atomic_swap_uint64(&lock->lock, 1) == 1)
|
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;
|
lock->waitTime += Time_GetTSC() - startTSC;
|
||||||
|
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
#include <sys/ktime.h>
|
#include <sys/ktime.h>
|
||||||
#include <sys/thread.h>
|
#include <sys/thread.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/disk.h>
|
||||||
|
#include <sys/vfs.h>
|
||||||
|
|
||||||
|
Handle *Console_OpenHandle();
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Syscall_Time()
|
Syscall_Time()
|
||||||
@ -32,9 +36,61 @@ Syscall_Exit(uint64_t status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user