This commit is contained in:
nub31
2025-09-06 22:07:17 +02:00
parent 45a9023bab
commit 4f55956fee
32 changed files with 89 additions and 83 deletions

View File

@@ -2,14 +2,12 @@
"version": 4, "version": 4,
"configurations": [ "configurations": [
{ {
"name": "test", "name": "kernel",
"defines": [ "defines": [
"DEBUG" "DEBUG"
], ],
"includePath": [ "includePath": [
"src/kernel", "src/lib"
"src/arch",
"src"
], ],
"intelliSenseMode": "linux-gcc-x64", "intelliSenseMode": "linux-gcc-x64",
"compilerPath": "/usr/bin/x86_64-elf-gcc", "compilerPath": "/usr/bin/x86_64-elf-gcc",

View File

@@ -31,6 +31,10 @@
"assert.h": "c", "assert.h": "c",
"io.h": "c", "io.h": "c",
"mem.h": "c", "mem.h": "c",
"string.h": "c" "string.h": "c",
"kernel.h": "c",
"printf.h": "c",
"vmm.h": "c",
"console.h": "c"
} }
} }

View File

@@ -8,7 +8,7 @@ LDFLAGS = -g
ASFLAGS = -g -F dwarf ASFLAGS = -g -F dwarf
# Do not modify # Do not modify
CFLAGS += -m64 -ffreestanding -nostdinc -nostdlib -fno-builtin -Wall -Wextra -Wshadow -std=c23 -I src -I src/kernel -I src/arch CFLAGS += -m64 -ffreestanding -nostdinc -nostdlib -fno-builtin -Wall -Wextra -Wshadow -std=c23 -I src/lib
LDFLAGS += LDFLAGS +=
ASFLAGS += -f elf64 ASFLAGS += -f elf64

View File

@@ -1,9 +1,11 @@
#include "arch.h"
#include "console.h" #include "console.h"
#include "mem/pmm.h" #include "mem/pmm.h"
#include "mem/vmm.h" #include "mem/vmm.h"
#include "panic.h" #include "panic.h"
#include "util.h" #include "util.h"
#include <arch.h>
#include <def.h>
#include <printf.h>
static void arch_halt() static void arch_halt()
{ {
@@ -20,9 +22,9 @@ static void arch_enable_interrupts()
enable_interrupts(); enable_interrupts();
} }
static void arch_panic(const char* msg) static void arch_panic()
{ {
panic(msg); panic();
} }
static void arch_console_putchar(char c) static void arch_console_putchar(char c)
@@ -49,7 +51,8 @@ void* arch_alloc(size_t page_count)
u64 physical_address = pmm_alloc(); u64 physical_address = pmm_alloc();
if (!physical_address) if (!physical_address)
{ {
panic("Out of physical memory"); printf("Out of physical memory");
panic();
} }
vmm_map(physical_address, virtual_address + (i * PAGE_SIZE), PTE_PRESENT | PTE_WRITABLE); vmm_map(physical_address, virtual_address + (i * PAGE_SIZE), PTE_PRESENT | PTE_WRITABLE);

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "std.h" #include <def.h>
#define VGA_BLACK 0 #define VGA_BLACK 0
#define VGA_BLUE 1 #define VGA_BLUE 1

View File

