From 34a995023d593b93d6ed5aeac2c3ba3fa58cc6e1 Mon Sep 17 00:00:00 2001 From: Atheria Date: Mon, 27 Oct 2025 19:19:34 +0700 Subject: [PATCH 1/3] EEVDF SIS --- arch/x86_64/asm/bss.asm | 25 +++++ arch/x86_64/asm/features.asm | 75 ++++++++++++++ arch/x86_64/asm/gdt.asm | 22 ++++ arch/x86_64/asm/macros.asm | 6 ++ arch/x86_64/asm/multiboot2.asm | 35 +++++++ arch/x86_64/asm/pxs.asm | 179 ++------------------------------- cmake/source.cmake | 2 + include/Scheduler.h | 15 +++ kernel/core/Kernel.c | 1 + kernel/sched/EEVDF.c | 72 +++++++++---- kernel/sched/EEVDF.h | 31 ++++-- kernel/sched/MLFQ.c | 26 ++--- kernel/sched/Shared.h | 7 -- 13 files changed, 281 insertions(+), 215 deletions(-) create mode 100644 arch/x86_64/asm/bss.asm create mode 100644 arch/x86_64/asm/features.asm create mode 100644 arch/x86_64/asm/gdt.asm create mode 100644 arch/x86_64/asm/macros.asm create mode 100644 arch/x86_64/asm/multiboot2.asm diff --git a/arch/x86_64/asm/bss.asm b/arch/x86_64/asm/bss.asm new file mode 100644 index 0000000..84b284b --- /dev/null +++ b/arch/x86_64/asm/bss.asm @@ -0,0 +1,25 @@ +section .bss +align 4096 +pml4_table: resb 4096 +pdp_table: resb 4096 +pd_table: resb 4096 +pd_table2: resb 4096 +pd_table3: resb 4096 +pd_table4: resb 4096 +; Reserve space for up to 64 additional PD tables (64GB support) +pd_tables_extended: resb (4096 * 60) + +align 16 +stack_bottom: resb 16384 ; 16KB stack +stack_top: + +section .data +multiboot_magic: dd 0 +multiboot_info: dq 0 ; The info pointer can be a 64-bit address, use dq + +; Dynamic memory mapping variables +highest_phys_addr_low: dd 0 +highest_phys_addr_high: dd 0 +memory_to_map_low: dd 0 +memory_to_map_high: dd 0 +num_pdp_entries: dd 0 \ No newline at end of file diff --git a/arch/x86_64/asm/features.asm b/arch/x86_64/asm/features.asm new file mode 100644 index 0000000..0091010 --- /dev/null +++ b/arch/x86_64/asm/features.asm @@ -0,0 +1,75 @@ +check_and_enable_features: + ; Test for CPUID capability (ID bit in EFLAGS) + pushfd + pop eax + mov ecx, eax + xor eax, 1 << 21 ; Flip the ID bit + push eax + popfd + pushfd + pop eax + xor eax, ecx + jz .no_cpuid_present ; If ID bit couldn't be flipped, CPUID not supported. + + debug_print 'C' ; CPUID detected + + ; Get basic CPU features (CPUID Leaf 1) + mov eax, 1 + cpuid + + ; EAX = Version Info (Model, Family, Stepping) + ; EBX = Brand Index, CLFLUSH size, Number of Logical Processors, APIC ID + ; ECX = Feature flags 1 (SSE3, SSSE3, SSE4.1, SSE4.2, AVX, etc.) + ; EDX = Feature flags 2 (FPU, VME, MMX, SSE, SSE2, FXSR, MSR, PAE, APIC, PGE, PSN, CMOV, MTRR, HTT, etc.) + + ; --- Enable FPU/SSE/SSE2/XMM support --- + ; This is required for modern C/C++ compiled code that uses floating point. + ; CR0.EM (Emulation) should be 0. + ; CR0.MP (Monitor Coprocessor) should be 1. + ; CR4.OSFXSR (Operating System FXSAVE/FXRSTOR Support) should be 1. + ; CR4.OSXMMEXCPT (Operating System Unmasked SIMD Floating-Point Exception Support) should be 1. + + ; Check for SSE support (EDX bit 25) + test edx, 1 << 25 ; SSE + jz .skip_sse_enable + + mov eax, cr0 + and eax, ~(1 << 2) ; Clear EM (Emulation) + or eax, 1 << 1 ; Set MP (Monitor Coprocessor) + mov cr0, eax + + mov eax, cr4 + or eax, 1 << 9 ; Set OSFXSR (Operating System FXSAVE/FXRSTOR Support) + or eax, 1 << 10 ; Set OSXMMEXCPT (Operating System Unmasked SIMD Floating-Point Exception Support) + mov cr4, eax + debug_print 'S' ; SSE Enabled + +.skip_sse_enable: + + ; --- Enable Write Protect (WP) in CR0 --- + ; CR0.WP (bit 16) protects read-only pages from ring 0 writes. + ; This is crucial for proper memory protection. + mov eax, cr0 + or eax, 1 << 16 ; Set WP bit + mov cr0, eax + debug_print 'W' ; Write Protect Enabled + + ; --- Enable No-Execute (NXE) in EFER MSR --- + ; This feature helps prevent buffer overflow attacks by marking memory pages as non-executable. + ; Requires PAE to be enabled. + ; Check for NX support (EDX bit 20 from CPUID leaf 1) + mov eax, 1 + cpuid + test edx, 1 << 20 ; NX (Execute Disable Bit) + jz .skip_nxe_enable + + mov ecx, 0xC0000080 ; EFER MSR + rdmsr + or eax, 1 << 11 ; Set NXE (No-Execute Enable) bit + wrmsr + debug_print 'N' ; NX Enabled + +.skip_nxe_enable: + +.no_cpuid_present: + ret diff --git a/arch/x86_64/asm/gdt.asm b/arch/x86_64/asm/gdt.asm new file mode 100644 index 0000000..085fb6d --- /dev/null +++ b/arch/x86_64/asm/gdt.asm @@ -0,0 +1,22 @@ +gdt64: + ; Null Descriptor + dq 0 +.code: equ $ - gdt64 ; offset 0x08 + dw 0xFFFF ; limit + dw 0 ; base + db 0 ; base + db 10011010b ; 0x9A - Present, DPL 0, Code, Executable, Read/Write + db 10101111b ; 0xAF - Granularity (4K), 64-bit Code (L-bit=1), Limit + db 0 ; base +.data: equ $ - gdt64 ; offset 0x10 + dw 0xFFFF ; limit + dw 0 ; base + db 0 ; base + db 10010010b ; 0x92 - Present, DPL 0, Data, Read/Write + db 11001111b ; 0xCF - Granularity (4K), 32-bit Segment, Limit + db 0 ; base +gdt_end: + +gdt64_pointer: + dw gdt_end - gdt64 - 1 ; GDT size + dq gdt64 ; GDT base address \ No newline at end of file diff --git a/arch/x86_64/asm/macros.asm b/arch/x86_64/asm/macros.asm new file mode 100644 index 0000000..6966b8f --- /dev/null +++ b/arch/x86_64/asm/macros.asm @@ -0,0 +1,6 @@ +; Macro for debugging output on Bochs/QEMU's 0xE9 port +%macro debug_print 1 + mov dx, 0xE9 + mov al, %1 + out dx, al +%endmacro \ No newline at end of file diff --git a/arch/x86_64/asm/multiboot2.asm b/arch/x86_64/asm/multiboot2.asm new file mode 100644 index 0000000..c880da0 --- /dev/null +++ b/arch/x86_64/asm/multiboot2.asm @@ -0,0 +1,35 @@ +section .multiboot +header_start: + dd 0xE85250D6 ; Multiboot2 magic number + dd 0 ; Architecture 0 (protected mode i386) + dd header_end - header_start ; header length + ; checksum = -(magic + arch + length) + dd -(0xE85250D6 + 0 + (header_end - header_start)) + +%ifdef VF_CONFIG_VESA_FB + ; Framebuffer tag - request specific graphics mode + align 8 +framebuffer_tag_start: + dw 5 ; type = framebuffer + dw 0 ; flags + dd 24 ; size + dd 800 ; width + dd 600 ; height + dd 32 ; depth (bits per pixel) +framebuffer_tag_end: + + ; VBE tag - request VBE info + align 8 +vbe_tag_start: + dw 7 ; type = VBE + dw 0 ; flags + dd vbe_tag_end - vbe_tag_start ; size +vbe_tag_end: +%endif + + ; End tag - required + align 8 + dw 0 ; type + dw 0 ; flags + dd 8 ; size +header_end: \ No newline at end of file diff --git a/arch/x86_64/asm/pxs.asm b/arch/x86_64/asm/pxs.asm index d9a6298..5aa07b5 100644 --- a/arch/x86_64/asm/pxs.asm +++ b/arch/x86_64/asm/pxs.asm @@ -1,72 +1,17 @@ -section .multiboot -header_start: - dd 0xE85250D6 ; Multiboot2 magic number - dd 0 ; Architecture 0 (protected mode i386) - dd header_end - header_start ; header length - ; checksum = -(magic + arch + length) - dd -(0xE85250D6 + 0 + (header_end - header_start)) - -%ifdef VF_CONFIG_VESA_FB - ; Framebuffer tag - request specific graphics mode - align 8 -framebuffer_tag_start: - dw 5 ; type = framebuffer - dw 0 ; flags - dd 24 ; size - dd 800 ; width - dd 600 ; height - dd 32 ; depth (bits per pixel) -framebuffer_tag_end: - - ; VBE tag - request VBE info - align 8 -vbe_tag_start: - dw 7 ; type = VBE - dw 0 ; flags - dd vbe_tag_end - vbe_tag_start ; size -vbe_tag_end: -%endif - - ; End tag - required - align 8 - dw 0 ; type - dw 0 ; flags - dd 8 ; size -header_end: +; ============================================================================ +; VoidFrame start code for x86_64 architecture +; ============================================================================ [bits 32] +%include "multiboot2.asm" +%include "bss.asm" + section .text -; Macro for debugging output on Bochs/QEMU's 0xE9 port -%macro debug_print 1 - mov dx, 0xE9 - mov al, %1 - out dx, al -%endmacro - -gdt64: - ; Null Descriptor - dq 0 -.code: equ $ - gdt64 ; offset 0x08 - dw 0xFFFF ; limit - dw 0 ; base - db 0 ; base - db 10011010b ; 0x9A - Present, DPL 0, Code, Executable, Read/Write - db 10101111b ; 0xAF - Granularity (4K), 64-bit Code (L-bit=1), Limit - db 0 ; base -.data: equ $ - gdt64 ; offset 0x10 - dw 0xFFFF ; limit - dw 0 ; base - db 0 ; base - db 10010010b ; 0x92 - Present, DPL 0, Data, Read/Write - db 11001111b ; 0xCF - Granularity (4K), 32-bit Segment, Limit - db 0 ; base -gdt_end: - -gdt64_pointer: - dw gdt_end - gdt64 - 1 ; GDT size - dq gdt64 ; GDT base address +%include "macros.asm" +%include "gdt.asm" +%include "features.asm" global start start: @@ -365,82 +310,6 @@ setup_dynamic_paging: popa ret -check_and_enable_features: - ; Test for CPUID capability (ID bit in EFLAGS) - pushfd - pop eax - mov ecx, eax - xor eax, 1 << 21 ; Flip the ID bit - push eax - popfd - pushfd - pop eax - xor eax, ecx - jz .no_cpuid_present ; If ID bit couldn't be flipped, CPUID not supported. - - debug_print 'C' ; CPUID detected - - ; Get basic CPU features (CPUID Leaf 1) - mov eax, 1 - cpuid - - ; EAX = Version Info (Model, Family, Stepping) - ; EBX = Brand Index, CLFLUSH size, Number of Logical Processors, APIC ID - ; ECX = Feature flags 1 (SSE3, SSSE3, SSE4.1, SSE4.2, AVX, etc.) - ; EDX = Feature flags 2 (FPU, VME, MMX, SSE, SSE2, FXSR, MSR, PAE, APIC, PGE, PSN, CMOV, MTRR, HTT, etc.) - - ; --- Enable FPU/SSE/SSE2/XMM support --- - ; This is required for modern C/C++ compiled code that uses floating point. - ; CR0.EM (Emulation) should be 0. - ; CR0.MP (Monitor Coprocessor) should be 1. - ; CR4.OSFXSR (Operating System FXSAVE/FXRSTOR Support) should be 1. - ; CR4.OSXMMEXCPT (Operating System Unmasked SIMD Floating-Point Exception Support) should be 1. - - ; Check for SSE support (EDX bit 25) - test edx, 1 << 25 ; SSE - jz .skip_sse_enable - - mov eax, cr0 - and eax, ~(1 << 2) ; Clear EM (Emulation) - or eax, 1 << 1 ; Set MP (Monitor Coprocessor) - mov cr0, eax - - mov eax, cr4 - or eax, 1 << 9 ; Set OSFXSR (Operating System FXSAVE/FXRSTOR Support) - or eax, 1 << 10 ; Set OSXMMEXCPT (Operating System Unmasked SIMD Floating-Point Exception Support) - mov cr4, eax - debug_print 'S' ; SSE Enabled - -.skip_sse_enable: - - ; --- Enable Write Protect (WP) in CR0 --- - ; CR0.WP (bit 16) protects read-only pages from ring 0 writes. - ; This is crucial for proper memory protection. - mov eax, cr0 - or eax, 1 << 16 ; Set WP bit - mov cr0, eax - debug_print 'W' ; Write Protect Enabled - - ; --- Enable No-Execute (NXE) in EFER MSR --- - ; This feature helps prevent buffer overflow attacks by marking memory pages as non-executable. - ; Requires PAE to be enabled. - ; Check for NX support (EDX bit 20 from CPUID leaf 1) - mov eax, 1 - cpuid - test edx, 1 << 20 ; NX (Execute Disable Bit) - jz .skip_nxe_enable - - mov ecx, 0xC0000080 ; EFER MSR - rdmsr - or eax, 1 << 11 ; Set NXE (No-Execute Enable) bit - wrmsr - debug_print 'N' ; NX Enabled - -.skip_nxe_enable: - -.no_cpuid_present: - ret - [bits 64] [extern KernelMain] @@ -463,7 +332,7 @@ long_mode: ; RDI is the first argument in the System V AMD64 ABI ; RSI is the second argument ; Use RDI/RSI directly, as Multiboot2 info pointer can be > 4GB - [default rel] + default rel mov edi, [multiboot_magic] ; EAX holds magic, so EDI will get the 32-bit magic mov rsi, [multiboot_info] ; EBX holds info pointer, but could be 64-bit, so use RSI @@ -476,30 +345,4 @@ long_mode: .halt: cli hlt - jmp .halt - -section .bss -align 4096 -pml4_table: resb 4096 -pdp_table: resb 4096 -pd_table: resb 4096 -pd_table2: resb 4096 -pd_table3: resb 4096 -pd_table4: resb 4096 -; Reserve space for up to 64 additional PD tables (64GB support) -pd_tables_extended: resb (4096 * 60) - -align 16 -stack_bottom: resb 16384 ; 16KB stack -stack_top: - -section .data -multiboot_magic: dd 0 -multiboot_info: dq 0 ; The info pointer can be a 64-bit address, use dq - -; Dynamic memory mapping variables -highest_phys_addr_low: dd 0 -highest_phys_addr_high: dd 0 -memory_to_map_low: dd 0 -memory_to_map_high: dd 0 -num_pdp_entries: dd 0 \ No newline at end of file + jmp .halt \ No newline at end of file diff --git a/cmake/source.cmake b/cmake/source.cmake index 3e5be65..b22d11c 100644 --- a/cmake/source.cmake +++ b/cmake/source.cmake @@ -183,6 +183,8 @@ include_directories( ports/6502 ports ports/raytracer + arch/x86_64 + arch/x86_64/asm arch/x86_64/features arch/x86_64/gdt arch/x86_64/idt diff --git a/include/Scheduler.h b/include/Scheduler.h index 331117c..00f844e 100644 --- a/include/Scheduler.h +++ b/include/Scheduler.h @@ -10,6 +10,21 @@ #include "EEVDF.h" #endif +#if defined(VF_CONFIG_SCHED_MLFQ) +#define PROC_FLAG_NONE 0U +#define PROC_FLAG_IMMUNE (1U << 0) +#define PROC_FLAG_CRITICAL (1U << 1) +#define PROC_FLAG_SUPERVISOR (1U << 3) +#define PROC_FLAG_CORE (PROC_FLAG_IMMUNE | PROC_FLAG_SUPERVISOR | PROC_FLAG_CRITICAL) +#elif defined(VF_CONFIG_SCHED_EEVDF) +#define PROC_FLAG_NONE EEVDF_CAP_NONE +#define PROC_FLAG_IMMUNE EEVDF_CAP_IMMUNE +#define PROC_FLAG_CRITICAL EEVDF_CAP_CRITICAL +#define PROC_FLAG_SUPERVISOR EEVDF_CAP_SUPERVISOR +#define PROC_FLAG_CORE EEVDF_CAP_CORE +#endif + + #if defined(VF_CONFIG_SCHED_MLFQ) typedef MLFQProcessControlBlock CurrentProcessControlBlock; #elif defined(VF_CONFIG_SCHED_EEVDF) diff --git a/kernel/core/Kernel.c b/kernel/core/Kernel.c index 900d6ee..571a33b 100644 --- a/kernel/core/Kernel.c +++ b/kernel/core/Kernel.c @@ -288,6 +288,7 @@ static void SetupMemoryProtection(void) { __asm__ volatile("mov %0, %%cr0" :: "r"(cr0) : "memory"); PrintKernel("System: Write Protection (WP) enabled\n"); + // Enable FSGSBASE for faster userspace context switches __asm__ volatile("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(7), "c"(0)); if (ebx & (1 << 0)) { diff --git a/kernel/sched/EEVDF.c b/kernel/sched/EEVDF.c index 589d68a..67a3118 100644 --- a/kernel/sched/EEVDF.c +++ b/kernel/sched/EEVDF.c @@ -594,7 +594,26 @@ static uint64_t EEVDFSecureHash(const void* data, const uint64_t len, uint64_t s return hash; } +static uint64_t EEVDFCalculateTokenChecksum(const EEVDFSecurityToken* token) { + return EEVDFSecureHash(token, offsetof(EEVDFSecurityToken, checksum), EEVDF_SECURITY_SALT); +} + +static uint64_t EEVDFCalculatePCBHash(const EEVDFProcessControlBlock* pcb) { + uint64_t hash = EEVDF_SECURITY_SALT; + + hash = EEVDFSecureHash(&pcb->pid, sizeof(pcb->pid), hash); + hash = EEVDFSecureHash(&pcb->privilege_level, sizeof(pcb->privilege_level), hash); + hash = EEVDFSecureHash(&pcb->token.capabilities, sizeof(pcb->token.capabilities), hash); + hash = EEVDFSecureHash(&pcb->stack, sizeof(pcb->stack), hash); + // hash = EEVDFSecureHash(&pcb->context.rip, sizeof(pcb->context.rip), hash); + hash = EEVDFSecureHash(pcb->ProcessRuntimePath, sizeof(pcb->ProcessRuntimePath), hash); + + return hash; +} + static uint64_t EEVDFCalculateSecureChecksum(const EEVDFSecurityToken* token, uint32_t pid) { + // This function is now deprecated. Use EEVDFCalculateTokenChecksum and EEVDFCalculatePCBHash instead. + // Keeping it for now to avoid immediate compile errors, but it should be removed. uint64_t base_hash = EEVDFSecureHash(token, offsetof(EEVDFSecurityToken, checksum), EEVDF_SECURITY_SALT); uint64_t pid_hash = EEVDFSecureHash(&pid, sizeof(pid), EEVDF_SECURITY_SALT); return base_hash ^ pid_hash; @@ -852,10 +871,10 @@ int EEVDFSchedInit(void) { token->magic = EEVDF_SECURITY_MAGIC; token->creator_pid = 0; token->privilege = EEVDF_PROC_PRIV_SYSTEM; - token->flags = EEVDF_PROC_FLAG_CORE; + token->capabilities = EEVDF_CAP_CORE; token->creation_tick = idle_proc->creation_time; - token->checksum = 0; - token->checksum = EEVDFCalculateSecureChecksum(token, 0); + token->checksum = EEVDFCalculateTokenChecksum(token); + token->pcb_hash = EEVDFCalculatePCBHash(idle_proc); FormatA(idle_proc->ProcessRuntimePath, sizeof(idle_proc->ProcessRuntimePath), "%s/%d", RuntimeServices, idle_proc->pid); @@ -865,7 +884,7 @@ int EEVDFSchedInit(void) { #ifdef VF_CONFIG_USE_VFSHELL // Create shell process PrintKernel("System: Creating shell process...\n"); - const uint32_t shell_pid = EEVDFCreateSecureProcess("VFShell", ShellProcess, EEVDF_PROC_PRIV_SYSTEM, EEVDF_PROC_FLAG_CORE); + const uint32_t shell_pid = EEVDFCreateSecureProcess("VFShell", ShellProcess, EEVDF_PROC_PRIV_SYSTEM, EEVDF_CAP_CORE); if (!shell_pid) { #ifndef VF_CONFIG_PANIC_OVERRIDE PANIC("CRITICAL: Failed to create shell process"); @@ -882,7 +901,7 @@ int EEVDFSchedInit(void) { return 0; } -uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), uint8_t priv, uint8_t flag) { +uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), uint8_t priv, uint64_t capabilities) { if (UNLIKELY(!entry_point)) { PANIC("EEVDFCreateProcess: NULL entry point"); } @@ -952,9 +971,10 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u token->magic = EEVDF_SECURITY_MAGIC; token->creator_pid = creator->pid; token->privilege = priv; - token->flags = flag; + token->capabilities = capabilities; token->creation_tick = proc->creation_time; - token->checksum = EEVDFCalculateSecureChecksum(token, new_pid); + token->checksum = EEVDFCalculateTokenChecksum(token); + token->pcb_hash = EEVDFCalculatePCBHash(proc); // Set up context uint64_t rsp = (uint64_t)stack; @@ -977,6 +997,9 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u FormatA(proc->ProcessRuntimePath, sizeof(proc->ProcessRuntimePath), "%s/%d", RuntimeProcesses, new_pid); + // Recalculate PCB hash after all relevant fields are set + token->pcb_hash = EEVDFCalculatePCBHash(proc); + #ifdef VF_CONFIG_USE_CERBERUS CerberusRegisterProcess(new_pid, (uint64_t)stack, EEVDF_STACK_SIZE); #endif @@ -995,7 +1018,7 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u } uint32_t EEVDFCreateProcess(const char* name, void (*entry_point)(void)) { - return EEVDFCreateSecureProcess(name, entry_point, EEVDF_PROC_PRIV_NORM, EEVDF_PROC_FLAG_NONE); + return EEVDFCreateSecureProcess(name, entry_point, EEVDF_PROC_PRIV_NORM, EEVDF_CAP_NONE); } EEVDFProcessControlBlock* EEVDFGetCurrentProcess(void) { @@ -1029,12 +1052,25 @@ void EEVDFYield(void) { // Security and Validation Functions // ============================================================================= -static int EEVDFValidateToken(const EEVDFSecurityToken* token, uint32_t pid) { - if (UNLIKELY(!token)) return 0; +static int EEVDFValidateToken(const EEVDFSecurityToken* token, const EEVDFProcessControlBlock* pcb) { + if (UNLIKELY(!token || !pcb)) return 0; if (UNLIKELY(token->magic != EEVDF_SECURITY_MAGIC)) return 0; - uint64_t expected_checksum = EEVDFCalculateSecureChecksum(token, pid); - return token->checksum == expected_checksum; + // Verify the token's internal checksum + uint64_t expected_token_checksum = EEVDFCalculateTokenChecksum(token); + if (token->checksum != expected_token_checksum) { + PrintKernelErrorF("EEVDF: Token checksum mismatch for PID %d. Expected 0x%lx, got 0x%lx\n", pcb->pid, expected_token_checksum, token->checksum); + return 0; + } + + // Verify the PCB hash stored within the token against the current PCB state + uint64_t current_pcb_hash = EEVDFCalculatePCBHash(pcb); + if (token->pcb_hash != current_pcb_hash) { + PrintKernelErrorF("EEVDF: PCB hash mismatch for PID %d. Expected 0x%lx, got 0x%lx\n", pcb->pid, current_pcb_hash, token->pcb_hash); + return 0; + } + + return 1; } static inline int EEVDFPreflightCheck(uint32_t slot) { @@ -1042,13 +1078,13 @@ static inline int EEVDFPreflightCheck(uint32_t slot) { EEVDFProcessControlBlock* proc = &processes[slot]; - if (UNLIKELY(!EEVDFValidateToken(&proc->token, proc->pid))) { + if (UNLIKELY(!EEVDFValidateToken(&proc->token, proc))) { EEVDFASTerminate(proc->pid, "Pre-flight token validation failure"); return 0; // Do not schedule this process. } if (UNLIKELY(proc->privilege_level == EEVDF_PROC_PRIV_SYSTEM && - !(proc->token.flags & (EEVDF_PROC_FLAG_SUPERVISOR | EEVDF_PROC_FLAG_CRITICAL | EEVDF_PROC_FLAG_IMMUNE)))) { + !(proc->token.capabilities & (EEVDF_CAP_SUPERVISOR | EEVDF_CAP_CRITICAL | EEVDF_CAP_IMMUNE)))) { EEVDFASTerminate(proc->pid, "Unauthorized privilege escalation"); return 0; // Do not schedule this process. } @@ -1065,7 +1101,7 @@ static inline int EEVDFPostflightCheck(uint32_t slot) { EEVDFProcessControlBlock* proc = &processes[slot]; - if (UNLIKELY(!EEVDFValidateToken(&proc->token, proc->pid))) { + if (UNLIKELY(!EEVDFValidateToken(&proc->token, proc))) { EEVDFASTerminate(proc->pid, "Post-execution token corruption"); return 0; // Do not re-queue this process } @@ -1116,14 +1152,14 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 } // Cannot terminate immune processes - if (UNLIKELY(proc->token.flags & EEVDF_PROC_FLAG_IMMUNE)) { + if (UNLIKELY(proc->token.capabilities & EEVDF_CAP_IMMUNE)) { rust_spinlock_unlock_irqrestore(eevdf_lock, flags); EEVDFASTerminate(caller->pid, "Attempted termination of immune process"); return; } // Cannot terminate critical system processes - if (UNLIKELY(proc->token.flags & EEVDF_PROC_FLAG_CRITICAL)) { + if (UNLIKELY(proc->token.capabilities & EEVDF_CAP_CRITICAL)) { rust_spinlock_unlock_irqrestore(eevdf_lock, flags); EEVDFASTerminate(caller->pid, "Attempted termination of critical process"); return; @@ -1131,7 +1167,7 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 } // Validate caller's token before allowing termination - if (UNLIKELY(!EEVDFValidateToken(&caller->token, caller->pid))) { + if (UNLIKELY(!EEVDFValidateToken(&caller->token, caller))) { rust_spinlock_unlock_irqrestore(eevdf_lock, flags); EEVDFASTerminate(caller->pid, "Token validation failed"); return; diff --git a/kernel/sched/EEVDF.h b/kernel/sched/EEVDF.h index d6bc603..56a14da 100644 --- a/kernel/sched/EEVDF.h +++ b/kernel/sched/EEVDF.h @@ -51,12 +51,24 @@ #define EEVDF_PROC_PRIV_NORM PROC_PRIV_NORM #define EEVDF_PROC_PRIV_RESTRICTED PROC_PRIV_RESTRICTED -// Security flags (same as MLFQ) -#define EEVDF_PROC_FLAG_NONE PROC_FLAG_NONE -#define EEVDF_PROC_FLAG_IMMUNE PROC_FLAG_IMMUNE -#define EEVDF_PROC_FLAG_CRITICAL PROC_FLAG_CRITICAL -#define EEVDF_PROC_FLAG_SUPERVISOR PROC_FLAG_SUPERVISOR -#define EEVDF_PROC_FLAG_CORE (EEVDF_PROC_FLAG_IMMUNE | EEVDF_PROC_FLAG_SUPERVISOR | EEVDF_PROC_FLAG_CRITICAL) +// Security flags (now granular capabilities) +#define EEVDF_CAP_NONE 0ULL +#define EEVDF_CAP_SYS_ADMIN (1ULL << 0) // Full system control +#define EEVDF_CAP_NET_ADMIN (1ULL << 1) // Network administration +#define EEVDF_CAP_NET_RAW (1ULL << 2) // Raw socket access +#define EEVDF_CAP_FILE_READ (1ULL << 3) // Read any file +#define EEVDF_CAP_FILE_WRITE (1ULL << 4) // Write any file +#define EEVDF_CAP_IPC_OWNER (1ULL << 5) // Own IPC objects +#define EEVDF_CAP_KILL (1ULL << 6) // Send signals to other processes +#define EEVDF_CAP_SETUID (1ULL << 7) // Change UID +#define EEVDF_CAP_SETGID (1ULL << 8) // Change GID +#define EEVDF_CAP_SYS_NICE (1ULL << 9) // Change process nice value +#define EEVDF_CAP_SYS_RESOURCE (1ULL << 10) // Modify resource limits +#define EEVDF_CAP_SYS_MODULE (1ULL << 11) // Load/unload kernel modules +#define EEVDF_CAP_IMMUNE (1ULL << 12) // Process cannot be killed by non-system processes +#define EEVDF_CAP_CRITICAL (1ULL << 13) // Process is critical for system operation +#define EEVDF_CAP_SUPERVISOR (1ULL << 14) // Process runs with supervisor privileges +#define EEVDF_CAP_CORE (EEVDF_CAP_IMMUNE | EEVDF_CAP_SUPERVISOR | EEVDF_CAP_CRITICAL) // Nice-to-weight conversion table (based on Linux CFS) extern const uint32_t eevdf_nice_to_weight[40]; @@ -67,9 +79,10 @@ typedef struct { uint64_t magic; uint32_t creator_pid; uint8_t privilege; - uint8_t flags; + uint64_t capabilities; // Renamed from 'flags' to be more explicit uint64_t creation_tick; - uint64_t checksum; + uint64_t checksum; // Checksum for the token itself + uint64_t pcb_hash; // Hash for critical PCB fields } __attribute__((packed)) EEVDFSecurityToken; // Use the same structure for context switching to avoid mismatches @@ -180,7 +193,7 @@ typedef struct { // Core scheduler functions int EEVDFSchedInit(void); uint32_t EEVDFCreateProcess(const char* name, void (*entry_point)(void)); -uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), uint8_t priv, uint8_t flag); +uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), uint8_t priv, uint64_t capabilities); EEVDFProcessControlBlock* EEVDFGetCurrentProcess(void); EEVDFProcessControlBlock* EEVDFGetCurrentProcessByPID(uint32_t pid); void EEVDFYield(void); diff --git a/kernel/sched/MLFQ.c b/kernel/sched/MLFQ.c index 9c4d696..85e0a9f 100644 --- a/kernel/sched/MLFQ.c +++ b/kernel/sched/MLFQ.c @@ -1,6 +1,6 @@ #include "MLFQ.h" - -#include "../../drivers/APIC/APIC.h" +#include "Scheduler.h" +#include "drivers/APIC/APIC.h" #include "Atomics.h" #include "Cerberus.h" #include "Compositor.h" @@ -1011,11 +1011,11 @@ void ProcessExitStub() { __builtin_unreachable(); } -uint32_t CreateSecureProcess(const char * name, void (*entry_point)(void), uint8_t privilege, uint32_t initial_flags) { +uint32_t MLFQCreateSecureProcess(const char * name, void (*entry_point)(void), uint8_t privilege, uint32_t initial_flags) { irq_flags_t flags = rust_spinlock_lock_irqsave(scheduler_lock); if (UNLIKELY(!entry_point)) { rust_spinlock_unlock_irqrestore(scheduler_lock, flags); - PANIC("CreateSecureProcess: NULL entry point"); + PANIC("MLFQCreateSecureProcess: NULL entry point"); } MLFQProcessControlBlock* creator = MLFQGetCurrentProcess(); @@ -1049,14 +1049,14 @@ uint32_t CreateSecureProcess(const char * name, void (*entry_point)(void), uint8 if (UNLIKELY(process_count >= MAX_PROCESSES)) { rust_spinlock_unlock_irqrestore(scheduler_lock, flags); - PANIC("CreateSecureProcess: Too many processes"); + PANIC("MLFQCreateSecureProcess: Too many processes"); } // Fast slot allocation int slot = FindFreeSlotFast(); if (UNLIKELY(slot == -1)) { rust_spinlock_unlock_irqrestore(scheduler_lock, flags); - PANIC("CreateSecureProcess: No free process slots"); + PANIC("MLFQCreateSecureProcess: No free process slots"); } uint32_t new_pid = 0; @@ -1075,7 +1075,7 @@ uint32_t CreateSecureProcess(const char * name, void (*entry_point)(void), uint8 if (new_pid == 0) { FreeSlotFast(slot); rust_spinlock_unlock_irqrestore(scheduler_lock, flags); - PANIC("CreateSecureProcess: PID exhaustion"); + PANIC("MLFQCreateSecureProcess: PID exhaustion"); } // Clear slot securely @@ -1086,7 +1086,7 @@ uint32_t CreateSecureProcess(const char * name, void (*entry_point)(void), uint8 if (UNLIKELY(!stack)) { FreeSlotFast(slot); rust_spinlock_unlock_irqrestore(scheduler_lock, flags); - PANIC("CreateSecureProcess: Failed to allocate stack"); + PANIC("MLFQCreateSecureProcess: Failed to allocate stack"); } // Initialize process with enhanced security and scheduling data @@ -1165,7 +1165,7 @@ uint32_t CreateSecureProcess(const char * name, void (*entry_point)(void), uint8 } uint32_t MLFQCreateProcess(const char * name, void (*entry_point)(void)) { - return CreateSecureProcess(name, entry_point, PROC_PRIV_NORM, PROC_FLAG_NONE); + return MLFQCreateSecureProcess(name, entry_point, PROC_PRIV_NORM, PROC_FLAG_NONE); } void MLFQCleanupTerminatedProcess(void) { @@ -1605,7 +1605,7 @@ static void Astra(void) { case 'p': PANIC("Astra: CRITICAL: Manual panic triggered via ProcINFO\n"); break; case 't': threat_level += 10; break; // for fun case 'k': ASTerminate(current->pid, "ProcINFO"); break; - case 'a': CreateSecureProcess("Astra", Astra, PROC_PRIV_SYSTEM, PROC_FLAG_CORE); break; + case 'a': MLFQCreateSecureProcess("Astra", Astra, PROC_PRIV_SYSTEM, PROC_FLAG_CORE); break; default: break; } int del_rc = VfsDelete(astra_path, false); @@ -1747,7 +1747,7 @@ int MLFQSchedInit(void) { #ifdef VF_CONFIG_USE_ASTRA PrintKernel("System: Creating AS (Astra)...\n"); - uint32_t AS_pid = CreateSecureProcess("Astra", Astra, PROC_PRIV_SYSTEM, PROC_FLAG_CORE); + uint32_t AS_pid = MLFQCreateSecureProcess("Astra", Astra, PROC_PRIV_SYSTEM, PROC_FLAG_CORE); if (!AS_pid) { #ifndef VF_CONFIG_PANIC_OVERRIDE PANIC("CRITICAL: Failed to create Astra"); @@ -1763,7 +1763,7 @@ int MLFQSchedInit(void) { #ifdef VF_CONFIG_USE_VFSHELL // Create shell process PrintKernel("System: Creating shell process...\n"); - uint32_t shell_pid = CreateSecureProcess("VFShell", ShellProcess, PROC_PRIV_SYSTEM, PROC_FLAG_CORE); + uint32_t shell_pid = MLFQCreateSecureProcess("VFShell", ShellProcess, PROC_PRIV_SYSTEM, PROC_FLAG_CORE); if (!shell_pid) { #ifndef VF_CONFIG_PANIC_OVERRIDE PANIC("CRITICAL: Failed to create shell process"); @@ -1778,7 +1778,7 @@ int MLFQSchedInit(void) { #ifdef VF_CONFIG_USE_DYNAMOX PrintKernel("System: Creating DynamoX...\n"); - uint32_t dx_pid = CreateSecureProcess("DynamoX",DynamoX, PROC_PRIV_SYSTEM, PROC_FLAG_CORE); + uint32_t dx_pid = MLFQCreateSecureProcess("DynamoX",DynamoX, PROC_PRIV_SYSTEM, PROC_FLAG_CORE); if (!dx_pid) { #ifndef VF_CONFIG_PANIC_OVERRIDE PANIC("CRITICAL: Failed to create DynamoX process"); diff --git a/kernel/sched/Shared.h b/kernel/sched/Shared.h index 8fc7ad0..60a3eb4 100644 --- a/kernel/sched/Shared.h +++ b/kernel/sched/Shared.h @@ -5,13 +5,6 @@ #define PROC_PRIV_NORM 1 // Normal processes #define PROC_PRIV_RESTRICTED 2 // Restricted processes -// Security flags -#define PROC_FLAG_NONE 0U -#define PROC_FLAG_IMMUNE (1U << 0) -#define PROC_FLAG_CRITICAL (1U << 1) -#define PROC_FLAG_SUPERVISOR (1U << 3) -#define PROC_FLAG_CORE (PROC_FLAG_IMMUNE | PROC_FLAG_SUPERVISOR | PROC_FLAG_CRITICAL) - typedef enum { PROC_TERMINATED = 0, PROC_READY, From 0b166cd70790e6078b1b7eb4be9c8a83786d515a Mon Sep 17 00:00:00 2001 From: Atheria Date: Mon, 27 Oct 2025 19:27:14 +0700 Subject: [PATCH 2/3] EEVDF SIS --- kernel/sched/EEVDF.c | 13 ++++++------- kernel/sched/EEVDF.h | 1 + kernel/sched/MLFQ.c | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/kernel/sched/EEVDF.c b/kernel/sched/EEVDF.c index 67a3118..a998c50 100644 --- a/kernel/sched/EEVDF.c +++ b/kernel/sched/EEVDF.c @@ -6,6 +6,7 @@ #include "Compositor.h" #include "Console.h" #include "Format.h" +#include "Gdt.h" #include "Ipc.h" #include "MemOps.h" #include "Panic.h" @@ -605,8 +606,7 @@ static uint64_t EEVDFCalculatePCBHash(const EEVDFProcessControlBlock* pcb) { hash = EEVDFSecureHash(&pcb->privilege_level, sizeof(pcb->privilege_level), hash); hash = EEVDFSecureHash(&pcb->token.capabilities, sizeof(pcb->token.capabilities), hash); hash = EEVDFSecureHash(&pcb->stack, sizeof(pcb->stack), hash); - // hash = EEVDFSecureHash(&pcb->context.rip, sizeof(pcb->context.rip), hash); - hash = EEVDFSecureHash(pcb->ProcessRuntimePath, sizeof(pcb->ProcessRuntimePath), hash); + hash = EEVDFSecureHash(&pcb->initial_entry_point, sizeof(pcb->initial_entry_point), hash); return hash; } @@ -865,6 +865,7 @@ int EEVDFSchedInit(void) { EEVDFSetTaskNice(idle_proc, 0); idle_proc->vruntime = 0; idle_proc->exec_start = GetNS(); + idle_proc->initial_entry_point = 0; // Idle process has no specific entry point // Initialize idle process security token EEVDFSecurityToken* token = &idle_proc->token; @@ -961,6 +962,7 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u proc->privilege_level = priv; proc->creation_time = EEVDFGetSystemTicks(); EEVDFSetTaskNice(proc, EEVDF_DEFAULT_NICE); + proc->initial_entry_point = (uint64_t)entry_point; // Store the immutable entry point // Set virtual time to current minimum to ensure fairness proc->vruntime = eevdf_scheduler.rq.min_vruntime; @@ -974,7 +976,6 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u token->capabilities = capabilities; token->creation_tick = proc->creation_time; token->checksum = EEVDFCalculateTokenChecksum(token); - token->pcb_hash = EEVDFCalculatePCBHash(proc); // Set up context uint64_t rsp = (uint64_t)stack; @@ -987,8 +988,8 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u proc->context.rsp = rsp; proc->context.rip = (uint64_t)entry_point; proc->context.rflags = 0x202; - proc->context.cs = 0x08; - proc->context.ss = 0x10; + proc->context.cs = KERNEL_CODE_SELECTOR; + proc->context.ss = KERNEL_DATA_SELECTOR; // Initialize IPC queue proc->ipc_queue.head = 0; @@ -1044,8 +1045,6 @@ EEVDFProcessControlBlock* EEVDFGetCurrentProcessByPID(uint32_t pid) { void EEVDFYield(void) { // Simple yield - just request a schedule need_schedule = 1; - volatile int delay = eevdf_scheduler.total_processes * 100; - while (delay-- > 0) __builtin_ia32_pause(); } // ============================================================================= diff --git a/kernel/sched/EEVDF.h b/kernel/sched/EEVDF.h index 56a14da..d1ade62 100644 --- a/kernel/sched/EEVDF.h +++ b/kernel/sched/EEVDF.h @@ -128,6 +128,7 @@ typedef struct { // Security and system fields (same as MLFQ) uint8_t privilege_level; + uint64_t initial_entry_point; // Immutable entry point for security hashing uint32_t io_operations; uint32_t preemption_count; uint64_t cpu_time_accumulated; diff --git a/kernel/sched/MLFQ.c b/kernel/sched/MLFQ.c index 85e0a9f..076ecc6 100644 --- a/kernel/sched/MLFQ.c +++ b/kernel/sched/MLFQ.c @@ -10,6 +10,7 @@ #endif #include "Console.h" #include "Format.h" +#include "Gdt.h" #include "Io.h" #include "Ipc.h" #include "MemOps.h" @@ -1145,8 +1146,8 @@ uint32_t MLFQCreateSecureProcess(const char * name, void (*entry_point)(void), u processes[slot].context.rsp = rsp; processes[slot].context.rip = (uint64_t)entry_point; processes[slot].context.rflags = 0x202; - processes[slot].context.cs = 0x08; - processes[slot].context.ss = 0x10; + processes[slot].context.cs = KERNEL_CODE_SELECTOR; + processes[slot].context.ss = KERNEL_DATA_SELECTOR; // Initialize IPC queue processes[slot].ipc_queue.head = 0; From a4e6198e8157619c74e4701adf51393c73cf0a10 Mon Sep 17 00:00:00 2001 From: Atheria Date: Mon, 27 Oct 2025 19:38:51 +0700 Subject: [PATCH 3/3] EEVDF SIS --- cmake/source.cmake | 1 + include/Scheduler.h | 133 +++------------------------ kernel/atomic/rust/src/ffi.rs | 1 + kernel/atomic/rust/src/spinlock.rs | 6 +- kernel/sched/Scheduler.c | 139 +++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 121 deletions(-) create mode 100644 kernel/sched/Scheduler.c diff --git a/cmake/source.cmake b/cmake/source.cmake index b22d11c..d1408a3 100644 --- a/cmake/source.cmake +++ b/cmake/source.cmake @@ -28,6 +28,7 @@ set(VFC_SOURCES set(SCHED_SOURCES kernel/sched/MLFQ.c kernel/sched/EEVDF.c + kernel/sched/Scheduler.c ) set(KERNEL_ETC_SOURCES diff --git a/include/Scheduler.h b/include/Scheduler.h index 00f844e..fbaf0b0 100644 --- a/include/Scheduler.h +++ b/include/Scheduler.h @@ -34,142 +34,37 @@ typedef void CurrentProcessControlBlock; #endif // Initialize the active scheduler -static inline __attribute__((always_inline)) int SchedulerInit() { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQSchedInit(); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFSchedInit(); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +int SchedulerInit(); // Create a new process -static inline __attribute__((always_inline)) uint32_t CreateProcess(const char * name, void (*entry_point)()) { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQCreateProcess (name, entry_point); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFCreateProcess (name, entry_point); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +uint32_t CreateProcess(const char * name, void (*entry_point)()); -static inline __attribute__((always_inline)) uint32_t CreateSecureProcess(const char * name, void (*entry_point)(), uint8_t priv, uint8_t flag) { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQCreateSecureProcess(name, entry_point, priv, flag); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFCreateSecureProcess(name, entry_point, priv, flag); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +uint32_t CreateSecureProcess(const char * name, void (*entry_point)(), uint8_t priv, uint8_t flag); -static inline __attribute__((always_inline)) CurrentProcessControlBlock* GetCurrentProcess() { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQGetCurrentProcess(); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFGetCurrentProcess(); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +CurrentProcessControlBlock* GetCurrentProcess(); -static inline __attribute__((always_inline)) CurrentProcessControlBlock* GetCurrentProcessByPID(uint32_t pid) { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQGetCurrentProcessByPID(pid); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFGetCurrentProcessByPID(pid); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +CurrentProcessControlBlock* GetCurrentProcessByPID(uint32_t pid); // Yield CPU -static inline __attribute__((always_inline)) void Yield() { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQYield(); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFYield(); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +void Yield(); // Main scheduler function (called from interrupt handler) -static inline __attribute__((always_inline)) void Schedule(Registers* regs) { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQSchedule(regs); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFSchedule(regs); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +void Schedule(Registers* regs); // Kill a process -static inline __attribute__((always_inline)) void KillProcess(uint32_t pid) { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQKillProcess(pid); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFKillProcess(pid); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +void KillProcess(uint32_t pid); -static inline __attribute__((always_inline)) void KillCurrentProcess(const char * reason) { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQKillCurrentProcess(reason); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFKillCurrentProcess(reason); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +void KillCurrentProcess(const char * reason); // List processes -static inline __attribute__((always_inline)) void ListProcesses() { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQListProcesses(); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFListProcesses(); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +void ListProcesses(); // Performande stats -static inline __attribute__((always_inline)) void DumpPerformanceStats() { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQDumpPerformanceStats(); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFDumpPerformanceStats(); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +void DumpPerformanceStats(); // Dump scheduler state -static inline __attribute__((always_inline)) void DumpSchedulerState() { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQDumpSchedulerState(); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFDumpSchedulerState(); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} - -static inline __attribute__((always_inline)) uint64_t GetSystemTicks() { -#if defined(VF_CONFIG_SCHED_MLFQ) - return MLFQGetSystemTicks(); -#elif defined(VF_CONFIG_SCHED_EEVDF) - return EEVDFGetSystemTicks(); -#elif defined(VF_CONFIG_SCHED_CFS) - return 0; // not implemented -#endif -} +void DumpSchedulerState(); +uint64_t GetSystemTicks(); -#endif // VOIDFRAME_SCHEDULER_H +#endif \ No newline at end of file diff --git a/kernel/atomic/rust/src/ffi.rs b/kernel/atomic/rust/src/ffi.rs index b1e2628..3ad2169 100644 --- a/kernel/atomic/rust/src/ffi.rs +++ b/kernel/atomic/rust/src/ffi.rs @@ -6,6 +6,7 @@ extern "C" { fn save_irq_flags() -> u64; fn restore_irq_flags(flags: u64); fn cli(); + pub(crate) fn Yield(); // Declare the C function for yielding } #[panic_handler] diff --git a/kernel/atomic/rust/src/spinlock.rs b/kernel/atomic/rust/src/spinlock.rs index e8cf5f4..0dc0049 100644 --- a/kernel/atomic/rust/src/spinlock.rs +++ b/kernel/atomic/rust/src/spinlock.rs @@ -104,9 +104,11 @@ impl SpinLock { backoff_delay(backoff); backoff = (backoff * 2).min(MAX_BACKOFF_CYCLES); } else { - // High contention: yield to scheduler (kernel would implement this) - backoff_delay(MAX_BACKOFF_CYCLES); + // High contention: yield to scheduler + unsafe { crate::ffi::Yield(); } local_spins = 0; + // Reset attempts to prevent immediate re-yielding if not scheduled away + attempts = 0; } } } diff --git a/kernel/sched/Scheduler.c b/kernel/sched/Scheduler.c new file mode 100644 index 0000000..2855d65 --- /dev/null +++ b/kernel/sched/Scheduler.c @@ -0,0 +1,139 @@ +#include "Scheduler.h" + +// Initialize the active scheduler +int SchedulerInit() { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQSchedInit(); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFSchedInit(); +#elif defined(VF_CONFIG_SCHED_CFS) + return 0; // not implemented +#endif +} + +// Create a new process +uint32_t CreateProcess(const char * name, void (*entry_point)()) { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQCreateProcess (name, entry_point); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFCreateProcess (name, entry_point); +#elif defined(VF_CONFIG_SCHED_CFS) + return 0; // not implemented +#endif +} + +uint32_t CreateSecureProcess(const char * name, void (*entry_point)(), uint8_t priv, uint8_t flag) { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQCreateSecureProcess(name, entry_point, priv, flag); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFCreateSecureProcess(name, entry_point, priv, flag); +#elif defined(VF_CONFIG_SCHED_CFS) + return 0; // not implemented +#endif +} + +CurrentProcessControlBlock* GetCurrentProcess() { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQGetCurrentProcess(); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFGetCurrentProcess(); +#elif defined(VF_CONFIG_SCHED_CFS) + return 0; // not implemented +#endif +} + +CurrentProcessControlBlock* GetCurrentProcessByPID(uint32_t pid) { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQGetCurrentProcessByPID(pid); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFGetCurrentProcessByPID(pid); +#elif defined(VF_CONFIG_SCHED_CFS) + return 0; // not implemented +#endif +} + +// Yield CPU +void Yield() { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQYield(); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFYield(); +#elif defined(VF_CONFIG_SCHED_CFS) + return; // not implemented +#endif +} + +// Main scheduler function (called from interrupt handler) +void Schedule(Registers* regs) { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQSchedule(regs); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFSchedule(regs); +#elif defined(VF_CONFIG_SCHED_CFS) + return; // not implemented +#endif +} + +// Kill a process +void KillProcess(uint32_t pid) { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQKillProcess(pid); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFKillProcess(pid); +#elif defined(VF_CONFIG_SCHED_CFS) + return; // not implemented +#endif +} + +void KillCurrentProcess(const char * reason) { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQKillCurrentProcess(reason); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFKillCurrentProcess(reason); +#elif defined(VF_CONFIG_SCHED_CFS) + return; // not implemented +#endif +} + +// List processes +void ListProcesses() { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQListProcesses(); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFListProcesses(); +#elif defined(VF_CONFIG_SCHED_CFS) + return; // not implemented +#endif +} + +// Performande stats +void DumpPerformanceStats() { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQDumpPerformanceStats(); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFDumpPerformanceStats(); +#elif defined(VF_CONFIG_SCHED_CFS) + return; // not implemented +#endif +} + +// Dump scheduler state +void DumpSchedulerState() { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQDumpSchedulerState(); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFDumpSchedulerState(); +#elif defined(VF_CONFIG_SCHED_CFS) + return; // not implemented +#endif +} + +uint64_t GetSystemTicks() { +#if defined(VF_CONFIG_SCHED_MLFQ) + return MLFQGetSystemTicks(); +#elif defined(VF_CONFIG_SCHED_EEVDF) + return EEVDFGetSystemTicks(); +#elif defined(VF_CONFIG_SCHED_CFS) + return 0; // not implemented +#endif +}