This commit is contained in:
nub31
2025-09-05 21:41:00 +02:00
parent 8e986807df
commit 0f6b66a486
21 changed files with 210 additions and 245 deletions

View File

@@ -2,34 +2,18 @@
#include "std.h" #include "std.h"
typedef struct
{
uint64_t base_address;
size_t length;
} memory_region_t;
typedef struct
{
memory_region_t* regions;
size_t num_regions;
} memory_map_t;
typedef void (*arch_panic_t)(const char*); typedef void (*arch_panic_t)(const char*);
typedef void (*arch_putchar_t)(char c); typedef void (*arch_putchar_t)(char c);
typedef uint64_t (*arch_page_size_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 memory_map_t (*arch_get_memory_map_t)();
typedef void (*arch_halt_t)(); typedef void (*arch_halt_t)();
typedef struct typedef struct
{ {
arch_panic_t panic; arch_panic_t panic;
arch_putchar_t putchar; arch_putchar_t putchar;
arch_page_size_t page_size;
arch_enable_interrupts_t enable_interrupts; arch_enable_interrupts_t enable_interrupts;
arch_disable_interrupts_t disable_interrupts; arch_disable_interrupts_t disable_interrupts;
arch_get_memory_map_t get_memory_map;
arch_halt_t halt; arch_halt_t halt;
} arch_api_t; } arch_api_t;

View File

@@ -5,15 +5,15 @@
typedef struct typedef struct
{ {
uint8_t character; u8 character;
uint8_t color; u8 color;
} vga_char_t; } vga_char_t;
static vga_char_t* vga_buffer = (vga_char_t*)0xb8000; static vga_char_t* vga_buffer = (vga_char_t*)0xb8000;
static uint8_t cursor_row = 0; static u8 cursor_row = 0;
static uint8_t cursor_col = 0; static u8 cursor_col = 0;
void console_put_char(char c, uint8_t color) void console_put_char(char c, u8 color)
{ {
switch (c) switch (c)
{ {
@@ -30,7 +30,7 @@ void console_put_char(char c, uint8_t color)
} }
case '\t': case '\t':
{ {
uint8_t remainder = 4 - (cursor_col % 4); u8 remainder = 4 - (cursor_col % 4);
cursor_col += remainder; cursor_col += remainder;
break; break;
} }

View File

@@ -21,5 +21,5 @@
#define VGA_DEFAULT_COLOR VGA_LIGHT_GRAY | VGA_BLACK << 4 #define VGA_DEFAULT_COLOR VGA_LIGHT_GRAY | VGA_BLACK << 4
void console_put_char(char character, uint8_t color); void console_put_char(char character, u8 color);
void console_clear(); void console_clear();

View File

@@ -26,7 +26,7 @@ void remap_pic()
outb(PIC2_DATA, 0); outb(PIC2_DATA, 0);
} }
void register_irq_handler(uint8_t irq, irq_handler_t handler) void register_irq_handler(u8 irq, irq_handler_t handler)
{ {
if (irq >= 16) if (irq >= 16)
{ {
@@ -40,7 +40,7 @@ void register_irq_handler(uint8_t irq, irq_handler_t handler)
void handle_irq(const isr_frame_t* frame) void handle_irq(const isr_frame_t* frame)
{ {
uint8_t irq = frame->int_no - 32; u8 irq = frame->int_no - 32;
if (irq_handlers[irq]) if (irq_handlers[irq])
{ {

View File

@@ -6,4 +6,4 @@ typedef void (*irq_handler_t)(const isr_frame_t*);
void remap_pic(); void remap_pic();
void handle_irq(const isr_frame_t* frame); void handle_irq(const isr_frame_t* frame);
void register_irq_handler(uint8_t irq, irq_handler_t handler); void register_irq_handler(u8 irq, irq_handler_t handler);

View File

@@ -4,9 +4,9 @@
typedef struct typedef struct
{ {
uint64_t r15, r14, r13, r12, r11, r10, r9, r8; u64 r15, r14, r13, r12, r11, r10, r9, r8;
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax; u64 rbp, rdi, rsi, rdx, rcx, rbx, rax;
uint64_t int_no; u64 int_no;
uint64_t err_code; u64 err_code;
uint64_t rip, cs, rflags, rsp, ss; u64 rip, cs, rflags, rsp, ss;
} __attribute__((packed)) isr_frame_t; } __attribute__((packed)) isr_frame_t;

View File

@@ -1,12 +1,13 @@
#include "arch.h"
#include "console/console.h" #include "console/console.h"
#include "interrupts/idt.h" #include "interrupts/idt.h"
#include "interrupts/irq.h" #include "interrupts/irq.h"
#include "kernel.h" #include "kernel.h"
#include "memory/mmap.h" #include "mem.h"
#include "panic.h" #include "panic.h"
#include "util.h" #include "util.h"
void x86_64_main(uint32_t magic, multiboot_info_t* info) void x86_64_main(u32 magic, multiboot_info_t* info)
{ {
console_clear(); console_clear();
@@ -21,28 +22,20 @@ void x86_64_main(uint32_t magic, multiboot_info_t* info)
} }
idt_init(); idt_init();
mem_init(info);
remap_pic(); remap_pic();
map_memory(info);
enable_interrupts(); enable_interrupts();
kernel_main(); kernel_main();
} }
void arch_console_putchar(char c) void console_putchar(char c)
{ {
console_put_char(c, VGA_DEFAULT_COLOR); console_put_char(c, VGA_DEFAULT_COLOR);
} }
uint64_t arch_page_size()
{
return 4096;
}
arch_api_t arch_api = { arch_api_t arch_api = {
.panic = panic, .putchar = console_putchar,
.putchar = arch_console_putchar,
.page_size = arch_page_size,
.enable_interrupts = enable_interrupts,
.disable_interrupts = disable_interrupts,
.get_memory_map = get_memory_map,
.halt = halt, .halt = halt,
}; };

134
src/arch/x86_64/mem.c Normal file
View File

@@ -0,0 +1,134 @@
#include "mem.h"
#include "x86_64/panic.h"
typedef struct
{
u64 base_address;
size_t length;
} memory_region_t;
typedef struct
{
memory_region_t* regions;
size_t num_regions;
} memory_map_t;
#define USABLE_REGION_SIZE 32
static memory_region_t usable_regions[USABLE_REGION_SIZE];
static size_t num_regions = 0;
#define BITMAP_SIZE 32768 // Supports up to 1GB of RAM
#define USABLE_REGION_SIZE 32
#define PAGE_SIZE 4096
static u8 page_bitmap[BITMAP_SIZE];
static u64 total_pages = 0;
static u64 free_pages = 0;
void mem_init(multiboot_info_t* info)
{
if (!(info->flags & (1 << 6)))
{
panic("Invalid memory map given by bootloader\n");
}
u64 offset = 0;
while (offset < info->mmap_length)
{
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(info->mmap_addr + offset);
if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE)
{
if (num_regions < USABLE_REGION_SIZE)
{
usable_regions[num_regions] = (memory_region_t){
.base_address = mmmt->addr,
.length = mmmt->len,
};
num_regions++;
}
else
{
printf("System has more memory than the memory map can hold\n");
break;
}
}
offset += mmmt->size + sizeof(mmmt->size);
}
memset(page_bitmap, 0xFF, BITMAP_SIZE);
for (size_t i = 0; i < num_regions; i++)
{
memory_region_t region = usable_regions[i];
u64 start_page = region.base_address / PAGE_SIZE;
u64 num_pages = region.length / PAGE_SIZE;
for (u64 page = start_page; page < start_page + num_pages; page++)
{
if (page < BITMAP_SIZE * 8)
{
page_bitmap[page / 8] &= ~(1 << (page % 8));
free_pages++;
total_pages++;
}
else
{
printf("System has more ram than the bitmap allows!\n");
break;
}
}
}
// Reserve first 64MB which is reserved by boot code
// todo(nub31): Later we should only identity map only the kernel pages or make a higher half kernel
for (u64 page = 0; page < (64 * 1024 * 1024) / PAGE_SIZE; page++)
{
if (page < BITMAP_SIZE * 8)
{
if (!(page_bitmap[page / 8] & (1 << (page % 8))))
{
page_bitmap[page / 8] |= (1 << (page % 8));
free_pages--;
}
}
}
}
u64 mem_alloc_physical_page()
{
for (size_t i = 0; i < BITMAP_SIZE; i++)
{
if (page_bitmap[i] != 0xFF)
{
for (int bit = 0; bit < 8; bit++)
{
if (!(page_bitmap[i] & (1 << bit)))
{
page_bitmap[i] |= (1 << bit);
free_pages--;
return ((i * 8 + bit) * PAGE_SIZE);
}
}
}
}
return 0;
}
void mem_free_physical_page(u64 address)
{
u64 page = address / PAGE_SIZE;
if (page < BITMAP_SIZE * 8)
{
if (page_bitmap[page / 8] & (1 << (page % 8)))
{
page_bitmap[page / 8] &= ~(1 << (page % 8));
free_pages++;
}
}
}

9
src/arch/x86_64/mem.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include "std.h"
#include "x86_64/multiboot.h"
void mem_init(multiboot_info_t* info);
u64 mem_alloc_physical_page();
void mem_free_physical_page(u64 address);

View File

@@ -1,49 +0,0 @@
#include "mmap.h"
#include "../panic.h"
#define USABLE_REGION_SIZE 32
static memory_region_t usable_regions[USABLE_REGION_SIZE];
static size_t num_regions = 0;
void map_memory(multiboot_info_t* info)
{
if (!(info->flags & (1 << 6)))
{
panic("Invalid memory map given by bootloader\n");
}
uint64_t offset = 0;
while (offset < info->mmap_length)
{
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(info->mmap_addr + offset);
if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE)
{
if (num_regions < USABLE_REGION_SIZE)
{
usable_regions[num_regions] = (memory_region_t){
.base_address = mmmt->addr,
.length = mmmt->len,
};
num_regions++;
}
else
{
printf("System has more memory than the memory map can hold\n");
break;
}
}
offset += mmmt->size + sizeof(mmmt->size);
}
}
memory_map_t get_memory_map()
{
return (memory_map_t){
.num_regions = num_regions,
.regions = usable_regions,
};
}

View File

@@ -1,7 +0,0 @@
#pragma once
#include "../multiboot.h"
#include "arch.h"
void map_memory(multiboot_info_t* mbd);
memory_map_t get_memory_map();

View File

@@ -68,14 +68,14 @@ enum
CPUID_FEAT_EDX_PBE = 1 << 31 CPUID_FEAT_EDX_PBE = 1 << 31
}; };
static inline void outb(uint16_t port, uint8_t val) static inline void outb(u16 port, u8 val)
{ {
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port)); __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
} }
static inline uint8_t inb(uint16_t port) static inline u8 inb(u16 port)
{ {
uint8_t ret; u8 ret;
__asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret; return ret;
} }
@@ -85,22 +85,22 @@ static inline void io_wait()
outb(0x80, 0); outb(0x80, 0);
} }
static inline void cpuid(uint32_t code, uint32_t* a, uint32_t* d) static inline void cpuid(u32 code, u32* a, u32* d)
{ {
__asm__ volatile("cpuid" : "=a"(*a), "=d"(*d) : "a"(code) : "ecx", "ebx"); __asm__ volatile("cpuid" : "=a"(*a), "=d"(*d) : "a"(code) : "ecx", "ebx");
} }
static inline uint64_t rdmsr(uint32_t msr) static inline u64 rdmsr(u32 msr)
{ {
uint32_t lo, hi; u32 lo, hi;
__asm__ volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); __asm__ volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return ((uint64_t)hi << 32) | lo; return ((u64)hi << 32) | lo;
} }
static inline void wrmsr(uint32_t msr, uint64_t value) static inline void wrmsr(u32 msr, u64 value)
{ {
uint32_t lo = (uint32_t)value; u32 lo = (u32)value;
uint32_t hi = (uint32_t)(value >> 32); u32 hi = (u32)(value >> 32);
__asm__ volatile("wrmsr" : : "c"(msr), "a"(lo), "d"(hi)); __asm__ volatile("wrmsr" : : "c"(msr), "a"(lo), "d"(hi));
} }

