paging: wip
This commit is contained in:
parent
2b3a27a398
commit
8c3f2d0de8
3 changed files with 167 additions and 0 deletions
|
@ -23,6 +23,8 @@ SECTIONS
|
|||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
text_start_addr = .;
|
||||
|
||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||
.limine_requests : {
|
||||
KEEP(*(.limine_requests_start))
|
||||
|
@ -37,9 +39,13 @@ SECTIONS
|
|||
*(.text .text.*)
|
||||
} :text
|
||||
|
||||
text_end_addr = .;
|
||||
|
||||
/* Move to the next memory page for .rodata */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
rodata_start_addr = .;
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
@ -50,9 +56,13 @@ SECTIONS
|
|||
*(.note.gnu.build-id)
|
||||
} :rodata
|
||||
|
||||
rodata_end_addr = .;
|
||||
|
||||
/* Move to the next memory page for .data */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
data_start_addr = .;
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
@ -66,6 +76,8 @@ SECTIONS
|
|||
*(COMMON)
|
||||
} :data
|
||||
|
||||
data_end_addr = .;
|
||||
|
||||
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
|
|
129
src/kernel/hal/x86_64/paging.c
Normal file
129
src/kernel/hal/x86_64/paging.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
#include <hal>
|
||||
#include <helpers/mem.h>
|
||||
#include <logger>
|
||||
#include <pmm>
|
||||
#include <string.h>
|
||||
|
||||
#include "mod.h"
|
||||
#include "paging.h"
|
||||
#include "pmm/mod.h"
|
||||
|
||||
static uint64_t* kernel_page_table = NULL;
|
||||
static size_t mapping_page_size = mib$(2);
|
||||
|
||||
static int64_t transform_flags(uint8_t flags) {
|
||||
int64_t ret = PAGE_NO_EXECUTE | PAGE_PRESENT;
|
||||
|
||||
if (flags & HAL_MAP_READ) {
|
||||
}
|
||||
|
||||
if (flags & HAL_MAP_NONE) {
|
||||
ret &= ~PAGE_PRESENT;
|
||||
}
|
||||
|
||||
if (flags & HAL_MAP_WRITE) {
|
||||
ret |= PAGE_WRITABLE;
|
||||
}
|
||||
|
||||
if (flags & HAL_MAP_EXEC) {
|
||||
ret &= ~PAGE_NO_EXECUTE;
|
||||
}
|
||||
|
||||
if (flags & HAL_MAP_USER) {
|
||||
ret |= PAGE_USER;
|
||||
}
|
||||
|
||||
if (flags & HAL_MAP_HUGE) {
|
||||
ret |= PAGE_HUGE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void* paging_get_pml_alloc(uint64_t* table, size_t index, bool alloc) {
|
||||
if (table[index] & PAGE_PRESENT) {
|
||||
return hal_mmap_l2h(PAGE_GET_PHYS(table[index]));
|
||||
} else if (alloc) {
|
||||
Allocator pmm = pmm_allocator();
|
||||
void* ptr = pmm.alloc(&pmm, page_size());
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(ptr, 0, page_size());
|
||||
table[index] = (uint64_t)hal_mmap_h2l((uint64_t)ptr) | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static HalMappingError map_page(uint64_t* table, uintptr_t vaddr, uintptr_t paddr, uint32_t flag) {
|
||||
if (!aligned$(vaddr, page_size())) {
|
||||
return HAL_MAP_VIRT_UNALIGNED;
|
||||
}
|
||||
|
||||
if (!aligned$(paddr, page_size())) {
|
||||
return HAL_MAP_PHYS_UNALIGNED;
|
||||
}
|
||||
|
||||
size_t pml1_entry = PMLX_GET_INDEX(vaddr, 0);
|
||||
size_t pml2_entry = PMLX_GET_INDEX(vaddr, 1);
|
||||
size_t pml3_entry = PMLX_GET_INDEX(vaddr, 2);
|
||||
size_t pml4_entry = PMLX_GET_INDEX(vaddr, 3);
|
||||
|
||||
uintptr_t* pml3 = paging_get_pml_alloc(table, pml4_entry, true);
|
||||
if (pml3 == NULL) {
|
||||
return HAL_MAP_COULDNT_ALLOCATE;
|
||||
}
|
||||
|
||||
if (mapping_page_size == gib$(1) && flag & PAGE_HUGE) {
|
||||
pml3[pml3_entry] = paddr | flag;
|
||||
return HAL_MAP_OK;
|
||||
}
|
||||
|
||||
uintptr_t* pml2 = paging_get_pml_alloc(pml3, pml3_entry, true);
|
||||
if (pml3 == NULL) {
|
||||
return HAL_MAP_COULDNT_ALLOCATE;
|
||||
}
|
||||
|
||||
if (flag & PAGE_HUGE) {
|
||||
pml2[pml2_entry] = paddr | flag;
|
||||
return HAL_MAP_OK;
|
||||
}
|
||||
|
||||
uintptr_t* pml1 = paging_get_pml_alloc(pml2, pml2_entry, true);
|
||||
if (pml1 == NULL) {
|
||||
return HAL_MAP_COULDNT_ALLOCATE;
|
||||
}
|
||||
|
||||
pml1[pml1_entry] = paddr | flag;
|
||||
return HAL_MAP_OK;
|
||||
}
|
||||
|
||||
HalMappingError hal_map_page(HalPage page, uintptr_t virt, uintptr_t phys, size_t length, uint8_t flags) {
|
||||
size_t len = align_up$(length, page_size());
|
||||
uintptr_t aligned_virt = align_down$(virt, page_size());
|
||||
uintptr_t aligned_phys = align_down$(phys, page_size());
|
||||
uint32_t arch_flags = transform_flags(flags);
|
||||
|
||||
for (size_t i = 0; i < len; i += page_size()) {
|
||||
HalMappingError err = map_page(page.ptr, aligned_virt + i, aligned_phys + i, arch_flags);
|
||||
|
||||
if (err != HAL_MAP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_MAP_OK;
|
||||
}
|
||||
|
||||
void paging_init(void) {
|
||||
Allocator pmm = pmm_allocator();
|
||||
kernel_page_table = pmm.alloc(&pmm, page_size());
|
||||
|
||||
if (kernel_page_table == NULL) [[clang::unlikely]] {
|
||||
panic$("Couldn't allocate kernel page table");
|
||||
}
|
||||
|
||||
memset(kernel_page_table, 0, page_size());
|
||||
}
|
26
src/kernel/hal/x86_64/paging.h
Normal file
26
src/kernel/hal/x86_64/paging.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PAGE_GET_PHYS(x) (x & 0x000ffffffffff000)
|
||||
#define PAGE_GET_FLAGS(x) (x & 0xfff)
|
||||
#define PMLX_GET_INDEX(addr, level) (((uint64_t)addr & ((uint64_t)0x1ff << (12 + level * 9))) >> (12 + level * 9))
|
||||
|
||||
enum pml_fields : uint64_t {
|
||||
PAGE_PRESENT = 1 << 0,
|
||||
PAGE_WRITABLE = 1 << 1,
|
||||
PAGE_USER = 1 << 2,
|
||||
PAGE_WRITE_THROUGH = 1 << 3,
|
||||
PAGE_NO_CACHE = 1 << 4,
|
||||
PAGE_ACCESSED = 1 << 5,
|
||||
PAGE_DIRTY = 1 << 6,
|
||||
PAGE_HUGE = 1 << 7,
|
||||
PAGE_GLOBAL = 1 << 8,
|
||||
PAGE_NO_EXECUTE = 1 << 63,
|
||||
};
|
||||
|
||||
struct [[gnu::packed]] _hal_page {
|
||||
uint64_t* ptr;
|
||||
};
|
||||
|
||||
void paging_init(void);
|
Loading…
Add table
Reference in a new issue