@@ -1,5 +1,6 @@
#include "exceptions.h" #include "exceptions.h"
#include "../panic.h" #include "../panic.h"
#include <printf.h>
static const char* exception_messages[32] = { static const char* exception_messages[32] = {
"divide by zero", "divide by zero",
@@ -39,5 +40,5 @@ static const char* exception_messages[32] = {
void handle_exception(const isr_frame_t* frame) void handle_exception(const isr_frame_t* frame)
{ {
printf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code); printf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code);
panic("An unhandled exception occurred"); panic();
} }

View File

@@ -1,5 +1,6 @@
#include "irq.h" #include "irq.h"
#include "../util.h" #include "../util.h"
#include <printf.h>
#define PIC1_COMMAND 0x20 #define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21 #define PIC1_DATA 0x21

View File

@@ -1,6 +1,8 @@
#include "isr.h" #include "isr.h"
#include "exceptions.h" #include "exceptions.h"
#include "irq.h" #include "irq.h"
#include <def.h>
#include <printf.h>
void handle_isr(const isr_frame_t* frame) void handle_isr(const isr_frame_t* frame)
{ {

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "std.h" #include <def.h>
typedef struct typedef struct
{ {

View File

@@ -1,11 +1,13 @@
#include "console.h" #include "console.h"
#include "interrupts/idt.h" #include "interrupts/idt.h"
#include "interrupts/irq.h" #include "interrupts/irq.h"
#include "kernel.h"
#include "mem/pmm.h" #include "mem/pmm.h"
#include "mem/vmm.h" #include "mem/vmm.h"
#include "panic.h" #include "panic.h"
#include "util.h" #include "util.h"
#include <printf.h>
extern void kernel_main();
void x86_64_main(u32 magic, multiboot_info_t* info, u32 kernel_page_count) void x86_64_main(u32 magic, multiboot_info_t* info, u32 kernel_page_count)
{ {
@@ -13,12 +15,14 @@ void x86_64_main(u32 magic, multiboot_info_t* info, u32 kernel_page_count)
if (magic != 0x2BADB002) if (magic != 0x2BADB002)
{ {
panic("Multiboot magic does not match\n"); printf("Multiboot magic does not match\n");
panic();
} }
if (info == NULL) if (info == NULL)
{ {
panic("Multiboot info is NULL\n"); printf("Multiboot info is NULL\n");
panic();
} }
idt_init(); idt_init();

View File

@@ -1,5 +1,7 @@
#include "pmm.h" #include "pmm.h"
#include "x86_64/panic.h" #include "../panic.h"
#include <mem.h>
#include <printf.h>
typedef struct typedef struct
{ {
@@ -27,7 +29,8 @@ void pmm_init(u32 kernel_page_count, multiboot_info_t* info)
{ {
if (!(info->flags & (1 << 6))) if (!(info->flags & (1 << 6)))
{ {
panic("Invalid memory map given by bootloader\n"); printf("Invalid memory map given by bootloader\n");
panic();
} }
u64 offset = 0; u64 offset = 0;
@@ -84,7 +87,8 @@ void pmm_init(u32 kernel_page_count, multiboot_info_t* info)
{ {
if (page >= BITMAP_PAGE_COUNT) if (page >= BITMAP_PAGE_COUNT)
{ {
panic("Bitmap is not large enough to hold the memory reserved by the kernel"); printf("Bitmap is not large enough to hold the memory reserved by the kernel");
panic();
} }
page_bitmap[page / 8] |= (1 << (page % 8)); page_bitmap[page / 8] |= (1 << (page % 8));
@@ -123,7 +127,7 @@ void pmm_free(u64 physical_address)
else else
{ {
printf("Physical address %x is already free", physical_address); printf("Physical address %x is already free", physical_address);
panic("Failed to free physical address"); panic();
} }
} }
} }

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "std.h" #include "../multiboot.h"
#include "x86_64/multiboot.h" #include <def.h>
// todo(nub31): Fixed at 2mb for now, might add support for 4k pages later // todo(nub31): Fixed at 2mb for now, might add support for 4k pages later
#define PAGE_SIZE MiB(2) #define PAGE_SIZE MiB(2)

View File

@@ -1,6 +1,7 @@
#include "vmm.h" #include "vmm.h"
#include "../panic.h"
#include "pmm.h" #include "pmm.h"
#include "x86_64/panic.h" #include <printf.h>
#define PML4_INDEX(addr) (((addr) >> 39) & 0x1FF) #define PML4_INDEX(addr) (((addr) >> 39) & 0x1FF)
#define PDPT_INDEX(addr) (((addr) >> 30) & 0x1FF) #define PDPT_INDEX(addr) (((addr) >> 30) & 0x1FF)
@@ -23,7 +24,8 @@ void vmm_init(u32 kernel_page_count)
{ {
if (page >= BITMAP_PAGE_COUNT) if (page >= BITMAP_PAGE_COUNT)
{ {
panic("Bitmap is not large enough to hold the addresses reserved by the kernel"); printf("Bitmap is not large enough to hold the addresses reserved by the kernel");
panic();
} }
page_bitmap[page / 8] |= (1 << (page % 8)); page_bitmap[page / 8] |= (1 << (page % 8));
@@ -75,7 +77,7 @@ void vmm_free_address(u64 virtual_address, size_t page_count)
if (start_page + page_count > BITMAP_PAGE_COUNT) if (start_page + page_count > BITMAP_PAGE_COUNT)
{ {
printf("Virtual address range exceeds bitmap bounds\n"); printf("Virtual address range exceeds bitmap bounds\n");
panic("Failed to free virtual address"); panic();
} }
for (size_t i = 0; i < page_count; i++) for (size_t i = 0; i < page_count; i++)
@@ -87,7 +89,7 @@ void vmm_free_address(u64 virtual_address, size_t page_count)
if (!(page_bitmap[byte_index] & (1 << bit_index))) if (!(page_bitmap[byte_index] & (1 << bit_index)))
{ {
printf("Virtual address 0x%x (page %u) is already free\n", virtual_address + (i * PAGE_SIZE), page); printf("Virtual address 0x%x (page %u) is already free\n", virtual_address + (i * PAGE_SIZE), page);
panic("Failed to free virtual address"); panic();
} }
} }
@@ -105,7 +107,7 @@ static u64 create_2mb_pte(u64 physical_address, u32 flags)
if (physical_address & (PAGE_SIZE - 1)) if (physical_address & (PAGE_SIZE - 1))
{ {
printf("Physical address not page aligned (0x%x)\n", physical_address); printf("Physical address not page aligned (0x%x)\n", physical_address);
panic("Failed to create PTE"); panic();
} }
return (physical_address & PTE_MASK) | flags | PTE_PS; return (physical_address & PTE_MASK) | flags | PTE_PS;
@@ -122,7 +124,7 @@ void vmm_map(u64 physical_address, u64 virtual_address, u32 flags)
{ {
// todo(nub31): Dynamically create a pdpt table // todo(nub31): Dynamically create a pdpt table
printf("PDPT not present at PML4 index %u\n", pml4_idx); printf("PDPT not present at PML4 index %u\n", pml4_idx);
panic("Failed to map virtual to physical page"); panic();
} }
u64* pdpt_physical_address = (u64*)(pdpt & PTE_MASK); u64* pdpt_physical_address = (u64*)(pdpt & PTE_MASK);
@@ -131,7 +133,7 @@ void vmm_map(u64 physical_address, u64 virtual_address, u32 flags)
{ {
// todo(nub31): Dynamically create a pd table // todo(nub31): Dynamically create a pd table
printf("PD not present at PDPT index %u\n", pdpt_idx); printf("PD not present at PDPT index %u\n", pdpt_idx);
panic("Failed to map virtual to physical page"); panic();
} }
u64* pd_physical_address = (u64*)(pd & PTE_MASK); u64* pd_physical_address = (u64*)(pd & PTE_MASK);
@@ -140,7 +142,7 @@ void vmm_map(u64 physical_address, u64 virtual_address, u32 flags)
if (entry & PTE_PRESENT) if (entry & PTE_PRESENT)
{ {
printf("Virtual address 0x%x is already mapped\n", virtual_address); printf("Virtual address 0x%x is already mapped\n", virtual_address);
panic("Failed to map virtual to physical page"); panic();
} }
pd_physical_address[pd_idx] = create_2mb_pte(physical_address, flags); pd_physical_address[pd_idx] = create_2mb_pte(physical_address, flags);
@@ -156,7 +158,7 @@ u64 vmm_unmap(u64 virtual_address)
if (!(pdpt_entry & PTE_PRESENT)) if (!(pdpt_entry & PTE_PRESENT))
{ {
printf("PDPT not present at PML4 index %llu\n", pml4_idx); printf("PDPT not present at PML4 index %llu\n", pml4_idx);
panic("Failed to unmap virtual address"); panic();
} }
u64* pdpt_physical_address = (u64*)(pdpt_entry & PTE_MASK); u64* pdpt_physical_address = (u64*)(pdpt_entry & PTE_MASK);
@@ -164,14 +166,14 @@ u64 vmm_unmap(u64 virtual_address)
if (!(pd_entry & PTE_PRESENT)) if (!(pd_entry & PTE_PRESENT))
{ {
printf("PD not present at PDPT index %llu\n", pdpt_idx); printf("PD not present at PDPT index %llu\n", pdpt_idx);
panic("Failed to unmap virtual address"); panic();
} }
u64* pd_physical_address = (u64*)(pd_entry & PTE_MASK); u64* pd_physical_address = (u64*)(pd_entry & PTE_MASK);
if (!(pd_physical_address[pd_idx] & PTE_PRESENT)) if (!(pd_physical_address[pd_idx] & PTE_PRESENT))
{ {
printf("Virtual address 0x%llx is not mapped\n", virtual_address); printf("Virtual address 0x%llx is not mapped\n", virtual_address);
panic("Failed to unmap virtual address"); panic();
} }
u64 physical_address = pd_physical_address[pd_idx] & PTE_MASK; u64 physical_address = pd_physical_address[pd_idx] & PTE_MASK;

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "std.h" #include <def.h>
// Defines the theoretical max virtual memory space the kernel can allocate // Defines the theoretical max virtual memory space the kernel can allocate
// The value must be a multible of 8 // The value must be a multible of 8

View File

@@ -1,9 +1,8 @@
#include "panic.h" #include "panic.h"
#include "util.h" #include "util.h"
void panic(const char* msg) void panic()
{ {
printf(msg);
disable_interrupts(); disable_interrupts();
halt(); halt();
} }

View File

@@ -1,3 +1,3 @@
#pragma once #pragma once
void panic(const char* msg); void panic();

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "std.h" #include <def.h>
enum enum
{ {

View File

@@ -1,5 +1,4 @@
#include "arch.h" #include <assert.h>
#include "assert.h"
typedef struct block_header typedef struct block_header
{ {

View File

@@ -1,6 +1,4 @@
#pragma once #pragma once
#include "std.h"
void* malloc(size_t size); void* malloc(size_t size);
void free(void* ptr); void free(void* ptr);

View File

@@ -1,22 +1,11 @@
#include "kernel.h" #include "kernel.h"
#include "alloc.h" #include <arch.h>
#include "arch.h" #include <printf.h>
#include "assert.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();

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "std.h" #include <def.h>
typedef void (*arch_console_putchar_t)(char c); typedef void (*arch_console_putchar_t)(char c);
typedef void (*arch_console_clear_t)(); typedef void (*arch_console_clear_t)();
@@ -22,7 +22,7 @@ typedef struct
const arch_mem_free_t free; const arch_mem_free_t free;
} arch_mem_api_t; } arch_mem_api_t;
typedef void (*arch_panic_t)(const char* msg); typedef void (*arch_panic_t)();
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)();

View File

@@ -1,13 +1,14 @@
#pragma once #pragma once
#include "arch.h" #include <arch.h>
// In arch code, make sure arch_api.panic is set up befire calling
static inline void assert(bool condition, const char* msg) static inline void assert(bool condition, const char* msg)
{ {
#if DEBUG #if DEBUG
if (!condition) if (!condition)
{ {
arch_api.panic(msg); arch_api.panic();
} }
#endif #endif
} }

View File

@@ -37,14 +37,20 @@ typedef signed long long i64;
#define INT16_MIN (-32768) #define INT16_MIN (-32768)
#define INT16_MAX 32767 #define INT16_MAX 32767
#define UINT16_MIN 0x0
#define UINT16_MAX 0xffff #define UINT16_MAX 0xffff
#define INT32_MIN (-2147483647 - 1) #define INT32_MIN (-2147483647 - 1)
#define INT32_MAX 2147483647 #define INT32_MAX 2147483647
#define UINT32_MIN 0x0
#define UINT32_MAX 0xffffffffU #define UINT32_MAX 0xffffffffU
#define INT64_MIN (-9223372036854775807LL - 1) #define INT64_MIN (-9223372036854775807LL - 1)
#define INT64_MAX 9223372036854775807LL #define INT64_MAX 9223372036854775807LL
#define UINT64_MIN 0x0
#define UINT64_MAX 0xffffffffffffffffULL #define UINT64_MAX 0xffffffffffffffffULL
#define INT8_C(x) x #define INT8_C(x) x
@@ -59,10 +65,7 @@ typedef signed long long i64;
#define INT64_C(x) x##LL #define INT64_C(x) x##LL
#define UINT64_C(x) x##ULL #define UINT64_C(x) x##ULL
#define INTMAX_C(x) x##LL #define KiB(count) (count * UINT64_C(count))
#define UINTMAX_C(x) x##ULL #define MiB(count) (KiB(count) * UINT64_C(count))
#define GiB(count) (MiB(count) * UINT64_C(count))
#define KiB(count) ((u64)count * 1024) #define TiB(count) (GiB(count) * UINT64_C(count))
#define MiB(count) (KiB((u64)count) * 1024)
#define GiB(count) (MiB((u64)count) * 1024)
#define TiB(count) (GiB((u64)count) * 1024)

6
src/lib/mem.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include <def.h>
void memset(void* destination, u8 value, size_t length);
void memcpy(void* destination, void* source, size_t length);

View File

@@ -1,4 +1,7 @@
#include "arch.h" #include "printf.h"
#include <arch.h>
#include <def.h>
#include <string.h>
void printf(const char* fmt, ...) void printf(const char* fmt, ...)
{ {

4
src/lib/printf.h Normal file
View File

@@ -0,0 +1,4 @@
#pragma once
// In arch code, make sure arch_api.console.putchar is set up befire calling
void printf(const char* fmt, ...);

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "std.h" #include <def.h>
int strcmp(const char* a, const char* b); int strcmp(const char* a, const char* b);
void reverse(char* str, size_t length); void reverse(char* str, size_t length);

View File

@@ -1,6 +0,0 @@
#pragma once
#include "stdlib/def.h"
#include "stdlib/io.h"
#include "stdlib/mem.h"
#include "stdlib/string.h"

View File

@@ -1,3 +0,0 @@
#pragma once
void printf(const char* fmt, ...);

View File

@@ -1,6 +0,0 @@
#pragma once
#include "std.h"
void memset(void* destination, u8 value, size_t length);
void memcpy(void* destination, void* source, size_t length);