...
This commit is contained in:
@@ -11,14 +11,18 @@ typedef struct
|
||||
const arch_console_clear_t clear;
|
||||
} arch_console_api_t;
|
||||
|
||||
typedef u64 (*arch_mem_get_page_size_t)();
|
||||
typedef size_t (*arch_mem_get_page_size_t)();
|
||||
typedef void* (*arch_mem_alloc_t)(size_t page_count);
|
||||
typedef void (*arch_mem_free_t)(void* virtual_address, size_t page_count);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const arch_mem_get_page_size_t get_page_size;
|
||||
const arch_mem_alloc_t alloc;
|
||||
const arch_mem_free_t free;
|
||||
} arch_mem_api_t;
|
||||
|
||||
typedef void (*arch_panic_t)(const char*);
|
||||
typedef void (*arch_panic_t)(const char* msg);
|
||||
typedef void (*arch_enable_interrupts_t)();
|
||||
typedef void (*arch_disable_interrupts_t)();
|
||||
typedef void (*arch_halt_t)();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "arch.h"
|
||||
#include "console.h"
|
||||
#include "mem/pmm.h"
|
||||
#include "mem/vmm.h"
|
||||
#include "panic.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -34,13 +35,44 @@ static void arch_console_clear()
|
||||
console_clear();
|
||||
}
|
||||
|
||||
static u64 arch_get_page_size()
|
||||
static size_t arch_get_page_size()
|
||||
{
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
void* arch_alloc(size_t page_count)
|
||||
{
|
||||
u64 virtual_address = vmm_alloc_address(page_count);
|
||||
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
{
|
||||
u64 physical_address = pmm_alloc();
|
||||
if (!physical_address)
|
||||
{
|
||||
panic("Out of physical memory");
|
||||
}
|
||||
|
||||
vmm_map(physical_address, virtual_address + (i * PAGE_SIZE), PTE_PRESENT | PTE_WRITABLE);
|
||||
}
|
||||
|
||||
return (void*)virtual_address;
|
||||
}
|
||||
|
||||
void arch_free(void* virtual_address, size_t page_count)
|
||||
{
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
{
|
||||
u64 physical_address = vmm_unmap((u64)virtual_address + (i * PAGE_SIZE));
|
||||
pmm_free(physical_address);
|
||||
}
|
||||
|
||||
vmm_free_address((u64)virtual_address, page_count);
|
||||
}
|
||||
|
||||
static const arch_mem_api_t arch_mem_api = {
|
||||
.get_page_size = arch_get_page_size,
|
||||
.alloc = arch_alloc,
|
||||
.free = arch_free,
|
||||
};
|
||||
|
||||
static const arch_console_api_t arch_console_api = {
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
|
||||
#define PTE_MASK 0x000FFFFFFFFFF000ULL
|
||||
|
||||
#define PTE_PRESENT (1ULL << 0)
|
||||
#define PTE_WRITABLE (1ULL << 1)
|
||||
#define PTE_USER (1ULL << 2)
|
||||
#define PTE_PS (1ULL << 7)
|
||||
|
||||
#define BITMAP_PAGE_COUNT (ADDRES_SPACE_SIZE / PAGE_SIZE)
|
||||
#define BITMAP_SIZE (BITMAP_PAGE_COUNT / 8)
|
||||
|
||||
@@ -185,33 +180,4 @@ u64 vmm_unmap(u64 virtual_address)
|
||||
__asm__ volatile("invlpg (%0)" : : "r"(virtual_address) : "memory");
|
||||
|
||||
return physical_address;
|
||||
}
|
||||
|
||||
void* vmm_alloc(size_t page_count)
|
||||
{
|
||||
u64 virtual_address = vmm_alloc_address(page_count);
|
||||
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
{
|
||||
u64 physical_address = pmm_alloc();
|
||||
if (!physical_address)
|
||||
{
|
||||
panic("Out of physical memory");
|
||||
}
|
||||
|
||||
vmm_map(physical_address, virtual_address + (i * PAGE_SIZE), PTE_PRESENT | PTE_WRITABLE);
|
||||
}
|
||||
|
||||
return (void*)virtual_address;
|
||||
}
|
||||
|
||||
void vmm_free(void* virtual_address, size_t page_count)
|
||||
{
|
||||
for (size_t i = 0; i < page_count; i++)
|
||||
{
|
||||
u64 physical_address = vmm_unmap((u64)virtual_address + (i * PAGE_SIZE));
|
||||
pmm_free(physical_address);
|
||||
}
|
||||
|
||||
vmm_free_address((u64)virtual_address, page_count);
|
||||
}
|
||||
@@ -6,6 +6,11 @@
|
||||
// The value must be a multible of 8
|
||||
#define ADDRES_SPACE_SIZE GiB(64)
|
||||
|
||||
#define PTE_PRESENT (1ULL << 0)
|
||||
#define PTE_WRITABLE (1ULL << 1)
|
||||
#define PTE_USER (1ULL << 2)
|
||||
#define PTE_PS (1ULL << 7)
|
||||
|
||||
void vmm_init(u32 kernel_page_count);
|
||||
|
||||
// Allocates a free page aligned block of virtual addresses
|
||||
@@ -19,10 +24,4 @@ void vmm_free_address(u64 virtual_address, size_t page_count);
|
||||
// Low level function to map a virtual address to a physical address
|
||||
void vmm_map(u64 physical_address, u64 virtual_address, u32 flags);
|
||||
// Low level function to unmap a virtual address from a physical address
|
||||
u64 vmm_unmap(u64 virtual_address);
|
||||
|
||||
// Allocates and maps `page_count` continuous pages and returns the virtual address of the first page
|
||||
void* vmm_alloc(size_t page_count);
|
||||
// Frees the pages allocated via `vmm_alloc` at the specified virtual address
|
||||
// Only use this function for pages mapped via `vmm_alloc`
|
||||
void vmm_free(void* virtual_address, size_t page_count);
|
||||
u64 vmm_unmap(u64 virtual_address);
|
||||
49
src/kernel/alloc.c
Normal file
49
src/kernel/alloc.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "arch.h"
|
||||
#include "assert.h"
|
||||
|
||||
typedef struct block_header
|
||||
{
|
||||
size_t size;
|
||||
bool is_free;
|
||||
struct block_header* next;
|
||||
struct block_header* prev;
|
||||
u8 data[];
|
||||
} block_header_t;
|
||||
|
||||
static block_header_t* heap_start = NULL;
|
||||
|
||||
#define HEADER_SIZE sizeof(block_header_t)
|
||||
|
||||
static block_header_t* find_free_block(size_t size)
|
||||
{
|
||||
block_header_t* current = heap_start;
|
||||
|
||||
while (current != NULL)
|
||||
{
|
||||
if (current->is_free && current->size >= size)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* malloc(size_t size)
|
||||
{
|
||||
// Align to pointer size
|
||||
size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
|
||||
|
||||
block_header_t* block = find_free_block(size);
|
||||
block->is_free = false;
|
||||
return (u8*)block + HEADER_SIZE;
|
||||
}
|
||||
|
||||
void free(void* ptr)
|
||||
{
|
||||
block_header_t* block = (block_header_t*)((u8*)ptr - HEADER_SIZE);
|
||||
assert(block->is_free, "Block is already free");
|
||||
block->is_free = true;
|
||||
}
|
||||
6
src/kernel/alloc.h
Normal file
6
src/kernel/alloc.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "std.h"
|
||||
|
||||
void* malloc(size_t size);
|
||||
void free(void* ptr);
|
||||
13
src/kernel/assert.h
Normal file
13
src/kernel/assert.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
static inline void assert(bool condition, const char* msg)
|
||||
{
|
||||
#if DEBUG
|
||||
if (!condition)
|
||||
{
|
||||
arch_api.panic(msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,10 +1,22 @@
|
||||
#include "kernel.h"
|
||||
#include "alloc.h"
|
||||
#include "arch.h"
|
||||
#include "assert.h"
|
||||
#include "std.h"
|
||||
|
||||
void kernel_main()
|
||||
{
|
||||
assert(false, "test");
|
||||
|
||||
arch_api.enable_interrupts();
|
||||
|
||||
u64* mem = malloc(1);
|
||||
*mem = 23;
|
||||
|
||||
printf("%d\n", *mem);
|
||||
|
||||
free(mem);
|
||||
|
||||
printf("Welcome to nub OS :)\n");
|
||||
printf("Kernel has exited\n");
|
||||
arch_api.halt();
|
||||
|
||||
Reference in New Issue
Block a user