Compare commits
3 Commits
aefb4f082b
...
8d87791fa2
Author | SHA1 | Date |
---|---|---|
Drew Galbraith | 8d87791fa2 | |
Drew Galbraith | 6f5b65de30 | |
Drew Galbraith | 7184f527a0 |
|
@ -11,6 +11,7 @@ add_executable(zion
|
||||||
memory/paging_util.cpp
|
memory/paging_util.cpp
|
||||||
memory/physical_memory.cpp
|
memory/physical_memory.cpp
|
||||||
scheduler/context_switch.s
|
scheduler/context_switch.s
|
||||||
|
scheduler/jump_user_space.s
|
||||||
scheduler/process.cpp
|
scheduler/process.cpp
|
||||||
scheduler/scheduler.cpp
|
scheduler/scheduler.cpp
|
||||||
scheduler/thread.cpp
|
scheduler/thread.cpp
|
||||||
|
|
|
@ -90,3 +90,5 @@ void InitGdt() {
|
||||||
"ltr %%ax;" ::
|
"ltr %%ax;" ::
|
||||||
: "rax");
|
: "rax");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetRsp0(uint64_t rsp0) { gTaskStateSegment.rsp0 = rsp0; }
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void InitGdt();
|
void InitGdt();
|
||||||
|
|
||||||
|
void SetRsp0(uint64_t rsp0);
|
||||||
|
|
|
@ -56,7 +56,7 @@ void badmemcpy(uint64_t base, uint64_t offset, uint64_t dest) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void LoadElfProgram(uint64_t base, uint64_t offset) {
|
uint64_t LoadElfProgram(uint64_t base, uint64_t offset) {
|
||||||
Elf64Header* header = reinterpret_cast<Elf64Header*>(base);
|
Elf64Header* header = reinterpret_cast<Elf64Header*>(base);
|
||||||
dbgln("phoff: %u phnum: %u", header->phoff, header->phnum);
|
dbgln("phoff: %u phnum: %u", header->phoff, header->phnum);
|
||||||
Elf64ProgramHeader* programs =
|
Elf64ProgramHeader* programs =
|
||||||
|
@ -71,4 +71,5 @@ void LoadElfProgram(uint64_t base, uint64_t offset) {
|
||||||
EnsureResident(program.vaddr, program.memsz);
|
EnsureResident(program.vaddr, program.memsz);
|
||||||
badmemcpy(base + program.offset, program.filesz, program.vaddr);
|
badmemcpy(base + program.offset, program.filesz, program.vaddr);
|
||||||
}
|
}
|
||||||
|
return header->entry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void LoadElfProgram(uint64_t base, uint64_t length);
|
// Loads the elf program and returns its entry point.
|
||||||
|
uint64_t LoadElfProgram(uint64_t base, uint64_t length);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#define PRESENT_BIT 0x1
|
#define PRESENT_BIT 0x1
|
||||||
#define READ_WRITE_BIT 0x2
|
#define READ_WRITE_BIT 0x2
|
||||||
|
#define USER_MODE_BIT 0x4;
|
||||||
#define SIGN_EXT 0xFFFF0000'00000000
|
#define SIGN_EXT 0xFFFF0000'00000000
|
||||||
#define RECURSIVE ((uint64_t)0x1FE)
|
#define RECURSIVE ((uint64_t)0x1FE)
|
||||||
#define PML_OFFSET 39
|
#define PML_OFFSET 39
|
||||||
|
@ -79,23 +80,29 @@ void MapPage(uint64_t virt, uint64_t phys) {
|
||||||
panic("Allocating Over Existing Page: %m", virt);
|
panic("Allocating Over Existing Page: %m", virt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t access_bits = PRESENT_BIT | READ_WRITE_BIT;
|
||||||
|
uint64_t higher_half = 0xffff8000'00000000;
|
||||||
|
if ((virt & higher_half) != higher_half) {
|
||||||
|
access_bits |= USER_MODE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!PageDirectoryPointerLoaded(virt)) {
|
if (!PageDirectoryPointerLoaded(virt)) {
|
||||||
uint64_t page = phys_mem::AllocatePage();
|
uint64_t page = phys_mem::AllocatePage();
|
||||||
*Pml4Entry(virt) = page | PRESENT_BIT | READ_WRITE_BIT;
|
*Pml4Entry(virt) = page | access_bits;
|
||||||
ZeroOutPage(PageDirectoryPointerEntry(virt));
|
ZeroOutPage(PageDirectoryPointerEntry(virt));
|
||||||
}
|
}
|
||||||
if (!PageDirectoryLoaded(virt)) {
|
if (!PageDirectoryLoaded(virt)) {
|
||||||
uint64_t page = phys_mem::AllocatePage();
|
uint64_t page = phys_mem::AllocatePage();
|
||||||
*PageDirectoryPointerEntry(virt) = page | PRESENT_BIT | READ_WRITE_BIT;
|
*PageDirectoryPointerEntry(virt) = page | access_bits;
|
||||||
ZeroOutPage(PageDirectoryEntry(virt));
|
ZeroOutPage(PageDirectoryEntry(virt));
|
||||||
}
|
}
|
||||||
if (!PageTableLoaded(virt)) {
|
if (!PageTableLoaded(virt)) {
|
||||||
uint64_t page = phys_mem::AllocatePage();
|
uint64_t page = phys_mem::AllocatePage();
|
||||||
*PageDirectoryEntry(virt) = page | PRESENT_BIT | READ_WRITE_BIT;
|
*PageDirectoryEntry(virt) = page | access_bits;
|
||||||
ZeroOutPage(PageTableEntry(virt));
|
ZeroOutPage(PageTableEntry(virt));
|
||||||
}
|
}
|
||||||
|
|
||||||
*PageTableEntry(virt) = PageAlign(phys) | PRESENT_BIT | READ_WRITE_BIT;
|
*PageTableEntry(virt) = PageAlign(phys) | access_bits;
|
||||||
ZeroOutPage(reinterpret_cast<uint64_t*>(virt));
|
ZeroOutPage(reinterpret_cast<uint64_t*>(virt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
.global jump_user_space
|
||||||
|
// rdi - entry point, rsi - user stack
|
||||||
|
jump_user_space:
|
||||||
|
cli
|
||||||
|
mov $0x23, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %es
|
||||||
|
mov %ax, %fs
|
||||||
|
mov %ax, %gs
|
||||||
|
|
||||||
|
pushq $0x23 # ss
|
||||||
|
pushq %rsi
|
||||||
|
pushf # Can we just push 0 for flags?
|
||||||
|
pushq $0x1B # cs
|
||||||
|
pushq %rdi
|
||||||
|
iretq
|
|
@ -1,12 +1,16 @@
|
||||||
#include "scheduler/thread.h"
|
#include "scheduler/thread.h"
|
||||||
|
|
||||||
|
#include "common/gdt.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "loader/elf_loader.h"
|
#include "loader/elf_loader.h"
|
||||||
|
#include "memory/paging_util.h"
|
||||||
#include "scheduler/process.h"
|
#include "scheduler/process.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
extern "C" void jump_user_space(uint64_t rip, uint64_t rsp);
|
||||||
|
|
||||||
extern "C" void thread_init() {
|
extern "C" void thread_init() {
|
||||||
asm("sti");
|
asm("sti");
|
||||||
sched::CurrentThread().Init();
|
sched::CurrentThread().Init();
|
||||||
|
@ -36,9 +40,10 @@ Thread::Thread(Process* proc, uint64_t tid, uint64_t elf_ptr)
|
||||||
uint64_t Thread::pid() { return process_->id(); }
|
uint64_t Thread::pid() { return process_->id(); }
|
||||||
|
|
||||||
void Thread::Init() {
|
void Thread::Init() {
|
||||||
LoadElfProgram(elf_ptr_, 0);
|
dbgln("[%u.%u]", pid(), id_);
|
||||||
while (true) {
|
uint64_t rip = LoadElfProgram(elf_ptr_, 0);
|
||||||
dbgln("[%u.%u]", pid(), id_);
|
uint64_t rsp = 0x80000000;
|
||||||
sched::Yield();
|
EnsureResident(rsp - 1, 1);
|
||||||
}
|
SetRsp0(rsp0_start_);
|
||||||
|
jump_user_space(rip, rsp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
|
#include "include/zcall.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
|
|
||||||
#define EFER 0xC0000080
|
#define EFER 0xC0000080
|
||||||
|
@ -53,5 +54,12 @@ void InitSyscall() {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void SyscallHandler(uint64_t call_id, char* message) {
|
extern "C" void SyscallHandler(uint64_t call_id, char* message) {
|
||||||
dbgln(message);
|
Thread& thread = sched::CurrentThread();
|
||||||
|
switch (call_id) {
|
||||||
|
case Z_DEBUG_PRINT:
|
||||||
|
dbgln("[%u.%u] %s", thread.pid(), thread.tid(), message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
panic("Unhandled syscall number: %u", call_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue