From c46157fad005a3bcc3e675048b3334a5b0711bb4 Mon Sep 17 00:00:00 2001 From: xamidev Date: Sat, 31 Jan 2026 14:13:48 +0100 Subject: [PATCH 1/7] Process linked list --- Makefile | 2 +- src/idt/idt.c | 2 + src/kmain.c | 10 ++++- src/sched/process.c | 99 +++++++++++++++++++++++++++++++++++++++++++ src/sched/process.h | 26 ++++++++++++ src/sched/scheduler.c | 9 ++++ src/sched/scheduler.h | 6 +++ test.bin | 1 + 8 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 src/sched/process.c create mode 100644 src/sched/process.h create mode 100644 src/sched/scheduler.c create mode 100644 src/sched/scheduler.h create mode 100644 test.bin diff --git a/Makefile b/Makefile index 486c919..dbaa534 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SOURCES = src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c +SOURCES = src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c build: rm -f *.o diff --git a/src/idt/idt.c b/src/idt/idt.c index c5094ce..434fb63 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -5,6 +5,7 @@ #include "io/kbd/ps2.h" #include #include +#include "sched/scheduler.h" struct interrupt_descriptor idt[256]; struct idtr idt_reg; @@ -187,6 +188,7 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) case 32: //DEBUG("Timer Interrupt"); ticks++; + scheduler_schedule(); // Send an EOI so that we can continue having interrupts outb(0x20, 0x20); break; diff --git a/src/kmain.c b/src/kmain.c index a2b0812..a30cbfe 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -14,6 +14,7 @@ #include "mem/paging/paging.h" #include "mem/paging/vmm.h" #include "mem/heap/kheap.h" +#include "sched/process.h" // Limine version used __attribute__((used, section(".limine_requests"))) @@ -76,6 +77,9 @@ const char* splash = "pepperOS version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSIO struct boot_context boot_ctx; +extern struct process_t* processes_list; +extern struct process_t* current_process; + // This is our entry point void kmain() { @@ -122,7 +126,11 @@ void kmain() { printf("testing, attention please %d\n", i); } - // term_scroll(); + + struct process_t* pedicel = process_create(); + + process_add(&processes_list, pedicel); + process_display_list(processes_list); hcf(); } diff --git a/src/sched/process.c b/src/sched/process.c new file mode 100644 index 0000000..3ce3654 --- /dev/null +++ b/src/sched/process.c @@ -0,0 +1,99 @@ +#include +#include "process.h" +#include "mem/heap/kheap.h" +#include "kernel.h" + +struct process_t* processes_list; +struct process_t* current_process; + +void process_init() +{ + processes_list = NULL; + current_process = NULL; +} + +// Only for debug +void process_display_list(struct process_t* processes_list) +{ + int process_view_id = 0; + struct process_t* tmp = processes_list; + while (tmp != NULL) + { + DEBUG("{%d: } -> ", process_view_id); + tmp = tmp->next; + process_view_id++; + } + DEBUG("NULL"); +} + +struct process_t* process_create() +{ + struct process_t* proc = (struct process_t*)kmalloc(sizeof(struct process_t)); + + if (!proc) return NULL; + + proc->context = NULL; + proc->status = READY; + proc->next = NULL; + + return proc; +} + +void process_add(struct process_t** processes_list, struct process_t* process) +{ + if (!process) return; + process->next = NULL; + + if (*processes_list == NULL) + { + // List is empty + *processes_list = process; + return; + } + + struct process_t* tmp = *processes_list; + while (tmp->next != NULL) + { + tmp = tmp->next; + } + // We're at last process before NULL + tmp->next = process; + // process->next = NULL; +} + +void process_delete(struct process_t** processes_list, struct process_t* process) +{ + if (!processes_list || !*processes_list || !process) return; + + if (*processes_list == process) + { + // process to delete is at head + *processes_list = process->next; + process->next = NULL; + kfree(process); + return; + } + + struct process_t* tmp = *processes_list; + while (tmp->next && tmp->next != process) + { + tmp = tmp->next; + } + + if (tmp->next == NULL) + { + // Didn't find the process + return; + } + + // We're at process before the one we want to delete + tmp->next = process->next; + process->next = NULL; + kfree(process); +} + +struct process_t* process_get_next(struct process_t* process) +{ + if (!process) return NULL; + return process->next; +} \ No newline at end of file diff --git a/src/sched/process.h b/src/sched/process.h new file mode 100644 index 0000000..b23249b --- /dev/null +++ b/src/sched/process.h @@ -0,0 +1,26 @@ +#ifndef PROCESS_H +#define PROCESS_H + +typedef enum +{ + READY, + RUNNING, + DEAD +} status_t; + +struct process_t +{ + status_t status; + struct cpu_status_t* context; + struct process_t* next; +}; + +void process_init(); +struct process_t* process_create(); +void process_add(struct process_t** processes_list, struct process_t* process); +void process_delete(struct process_t** processes_list, struct process_t* process); +struct process_t* process_get_next(struct process_t* process); + +void process_display_list(struct process_t* processes_list); + +#endif \ No newline at end of file diff --git a/src/sched/scheduler.c b/src/sched/scheduler.c new file mode 100644 index 0000000..1ac1ed5 --- /dev/null +++ b/src/sched/scheduler.c @@ -0,0 +1,9 @@ +#include "kernel.h" + +extern struct process_t* processes_list; +extern struct process_t* current_process; + +void scheduler_schedule() +{ + DEBUG("Scheduler called!"); +} \ No newline at end of file diff --git a/src/sched/scheduler.h b/src/sched/scheduler.h new file mode 100644 index 0000000..daf425e --- /dev/null +++ b/src/sched/scheduler.h @@ -0,0 +1,6 @@ +#ifndef SCHEDULER_H +#define SCHEDULER_H + +void scheduler_schedule(); + +#endif \ No newline at end of file diff --git a/test.bin b/test.bin new file mode 100644 index 0000000..60f94fd --- /dev/null +++ b/test.bin @@ -0,0 +1 @@ +ΈοΎ­ήλώ \ No newline at end of file -- 2.49.1 From 4a90de95215e57f13bd0631f7d60e66dce2afc09 Mon Sep 17 00:00:00 2001 From: xamidev Date: Sun, 1 Feb 2026 11:25:43 +0100 Subject: [PATCH 2/7] 10ms Round Robin scheduler (blank processes) --- src/idt/idt.c | 7 ++++++- src/kernel.h | 3 +++ src/kmain.c | 27 +++++++++++++++------------ src/sched/process.c | 2 +- src/sched/scheduler.c | 28 +++++++++++++++++++++++++++- src/sched/scheduler.h | 1 + src/string/string.c | 13 +++++++++++++ src/string/string.h | 1 + 8 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/idt/idt.c b/src/idt/idt.c index 434fb63..f6665bf 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -188,7 +188,12 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) case 32: //DEBUG("Timer Interrupt"); ticks++; - scheduler_schedule(); + if (ticks % SCHEDULER_QUANTUM == 0) + { + CLEAR_INTERRUPTS; + scheduler_schedule(); + SET_INTERRUPTS; + } // Send an EOI so that we can continue having interrupts outb(0x20, 0x20); break; diff --git a/src/kernel.h b/src/kernel.h index a4a2736..1ce75d6 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -36,4 +36,7 @@ struct boot_context struct limine_kernel_address_response* kaddr; }; +// 1 tick = 1 ms => quantum = 10ms +#define SCHEDULER_QUANTUM 10 + #endif diff --git a/src/kmain.c b/src/kmain.c index a30cbfe..4874f7f 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -15,6 +15,7 @@ #include "mem/paging/vmm.h" #include "mem/heap/kheap.h" #include "sched/process.h" +#include "sched/scheduler.h" // Limine version used __attribute__((used, section(".limine_requests"))) @@ -57,6 +58,7 @@ static volatile LIMINE_REQUESTS_END_MARKER; // Panic (should dump registers etc. in the future) void hcf() { + //CLEAR_INTERRUPTS; for (;;) { asm("hlt"); @@ -101,7 +103,6 @@ void kmain() gdt_init(); idt_init(); timer_init(); - SET_INTERRUPTS; pmm_init(boot_ctx.mmap, boot_ctx.hhdm); @@ -116,21 +117,23 @@ void kmain() void* ptr3 = kmalloc(5); DEBUG("(KMALLOC TEST) Allocated 5 bytes at 0x%p", ptr3); vmm_init(); + + struct process_t* pedicel = process_create(); + struct process_t* two = process_create(); + struct process_t* three = process_create(); + + process_add(&processes_list, pedicel); + process_add(&processes_list, two); + process_add(&processes_list, three); + process_display_list(processes_list); + + scheduler_init(); + + SET_INTERRUPTS; keyboard_init(FR); - term_init(); kputs(splash); - for (int i=0; i<10; i++) - { - printf("testing, attention please %d\n", i); - } - - struct process_t* pedicel = process_create(); - - process_add(&processes_list, pedicel); - process_display_list(processes_list); - hcf(); } diff --git a/src/sched/process.c b/src/sched/process.c index 3ce3654..574de44 100644 --- a/src/sched/process.c +++ b/src/sched/process.c @@ -19,7 +19,7 @@ void process_display_list(struct process_t* processes_list) struct process_t* tmp = processes_list; while (tmp != NULL) { - DEBUG("{%d: } -> ", process_view_id); + DEBUG("{%d: %p} -> ", process_view_id, tmp); tmp = tmp->next; process_view_id++; } diff --git a/src/sched/scheduler.c b/src/sched/scheduler.c index 1ac1ed5..6bf3a39 100644 --- a/src/sched/scheduler.c +++ b/src/sched/scheduler.c @@ -1,9 +1,35 @@ #include "kernel.h" +#include "process.h" extern struct process_t* processes_list; extern struct process_t* current_process; +// DEBUG: how many times we did schedule +int scheduled = 0; + +void scheduler_init() +{ + // Choose first process? + current_process = processes_list; +} + void scheduler_schedule() { - DEBUG("Scheduler called!"); + //DEBUG("Scheduler called!"); + if (current_process->next != NULL) + { + current_process = current_process->next; + } else + { + current_process = processes_list; + } + scheduled++; + DEBUG("SCHEDULER CALLED: current_process=%p", current_process); + + // debug + /* if (scheduled == 5) + { + DEBUG("enough, halting"); + hcf(); + } */ } \ No newline at end of file diff --git a/src/sched/scheduler.h b/src/sched/scheduler.h index daf425e..6da8442 100644 --- a/src/sched/scheduler.h +++ b/src/sched/scheduler.h @@ -2,5 +2,6 @@ #define SCHEDULER_H void scheduler_schedule(); +void scheduler_init(); #endif \ No newline at end of file diff --git a/src/string/string.c b/src/string/string.c index 1992eee..0d63d14 100644 --- a/src/string/string.c +++ b/src/string/string.c @@ -1,6 +1,19 @@ +#include + char* strcpy(char *dest, const char *src) { char *temp = dest; while((*dest++ = *src++)); return temp; +} + +// https://stackoverflow.com/questions/2488563/strcat-implementation +char *strcat(char *dest, const char *src){ + size_t i,j; + for (i = 0; dest[i] != '\0'; i++) + ; + for (j = 0; src[j] != '\0'; j++) + dest[i+j] = src[j]; + dest[i+j] = '\0'; + return dest; } \ No newline at end of file diff --git a/src/string/string.h b/src/string/string.h index 49a8ea0..1c0306e 100644 --- a/src/string/string.h +++ b/src/string/string.h @@ -2,5 +2,6 @@ #define STRING_H char *strcpy(char *dest, const char *src); +char *strcat(char *dest, const char *src); #endif \ No newline at end of file -- 2.49.1 From 7bb542d9013bb491f6b9c235a111f582c37fb864 Mon Sep 17 00:00:00 2001 From: xamidev Date: Mon, 2 Feb 2026 11:05:27 +0100 Subject: [PATCH 3/7] bump-allocated PID but kheap needs fix to kmalloc more than PAGE_SIZE --- src/kmain.c | 25 +++++++++++++++++------- src/mem/heap/kheap.c | 9 +++++++++ src/mem/heap/kheap.h | 1 + src/sched/process.c | 29 +++++++++++++++++++++++++--- src/sched/process.h | 10 +++++++++- src/sched/scheduler.c | 45 ++++++++++++++++++++++++------------------- src/string/string.c | 7 +++++++ src/string/string.h | 1 + 8 files changed, 96 insertions(+), 31 deletions(-) diff --git a/src/kmain.c b/src/kmain.c index 4874f7f..aeb02fd 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -82,6 +82,21 @@ struct boot_context boot_ctx; extern struct process_t* processes_list; extern struct process_t* current_process; +void pedicel_main(void* arg) +{ + +} + +void two_main(void* arg) +{ + +} + +void three_main(void* arg) +{ + +} + // This is our entry point void kmain() { @@ -118,13 +133,9 @@ void kmain() vmm_init(); - struct process_t* pedicel = process_create(); - struct process_t* two = process_create(); - struct process_t* three = process_create(); - - process_add(&processes_list, pedicel); - process_add(&processes_list, two); - process_add(&processes_list, three); + struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0); + struct process_t* two = process_create("two", (void*)two_main, 0); + struct process_t* three = process_create("three", (void*)three_main, 0); process_display_list(processes_list); scheduler_init(); diff --git a/src/mem/heap/kheap.c b/src/mem/heap/kheap.c index aff1f48..493f4e6 100644 --- a/src/mem/heap/kheap.c +++ b/src/mem/heap/kheap.c @@ -3,6 +3,7 @@ #include "mem/paging/pmm.h" #include #include +#include "sched/process.h" extern uint64_t kernel_phys_base; extern uint64_t kernel_virt_base; @@ -103,4 +104,12 @@ void kfree(void* ptr) // Set it free! struct heap_block_t* block = (struct heap_block_t*)((uintptr_t)ptr - sizeof(struct heap_block_t)); block->free = true; +} + +// Should alloc enough for a stack (at least 64kb) to be used for a process. +// Should return a pointer to top of the stack (as stack grows DOWNWARDS) +void* kalloc_stack() +{ + void* ptr = kmalloc(PROCESS_STACK_SIZE); + return ptr+PROCESS_STACK_SIZE; } \ No newline at end of file diff --git a/src/mem/heap/kheap.h b/src/mem/heap/kheap.h index f8bb8b5..2576c59 100644 --- a/src/mem/heap/kheap.h +++ b/src/mem/heap/kheap.h @@ -22,5 +22,6 @@ struct heap_block_t void kheap_init(); void* kmalloc(size_t size); void kfree(void* ptr); +void* kalloc_stack(); #endif \ No newline at end of file diff --git a/src/sched/process.c b/src/sched/process.c index 574de44..e8e8201 100644 --- a/src/sched/process.c +++ b/src/sched/process.c @@ -2,10 +2,14 @@ #include "process.h" #include "mem/heap/kheap.h" #include "kernel.h" +#include "string/string.h" +#include "mem/gdt/gdt.h" struct process_t* processes_list; struct process_t* current_process; +size_t next_free_pid = 0; + void process_init() { processes_list = NULL; @@ -26,16 +30,35 @@ void process_display_list(struct process_t* processes_list) DEBUG("NULL"); } -struct process_t* process_create() +struct process_t* process_create(char* name, void(*function)(void*), void* arg) { + CLEAR_INTERRUPTS; struct process_t* proc = (struct process_t*)kmalloc(sizeof(struct process_t)); + struct cpu_status_t* ctx = (struct cpu_status_t*)kmalloc(sizeof(struct cpu_status_t)); + + // No more memory? if (!proc) return NULL; + if (!ctx) return NULL; - proc->context = NULL; + strncpy(proc->name, name, PROCESS_NAME_MAX); + proc->pid = next_free_pid++; proc->status = READY; - proc->next = NULL; + proc->context = ctx; + proc->context->iret_ss = KERNEL_DATA_SEGMENT; // process will live in kernel mode + proc->context->iret_rsp = (uint64_t)kalloc_stack(); + proc->context->iret_flags = 0x202; //bit 2 and 9 set (Interrupt Flag) + proc->context->iret_cs = KERNEL_CODE_SEGMENT; + proc->context->iret_rip = (uint64_t)function; // beginning of executable code + proc->context->rdi = (uint64_t)arg; // 1st arg is in rdi (as per x64 calling convention) + proc->context->rbp = 0; + + proc->next = 0; + + process_add(&processes_list, proc); + + SET_INTERRUPTS; return proc; } diff --git a/src/sched/process.h b/src/sched/process.h index b23249b..c60f838 100644 --- a/src/sched/process.h +++ b/src/sched/process.h @@ -1,6 +1,8 @@ #ifndef PROCESS_H #define PROCESS_H +#include + typedef enum { READY, @@ -8,15 +10,21 @@ typedef enum DEAD } status_t; +#define PROCESS_NAME_MAX 64 +#define PROCESS_STACK_SIZE 0x100 // 64kb + struct process_t { + size_t pid; + char name[PROCESS_NAME_MAX]; + status_t status; struct cpu_status_t* context; struct process_t* next; }; void process_init(); -struct process_t* process_create(); +struct process_t* process_create(char* name, void(*function)(void*), void* arg); void process_add(struct process_t** processes_list, struct process_t* process); void process_delete(struct process_t** processes_list, struct process_t* process); struct process_t* process_get_next(struct process_t* process); diff --git a/src/sched/scheduler.c b/src/sched/scheduler.c index 6bf3a39..6a94bf0 100644 --- a/src/sched/scheduler.c +++ b/src/sched/scheduler.c @@ -4,32 +4,37 @@ extern struct process_t* processes_list; extern struct process_t* current_process; -// DEBUG: how many times we did schedule -int scheduled = 0; - void scheduler_init() { // Choose first process? current_process = processes_list; } -void scheduler_schedule() +struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context) { - //DEBUG("Scheduler called!"); - if (current_process->next != NULL) - { - current_process = current_process->next; - } else - { - current_process = processes_list; - } - scheduled++; - DEBUG("SCHEDULER CALLED: current_process=%p", current_process); + current_process->context = context; + current_process->status = READY; - // debug - /* if (scheduled == 5) - { - DEBUG("enough, halting"); - hcf(); - } */ + for (;;) { + struct process_t* prev_process = current_process; + if (current_process->next != NULL) + { + current_process = current_process->next; + } else + { + current_process = processes_list; + } + + if (current_process != NULL && current_process->status == DEAD) + { + process_delete(&prev_process, current_process); + } else + { + current_process->status = RUNNING; + break; + } + } + + DEBUG("SCHEDULER CALLED: current_process=%p", current_process); + return current_process->context; } \ No newline at end of file diff --git a/src/string/string.c b/src/string/string.c index 0d63d14..0d52028 100644 --- a/src/string/string.c +++ b/src/string/string.c @@ -16,4 +16,11 @@ char *strcat(char *dest, const char *src){ dest[i+j] = src[j]; dest[i+j] = '\0'; return dest; +} + +// https://stackoverflow.com/questions/14159625/implementation-of-strncpy +void strncpy(char* dst, const char* src, size_t n) +{ + size_t i = 0; + while(i++ != n && (*dst++ = *src++)); } \ No newline at end of file diff --git a/src/string/string.h b/src/string/string.h index 1c0306e..7e9d8a5 100644 --- a/src/string/string.h +++ b/src/string/string.h @@ -3,5 +3,6 @@ char *strcpy(char *dest, const char *src); char *strcat(char *dest, const char *src); +void strncpy(char* dst, const char* src, size_t n); #endif \ No newline at end of file -- 2.49.1 From 7f997f6611090e349aa0c1306ddacb8139126072 Mon Sep 17 00:00:00 2001 From: xamidev Date: Thu, 5 Feb 2026 21:18:21 +0100 Subject: [PATCH 4/7] alloc_stack ok (HHDM mapped from mmap) --- Makefile | 4 ++- README.md | 20 ++++++++++---- src/idt/idt.c | 2 ++ src/kmain.c | 7 +---- src/mem/heap/kheap.c | 61 +++++++++++++++++++++++++++++------------ src/mem/heap/kheap.h | 1 + src/mem/paging/paging.c | 47 ++++++++++++++++++++++++------- src/mem/paging/paging.h | 9 ++++-- src/sched/process.h | 2 +- 9 files changed, 110 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index dbaa534..c4394ba 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ SOURCES = src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c +PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable + build: rm -f *.o - x86_64-elf-gcc -g -c -Isrc $(SOURCES) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel + x86_64-elf-gcc -g -c -Isrc $(SOURCES) $(PROBLEMATIC_FLAGS) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o nasm -f elf64 src/idt/idt.S -o idt_stub.o x86_64-elf-ld -o pepperk -T linker.ld *.o diff --git a/README.md b/README.md index 6fc722f..e6cc45a 100644 --- a/README.md +++ b/README.md @@ -11,18 +11,28 @@ To run it with QEMU, `make run` The basics that I'm targeting are: +### Basic utility of what we call a "kernel" + - Fix terminal driver (backspace issues, scrolling) OR add Flanterm or equivalent -- Implement paging / see what Limine does at boot with memory management - Implement tasks, and task switching - Load an executable -- Scheduler (round-robin using the PIT timer interrupt) -- Filesystem (TAR for read-only initfs, then maybe read-write using FAT12/16/32 +- Filesystem (TAR for read-only initfs, then maybe read-write using FAT12/16/32 or easier fs) w/ VFS layer - Getting to userspace (syscalls) - Porting musl libc or equivalent -In the future, maybe? +### Scalability/maintenance/expansion features -- SMP support +- Global config header file +- Documentation +- SOME error handling in functions +- Unit tests +- Good error codes (like Linux kernel: ENOMEM, ENOENT, ...) +- Make the panic function work within itself without dependencies + error message (and still get cpu context?) + +### Optional features + +In the future, maybe? +- SMP support (Limine provides functionality to make this easier) - Parsing the ACPI tables and using them for something - Replacing the PIT timer with APIC diff --git a/src/idt/idt.c b/src/idt/idt.c index f6665bf..8ac633f 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -188,12 +188,14 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) case 32: //DEBUG("Timer Interrupt"); ticks++; + if (ticks % SCHEDULER_QUANTUM == 0) { CLEAR_INTERRUPTS; scheduler_schedule(); SET_INTERRUPTS; } + // Send an EOI so that we can continue having interrupts outb(0x20, 0x20); break; diff --git a/src/kmain.c b/src/kmain.c index aeb02fd..68cd159 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -67,7 +67,7 @@ void hcf() void panic(struct cpu_status_t* ctx) { - DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m at rip=%p\nSomething went horribly wrong! vect=0x%.2x errcode=0x%x\nrax=%p rbx=%p rcx=%p rdx=%p\nrsi=%p rdi=%p r8=%p r9=%p\nr10=%p r11=%p r12=%p r13=%p\nr14=%p r15=%p\n\nflags=%p\nstack at rbp=%p\nHalting...", + DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m at rip=%p\nSomething went horribly wrong! vect=0x%.2x errcode=0x%x\n\rrax=%p rbx=%p rcx=%p rdx=%p\n\rrsi=%p rdi=%p r8=%p r9=%p\n\rr10=%p r11=%p r12=%p r13=%p\n\rr14=%p r15=%p\n\n\rflags=%p\n\rstack at rbp=%p\n\rHalting...", ctx->iret_rip, ctx->vector_number, ctx->error_code, ctx->rax, ctx->rbx, ctx->rcx, ctx->rdx, ctx->rsi, ctx->rdi, ctx->r8, ctx->r9, ctx->r10, ctx->r11, ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->iret_flags, @@ -126,11 +126,6 @@ void kmain() kheap_init(); - void* ptr = kmalloc(10); DEBUG("(KMALLOC TEST) Allocated 10 bytes at 0x%p", ptr); - void* ptr2 = kmalloc(200); DEBUG("(KMALLOC TEST) Allocated 200 bytes at 0x%p", ptr2); - kfree(ptr); - void* ptr3 = kmalloc(5); DEBUG("(KMALLOC TEST) Allocated 5 bytes at 0x%p", ptr3); - vmm_init(); struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0); diff --git a/src/mem/heap/kheap.c b/src/mem/heap/kheap.c index 493f4e6..ee1ee34 100644 --- a/src/mem/heap/kheap.c +++ b/src/mem/heap/kheap.c @@ -16,12 +16,24 @@ static uintptr_t end; // Kernel root table (level 4) extern uint64_t *kernel_pml4; -static void kheap_map_page() +static void kheap_grow(size_t size) +{ + size_t pages = ALIGN_UP(size + sizeof(struct heap_block_t), PAGE_SIZE) / PAGE_SIZE; + + if (pages == 0) pages = 1; + + for (size_t i = 0; i < pages; i++) + { + kheap_map_page(); + } +} + +void kheap_map_page() { uintptr_t phys = pmm_alloc(); paging_map_page(kernel_pml4, end, phys, PTE_PRESENT | PTE_WRITABLE | PTE_NOEXEC); end += PAGE_SIZE; - DEBUG("Mapped first kheap page"); + //DEBUG("Mapped first kheap page"); } void kheap_init() @@ -44,6 +56,7 @@ void* kmalloc(size_t size) { // No size, no memory allocated! if (!size) return NULL; + size = ALIGN(size); struct heap_block_t* curr = head; @@ -53,17 +66,16 @@ void* kmalloc(size_t size) if (curr->free && curr->size >= size) { // We split the block if it is big enough - if (curr->size > size + sizeof(struct heap_block_t)) + if (curr->size >= size + BLOCK_MIN_SIZE) { - struct heap_block_t* new_block = (struct heap_block_t*)((uintptr_t)curr + sizeof(struct heap_block_t) + size); - // We have to subtract the size of our block struct - new_block->size = curr->size - size - sizeof(struct heap_block_t); - new_block->free = true; - - // Then we chain up the block in the list - new_block->next = curr->next; - curr->next = new_block; + //struct heap_block_t* new_block = (struct heap_block_t*)((uintptr_t)curr + sizeof(struct heap_block_t) + size); + struct heap_block_t* split = (struct heap_block_t*)((uintptr_t)curr + sizeof(*curr) + size); + + split->size = curr->size - size - sizeof(*curr); + split->free = true; + split->next = curr->next; + curr->next = split; curr->size = size; } @@ -75,14 +87,14 @@ void* kmalloc(size_t size) curr = curr->next; } - // If we're hear it means we didn't have enough memory + // If we're here it means we didn't have enough memory // for the block allocation. So we will allocate more.. uintptr_t old_end = end; - kheap_map_page(); + kheap_grow(size + sizeof(struct heap_block_t)); struct heap_block_t* block = (struct heap_block_t*)old_end; - block->size = PAGE_SIZE - sizeof(struct heap_block_t); - block->free = false; + block->size = ALIGN_UP(end - old_end - sizeof(struct heap_block_t), 16); + block->free = true; block->next = NULL; // Put the block at the end of the list @@ -93,7 +105,7 @@ void* kmalloc(size_t size) } curr->next = block; - return (void*)((uintptr_t)block + sizeof(struct heap_block_t)); + return kmalloc(size); } void kfree(void* ptr) @@ -104,12 +116,25 @@ void kfree(void* ptr) // Set it free! struct heap_block_t* block = (struct heap_block_t*)((uintptr_t)ptr - sizeof(struct heap_block_t)); block->free = true; + + // merge adjacent free blocks (coalescing) + struct heap_block_t* curr = head; + while (curr && curr->next) + { + if (curr->free && curr->next->free) + { + curr->size += sizeof(*curr) + curr->next->size; + curr->next = curr->next->next; + continue; + } + curr = curr->next; + } } // Should alloc enough for a stack (at least 64kb) to be used for a process. // Should return a pointer to top of the stack (as stack grows DOWNWARDS) void* kalloc_stack() { - void* ptr = kmalloc(PROCESS_STACK_SIZE); - return ptr+PROCESS_STACK_SIZE; + uint8_t* ptr = kmalloc(PROCESS_STACK_SIZE); + return ptr ? ptr+PROCESS_STACK_SIZE : NULL; } \ No newline at end of file diff --git a/src/mem/heap/kheap.h b/src/mem/heap/kheap.h index 2576c59..61b097e 100644 --- a/src/mem/heap/kheap.h +++ b/src/mem/heap/kheap.h @@ -23,5 +23,6 @@ void kheap_init(); void* kmalloc(size_t size); void kfree(void* ptr); void* kalloc_stack(); +void kheap_map_page(); #endif \ No newline at end of file diff --git a/src/mem/paging/paging.c b/src/mem/paging/paging.c index ce07aa1..c2a1a28 100644 --- a/src/mem/paging/paging.c +++ b/src/mem/paging/paging.c @@ -69,7 +69,7 @@ void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_ root_table[pml4_i] = VIRT_TO_PHYS(pdpt) | PTE_PRESENT | PTE_WRITABLE; } else { - pdpt = (uint64_t *)PHYS_TO_VIRT(root_table[pml4_i] & ~0xFFFULL); + pdpt = (uint64_t *)PHYS_TO_VIRT(root_table[pml4_i] & PTE_ADDR_MASK); } // PDPT: same here @@ -79,7 +79,7 @@ void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_ pdpt[pdpt_i] = VIRT_TO_PHYS(pd) | PTE_PRESENT | PTE_WRITABLE; } else { - pd = (uint64_t *)PHYS_TO_VIRT(pdpt[pdpt_i] & ~0xFFFULL); + pd = (uint64_t *)PHYS_TO_VIRT(pdpt[pdpt_i] & PTE_ADDR_MASK); } // PD: and here @@ -89,7 +89,7 @@ void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_ pd[pd_i] = VIRT_TO_PHYS(pt) | PTE_PRESENT | PTE_WRITABLE; } else { - pt = (uint64_t *)PHYS_TO_VIRT(pd[pd_i] & ~0xFFFULL); + pt = (uint64_t *)PHYS_TO_VIRT(pd[pd_i] & PTE_ADDR_MASK); } // PT: finally, populate the page table entry @@ -102,13 +102,16 @@ void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_ uint64_t kernel_phys_base; uint64_t kernel_virt_base; -void paging_init(struct limine_kernel_address_response* kaddr, struct limine_framebuffer* fb) +extern struct boot_context boot_ctx; + +void paging_init() { // We should map the kernel, GDT, IDT, stack, framebuffer. // Optionally we could map ACPI tables (we can find them in the Limine memmap) - kernel_phys_base = kaddr->physical_base; - kernel_virt_base = kaddr->virtual_base; + kernel_phys_base = boot_ctx.kaddr->physical_base; + kernel_virt_base = boot_ctx.kaddr->virtual_base; + struct limine_framebuffer* fb = boot_ctx.fb; DEBUG("Kernel lives at virt=0x%p phys=0x%p", kernel_virt_base, kernel_phys_base); @@ -117,14 +120,38 @@ void paging_init(struct limine_kernel_address_response* kaddr, struct limine_fra // for debug uint64_t page_count = 0; - // HHDM map first 1 GB using given offset - for (uint64_t i=0; i<0x40000000; i += PAGE_SIZE) + // Find max physical address from limine memmap + uint64_t max_phys = 0; + for (uint64_t i=0; ientry_count; i++) + { + struct limine_memmap_entry* entry = boot_ctx.mmap->entries[i]; + if (entry->length == 0) + { + continue; + } + uint64_t top = entry->base + entry->length; + if (top > max_phys) + { + max_phys = top; + } + //DEBUG("max_phys=0x%p", max_phys); + } + + // 4GB + if (max_phys > 0x100000000) + { + DEBUG("WARNING: max_phys capped to 4GB (0x100000000) (from max_phys=%p)", max_phys); + max_phys = 0x100000000; + } + + // HHDM map up to max_phys or 4GB, whichever is smaller, using given offset + for (uint64_t i=0; i #include +#include "mem/heap/kheap.h" -void paging_init(struct limine_kernel_address_response* kaddr, struct limine_framebuffer* fb); +void paging_init(); void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_t flags); extern uint64_t hhdm_off; @@ -15,10 +16,14 @@ extern uint64_t hhdm_off; #define PHYS_TO_VIRT(x) ((void*)((uintptr_t)(x) + hhdm_off)) #define VIRT_TO_PHYS(x) ((uintptr_t)(x) - hhdm_off) +#define PTE_ADDR_MASK 0x000FFFFFFFFFF000 // Stole it #define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) #define ALIGN_DOWN(x, align) ((x) & ~((align) - 1)) -#define PAGE_ALIGN_DOWN(x) ((x) & ~0xFFFULL) +#define PAGE_ALIGN_DOWN(x) ((x) & PTE_ADDR_MASK) + +#define ALIGN(size) ALIGN_UP(size, 16) +#define BLOCK_MIN_SIZE (sizeof(struct heap_block_t) + 16) #define PML4_INDEX(x) (((x) >> 39) & 0x1FF) #define PDPT_INDEX(x) (((x) >> 30) & 0x1FF) diff --git a/src/sched/process.h b/src/sched/process.h index c60f838..9ec19bd 100644 --- a/src/sched/process.h +++ b/src/sched/process.h @@ -11,7 +11,7 @@ typedef enum } status_t; #define PROCESS_NAME_MAX 64 -#define PROCESS_STACK_SIZE 0x100 // 64kb +#define PROCESS_STACK_SIZE 0x10000 // 64kb struct process_t { -- 2.49.1 From 38710653be247fcca65761eebab9dcd28d65c3bd Mon Sep 17 00:00:00 2001 From: xamidev Date: Fri, 6 Feb 2026 13:59:46 +0100 Subject: [PATCH 5/7] Config header file + comment header --- README.md | 2 +- src/config.h | 30 ++++++++++++++++++++++++++++++ src/idt/idt.S | 6 +++++- src/idt/idt.c | 6 ++++++ src/idt/idt.h | 6 ++++++ src/io/kbd/ps2.c | 6 +++++- src/io/kbd/ps2.h | 6 ++++++ src/io/serial/serial.c | 6 ++++++ src/io/serial/serial.h | 6 ++++++ src/io/term/term.c | 9 ++++++++- src/io/term/term.h | 6 ++++++ src/kernel.h | 10 ++++++---- src/kmain.c | 7 +++++++ src/mem/gdt/gdt.c | 6 ++++++ src/mem/gdt/gdt.h | 6 ++++++ src/mem/heap/kheap.c | 7 +++++++ src/mem/heap/kheap.h | 9 ++++++--- src/mem/misc/utils.c | 6 ++++++ src/mem/misc/utils.h | 7 +++++++ src/mem/paging/paging.c | 7 +++++++ src/mem/paging/paging.h | 13 ++++++------- src/mem/paging/pmm.c | 6 +++++- src/mem/paging/pmm.h | 6 ++++++ src/mem/paging/vmm.c | 6 ++++++ src/mem/paging/vmm.h | 6 ++++++ src/sched/process.c | 7 +++++++ src/sched/process.h | 10 +++++++--- src/sched/scheduler.c | 8 +++++++- src/sched/scheduler.h | 6 ++++++ src/string/string.c | 6 ++++++ src/string/string.h | 6 ++++++ src/time/timer.c | 6 ++++++ src/time/timer.h | 6 ++++++ 33 files changed, 223 insertions(+), 23 deletions(-) create mode 100644 src/config.h diff --git a/README.md b/README.md index e6cc45a..d2faa93 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The basics that I'm targeting are: ### Basic utility of what we call a "kernel" - Fix terminal driver (backspace issues, scrolling) OR add Flanterm or equivalent -- Implement tasks, and task switching +- Implement tasks, and task switching + context switching and spinlock acquire/release - Load an executable - Filesystem (TAR for read-only initfs, then maybe read-write using FAT12/16/32 or easier fs) w/ VFS layer - Getting to userspace (syscalls) diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..4ddea04 --- /dev/null +++ b/src/config.h @@ -0,0 +1,30 @@ +/* + * @author xamidev + * @brief PepperOS configuration file + * @license GPL-3.0-only + */ + +#ifndef CONFIG_H +#define CONFIG_H + +/* version */ +#define PEPPEROS_VERSION_MAJOR "0" +#define PEPPEROS_VERSION_MINOR "0" +#define PEPPEROS_VERSION_PATCH "1" + +/* process */ +#define PROCESS_NAME_MAX 64 +#define PROCESS_STACK_SIZE 0x10000 // 64kb + +/* kernel */ +#define KERNEL_BASE 0xFFFFFFFF80000000ULL +// 2 MB should be enough (as of now, the whole kernel ELF is around 75kb) +#define KERNEL_SIZE 0x200000 + +/* heap */ +#define KHEAP_SIZE (16*1024*1024) + +/* term */ +#define TERM_HISTORY_MAX_LINES 256 + +#endif \ No newline at end of file diff --git a/src/idt/idt.S b/src/idt/idt.S index fe5cf58..de819e6 100644 --- a/src/idt/idt.S +++ b/src/idt/idt.S @@ -1,4 +1,8 @@ -; Assembly stub for the IDT +; +; @author xamidev +; @brief Stub for Interrupt Descriptor Table handlers +; @license GPL-3.0-only +; bits 64 diff --git a/src/idt/idt.c b/src/idt/idt.c index 8ac633f..44584e3 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Interrupt Descriptor Table setup and dispatching + * @license GPL-3.0-only + */ + #include "idt.h" #include #include diff --git a/src/idt/idt.h b/src/idt/idt.h index 3b61abb..898e49c 100644 --- a/src/idt/idt.h +++ b/src/idt/idt.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Interrupt Descriptor Table setup and dispatching + * @license GPL-3.0-only + */ + #ifndef IDT_H #define IDT_H diff --git a/src/io/kbd/ps2.c b/src/io/kbd/ps2.c index df82811..79d777e 100644 --- a/src/io/kbd/ps2.c +++ b/src/io/kbd/ps2.c @@ -1,4 +1,8 @@ -// PS/2 Keyboard support +/* + * @author xamidev + * @brief PS/2 Keyboard driver + * @license GPL-3.0-only + */ #include "io/serial/serial.h" #include "ps2.h" diff --git a/src/io/kbd/ps2.h b/src/io/kbd/ps2.h index 5b1c207..031fd91 100644 --- a/src/io/kbd/ps2.h +++ b/src/io/kbd/ps2.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief PS/2 Keyboard driver + * @license GPL-3.0-only + */ + #ifndef PS2_H #define PS2_H diff --git a/src/io/serial/serial.c b/src/io/serial/serial.c index c70af76..9073839 100644 --- a/src/io/serial/serial.c +++ b/src/io/serial/serial.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Debug serial driver + * @license GPL-3.0-only + */ + #include #include "serial.h" diff --git a/src/io/serial/serial.h b/src/io/serial/serial.h index 6144ce8..dc29d14 100644 --- a/src/io/serial/serial.h +++ b/src/io/serial/serial.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Debug serial driver + * @license GPL-3.0-only + */ + #ifndef SERIAL_H #define SERIAL_H diff --git a/src/io/term/term.c b/src/io/term/term.c index ae91835..98893ed 100644 --- a/src/io/term/term.c +++ b/src/io/term/term.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Framebuffer-based terminal driver + * @license GPL-3.0-only + */ + // Terminal output /* There are a couple of bugs here and there but for now I don't care too much @@ -10,6 +16,7 @@ because this shitty implementation will be replaced one day by Flanterm #include #include "term.h" #include "mem/misc/utils.h" +#include "config.h" extern struct boot_context boot_ctx; @@ -37,7 +44,7 @@ static Cursor cursor = {0, 0}; static uint8_t* fb; static struct limine_framebuffer* framebuffer; -uint8_t lines_length[MAX_LINES]; +uint8_t lines_length[TERM_HISTORY_MAX_LINES]; static inline size_t term_max_cols(void) { diff --git a/src/io/term/term.h b/src/io/term/term.h index e53981d..1ed14f1 100644 --- a/src/io/term/term.h +++ b/src/io/term/term.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Framebuffer-based terminal driver + * @license GPL-3.0-only + */ + #ifndef TERM_H #define TERM_H diff --git a/src/kernel.h b/src/kernel.h index 1ce75d6..2ac193c 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -1,10 +1,12 @@ +/* + * @author xamidev + * @brief Kernel global macros + * @license GPL-3.0-only + */ + #ifndef KERNEL_H #define KERNEL_H -#define PEPPEROS_VERSION_MAJOR "0" -#define PEPPEROS_VERSION_MINOR "0" -#define PEPPEROS_VERSION_PATCH "1" - enum ErrorCodes { ENOMEM, diff --git a/src/kmain.c b/src/kmain.c index 68cd159..d324331 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief PepperOS kernel entry point + * @license GPL-3.0-only + */ + #include #include #include @@ -16,6 +22,7 @@ #include "mem/heap/kheap.h" #include "sched/process.h" #include "sched/scheduler.h" +#include "config.h" // Limine version used __attribute__((used, section(".limine_requests"))) diff --git a/src/mem/gdt/gdt.c b/src/mem/gdt/gdt.c index 68961b5..fd5a318 100644 --- a/src/mem/gdt/gdt.c +++ b/src/mem/gdt/gdt.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Global Descriptor Table (for legacy reasons) + * @license GPL-3.0-only + */ + #include "gdt.h" #include #include "io/serial/serial.h" diff --git a/src/mem/gdt/gdt.h b/src/mem/gdt/gdt.h index 3c15b3a..a122387 100644 --- a/src/mem/gdt/gdt.h +++ b/src/mem/gdt/gdt.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Global Descriptor Table (for legacy reasons) + * @license GPL-3.0-only + */ + #ifndef GDT_H #define GDT_H diff --git a/src/mem/heap/kheap.c b/src/mem/heap/kheap.c index ee1ee34..220471a 100644 --- a/src/mem/heap/kheap.c +++ b/src/mem/heap/kheap.c @@ -1,9 +1,16 @@ +/* + * @author xamidev + * @brief Kernel heap + * @license GPL-3.0-only + */ + #include "kheap.h" #include "mem/paging/paging.h" #include "mem/paging/pmm.h" #include #include #include "sched/process.h" +#include "config.h" extern uint64_t kernel_phys_base; extern uint64_t kernel_virt_base; diff --git a/src/mem/heap/kheap.h b/src/mem/heap/kheap.h index 61b097e..111cf7b 100644 --- a/src/mem/heap/kheap.h +++ b/src/mem/heap/kheap.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Kernel heap + * @license GPL-3.0-only + */ + #ifndef KHEAP_H #define KHEAP_H @@ -6,9 +12,6 @@ // When the kernel heap is ready, we can alloc our VM object linked list // and then continue working on the VMM. -// 16MB should be enough for some linked lists -#define KHEAP_SIZE (16*1024*1024) - #include #include diff --git a/src/mem/misc/utils.c b/src/mem/misc/utils.c index bb5ca8a..8f7a43f 100644 --- a/src/mem/misc/utils.c +++ b/src/mem/misc/utils.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Common memory utilities + * @license GPL-3.0-only + */ + #include #include #include diff --git a/src/mem/misc/utils.h b/src/mem/misc/utils.h index 169d88d..197bf12 100644 --- a/src/mem/misc/utils.h +++ b/src/mem/misc/utils.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Common memory utilities + * @license GPL-3.0-only + */ + #ifndef MEM_UTILS_H #define MEM_UTILS_H @@ -8,6 +14,7 @@ void* memset(void* s, int c, size_t n); void* memmove(void *dest, const void* src, size_t n); int memcmp(const void* s1, const void* s2, size_t n); +// DEBUG void memmap_display(struct limine_memmap_response* response); void hhdm_display(struct limine_hhdm_response* hhdm); diff --git a/src/mem/paging/paging.c b/src/mem/paging/paging.c index c2a1a28..0597943 100644 --- a/src/mem/paging/paging.c +++ b/src/mem/paging/paging.c @@ -1,8 +1,15 @@ +/* + * @author xamidev + * @brief x64 4-level paging implementation + * @license GPL-3.0-only + */ + #include "paging.h" #include "pmm.h" #include #include #include +#include "config.h" /* Paging on x86 uses four different page table levels: diff --git a/src/mem/paging/paging.h b/src/mem/paging/paging.h index b93be70..34afeaa 100644 --- a/src/mem/paging/paging.h +++ b/src/mem/paging/paging.h @@ -1,8 +1,13 @@ +/* + * @author xamidev + * @brief x64 4-level paging implementation + * @license GPL-3.0-only + */ + #ifndef PAGING_H #define PAGING_H #define PAGE_SIZE 4096 -#define BITS_PER_ROW 64 #include #include @@ -40,10 +45,4 @@ extern uint64_t hhdm_off; #define PTE_HUGE (1ULL << 7) #define PTE_NOEXEC (1ULL << 63) -// Specified in linker.ld -#define KERNEL_BASE 0xFFFFFFFF80000000ULL - -// 2 MB should be enough (as of now, the whole kernel ELF is around 75kb) -#define KERNEL_SIZE 0x200000 - #endif \ No newline at end of file diff --git a/src/mem/paging/pmm.c b/src/mem/paging/pmm.c index 2128f88..6b0d616 100644 --- a/src/mem/paging/pmm.c +++ b/src/mem/paging/pmm.c @@ -1,4 +1,8 @@ -// OMG here we are. I'm cooked. +/* + * @author xamidev + * @brief Physical memory manager from freelist + * @license GPL-3.0-only + */ /* pmm - Physical Memory Manager diff --git a/src/mem/paging/pmm.h b/src/mem/paging/pmm.h index 084c334..a166727 100644 --- a/src/mem/paging/pmm.h +++ b/src/mem/paging/pmm.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Physical memory manager from freelist + * @license GPL-3.0-only + */ + #ifndef PAGING_PMM_H #define PAGING_PMM_H diff --git a/src/mem/paging/vmm.c b/src/mem/paging/vmm.c index 1d5a4ad..f7f3256 100644 --- a/src/mem/paging/vmm.c +++ b/src/mem/paging/vmm.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Virtual memory manager + * @license GPL-3.0-only + */ + /* The VMM (virtual memory manager) will have two roles: - mapping pages diff --git a/src/mem/paging/vmm.h b/src/mem/paging/vmm.h index 3f862be..b70e1a8 100644 --- a/src/mem/paging/vmm.h +++ b/src/mem/paging/vmm.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Virtual memory manager + * @license GPL-3.0-only + */ + #ifndef VMM_H #define VMM_H diff --git a/src/sched/process.c b/src/sched/process.c index e8e8201..9161a37 100644 --- a/src/sched/process.c +++ b/src/sched/process.c @@ -1,9 +1,16 @@ +/* + * @author xamidev + * @brief Process linked list implementation + * @license GPL-3.0-only + */ + #include #include "process.h" #include "mem/heap/kheap.h" #include "kernel.h" #include "string/string.h" #include "mem/gdt/gdt.h" +#include "config.h" struct process_t* processes_list; struct process_t* current_process; diff --git a/src/sched/process.h b/src/sched/process.h index 9ec19bd..b5b0124 100644 --- a/src/sched/process.h +++ b/src/sched/process.h @@ -1,7 +1,14 @@ +/* + * @author xamidev + * @brief Process definition + * @license GPL-3.0-only + */ + #ifndef PROCESS_H #define PROCESS_H #include +#include "config.h" typedef enum { @@ -10,9 +17,6 @@ typedef enum DEAD } status_t; -#define PROCESS_NAME_MAX 64 -#define PROCESS_STACK_SIZE 0x10000 // 64kb - struct process_t { size_t pid; diff --git a/src/sched/scheduler.c b/src/sched/scheduler.c index 6a94bf0..0299ce8 100644 --- a/src/sched/scheduler.c +++ b/src/sched/scheduler.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Round-robin scheduler + * @license GPL-3.0-only + */ + #include "kernel.h" #include "process.h" @@ -35,6 +41,6 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context) } } - DEBUG("SCHEDULER CALLED: current_process=%p", current_process); + DEBUG("current_process={pid=%u name='%s'}", current_process->pid, current_process->name); return current_process->context; } \ No newline at end of file diff --git a/src/sched/scheduler.h b/src/sched/scheduler.h index 6da8442..b4d7516 100644 --- a/src/sched/scheduler.h +++ b/src/sched/scheduler.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Round-robin scheduler + * @license GPL-3.0-only + */ + #ifndef SCHEDULER_H #define SCHEDULER_H diff --git a/src/string/string.c b/src/string/string.c index 0d52028..f95f000 100644 --- a/src/string/string.c +++ b/src/string/string.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief String manipulation utilities + * @license GPL-3.0-only + */ + #include char* strcpy(char *dest, const char *src) diff --git a/src/string/string.h b/src/string/string.h index 7e9d8a5..7a59a3a 100644 --- a/src/string/string.h +++ b/src/string/string.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief String manipulation functions + * @license GPL-3.0-only + */ + #ifndef STRING_H #define STRING_H diff --git a/src/time/timer.c b/src/time/timer.c index a632a57..781c677 100644 --- a/src/time/timer.c +++ b/src/time/timer.c @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief Programmable Interval Timer init and enabling + * @license GPL-3.0-only + */ + #include #include "io/serial/serial.h" #include diff --git a/src/time/timer.h b/src/time/timer.h index bb0c8d4..8b398fd 100644 --- a/src/time/timer.h +++ b/src/time/timer.h @@ -1,3 +1,9 @@ +/* + * @author xamidev + * @brief PIT functions + * @license GPL-3.0-only + */ + #ifndef TIMER_H #define TIMER_H -- 2.49.1 From 8aad1235c38bbf521cc7c8c2bc66f820dde0e02b Mon Sep 17 00:00:00 2001 From: xamidev Date: Fri, 6 Feb 2026 14:39:19 +0100 Subject: [PATCH 6/7] A bit of cleaning --- Makefile | 2 +- README.md | 1 - src/boot/boot.c | 41 ++++++++++++++++++++++++++++++++ src/config.h | 5 ++++ src/idt/idt.c | 4 ++-- src/io/term/term.h | 2 -- src/kernel.h | 3 --- src/kmain.c | 58 +++++++++++----------------------------------- 8 files changed, 62 insertions(+), 54 deletions(-) create mode 100644 src/boot/boot.c diff --git a/Makefile b/Makefile index c4394ba..ce177d1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SOURCES = src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c +SOURCES = src/boot/boot.c src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable diff --git a/README.md b/README.md index d2faa93..7b60818 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ The basics that I'm targeting are: ### Scalability/maintenance/expansion features -- Global config header file - Documentation - SOME error handling in functions - Unit tests diff --git a/src/boot/boot.c b/src/boot/boot.c new file mode 100644 index 0000000..f10c4e1 --- /dev/null +++ b/src/boot/boot.c @@ -0,0 +1,41 @@ +/* + * @author xamidev + * @brief Limine requests for boot + * @license GPL-3.0-only + */ + +#include + +// Framebuffer request +__attribute__((used, section(".limine_requests"))) +volatile struct limine_framebuffer_request framebuffer_request = { + .id = LIMINE_FRAMEBUFFER_REQUEST, + .revision = 0 +}; + +// Memory map request +__attribute__((used, section(".limine_requests"))) +volatile struct limine_memmap_request memmap_request = { + .id = LIMINE_MEMMAP_REQUEST, + .revision = 0 +}; + +// Higher Half Direct Map +__attribute__((used, section(".limine_requests"))) +volatile struct limine_hhdm_request hhdm_request = { + .id = LIMINE_HHDM_REQUEST, + .revision = 0 +}; + +// Executable Address/Kernel Address (find base phys/virt address of kernel) +__attribute__((used, section(".limine_requests"))) +volatile struct limine_kernel_address_request kerneladdr_request = { + .id = LIMINE_KERNEL_ADDRESS_REQUEST, + .revision = 0 +}; + +__attribute__((used, section(".limine_requests_start"))) +volatile LIMINE_REQUESTS_START_MARKER; + +__attribute__((used, section(".limine_requests_end"))) +volatile LIMINE_REQUESTS_END_MARKER; \ No newline at end of file diff --git a/src/config.h b/src/config.h index 4ddea04..a77d092 100644 --- a/src/config.h +++ b/src/config.h @@ -11,11 +11,16 @@ #define PEPPEROS_VERSION_MAJOR "0" #define PEPPEROS_VERSION_MINOR "0" #define PEPPEROS_VERSION_PATCH "1" +#define PEPPEROS_SPLASH "pepperOS version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n" /* process */ #define PROCESS_NAME_MAX 64 #define PROCESS_STACK_SIZE 0x10000 // 64kb +/* sched */ +// 1 tick = 1 ms => quantum = 10ms +#define SCHEDULER_QUANTUM 10 + /* kernel */ #define KERNEL_BASE 0xFFFFFFFF80000000ULL // 2 MB should be enough (as of now, the whole kernel ELF is around 75kb) diff --git a/src/idt/idt.c b/src/idt/idt.c index 44584e3..d70e89a 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -12,6 +12,7 @@ #include #include #include "sched/scheduler.h" +#include "config.h" struct interrupt_descriptor idt[256]; struct idtr idt_reg; @@ -191,8 +192,7 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) DEBUG("Control Protection Exception!"); break; - case 32: - //DEBUG("Timer Interrupt"); + case 32: // Timer Interrupt ticks++; if (ticks % SCHEDULER_QUANTUM == 0) diff --git a/src/io/term/term.h b/src/io/term/term.h index 1ed14f1..99c0cd9 100644 --- a/src/io/term/term.h +++ b/src/io/term/term.h @@ -17,8 +17,6 @@ enum TermColors WHITE = 0xffffff }; -#define MAX_LINES 256 - #define PSF1_FONT_MAGIC 0x0436 typedef struct diff --git a/src/kernel.h b/src/kernel.h index 2ac193c..11f5777 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -38,7 +38,4 @@ struct boot_context struct limine_kernel_address_response* kaddr; }; -// 1 tick = 1 ms => quantum = 10ms -#define SCHEDULER_QUANTUM 10 - #endif diff --git a/src/kmain.c b/src/kmain.c index d324331..7d74dd2 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -26,52 +26,17 @@ // Limine version used __attribute__((used, section(".limine_requests"))) -static volatile LIMINE_BASE_REVISION(3); +volatile LIMINE_BASE_REVISION(3); -// Framebuffer request -__attribute__((used, section(".limine_requests"))) -static volatile struct limine_framebuffer_request framebuffer_request = { - .id = LIMINE_FRAMEBUFFER_REQUEST, - .revision = 0 -}; - -// Memory map request -__attribute__((used, section(".limine_requests"))) -static volatile struct limine_memmap_request memmap_request = { - .id = LIMINE_MEMMAP_REQUEST, - .revision = 0 -}; - -// Higher Half Direct Map -__attribute__((used, section(".limine_requests"))) -static volatile struct limine_hhdm_request hhdm_request = { - .id = LIMINE_HHDM_REQUEST, - .revision = 0 -}; - -// Executable Address/Kernel Address (find base phys/virt address of kernel) -__attribute__((used, section(".limine_requests"))) -static volatile struct limine_kernel_address_request kerneladdr_request = { - .id = LIMINE_KERNEL_ADDRESS_REQUEST, - .revision = 0 -}; - -__attribute__((used, section(".limine_requests_start"))) -static volatile LIMINE_REQUESTS_START_MARKER; - -__attribute__((used, section(".limine_requests_end"))) -static volatile LIMINE_REQUESTS_END_MARKER; - -// Panic (should dump registers etc. in the future) +// Halt and catch fire (makes machine stall) void hcf() { - //CLEAR_INTERRUPTS; - for (;;) - { - asm("hlt"); - } + CLEAR_INTERRUPTS; for (;;)asm("hlt"); } +// Doing nothing (can be interrupted) +void idle() {for(;;)asm("hlt");} + void panic(struct cpu_status_t* ctx) { DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m at rip=%p\nSomething went horribly wrong! vect=0x%.2x errcode=0x%x\n\rrax=%p rbx=%p rcx=%p rdx=%p\n\rrsi=%p rdi=%p r8=%p r9=%p\n\rr10=%p r11=%p r12=%p r13=%p\n\rr14=%p r15=%p\n\n\rflags=%p\n\rstack at rbp=%p\n\rHalting...", @@ -82,10 +47,13 @@ void panic(struct cpu_status_t* ctx) hcf(); } -const char* splash = "pepperOS version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n"; - struct boot_context boot_ctx; +extern volatile struct limine_framebuffer_request framebuffer_request; +extern volatile struct limine_memmap_request memmap_request; +extern volatile struct limine_hhdm_request hhdm_request; +extern volatile struct limine_kernel_address_request kerneladdr_request; + extern struct process_t* processes_list; extern struct process_t* current_process; @@ -146,7 +114,7 @@ void kmain() keyboard_init(FR); term_init(); - kputs(splash); + kputs(PEPPEROS_SPLASH); - hcf(); + idle(); } -- 2.49.1 From 4fbd9b39879cd9dbce8fe2eec38faccc96088a81 Mon Sep 17 00:00:00 2001 From: xamidev Date: Fri, 6 Feb 2026 21:44:51 +0100 Subject: [PATCH 7/7] minor fix --- src/sched/process.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sched/process.h b/src/sched/process.h index b5b0124..e6dedbc 100644 --- a/src/sched/process.h +++ b/src/sched/process.h @@ -35,4 +35,4 @@ struct process_t* process_get_next(struct process_t* process); void process_display_list(struct process_t* processes_list); -#endif \ No newline at end of file +#endif -- 2.49.1