From c60b78b3075b9a6acfadecde4bf52bbddd8e77cd Mon Sep 17 00:00:00 2001 From: Atheria Date: Wed, 9 Jul 2025 15:38:41 +0700 Subject: [PATCH] FCKED --- Boot/boot.asm | 32 +++++--- Kernel/Core/Kernel.c | 24 +++++- Kernel/Drivers/Interrupts.c | 25 ++++-- Kernel/Process/Process.c | 152 +++++++++++++----------------------- Kernel/Process/Process.h | 25 +++--- Kernel/Process/Switch.asm | 118 ++++++++++++++++++---------- Kernel/System/Syscall.c | 2 +- grub.cfg | 1 + meson.build | 2 +- 9 files changed, 208 insertions(+), 173 deletions(-) diff --git a/Boot/boot.asm b/Boot/boot.asm index 8715fff..9e7cbc5 100644 --- a/Boot/boot.asm +++ b/Boot/boot.asm @@ -3,7 +3,7 @@ header_start: dd 0xE85250D6 ; Multiboot2 magic number dd 0 ; Architecture 0 (protected mode i386) dd header_end - header_start ; header length - dd -(0xE85250D6 + 0 + (header_end - header_start)) ; checksum + dd 0x17ADAF12 ; checksum (calculated: -(0xE85250D6 + 0 + 24)) ; end tag dw 0 ; type dw 0 ; flags @@ -14,6 +14,13 @@ bits 32 section .text +; Macro for debugging output +%macro debug_print 1 + mov dx, 0xE9 + mov al, %1 + out dx, al +%endmacro + ; Enhanced GDT for long mode (keeping your original structure) gdt64: dq 0 ; NULL descriptor @@ -37,12 +44,14 @@ gdt64: global start start: + debug_print '1' cli cld ; Save multiboot info for kernel mov [multiboot_magic], eax mov [multiboot_info], ebx + debug_print 'B' ; Setup temporary stack mov esp, stack_top @@ -52,15 +61,18 @@ start: ; Load GDT (same as original) lgdt [gdt64.pointer] + debug_print '2' ; Enable PAE (same as original) mov eax, cr4 or eax, 1 << 5 mov cr4, eax + debug_print '3' ; Setup paging (keeping your original mapping approach) mov edi, pml4_table mov cr3, edi + debug_print '4' ; Initialize the tables by zeroing them out (same as original) mov edi, pml4_table @@ -89,19 +101,23 @@ start: add edi, 8 add eax, 0x200000 ; Next 2MB loop .map_loop + debug_print '5' ; Enable long mode (same as original) mov ecx, 0xC0000080 ; EFER MSR rdmsr or eax, 1 << 8 ; LME (Long Mode Enable) wrmsr + debug_print '6' ; Enable paging (same as original) mov eax, cr0 or eax, 1 << 31 ; PG (Paging) mov cr0, eax + debug_print '7' ; Jump to long mode (same as original) + debug_print '8' jmp 0x08:long_mode ; Check and enable CPU features (non-critical) @@ -144,6 +160,7 @@ bits 64 extern KernelMain long_mode: + debug_print '9' ; Load data segments (same as original) mov ax, 0x10 ; selector for data segment mov ss, ax @@ -157,18 +174,13 @@ long_mode: ; Clear direction flag cld - - ; DEBUG: Write 'BOOT' to VGA before calling C code - mov rax, 0xb8000 - mov word [rax], 0x0442 ; Red 'B' - mov word [rax+2], 0x044F ; Red 'O' - mov word [rax+4], 0x044F ; Red 'O' - mov word [rax+6], 0x0454 ; Red 'T' + ; Pass multiboot info to kernel mov rdi, [multiboot_magic] mov rsi, [multiboot_info] + debug_print 'A' ; Jump to the C kernel (same as original) call KernelMain @@ -179,8 +191,8 @@ long_mode: jmp .halt_loop section .data -multiboot_magic: dq 0 -multiboot_info: dq 0 +multiboot_magic: dd 0 +multiboot_info: dd 0 section .bss diff --git a/Kernel/Core/Kernel.c b/Kernel/Core/Kernel.c index 5c62b03..ece7293 100644 --- a/Kernel/Core/Kernel.c +++ b/Kernel/Core/Kernel.c @@ -15,6 +15,8 @@ int CurrentLine = 0; int CurrentColumn = 0; void ClearScreen(){ + PrintKernel("ClearScreen\n"); + char *vidptr = (char*)0xb8000; for (int j = 0; j < 80 * 25 * 2; j += 2) { vidptr[j] = ' '; @@ -155,7 +157,23 @@ void PrintKernelAt(const char *str, int line, int col) { } } +void RemapPIC() { + + outb(0x20, 0x11); // Start init + outb(0xA0, 0x11); + outb(0x21, 0x20); // Master offset = 0x20 (32) + outb(0xA1, 0x28); // Slave offset = 0x28 (40) + outb(0x21, 0x04); + outb(0xA1, 0x02); + outb(0x21, 0x01); + outb(0xA1, 0x01); + outb(0x21, 0xFF); // Mask all + outb(0xA1, 0xFF); +} + + void KernelMain(uint32_t magic, uint32_t info) { + PrintKernel("KernelMain\n"); ClearScreen(); PrintKernel("[SUCCESS] VoidFrame Kernel - Version 0.0.1-alpha loaded\n"); @@ -178,11 +196,11 @@ void KernelMain(uint32_t magic, uint32_t info) { PrintKernel("[SUCCESS] Core system modules loaded\n"); - // Timer setup for scheduling + RemapPIC(); outb(0x43, 0x36); // Command: channel 0, lobyte/hibyte, rate generator outb(0x40, 0x4B); // Low byte of divisor (299 = ~4000Hz) outb(0x40, 0x01); // High byte of divisor - outb(0x21, inb(0x21) & ~0x03); + outb(0x21, inb(0x21) & ~1); // Enable interrupts asm volatile("sti"); @@ -190,7 +208,7 @@ void KernelMain(uint32_t magic, uint32_t info) { PrintKernel("[SUCCESS] Kernel initialization complete - entering main loop\n"); while (1) { if (ShouldSchedule()) { - Schedule(); + RequestSchedule(); } asm volatile("hlt"); // Wait for the next interrupt } diff --git a/Kernel/Drivers/Interrupts.c b/Kernel/Drivers/Interrupts.c index 508f5ec..d3749aa 100644 --- a/Kernel/Drivers/Interrupts.c +++ b/Kernel/Drivers/Interrupts.c @@ -1,6 +1,7 @@ #include "../Core/stdint.h" #include "../Core/Kernel.h" #include "Io.h" +#include "../Core/Panic.h" #include "../Process/Process.h" #define likely(x) __builtin_expect(!!(x), 1) @@ -64,17 +65,31 @@ static void FastDisplayTicks(uint64_t ticks) { } } +void PrintStack(uint64_t* ptr, int count) { + for (int i = 0; i < count; i++) { + PrintKernelHex(ptr[i]); + PrintKernel(" "); + } + PrintKernel("\n"); +} + // The C-level interrupt handler void InterruptHandler(struct Registers* regs) { - - // Handle timer interrupt (IRQ0, remapped to 32) - if (likely(regs->interrupt_number == 32)) { + PrintKernel("Stack dump: "); + PrintStack((uint64_t*)regs, 20); + PrintKernel("InterruptHandler: interrupt_number="); + PrintKernelInt(regs->interrupt_number); + PrintKernel("\n"); + if (regs->interrupt_number == 32) { tick_count++; + FastDisplayTicks(tick_count); // Re-enabled outb(0x20, 0x20); - ScheduleFromInterrupt(regs); + ScheduleFromInterrupt(regs); // Re-enabled return; } - + // if (regs->interrupt_number == 13) { + // Panic("InterruptHandler: Page fault (GPF handler)"); + // } // Send EOI to PICs for other hardware interrupts if (regs->interrupt_number >= 40) { outb(0xA0, 0x20); // EOI to slave PIC diff --git a/Kernel/Process/Process.c b/Kernel/Process/Process.c index 80e5562..222a384 100644 --- a/Kernel/Process/Process.c +++ b/Kernel/Process/Process.c @@ -3,6 +3,7 @@ #include "Memory.h" #include "Panic.h" #include "Io.h" +#include "../Memory/MemOps.h" // Use kernel memory ops instead of #define NULL ((void*)0) static Process processes[MAX_PROCESSES]; static uint32_t next_pid = 1; @@ -53,6 +54,8 @@ void RequestSchedule(void) { } void ProcessInit(void) { + PrintKernel("ProcessInit\n"); + // Clear all processes for (int i = 0; i < MAX_PROCESSES; i++) { processes[i].pid = 0; @@ -80,15 +83,20 @@ void ProcessInit(void) { } uint32_t CreateProcess(void (*entry_point)(void)) { + PrintKernel("CreateProcess\n"); + return CreateSecureProcess(entry_point, PROC_PRIV_USER); } void SecureProcessExitStub() { - PrintKernel("[SKIS] Process returned! This shouldn't happen!\n"); + PrintKernel("SecureProcessExitStub\n"); + + PrintKernel("[SECURITY] Process returned! This shouldn't happen!\n"); while (1) { __asm__ __volatile__("hlt"); } } uint32_t CreateSecureProcess(void (*entry_point)(void), uint8_t privilege) { + PrintKernel("CreateSecureProcess\n"); if (!entry_point) { Panic("CreateSecureProcess: NULL entry point"); } @@ -140,32 +148,45 @@ uint32_t CreateSecureProcess(void (*entry_point)(void), uint8_t privilege) { init_token(&processes[slot].token, creator_pid, privilege); // Clear context - for (int i = 0; i < sizeof(ProcessContext)/8; i++) { - ((uint64_t*)&processes[slot].context)[i] = 0; - } + FastMemset(&processes[slot].context, 0, sizeof(ProcessContext)); - // Set up initial context - // Start RSP at the very top of the stack (STACK_SIZE) - // Then push the exit stub onto the stack - processes[slot].context.rsp = (uint64_t)processes[slot].stack + STACK_SIZE; - uint64_t* stack_ptr = (uint64_t*)processes[slot].context.rsp; - *(--stack_ptr) = (uint64_t)&SecureProcessExitStub; - processes[slot].context.rsp = (uint64_t)stack_ptr; // Update RSP after pushing + uint64_t rsp = (uint64_t)processes[slot].stack + STACK_SIZE; + rsp &= ~0xF; // 16-byte alignment - // Ensure RSP is 16-byte aligned for the entry_point function - processes[slot].context.rsp &= ~0xF; // Clear the last 4 bits to align to 16 bytes + // Set up stack with proper return address + uint64_t* stack_ptr = (uint64_t*)rsp; + *(--stack_ptr) = (uint64_t)&SecureProcessExitStub; + // Initialize the context as a proper interrupt frame + processes[slot].context.rsp = (uint64_t)stack_ptr; processes[slot].context.rip = (uint64_t)entry_point; - processes[slot].context.rflags = 0x202; + processes[slot].context.rflags = 0x202; // Interrupts enabled, bit 1 always 1 + processes[slot].context.cs = 0x08; // Kernel code segment + processes[slot].context.ss = 0x10; // Kernel data segment + processes[slot].context.ds = 0x10; // Kernel data segment + processes[slot].context.es = 0x10; // Kernel data segment + processes[slot].context.fs = 0x10; // Kernel data segment + processes[slot].context.gs = 0x10; // Kernel data segment + processes[slot].context.interrupt_number = 0; + processes[slot].context.error_code = 0; process_count++; - return processes[slot].pid; } -void Schedule(void) { - if (process_count <= 1) return; +void ScheduleFromInterrupt(struct Registers* regs) { + PrintKernel("ScheduleFromInterrupt\n"); + + if (!regs) { + Panic("ScheduleFromInterrupt: NULL registers"); + } + + if (current_process >= MAX_PROCESSES) { + Panic("ScheduleFromInterrupt: Invalid current process"); + } + if (process_count <= 1) return; + // Find next ready process, prioritizing system processes uint32_t next = (current_process + 1) % MAX_PROCESSES; uint32_t start = next; @@ -199,6 +220,10 @@ void Schedule(void) { // Switch to best candidate if different from current if (best_candidate != current_process) { + // Save current process's full interrupt frame + // Now this is safe because ProcessContext == struct Registers + FastMemcpy(&processes[current_process].context, regs, sizeof(struct Registers)); + // Update current process state if (processes[current_process].state == PROC_RUNNING) { processes[current_process].state = PROC_READY; @@ -207,92 +232,15 @@ void Schedule(void) { // Update new process state processes[best_candidate].state = PROC_RUNNING; - // Context switch - ProcessContext* old_ctx = &processes[current_process].context; - ProcessContext* new_ctx = &processes[best_candidate].context; + // Restore next process's full interrupt frame + FastMemcpy(regs, &processes[best_candidate].context, sizeof(struct Registers)); current_process = best_candidate; - SwitchContext(old_ctx, new_ctx); } } - -void ScheduleFromInterrupt(struct Registers* regs) { - if (!regs) { - Panic("ScheduleFromInterrupt: NULL registers"); - } - - if (current_process >= MAX_PROCESSES) { - Panic("ScheduleFromInterrupt: Invalid current process"); - } - - if (process_count <= 1) return; - - // Find next ready process - uint32_t next = (current_process + 1) % MAX_PROCESSES; - uint32_t start = next; - - do { - if (processes[next].state == PROC_READY || processes[next].state == PROC_RUNNING) { - if (next == current_process) { - next = (next + 1) % MAX_PROCESSES; - if (next == start) break; - continue; - } - - // Save current process context from interrupt frame - processes[current_process].context.rax = regs->rax; - processes[current_process].context.rbx = regs->rbx; - processes[current_process].context.rcx = regs->rcx; - processes[current_process].context.rdx = regs->rdx; - processes[current_process].context.rsi = regs->rsi; - processes[current_process].context.rdi = regs->rdi; - processes[current_process].context.rbp = regs->rbp; - processes[current_process].context.rsp = regs->rsp; - processes[current_process].context.r8 = regs->r8; - processes[current_process].context.r9 = regs->r9; - processes[current_process].context.r10 = regs->r10; - processes[current_process].context.r11 = regs->r11; - processes[current_process].context.r12 = regs->r12; - processes[current_process].context.r13 = regs->r13; - processes[current_process].context.r14 = regs->r14; - processes[current_process].context.r15 = regs->r15; - processes[current_process].context.rip = regs->rip; - processes[current_process].context.rflags = regs->rflags; - - // Update states - if (processes[current_process].state == PROC_RUNNING) { - processes[current_process].state = PROC_READY; - } - processes[next].state = PROC_RUNNING; - - // Load new process context into interrupt frame - regs->rax = processes[next].context.rax; - regs->rbx = processes[next].context.rbx; - regs->rcx = processes[next].context.rcx; - regs->rdx = processes[next].context.rdx; - regs->rsi = processes[next].context.rsi; - regs->rdi = processes[next].context.rdi; - regs->rbp = processes[next].context.rbp; - regs->rsp = processes[next].context.rsp; - regs->r8 = processes[next].context.r8; - regs->r9 = processes[next].context.r9; - regs->r10 = processes[next].context.r10; - regs->r11 = processes[next].context.r11; - regs->r12 = processes[next].context.r12; - regs->r13 = processes[next].context.r13; - regs->r14 = processes[next].context.r14; - regs->r15 = processes[next].context.r15; - regs->rip = processes[next].context.rip; - regs->rflags = processes[next].context.rflags; - - current_process = next; - return; - } - next = (next + 1) % MAX_PROCESSES; - } while (next != start); -} - Process* GetCurrentProcess(void) { + PrintKernel("GetCurrentProcess\n"); + if (current_process >= MAX_PROCESSES) { Panic("GetCurrentProcess: Invalid current process index"); } @@ -300,6 +248,8 @@ Process* GetCurrentProcess(void) { } Process* GetProcessByPid(uint32_t pid) { + PrintKernel("GetProcessByPid\n"); + for (int i = 0; i < MAX_PROCESSES; i++) { if (processes[i].pid == pid && processes[i].state != PROC_TERMINATED) { return &processes[i]; @@ -309,6 +259,8 @@ Process* GetProcessByPid(uint32_t pid) { } void RegisterSecurityManager(uint32_t pid) { + PrintKernel("RegisterSecurityManager\n"); + security_manager_pid = pid; PrintKernel("[SECURITY] Security manager registered with PID: "); PrintKernelInt(pid); @@ -316,6 +268,7 @@ void RegisterSecurityManager(uint32_t pid) { } void SystemService(void) { + PrintKernel("SystemService\n"); PrintKernel("[SYSTEM] System service started\n"); while (1) { // Do system work @@ -324,6 +277,7 @@ void SystemService(void) { } void SecureKernelIntegritySubsystem(void) { + PrintKernel("SecureKernelIntegritySubsystem\n"); // Register this process as the security manager Process* current = GetCurrentProcess(); if (current) { @@ -363,4 +317,4 @@ void SecureKernelIntegritySubsystem(void) { // Small delay to prevent excessive CPU usage for (volatile int i = 0; i < 1000; i++); } -} +} \ No newline at end of file diff --git a/Kernel/Process/Process.h b/Kernel/Process/Process.h index f352454..b20c200 100644 --- a/Kernel/Process/Process.h +++ b/Kernel/Process/Process.h @@ -25,11 +25,19 @@ typedef enum { PROC_TERMINATED = 0 } ProcessState; -typedef struct { - uint64_t rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp; - uint64_t r8, r9, r10, r11, r12, r13, r14, r15; - uint64_t rip, rflags; -} ProcessContext; +// DO NOT TOUCH THIS STRUCTURE - must match interrupt ASM stack layout +typedef struct Registers { + uint64_t r15, r14, r13, r12, r11, r10, r9, r8; + uint64_t rbp, rsi, rdi, rdx, rcx, rbx, rax; + uint64_t ds, es, fs, gs; + uint64_t interrupt_number; + uint64_t error_code; + uint64_t rip, cs, rflags; + uint64_t rsp, ss; +} __attribute__((packed)) Registers; + +// Use the same structure for context switching to avoid mismatches +typedef struct Registers ProcessContext; typedef struct { uint32_t pid; @@ -43,13 +51,6 @@ typedef struct { ProcessContext context; } Process; -struct Registers { - uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14, r15; - uint64_t interrupt_number; - uint64_t error_code; - uint64_t rip, cs, rflags, rsp; -}; - void ProcessInit(void); uint32_t CreateProcess(void (*entry_point)(void)); uint32_t CreateSecureProcess(void (*entry_point)(void), uint8_t privilege); diff --git a/Kernel/Process/Switch.asm b/Kernel/Process/Switch.asm index 791af20..27d9eb5 100644 --- a/Kernel/Process/Switch.asm +++ b/Kernel/Process/Switch.asm @@ -3,59 +3,93 @@ bits 64 global SwitchContext ; void SwitchContext(ProcessContext* old, ProcessContext* new) +; ProcessContext is now same as Registers struct SwitchContext: - ; Save current context to old - mov [rdi + 0], rax - mov [rdi + 8], rbx - mov [rdi + 16], rcx - mov [rdi + 24], rdx - mov [rdi + 32], rsi - mov [rdi + 40], rdi - mov [rdi + 48], rbp - mov [rdi + 56], rsp - mov [rdi + 64], r8 - mov [rdi + 72], r9 - mov [rdi + 80], r10 - mov [rdi + 88], r11 - mov [rdi + 96], r12 - mov [rdi + 104], r13 - mov [rdi + 112], r14 - mov [rdi + 120], r15 - - ; Save return address (RIP) - mov rax, [rsp] + ; Save current context to old (matching Registers struct layout) + mov [rdi + 0], r15 + mov [rdi + 8], r14 + mov [rdi + 16], r13 + mov [rdi + 24], r12 + mov [rdi + 32], r11 + mov [rdi + 40], r10 + mov [rdi + 48], r9 + mov [rdi + 56], r8 + mov [rdi + 64], rbp + mov [rdi + 72], rsi + mov [rdi + 80], rdi + mov [rdi + 88], rdx + mov [rdi + 96], rcx + mov [rdi + 104], rbx + mov [rdi + 112], rax + + ; Save segment registers + mov ax, ds + mov [rdi + 120], rax + mov ax, es mov [rdi + 128], rax + mov ax, fs + mov [rdi + 136], rax + mov ax, gs + mov [rdi + 144], rax + + ; Skip interrupt_number and error_code (152, 160) + + ; Save return address as RIP + mov rax, [rsp] + mov [rdi + 168], rax + + ; Save CS (assume kernel code segment) + mov word [rdi + 176], 0x08 ; Save RFLAGS pushfq pop rax - mov [rdi + 136], rax + mov [rdi + 184], rax + + ; Save RSP (after return address) + mov rax, rsp + add rax, 8 ; Account for return address + mov [rdi + 192], rax + + ; Save SS (assume kernel data segment) + mov word [rdi + 200], 0x10 ; Load new context from new - mov rax, [rsi + 0] - mov rbx, [rsi + 8] - mov rcx, [rsi + 16] - mov rdx, [rsi + 24] - mov rbp, [rsi + 48] - mov rsp, [rsi + 56] - mov r8, [rsi + 64] - mov r9, [rsi + 72] - mov r10, [rsi + 80] - mov r11, [rsi + 88] - mov r12, [rsi + 96] - mov r13, [rsi + 104] - mov r14, [rsi + 112] - mov r15, [rsi + 120] + mov r15, [rsi + 0] + mov r14, [rsi + 8] + mov r13, [rsi + 16] + mov r12, [rsi + 24] + mov r11, [rsi + 32] + mov r10, [rsi + 40] + mov r9, [rsi + 48] + mov r8, [rsi + 56] + mov rbp, [rsi + 64] + ; rsi will be loaded last + mov rdi, [rsi + 80] + mov rdx, [rsi + 88] + mov rcx, [rsi + 96] + mov rbx, [rsi + 104] + mov rax, [rsi + 112] + + ; Load segment registers + mov ax, [rsi + 120] + mov ds, ax + mov ax, [rsi + 128] + mov es, ax + mov ax, [rsi + 136] + mov fs, ax + mov ax, [rsi + 144] + mov gs, ax + + ; Load RSP + mov rsp, [rsi + 192] ; Load RFLAGS - push qword [rsi + 136] + push qword [rsi + 184] popfq - ; Load new RIP and jump - push qword [rsi + 128] - - ; Load RSI and RDI last - mov rdi, [rsi + 40] - mov rsi, [rsi + 32] + ; Load new RIP and jump (load rsi last) + push qword [rsi + 168] + mov rsi, [rsi + 72] ; Load rsi last ret ; Jump to new RIP \ No newline at end of file diff --git a/Kernel/System/Syscall.c b/Kernel/System/Syscall.c index 2c1e67b..0b3c058 100644 --- a/Kernel/System/Syscall.c +++ b/Kernel/System/Syscall.c @@ -18,7 +18,7 @@ uint64_t SyscallHandler(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint if (current) { current->state = PROC_TERMINATED; } - Schedule(); // Switch to next process + RequestSchedule(); // Switch to next process return 0; case SYS_WRITE: diff --git a/grub.cfg b/grub.cfg index b017221..d666799 100644 --- a/grub.cfg +++ b/grub.cfg @@ -3,6 +3,7 @@ set default=0 menuentry "VoidFrame" { set gfxpayload=text + terminal_output console multiboot2 /boot/voidframe.krnl boot } diff --git a/meson.build b/meson.build index 4e85626..ac839cc 100644 --- a/meson.build +++ b/meson.build @@ -121,5 +121,5 @@ iso = custom_target('VoidFrame.iso', # Run target run_target('run', - command : ['qemu-system-x86_64', '-cdrom', 'VoidFrame.iso', '-no-reboot', '-no-shutdown' , '-m', '1G'] + command : ['qemu-system-x86_64', '-cdrom', 'VoidFrame.iso', '-no-reboot', '-no-shutdown', '-debugcon', 'stdio' , '-m', '1G'] ) \ No newline at end of file