Compare commits

..

No commits in common. "81f56083c5fc9c946d36b731d379589e633285f1" and "9b3c7816a3d9aef6148af4b126b71f96d3a3f1ca" have entirely different histories.

9 changed files with 49 additions and 106 deletions

View File

@ -1,10 +1,37 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
extern "C" uint64_t asm_get_rflags();
namespace Utilities namespace Utilities
{ {
inline uint64_t get_blocks_from_size(uint64_t blocksize, uint64_t size) inline uint64_t get_blocks_from_size(uint64_t blocksize, uint64_t size)
{ {
return (size + (blocksize - 1)) / blocksize; return (size + (blocksize - 1)) / blocksize;
} }
inline uint64_t get_rflags()
{
return asm_get_rflags();
}
inline uint64_t get_top_of_stack(uint64_t bottom, uint64_t stack_pages)
{
return bottom + (stack_pages * PAGE_SIZE) - sizeof(uintptr_t);
}
inline uint64_t round_down_to_nearest_page(uint64_t addr)
{
return addr - (addr % PAGE_SIZE);
}
inline uint64_t round_up_to_nearest_page(uint64_t addr)
{
if (addr % PAGE_SIZE) return addr + (PAGE_SIZE - (addr % PAGE_SIZE));
return addr;
}
} }

View File

@ -1,24 +0,0 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
inline uintptr_t get_top_of_stack(uintptr_t bottom, size_t stack_pages)
{
return bottom + (stack_pages * PAGE_SIZE) - sizeof(uintptr_t);
}
inline uintptr_t round_down_to_nearest_page(uintptr_t addr)
{
return addr - (addr % PAGE_SIZE);
}
inline uintptr_t round_up_to_nearest_page(uintptr_t addr)
{
if (addr % PAGE_SIZE) return addr + (PAGE_SIZE - (addr % PAGE_SIZE));
return addr;
}

View File

@ -1,52 +0,0 @@
#pragma once
#include <stdint.h>
extern "C" uintptr_t asm_get_rflags();
extern "C" void asm_set_rflags(uintptr_t);
inline uintptr_t read_rflags()
{
return asm_get_rflags();
}
inline void write_rflags(uintptr_t value)
{
asm_set_rflags(value);
}
inline uintptr_t read_cr0()
{
uintptr_t value;
asm volatile("mov %%cr0, %0" : "=r"(value));
return value;
}
inline uintptr_t read_cr3()
{
uintptr_t value;
asm volatile("mov %%cr3, %0" : "=r"(value));
return value;
}
inline uintptr_t read_cr4()
{
uintptr_t value;
asm volatile("mov %%cr4, %0" : "=r"(value));
return value;
}
template <typename T> inline void write_cr0(T value)
{
asm volatile("mov %0, %%cr0" : : "r"(value));
}
template <typename T> inline void write_cr3(T value)
{
asm volatile("mov %0, %%cr3" : : "r"(value));
}
template <typename T> inline void write_cr4(T value)
{
asm volatile("mov %0, %%cr4" : : "r"(value));
}

View File