View File

@@ -1,11 +1,7 @@
#include "kernel.h" #include "kernel.h"
#include "pmm.h" #include "std.h"
void kernel_main() void kernel_main()
{ {
pmm_init();
uint64_t page = pmm_alloc_page();
printf("page: %u\n", page);
printf("Welcome to nub OS :)\n"); printf("Welcome to nub OS :)\n");
} }

View File

@@ -1,88 +0,0 @@
#include "pmm.h"
#include "arch.h"
#define BITMAP_SIZE 32768 // Supports up to 1GB of RAM
#define USABLE_REGION_SIZE 32
static uint8_t page_bitmap[BITMAP_SIZE];
static uint64_t total_pages = 0;
static uint64_t free_pages = 0;
void pmm_init()
{
memory_map_t memory_map = arch_api.get_memory_map();
memset(page_bitmap, 0xFF, BITMAP_SIZE);
for (size_t i = 0; i < memory_map.num_regions; i++)
{
memory_region_t region = memory_map.regions[i];
uint64_t start_page = region.base_address / arch_api.page_size();
uint64_t num_pages = region.length / arch_api.page_size();
for (uint64_t page = start_page; page < start_page + num_pages; page++)
{
if (page < BITMAP_SIZE * 8)
{
page_bitmap[page / 8] &= ~(1 << (page % 8));
free_pages++;
total_pages++;
}
else
{
printf("System has more ram than the bitmap allows!\n");
break;
}
}
}
// Reserve first 64MB which is reserved by boot code
for (uint64_t page = 0; page < (64 * 1024 * 1024) / arch_api.page_size(); page++)
{
if (page < BITMAP_SIZE * 8)
{
if (!(page_bitmap[page / 8] & (1 << (page % 8))))
{
page_bitmap[page / 8] |= (1 << (page % 8));
free_pages--;
}
}
}
}
// Returns the address of first free physical page
uint64_t pmm_alloc_page()
{
for (size_t i = 0; i < BITMAP_SIZE; i++)
{
if (page_bitmap[i] != 0xFF)
{
for (int bit = 0; bit < 8; bit++)
{
if (!(page_bitmap[i] & (1 << bit)))
{
page_bitmap[i] |= (1 << bit);
free_pages--;
return ((i * 8 + bit) * arch_api.page_size());
}
}
}
}
return 0;
}
// Frees the physical page at the specified address
void pmm_free_page(uint64_t addr)
{
uint64_t page = addr / arch_api.page_size();
if (page < BITMAP_SIZE * 8)
{
if (page_bitmap[page / 8] & (1 << (page % 8)))
{
page_bitmap[page / 8] &= ~(1 << (page % 8));
free_pages++;
}
}
}

