...
This commit is contained in:
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -15,6 +15,9 @@
|
|||||||
"unordered_set": "c",
|
"unordered_set": "c",
|
||||||
"vector": "c",
|
"vector": "c",
|
||||||
"any": "c",
|
"any": "c",
|
||||||
"system_error": "c"
|
"system_error": "c",
|
||||||
|
"std.h": "c",
|
||||||
|
"panic.h": "c",
|
||||||
|
"pmm.h": "c"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "mem.h"
|
#include "mem/pmm.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "interrupts/idt.h"
|
#include "interrupts/idt.h"
|
||||||
#include "interrupts/irq.h"
|
#include "interrupts/irq.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "mem.h"
|
#include "mem/pmm.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ void x86_64_main(u32 magic, multiboot_info_t* info)
|
|||||||
remap_pic();
|
remap_pic();
|
||||||
enable_interrupts();
|
enable_interrupts();
|
||||||
|
|
||||||
mem_init(info);
|
pmm_init(info);
|
||||||
|
|
||||||
kernel_main();
|
kernel_main();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "std.h"
|
|
||||||
#include "x86_64/multiboot.h"
|
|
||||||
|
|
||||||
#define KiB(count) ((u64)count * 1024)
|
|
||||||
#define MiB(count) (KiB((u64)count) * 1024)
|
|
||||||
#define GiB(count) (MiB((u64)count) * 1024)
|
|
||||||
#define TiB(count) (GiB((u64)count) * 1024)
|
|
||||||
|
|
||||||
// Fixed at 2mb for now
|
|
||||||
#define PAGE_SIZE MiB(2)
|
|
||||||
// Defines the theoretical max memory the kernel can allocate, not the actual memory of the system
|
|
||||||
// The value must be a multible of 8
|
|
||||||
#define MAX_MEMORY GiB(64)
|
|
||||||
|
|
||||||
void mem_init(multiboot_info_t* info);
|
|
||||||
|
|
||||||
u64 mem_alloc_2mb_physical_page();
|
|
||||||
void mem_free_2mb_physical_page(u64 address);
|
|
||||||
|
|
||||||
void mem_map_2mb_page(u64 virtual_address, u64 physical_address);
|
|
||||||
u64 mem_unmap_2mb_page(u64 virtual_address);
|
|
||||||
|
|
||||||
void* mem_alloc_2mb(u64 virtual_address);
|
|
||||||
void mem_free_2mb(u64 virtual_address);
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "mem.h"
|
#include "pmm.h"
|
||||||
#include "x86_64/panic.h"
|
#include "x86_64/panic.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -25,20 +25,7 @@ static u8 page_bitmap[BITMAP_SIZE];
|
|||||||
static u64 total_pages = 0;
|
static u64 total_pages = 0;
|
||||||
static u64 free_pages = 0;
|
static u64 free_pages = 0;
|
||||||
|
|
||||||
#define PML4_INDEX(addr) (((addr) >> 39) & 0x1FF)
|
void pmm_init(multiboot_info_t* info)
|
||||||
#define PDPT_INDEX(addr) (((addr) >> 30) & 0x1FF)
|
|
||||||
#define PD_INDEX(addr) (((addr) >> 21) & 0x1FF)
|
|
||||||
|
|
||||||
#define PTE_MASK 0x000FFFFFFFFFF000ULL
|
|
||||||
|
|
||||||
#define PTE_PRESENT (1ULL << 0)
|
|
||||||
#define PTE_WRITABLE (1ULL << 1)
|
|
||||||
#define PTE_USER (1ULL << 2)
|
|
||||||
#define PTE_PS (1ULL << 7)
|
|
||||||
|
|
||||||
extern u64 pml4[];
|
|
||||||
|
|
||||||
void mem_init(multiboot_info_t* info)
|
|
||||||
{
|
{
|
||||||
if (!(info->flags & (1 << 6)))
|
if (!(info->flags & (1 << 6)))
|
||||||
{
|
{
|
||||||
@@ -115,7 +102,7 @@ void mem_init(multiboot_info_t* info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 mem_alloc_2mb_physical_page()
|
u64 pmm_alloc()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < BITMAP_SIZE; i++)
|
for (size_t i = 0; i < BITMAP_SIZE; i++)
|
||||||
{
|
{
|
||||||
@@ -136,7 +123,7 @@ u64 mem_alloc_2mb_physical_page()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_free_2mb_physical_page(u64 address)
|
void pmm_free(u64 address)
|
||||||
{
|
{
|
||||||
u64 page = address / PAGE_SIZE;
|
u64 page = address / PAGE_SIZE;
|
||||||
if (page < BITMAP_SIZE * 8)
|
if (page < BITMAP_SIZE * 8)
|
||||||
@@ -147,103 +134,4 @@ void mem_free_2mb_physical_page(u64 address)
|
|||||||
free_pages++;
|
free_pages++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static u64 create_pte(u64 physical_address)
|
|
||||||
{
|
|
||||||
if (physical_address & (PAGE_SIZE - 1))
|
|
||||||
{
|
|
||||||
printf("Physical address not page aligned (0x%x)\n", physical_address);
|
|
||||||
panic("Failed to create PTE");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (physical_address & PTE_MASK) | PTE_PRESENT | PTE_WRITABLE | PTE_PS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mem_map_2mb_page(u64 virtual_address, u64 physical_address)
|
|
||||||
{
|
|
||||||
u64 pml4_idx = PML4_INDEX(virtual_address);
|
|
||||||
u64 pdpt_idx = PDPT_INDEX(virtual_address);
|
|
||||||
u64 pd_idx = PD_INDEX(virtual_address);
|
|
||||||
|
|
||||||
u64 pdpt = pml4[pml4_idx];
|
|
||||||
if (!(pdpt & PTE_PRESENT))
|
|
||||||
{
|
|
||||||
// todo(nub31): Dynamically create a pdpt table
|
|
||||||
printf("PDPT not present at PML4 index %u\n", pml4_idx);
|
|
||||||
panic("Failed to map virtual to physical page");
|
|
||||||
}
|
|
||||||
|
|
||||||
u64* pdpt_phys = (u64*)(pdpt & PTE_MASK);
|
|
||||||
u64 pd = pdpt_phys[pdpt_idx];
|
|
||||||
if (!(pd & PTE_PRESENT))
|
|
||||||
{
|
|
||||||
// todo(nub31): Dynamically create a pd table
|
|
||||||
printf("PD not present at PDPT index %u\n", pdpt_idx);
|
|
||||||
panic("Failed to map virtual to physical page");
|
|
||||||
}
|
|
||||||
|
|
||||||
u64* pd_phys = (u64*)(pd & PTE_MASK);
|
|
||||||
u64 entry = pd_phys[pd_idx];
|
|
||||||
|
|
||||||
if (entry & PTE_PRESENT)
|
|
||||||
{
|
|
||||||
printf("Virtual address 0x%x is already mapped\n", virtual_address);
|
|
||||||
panic("Failed to map virtual to physical page");
|
|
||||||
}
|
|
||||||
|
|
||||||
pd_phys[pd_idx] = create_pte(physical_address);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 mem_unmap_2mb_page(u64 virtual_address)
|
|
||||||
{
|
|
||||||
u64 pml4_idx = PML4_INDEX(virtual_address);
|
|
||||||
u64 pdpt_idx = PDPT_INDEX(virtual_address);
|
|
||||||
u64 pd_idx = PD_INDEX(virtual_address);
|
|
||||||
|
|
||||||
u64 pdpt_entry = pml4[pml4_idx];
|
|
||||||
if (!(pdpt_entry & PTE_PRESENT))
|
|
||||||
{
|
|
||||||
printf("PDPT not present at PML4 index %llu\n", pml4_idx);
|
|
||||||
panic("Failed to unmap virtual address");
|
|
||||||
}
|
|
||||||
|
|
||||||
u64* pdpt_phys = (u64*)(pdpt_entry & PTE_MASK);
|
|
||||||
u64 pd_entry = pdpt_phys[pdpt_idx];
|
|
||||||
if (!(pd_entry & PTE_PRESENT))
|
|
||||||
{
|
|
||||||
printf("PD not present at PDPT index %llu\n", pdpt_idx);
|
|
||||||
panic("Failed to unmap virtual address");
|
|
||||||
}
|
|
||||||
|
|
||||||
u64* pd_phys = (u64*)(pd_entry & PTE_MASK);
|
|
||||||
if (!(pd_phys[pd_idx] & PTE_PRESENT))
|
|
||||||
{
|
|
||||||
printf("Virtual address 0x%llx is not mapped\n", virtual_address);
|
|
||||||
panic("Failed to unmap virtual address");
|
|
||||||
}
|
|
||||||
u64 phys = pd_phys[pd_idx] & PTE_MASK;
|
|
||||||
pd_phys[pd_idx] = 0;
|
|
||||||
|
|
||||||
__asm__ volatile("invlpg (%0)" : : "r"(virtual_address) : "memory");
|
|
||||||
|
|
||||||
return phys;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* mem_alloc_2mb(u64 virtual_address)
|
|
||||||
{
|
|
||||||
u64 phys = mem_alloc_2mb_physical_page();
|
|
||||||
if (!phys)
|
|
||||||
{
|
|
||||||
panic("Out of physical memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
mem_map_2mb_page(virtual_address, phys);
|
|
||||||
return (void*)virtual_address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mem_free_2mb(u64 virtual_address)
|
|
||||||
{
|
|
||||||
u64 phys = mem_unmap_2mb_page(virtual_address);
|
|
||||||
mem_free_2mb_physical_page(phys);
|
|
||||||
}
|
}
|
||||||
19
src/arch/x86_64/mem/pmm.h
Normal file
19
src/arch/x86_64/mem/pmm.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "std.h"
|
||||||
|
#include "x86_64/multiboot.h"
|
||||||
|
|
||||||
|
// Fixed at 2mb for now
|
||||||
|
#define PAGE_SIZE MiB(2)
|
||||||
|
|
||||||
|
// Defines the theoretical max memory the kernel can allocate, not the actual memory of the system
|
||||||
|
// The value must be a multible of 8
|
||||||
|
#define MAX_MEMORY GiB(64)
|
||||||
|
|
||||||
|
void pmm_init(multiboot_info_t* info);
|
||||||
|
|
||||||
|
// Allocate a 2mb physical page
|
||||||
|
u64 pmm_alloc();
|
||||||
|
|
||||||
|
// Free the 2mb physical page at the specified address
|
||||||
|
void pmm_free(u64 address);
|
||||||
115
src/arch/x86_64/mem/vmm.c
Normal file
115
src/arch/x86_64/mem/vmm.c
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#include "vmm.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "x86_64/panic.h"
|
||||||
|
|
||||||
|
#define PML4_INDEX(addr) (((addr) >> 39) & 0x1FF)
|
||||||
|
#define PDPT_INDEX(addr) (((addr) >> 30) & 0x1FF)
|
||||||
|
#define PD_INDEX(addr) (((addr) >> 21) & 0x1FF)
|
||||||
|
|
||||||
|
#define PTE_MASK 0x000FFFFFFFFFF000ULL
|
||||||
|
|
||||||
|
#define PTE_PRESENT (1ULL << 0)
|
||||||
|
#define PTE_WRITABLE (1ULL << 1)
|
||||||
|
#define PTE_USER (1ULL << 2)
|
||||||
|
#define PTE_PS (1ULL << 7)
|
||||||
|
|
||||||
|
extern u64 pml4[];
|
||||||
|
|
||||||
|
static u64 create_pte(u64 physical_address)
|
||||||
|
{
|
||||||
|
if (physical_address & (PAGE_SIZE - 1))
|
||||||
|
{
|
||||||
|
printf("Physical address not page aligned (0x%x)\n", physical_address);
|
||||||
|
panic("Failed to create PTE");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (physical_address & PTE_MASK) | PTE_PRESENT | PTE_WRITABLE | PTE_PS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vmm_map(u64 virtual_address, u64 physical_address)
|
||||||
|
{
|
||||||
|
u64 pml4_idx = PML4_INDEX(virtual_address);
|
||||||
|
u64 pdpt_idx = PDPT_INDEX(virtual_address);
|
||||||
|
u64 pd_idx = PD_INDEX(virtual_address);
|
||||||
|
|
||||||
|
u64 pdpt = pml4[pml4_idx];
|
||||||
|
if (!(pdpt & PTE_PRESENT))
|
||||||
|
{
|
||||||
|
// todo(nub31): Dynamically create a pdpt table
|
||||||
|
printf("PDPT not present at PML4 index %u\n", pml4_idx);
|
||||||
|
panic("Failed to map virtual to physical page");
|
||||||
|
}
|
||||||
|
|
||||||
|
u64* pdpt_phys = (u64*)(pdpt & PTE_MASK);
|
||||||
|
u64 pd = pdpt_phys[pdpt_idx];
|
||||||
|
if (!(pd & PTE_PRESENT))
|
||||||
|
{
|
||||||
|
// todo(nub31): Dynamically create a pd table
|
||||||
|
printf("PD not present at PDPT index %u\n", pdpt_idx);
|
||||||
|
panic("Failed to map virtual to physical page");
|
||||||
|
}
|
||||||
|
|
||||||
|
u64* pd_phys = (u64*)(pd & PTE_MASK);
|
||||||
|
u64 entry = pd_phys[pd_idx];
|
||||||
|
|
||||||
|
if (entry & PTE_PRESENT)
|
||||||
|
{
|
||||||
|
printf("Virtual address 0x%x is already mapped\n", virtual_address);
|
||||||
|
panic("Failed to map virtual to physical page");
|
||||||
|
}
|
||||||
|
|
||||||
|
pd_phys[pd_idx] = create_pte(physical_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 vmm_unmap(u64 virtual_address)
|
||||||
|
{
|
||||||
|
u64 pml4_idx = PML4_INDEX(virtual_address);
|
||||||
|
u64 pdpt_idx = PDPT_INDEX(virtual_address);
|
||||||
|
u64 pd_idx = PD_INDEX(virtual_address);
|
||||||
|
|
||||||
|
u64 pdpt_entry = pml4[pml4_idx];
|
||||||
|
if (!(pdpt_entry & PTE_PRESENT))
|
||||||
|
{
|
||||||
|
printf("PDPT not present at PML4 index %llu\n", pml4_idx);
|
||||||
|
panic("Failed to unmap virtual address");
|
||||||
|
}
|
||||||
|
|
||||||
|
u64* pdpt_phys = (u64*)(pdpt_entry & PTE_MASK);
|
||||||
|
u64 pd_entry = pdpt_phys[pdpt_idx];
|
||||||
|
if (!(pd_entry & PTE_PRESENT))
|
||||||
|
{
|
||||||
|
printf("PD not present at PDPT index %llu\n", pdpt_idx);
|
||||||
|
panic("Failed to unmap virtual address");
|
||||||
|
}
|
||||||
|
|
||||||
|
u64* pd_phys = (u64*)(pd_entry & PTE_MASK);
|
||||||
|
if (!(pd_phys[pd_idx] & PTE_PRESENT))
|
||||||
|
{
|
||||||
|
printf("Virtual address 0x%llx is not mapped\n", virtual_address);
|
||||||
|
panic("Failed to unmap virtual address");
|
||||||
|
}
|
||||||
|
u64 phys = pd_phys[pd_idx] & PTE_MASK;
|
||||||
|
pd_phys[pd_idx] = 0;
|
||||||
|
|
||||||
|
__asm__ volatile("invlpg (%0)" : : "r"(virtual_address) : "memory");
|
||||||
|
|
||||||
|
return phys;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* vmm_alloc(u64 virtual_address)
|
||||||
|
{
|
||||||
|
u64 phys = pmm_alloc();
|
||||||
|
if (!phys)
|
||||||
|
{
|
||||||
|
panic("Out of physical memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
vmm_map(virtual_address, phys);
|
||||||
|
return (void*)virtual_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vmm_free(u64 virtual_address)
|
||||||
|
{
|
||||||
|
u64 phys = vmm_unmap(virtual_address);
|
||||||
|
pmm_free(phys);
|
||||||
|
}
|
||||||
9
src/arch/x86_64/mem/vmm.h
Normal file
9
src/arch/x86_64/mem/vmm.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "std.h"
|
||||||
|
|
||||||
|
void vmm_map(u64 virtual_address, u64 physical_address);
|
||||||
|
u64 vmm_unmap(u64 virtual_address);
|
||||||
|
|
||||||
|
void* vmm_alloc(u64 virtual_address);
|
||||||
|
void vmm_free(u64 virtual_address);
|
||||||
@@ -61,3 +61,8 @@ typedef signed long long i64;
|
|||||||
|
|
||||||
#define INTMAX_C(x) x##LL
|
#define INTMAX_C(x) x##LL
|
||||||
#define UINTMAX_C(x) x##ULL
|
#define UINTMAX_C(x) x##ULL
|
||||||
|
|
||||||
|
#define KiB(count) ((u64)count * 1024)
|
||||||
|
#define MiB(count) (KiB((u64)count) * 1024)
|
||||||
|
#define GiB(count) (MiB((u64)count) * 1024)
|
||||||
|
#define TiB(count) (GiB((u64)count) * 1024)
|
||||||
Reference in New Issue
Block a user