...
This commit is contained in:
19
.clangd
19
.clangd
@@ -1,19 +0,0 @@
|
|||||||
CompileFlags:
|
|
||||||
Add:
|
|
||||||
- "-target"
|
|
||||||
- "x86_64-unknown-none"
|
|
||||||
- "-ffreestanding"
|
|
||||||
- "-fno-builtin"
|
|
||||||
- "-fno-common"
|
|
||||||
- "-Wall"
|
|
||||||
- "-Wextra"
|
|
||||||
- "-Wshadow"
|
|
||||||
- "-fno-strict-aliasing"
|
|
||||||
- "-nostdinc"
|
|
||||||
- "-nostdlib"
|
|
||||||
- "-I"
|
|
||||||
- "/home/oliste/repos/nub-os/src"
|
|
||||||
- "-I"
|
|
||||||
- "/home/oliste/repos/nub-os/src/kernel"
|
|
||||||
- "-I"
|
|
||||||
- "/home/oliste/repos/nub-os/src/arch"
|
|
||||||
19
.vscode/c_cpp_properties.json
vendored
Normal file
19
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"version": 4,
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"defines": [
|
||||||
|
"DEBUG"
|
||||||
|
],
|
||||||
|
"includePath": [
|
||||||
|
"src/kernel",
|
||||||
|
"src/arch",
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"intelliSenseMode": "linux-gcc-x64",
|
||||||
|
"compilerPath": "/usr/bin/x86_64-elf-gcc",
|
||||||
|
"cStandard": "c23"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
15
.vscode/settings.json
vendored
15
.vscode/settings.json
vendored
@@ -18,6 +18,19 @@
|
|||||||
"system_error": "c",
|
"system_error": "c",
|
||||||
"std.h": "c",
|
"std.h": "c",
|
||||||
"panic.h": "c",
|
"panic.h": "c",
|
||||||
"pmm.h": "c"
|
"pmm.h": "c",
|
||||||
|
"array": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"ranges": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"valarray": "cpp",
|
||||||
|
"alloc.h": "c",
|
||||||
|
"arch.h": "c",
|
||||||
|
"def.h": "c",
|
||||||
|
"assert.h": "c",
|
||||||
|
"io.h": "c",
|
||||||
|
"mem.h": "c",
|
||||||
|
"string.h": "c"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
12
makefile
12
makefile
@@ -2,9 +2,15 @@ CC = x86_64-elf-gcc
|
|||||||
LD = x86_64-elf-ld
|
LD = x86_64-elf-ld
|
||||||
AS = nasm
|
AS = nasm
|
||||||
|
|
||||||
CFLAGS = -m64 -ffreestanding -nostdinc -nostdlib -fno-builtin -Wall -Wextra -Wshadow -std=c11 -I src -I src/kernel -I src/arch -g
|
# Modify these settings here for defines and debug info
|
||||||
LDFLAGS = -g
|
CFLAGS = -g -D DEBUG
|
||||||
ASFLAGS = -f elf64 -g -F dwarf
|
LDFLAGS = -g
|
||||||
|
ASFLAGS = -g -F dwarf
|
||||||
|
|
||||||
|
# Do not modify
|
||||||
|
CFLAGS += -m64 -ffreestanding -nostdinc -nostdlib -fno-builtin -Wall -Wextra -Wshadow -std=c23 -I src -I src/kernel -I src/arch
|
||||||
|
LDFLAGS +=
|
||||||
|
ASFLAGS += -f elf64
|
||||||
|
|
||||||
SRC_C := $(shell find src -name '*.c')
|
SRC_C := $(shell find src -name '*.c')
|
||||||
SRC_ASM := $(shell find src -name '*.asm')
|
SRC_ASM := $(shell find src -name '*.asm')
|
||||||
|
|||||||
@@ -11,14 +11,18 @@ typedef struct
|
|||||||
const arch_console_clear_t clear;
|
const arch_console_clear_t clear;
|
||||||
} arch_console_api_t;
|
} 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
|
typedef struct
|
||||||
{
|
{
|
||||||
const arch_mem_get_page_size_t get_page_size;
|
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;
|
} 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_enable_interrupts_t)();
|
||||||
typedef void (*arch_disable_interrupts_t)();
|
typedef void (*arch_disable_interrupts_t)();
|
||||||
typedef void (*arch_halt_t)();
|
typedef void (*arch_halt_t)();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "mem/pmm.h"
|
#include "mem/pmm.h"
|
||||||
|
#include "mem/vmm.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -34,13 +35,44 @@ static void arch_console_clear()
|
|||||||
console_clear();
|
console_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 arch_get_page_size()
|
static size_t arch_get_page_size()
|
||||||
{
|
{
|
||||||
return 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 = {
|
static const arch_mem_api_t arch_mem_api = {
|
||||||
.get_page_size = arch_get_page_size,
|
.get_page_size = arch_get_page_size,
|
||||||
|
.alloc = arch_alloc,
|
||||||
|
.free = arch_free,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const arch_console_api_t arch_console_api = {
|
static const arch_console_api_t arch_console_api = {
|
||||||
|
|||||||
@@ -8,11 +8,6 @@
|
|||||||
|
|
||||||
#define PTE_MASK 0x000FFFFFFFFFF000ULL
|
#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_PAGE_COUNT (ADDRES_SPACE_SIZE / PAGE_SIZE)
|
||||||
#define BITMAP_SIZE (BITMAP_PAGE_COUNT / 8)
|
#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");
|
__asm__ volatile("invlpg (%0)" : : "r"(virtual_address) : "memory");
|
||||||
|
|
||||||
return physical_address;
|
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
|
// The value must be a multible of 8
|
||||||
#define ADDRES_SPACE_SIZE GiB(64)
|
#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);
|
void vmm_init(u32 kernel_page_count);
|
||||||
|
|
||||||
// Allocates a free page aligned block of virtual addresses
|
// 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
|
// Low level function to map a virtual address to a physical address
|
||||||
void vmm_map(u64 physical_address, u64 virtual_address, u32 flags);
|
void vmm_map(u64 physical_address, u64 virtual_address, u32 flags);
|
||||||
// Low level function to unmap a virtual address from a physical address
|
// Low level function to unmap a virtual address from a physical address
|
||||||
u64 vmm_unmap(u64 virtual_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);
|
|
||||||
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 "kernel.h"
|
||||||
|
#include "alloc.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
|
#include "assert.h"
|
||||||
#include "std.h"
|
#include "std.h"
|
||||||
|
|
||||||
void kernel_main()
|
void kernel_main()
|
||||||
{
|
{
|
||||||
|
assert(false, "test");
|
||||||
|
|
||||||
arch_api.enable_interrupts();
|
arch_api.enable_interrupts();
|
||||||
|
|
||||||
|
u64* mem = malloc(1);
|
||||||
|
*mem = 23;
|
||||||
|
|
||||||
|
printf("%d\n", *mem);
|
||||||
|
|
||||||
|
free(mem);
|
||||||
|
|
||||||
printf("Welcome to nub OS :)\n");
|
printf("Welcome to nub OS :)\n");
|
||||||
printf("Kernel has exited\n");
|
printf("Kernel has exited\n");
|
||||||
arch_api.halt();
|
arch_api.halt();
|
||||||
|
|||||||
Reference in New Issue
Block a user