Compare commits
No commits in common. "81f56083c5fc9c946d36b731d379589e633285f1" and "9b3c7816a3d9aef6148af4b126b71f96d3a3f1ca" have entirely different histories.
81f56083c5
...
9b3c7816a3
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
@ -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;
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
@ -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;
|
||||||
|
@ -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
|
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user