View File

@@ -1,7 +0,0 @@
#pragma once
#include "std.h"
void pmm_init();
uint64_t pmm_alloc_page();
void pmm_free_page(uint64_t addr);

View File

@@ -18,29 +18,18 @@ typedef __builtin_va_list va_list;
#endif #endif
typedef unsigned long size_t; typedef unsigned long size_t;
typedef long ptrdiff_t;
typedef long intptr_t;
typedef unsigned long uintptr_t; typedef unsigned long uintptr_t;
#define offsetof(type, member) __builtin_offsetof(type, member) #define offsetof(type, member) __builtin_offsetof(type, member)
typedef signed char int8_t; typedef unsigned char u8;
typedef unsigned char uint8_t; typedef signed char i8;
typedef signed short int16_t; typedef unsigned short u16;
typedef unsigned short uint16_t; typedef signed short i16;
typedef signed int int32_t; typedef unsigned int u32;
typedef unsigned int uint32_t; typedef signed int i32;
typedef signed long long int64_t; typedef unsigned long long u64;
typedef unsigned long long uint64_t; typedef signed long long i64;
typedef uint8_t u8;
typedef int8_t i8;
typedef uint16_t u16;
typedef int16_t i16;
typedef uint32_t u32;
typedef int32_t i32;
typedef uint64_t u64;
typedef int64_t i64;
#define INT8_MIN (-128) #define INT8_MIN (-128)
#define INT8_MAX 127 #define INT8_MAX 127