@ -1,6 +1,6 @@
#include "interrupts/Interrupts.h" #include "interrupts/Interrupts.h"
#include "misc/utils.h"
#include "trace/StackTracer.h" #include "trace/StackTracer.h"
#include "utils/Registers.h"
void Interrupts::disable() void Interrupts::disable()
{ {
@ -29,7 +29,7 @@ void Interrupts::return_from_handler(Context* context)
bool Interrupts::are_enabled() bool Interrupts::are_enabled()
{ {
return (read_rflags() & 0x200) > 0; return (Utilities::get_rflags() & 0x200) > 0;
} }
static bool saved_interrupt_state; static bool saved_interrupt_state;

View File

@ -32,9 +32,3 @@ asm_get_rflags:
pushfq pushfq
pop rax pop rax
ret ret
global asm_set_rflags
asm_set_rflags:
push rdi
popfq
ret

View File

@ -87,6 +87,10 @@ extern "C" void _start()
PIC::enable_master(0b11111100); // enable keyboard and PIT PIC::enable_master(0b11111100); // enable keyboard and PIT
PIC::enable_slave(0b11111111); PIC::enable_slave(0b11111111);
kinfoln("Prepared PIC");
Interrupts::enable(); // Task switching commences here
kinfoln("Interrupts enabled"); kinfoln("Interrupts enabled");
PCI::scan([](PCI::Device& dev) { PCI::scan([](PCI::Device& dev) {

View File

@ -6,8 +6,6 @@
#include "memory/PMM.h" #include "memory/PMM.h"
#include "misc/utils.h" #include "misc/utils.h"
#include "std/string.h" #include "std/string.h"
#include "utils/Addresses.h"
#include "utils/Registers.h"
static PageTable* kernel_pml4; static PageTable* kernel_pml4;
static PageTable* current_pml4; static PageTable* current_pml4;
@ -57,13 +55,13 @@ bool VMM::is_using_kernel_address_space()
void VMM::init() void VMM::init()
{ {
kernel_pml4 = (PageTable*)read_cr3(); asm volatile("mov %%cr3, %0" : "=r"(current_pml4));
current_pml4 = kernel_pml4; kernel_pml4 = current_pml4;
} }
void VMM::unmap(uint64_t vaddr) void VMM::unmap(uint64_t vaddr)
{ {
vaddr = round_down_to_nearest_page(vaddr); vaddr = Utilities::round_down_to_nearest_page(vaddr);
PageDirectoryEntry* pde = find_pde(current_pml4, vaddr); PageDirectoryEntry* pde = find_pde(current_pml4, vaddr);
if (!pde) return; // Already unmapped if (!pde) return; // Already unmapped
@ -90,7 +88,7 @@ void VMM::remap(uint64_t vaddr, int flags)
uint64_t VMM::get_physical(uint64_t vaddr) uint64_t VMM::get_physical(uint64_t vaddr)
{ {
PageDirectoryEntry* pde = find_pde(current_pml4, round_down_to_nearest_page(vaddr)); PageDirectoryEntry* pde = find_pde(current_pml4, Utilities::round_down_to_nearest_page(vaddr));
if (!pde) return UINT64_MAX; // Not mapped if (!pde) return UINT64_MAX; // Not mapped
return pde->get_address() | (vaddr % PAGE_SIZE); return pde->get_address() | (vaddr % PAGE_SIZE);
@ -98,7 +96,7 @@ uint64_t VMM::get_physical(uint64_t vaddr)
uint64_t VMM::get_flags(uint64_t vaddr) uint64_t VMM::get_flags(uint64_t vaddr)
{ {
PageDirectoryEntry* pde = find_pde(current_pml4, round_down_to_nearest_page(vaddr)); PageDirectoryEntry* pde = find_pde(current_pml4, Utilities::round_down_to_nearest_page(vaddr));
if (!pde) return 0; // Not mapped if (!pde) return 0; // Not mapped
uint64_t flags = 0; uint64_t flags = 0;
@ -109,7 +107,7 @@ uint64_t VMM::get_flags(uint64_t vaddr)
void VMM::map(uint64_t vaddr, uint64_t paddr, int flags) void VMM::map(uint64_t vaddr, uint64_t paddr, int flags)
{ {
vaddr = round_down_to_nearest_page(vaddr); vaddr = Utilities::round_down_to_nearest_page(vaddr);
PageDirectoryEntry* pde = find_pde(current_pml4, vaddr); PageDirectoryEntry* pde = find_pde(current_pml4, vaddr);
bool will_flush_tlb = true; bool will_flush_tlb = true;
if (!pde) if (!pde)
@ -123,7 +121,7 @@ void VMM::map(uint64_t vaddr, uint64_t paddr, int flags)
pde = create_pde_if_not_exists(current_pml4, vaddr); pde = create_pde_if_not_exists(current_pml4, vaddr);
} }
pde->set_address(round_down_to_nearest_page(paddr)); pde->set_address(Utilities::round_down_to_nearest_page(paddr));
if (flags & User) propagate_user(current_pml4, vaddr); if (flags & User) propagate_user(current_pml4, vaddr);
else else
pde->user = false; pde->user = false;

View File

@ -13,7 +13,6 @@
#include "std/stdlib.h" #include "std/stdlib.h"
#include "std/string.h" #include "std/string.h"
#include "sys/elf/ELF.h" #include "sys/elf/ELF.h"
#include "utils/Addresses.h"
static const char* format_permissions(uint32_t flags) static const char* format_permissions(uint32_t flags)
{ {
@ -91,8 +90,8 @@ ELFImage* ELFLoader::load_elf_from_vfs(VFS::Node* node)
ASSERT(phdr.p_vaddr); ASSERT(phdr.p_vaddr);
uint64_t pages = Utilities::get_blocks_from_size(PAGE_SIZE, (phdr.p_vaddr % PAGE_SIZE) + phdr.p_memsz); uint64_t pages = Utilities::get_blocks_from_size(PAGE_SIZE, (phdr.p_vaddr % PAGE_SIZE) + phdr.p_memsz);
void* buffer = (void*)((uint64_t)MemoryManager::get_pages_at(round_down_to_nearest_page(phdr.p_vaddr), void* buffer = (void*)((uint64_t)MemoryManager::get_pages_at(
pages, MAP_READ_WRITE) + Utilities::round_down_to_nearest_page(phdr.p_vaddr), pages, MAP_READ_WRITE) +
(phdr.p_vaddr % PAGE_SIZE)); (phdr.p_vaddr % PAGE_SIZE));
VMM::apply_address_space(); VMM::apply_address_space();
@ -194,7 +193,7 @@ void ELFLoader::release_elf_image(ELFImage* image)
{ {
ELFSection& section = image->sections[i]; ELFSection& section = image->sections[i];
kdbgln("Freeing up section %lx, was using %ld pages", section.base, section.pages); kdbgln("Freeing up section %lx, was using %ld pages", section.base, section.pages);
MemoryManager::release_pages((void*)round_down_to_nearest_page(section.base), section.pages); MemoryManager::release_pages((void*)Utilities::round_down_to_nearest_page(section.base), section.pages);
} }
kfree(image); kfree(image);
} }

View File

@ -14,8 +14,6 @@
#include "sys/elf/ELFLoader.h" #include "sys/elf/ELFLoader.h"
#include "thread/PIT.h" #include "thread/PIT.h"
#include "thread/Task.h" #include "thread/Task.h"
#include "utils/Addresses.h"
#include "utils/Registers.h"
static uint64_t task_num = 0; static uint64_t task_num = 0;
@ -36,7 +34,7 @@ void Scheduler::init()
memset(&idle_task, 0, sizeof(Task)); memset(&idle_task, 0, sizeof(Task));
idle_task.id = free_tid++; idle_task.id = free_tid++;
idle_task.regs.rip = (uint64_t)idle_task_function; idle_task.regs.rip = (uint64_t)idle_task_function;
idle_task.regs.rsp = get_top_of_stack((uint64_t)MemoryManager::get_page(), 1); idle_task.regs.rsp = Utilities::get_top_of_stack((uint64_t)MemoryManager::get_page(), 1);
idle_task.regs.cs = 0x08; idle_task.regs.cs = 0x08;
idle_task.regs.ss = 0x10; idle_task.regs.ss = 0x10;
idle_task.regs.rflags = (1 << 21) | (1 << 9); idle_task.regs.rflags = (1 << 21) | (1 << 9);
@ -57,7 +55,6 @@ void Scheduler::init()
// the other registers will be saved next task switch // the other registers will be saved next task switch
frequency = 1000 / PIT::frequency(); frequency = 1000 / PIT::frequency();
kdbgln("frequency: %ld", frequency);
} }
void Scheduler::add_kernel_task(void (*task)(void)) void Scheduler::add_kernel_task(void (*task)(void))
@ -69,11 +66,11 @@ void Scheduler::add_kernel_task(void (*task)(void))
new_task->regs.rip = (uint64_t)task; new_task->regs.rip = (uint64_t)task;
new_task->allocated_stack = new_task->allocated_stack =
(uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK); // 16 KB is enough for everyone, right? (uint64_t)MemoryManager::get_pages(TASK_PAGES_IN_STACK); // 16 KB is enough for everyone, right?
new_task->regs.rsp = get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK); new_task->regs.rsp = Utilities::get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK);
new_task->regs.cs = 0x08; new_task->regs.cs = 0x08;
new_task->regs.ss = 0x10; new_task->regs.ss = 0x10;
new_task->regs.ds = 0x10; new_task->regs.ds = 0x10;
new_task->regs.rflags = read_rflags() | 0x200; // enable interrupts new_task->regs.rflags = Utilities::get_rflags() | 0x200; // enable interrupts
new_task->task_sleep = 0; new_task->task_sleep = 0;
new_task->task_time = 0; new_task->task_time = 0;
new_task->cpu_time = 0; new_task->cpu_time = 0;
@ -98,7 +95,7 @@ void Scheduler::add_user_task(void* task)
new_task->regs.rip = (uint64_t)task; new_task->regs.rip = (uint64_t)task;
new_task->allocated_stack = (uint64_t)MemoryManager::get_pages( new_task->allocated_stack = (uint64_t)MemoryManager::get_pages(
TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right? TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right?
new_task->regs.rsp = get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK); new_task->regs.rsp = Utilities::get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK);
new_task->regs.cs = 0x18 | 0x03; new_task->regs.cs = 0x18 | 0x03;
new_task->regs.ss = 0x20 | 0x03; new_task->regs.ss = 0x20 | 0x03;
new_task->regs.ds = 0x20 | 0x03; new_task->regs.ds = 0x20 | 0x03;
@ -142,7 +139,7 @@ void Scheduler::load_user_task(const char* filename)
new_task->image = image; new_task->image = image;
new_task->allocated_stack = (uint64_t)MemoryManager::get_pages( new_task->allocated_stack = (uint64_t)MemoryManager::get_pages(
TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right? TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right?
new_task->regs.rsp = get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK); new_task->regs.rsp = Utilities::get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK);
new_task->regs.cs = 0x18 | 0x03; new_task->regs.cs = 0x18 | 0x03;
new_task->regs.ss = 0x20 | 0x03; new_task->regs.ss = 0x20 | 0x03;
new_task->regs.ds = 0x20 | 0x03; new_task->regs.ds = 0x20 | 0x03;
@ -169,7 +166,7 @@ void Scheduler::reset_task(Task* task, ELFImage* new_image)
task->state = task->Running; task->state = task->Running;
task->regs.rip = new_image->entry; task->regs.rip = new_image->entry;
task->image = new_image; task->image = new_image;
task->regs.rsp = get_top_of_stack(task->allocated_stack, TASK_PAGES_IN_STACK); task->regs.rsp = Utilities::get_top_of_stack(task->allocated_stack, TASK_PAGES_IN_STACK);
task->regs.cs = 0x18 | 0x03; task->regs.cs = 0x18 | 0x03;
task->regs.ss = 0x20 | 0x03; task->regs.ss = 0x20 | 0x03;
task->regs.ds = 0x20 | 0x03; task->regs.ds = 0x20 | 0x03;