View File

@@ -27,12 +27,12 @@ void printf(const char* fmt, ...)
} }
else if (fmt[i] == 'c') else if (fmt[i] == 'c')
{ {
char character = (char)va_arg(args, int64_t); char character = (char)va_arg(args, u64);
arch_api.putchar(character); arch_api.putchar(character);
} }
else if (fmt[i] == 'd') else if (fmt[i] == 'd')
{ {
int64_t val = va_arg(args, int64_t); u64 val = va_arg(args, u64);
char buf[21]; char buf[21];
itoa64(val, buf); itoa64(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++) for (size_t j = 0; buf[j] != '\0'; j++)
@@ -42,7 +42,7 @@ void printf(const char* fmt, ...)
} }
else if (fmt[i] == 'u') else if (fmt[i] == 'u')
{ {
uint64_t val = va_arg(args, uint64_t); u64 val = va_arg(args, u64);
char buf[21]; char buf[21];
uitoa64(val, buf); uitoa64(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++) for (size_t j = 0; buf[j] != '\0'; j++)
@@ -52,7 +52,7 @@ void printf(const char* fmt, ...)
} }
else if (fmt[i] == 'x') else if (fmt[i] == 'x')
{ {
uint64_t val = va_arg(args, uint64_t); u64 val = va_arg(args, u64);
char buf[17]; char buf[17];
uitoa64_hex(val, buf); uitoa64_hex(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++) for (size_t j = 0; buf[j] != '\0'; j++)

View File

@@ -1,9 +1,17 @@
#include "mem.h" #include "mem.h"
void memset(void* destination, uint8_t value, size_t length) void memset(void* destination, u8 value, size_t length)
{ {
for (size_t i = 0; i < length; i++) for (size_t i = 0; i < length; i++)
{ {
((uint8_t*)destination)[i] = value; ((u8*)destination)[i] = value;
}
}
void memcpy(void* destination, void* source, size_t length)
{
for (size_t i = 0; i < length; i++)
{
((u8*)destination)[i] = ((u8*)source)[i];
} }
} }

View File

@@ -2,4 +2,5 @@
#include "std.h" #include "std.h"
void memset(void* destination, uint8_t value, size_t length); void memset(void* destination, u8 value, size_t length);
void memcpy(void* destination, void* source, size_t length);

View File

@@ -1,6 +1,6 @@
#include "string.h" #include "string.h"
int kstrcmp(const char* a, const char* b) int strcmp(const char* a, const char* b)
{ {
while ((*a != '\0' && *b != '\0') && *a == *b) while ((*a != '\0' && *b != '\0') && *a == *b)
{ {
@@ -25,7 +25,7 @@ void reverse(char* str, size_t length)
} }
} }
void itoa64(int64_t value, char* buffer) void itoa64(i64 value, char* buffer)
{ {
char temp[21]; char temp[21];
int i = 0, j = 0; int i = 0, j = 0;
@@ -75,7 +75,7 @@ void itoa64(int64_t value, char* buffer)
buffer[j] = '\0'; buffer[j] = '\0';
} }
void uitoa64(uint64_t value, char* buffer) void uitoa64(u64 value, char* buffer)
{ {
char temp[21]; char temp[21];
int i = 0, j = 0; int i = 0, j = 0;
@@ -100,7 +100,7 @@ void uitoa64(uint64_t value, char* buffer)
buffer[j] = '\0'; buffer[j] = '\0';
} }
void uitoa64_hex(uint64_t value, char* buffer) void uitoa64_hex(u64 value, char* buffer)
{ {
const char* digits = "0123456789abcdef"; const char* digits = "0123456789abcdef";
char temp[17]; char temp[17];

View File

@@ -3,6 +3,8 @@
#include "std.h" #include "std.h"
int strcmp(const char* a, const char* b); int strcmp(const char* a, const char* b);
void uitoa64(uint64_t value, char* buffer); void reverse(char* str, size_t length);
void itoa64(int64_t value, char* buffer);
void uitoa64_hex(uint64_t value, char* buffer); void uitoa64(u64 value, char* buffer);
void itoa64(i64 value, char* buffer);
void uitoa64_hex(u64 value, char* buffer);