From 6317f87bc8198720fc9448e2f278be534d47adc8 Mon Sep 17 00:00:00 2001 From: Atheria Date: Sun, 2 Nov 2025 15:51:04 +0700 Subject: [PATCH 1/5] Cmake fixes --- CMakeLists.txt | 14 ++++++-------- README.md | 16 +++++++++------- docs/DEVELOPMENT.md | 12 +++++++----- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f95304..a19704b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,10 +4,10 @@ cmake_minimum_required(VERSION 3.30) set_property(GLOBAL PROPERTY RULE_MESSAGES OFF) project(VoidFrame - VERSION 0.0.2 + VERSION 0.0.2.4 LANGUAGES C CXX ASM_NASM HOMEPAGE_URL "https://github.com/assembler-0/VoidFrame" - DESCRIPTION "A hobbyist operating system kernel written in C and Rust" + DESCRIPTION "A hobbyist operating system kernel written in C/C++ Assembly Rust" ) enable_language(ASM_NASM) @@ -52,12 +52,7 @@ if(NOT CMAKE_TOOLCHAIN_FILE) message(STATUS "Defaulting to Windows x86_64 toolchain file: ${CMAKE_TOOLCHAIN_FILE}") endif() else() - message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}") -endif() - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) - message(WARNING "CMAKE_BUILD_TYPE not set. Defaulting to Release.") + message(STATUS "CMake: Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}") endif() if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") @@ -131,6 +126,9 @@ endif() link_rust_library(voidframe.krnl voidframe-spinlock) link_rust_library(voidframe.krnl voidframe-mm) +add_dependencies(voidframe.krnl voidframe_mm) +add_dependencies(voidframe.krnl cargo-build_voidframe_spinlock) + # Configure the linker to use ld.lld with proper arguments set_target_properties(voidframe.krnl PROPERTIES LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/voidframe.ld" diff --git a/README.md b/README.md index d23c2dc..6e0d764 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ ## About -VoidFrame is a 64-bit **ring-0** kernel designed for the x86_64 architecture written in C and assembly (nasm). +VoidFrame is a 64-bit **ring-0** kernel designed for the x86_64 architecture written in C/C++, assembly (nasm) and Rust. This kernel was intended and targeted for people who want to learn about operating systems and want to make a piece of their own. As the designer of this kernel, I just wanted to make something that is simple, fast, secure and easy to understand. Which obviously means that it is not a perfect kernel. And it breaks all the time. @@ -26,12 +26,12 @@ It would be amazing if you could contribute to this project! ## Prerequisites (development) - x64-compatible cpu (used: Intel i3-12100F) -- POSIX-compliant OS (SysV ABI) (used: Arch Linux 6.16.9-arch1-1) +- POSIX-compliant OS (SysV ABI) (used: Arch Linux 6.17.6-arch1-1) - cmake >= 3.20 (used: cmake 4.1.2) -- ninja >= 1.11 (used: ninja 1.21.1) -- clang/++ >= 18.0.0 (used: 20.1.8) +- ninja >= 1.11 (used: ninja 1.13.1) +- clang/++ >= 18.0.0 (used: 21.1.4) - rustup (nightly, bare metal toolchain) >= 1.89.0 (used: 1.92.0-nightly) -- nasm >= 2.16 (used: 2.16.03) +- nasm >= 2.16 (used: 3.01) - qemu >= 7.0.0 (used: 10.1.0) - mkfs.fat - mkfs.ext2 @@ -45,8 +45,10 @@ git clone https://github.com/assembler-0/VoidFrame.git cd VoidFrame mkdir build cd build -ccmake .. -G Ninja # 'c' -> 'e' -> 'q' -- IMPORTATNT! -cmake .. +cmake .. -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain/linux-x64.cmake \ + -DCMAKE_BUILD_TYPE=Release +cmake .. # IMPORTANT: for some reason, this command is needed for the first time ninja -j$(nproc) ninja run ``` diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index cf312f5..4eec73f 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -102,9 +102,7 @@ The recommended approach is to use [WSL](https://learn.microsoft.com/en-us/windo ## 3. Building VoidFrame -After installing the dependencies, you can build the kernel using one of the supported build systems. All commands should be run from the root of the VoidFrame repository. - -### Using CMake (actively maintained) +After installing the dependencies, you can build the kernel using CMake. ```bash # 1. Create a build directory @@ -112,9 +110,13 @@ mkdir -p build && cd build # 2. Configure the project (example for Linux) cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain/linux-x64.cmake +cmake .. + +# 3. Features configuration +ccmake . -# 3. Build the kernel -ninja +# 4. Build the all targets +ninja -j$(nproc) # 4. Run the kernel in QEMU ninja run From 2640b535ff1740bb0137f252ff00d427fdf2f999 Mon Sep 17 00:00:00 2001 From: Atheria Date: Sun, 2 Nov 2025 16:19:15 +0700 Subject: [PATCH 2/5] CTZLL --- kernel/sched/EEVDF.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/kernel/sched/EEVDF.c b/kernel/sched/EEVDF.c index 1522147..3cf43db 100644 --- a/kernel/sched/EEVDF.c +++ b/kernel/sched/EEVDF.c @@ -104,13 +104,8 @@ static inline int FastFFS(const uint64_t value) { return __builtin_ctzll(value); } -static inline int FastCLZ(const uint64_t value) { - return __builtin_clzll(value); -} static inline uint64_t GetNS(void) { - // Convert APIC ticks to nanoseconds - // Assuming APIC_HZ is in Hz, convert to ns return (APICticks * 1000000000ULL) / APIC_HZ; } @@ -216,15 +211,17 @@ static void EEVDFRBNodeInit(EEVDFRBNode* node, uint32_t slot) { } static EEVDFRBNode* EEVDFAllocRBNode(uint32_t slot) { - for (uint32_t i = 0; i < EEVDF_MAX_PROCESSES; i++) { - uint32_t word_idx = i / 32; - uint32_t bit_idx = i % 32; - - if (!(rb_node_pool_bitmap[word_idx] & (1U << bit_idx))) { - rb_node_pool_bitmap[word_idx] |= (1U << bit_idx); - EEVDFRBNode* node = &rb_node_pool[i]; - EEVDFRBNodeInit(node, slot); - return node; + for (uint32_t word = 0; word < (EEVDF_MAX_PROCESSES + 31) / 32; word++) { + uint32_t available = ~rb_node_pool_bitmap[word]; + if (available) { + int bit = __builtin_ctz(available); + uint32_t index = word * 32 + bit; + if (index < EEVDF_MAX_PROCESSES) { + rb_node_pool_bitmap[word] |= (1U << bit); + EEVDFRBNode* node = &rb_node_pool[index]; + EEVDFRBNodeInit(node, slot); + return node; + } } } return NULL; From 05ed503e8ae31798f3cd643ada2d6976178285cc Mon Sep 17 00:00:00 2001 From: Atheria Date: Sun, 2 Nov 2025 17:03:14 +0700 Subject: [PATCH 3/5] EEVDF opts and increased locks LIM --- kernel/atomic/rust/src/ffi.rs | 20 +-- kernel/sched/EEVDF.c | 328 ++++++++++++++++++---------------- 2 files changed, 179 insertions(+), 169 deletions(-) diff --git a/kernel/atomic/rust/src/ffi.rs b/kernel/atomic/rust/src/ffi.rs index a215dff..c544682 100644 --- a/kernel/atomic/rust/src/ffi.rs +++ b/kernel/atomic/rust/src/ffi.rs @@ -20,13 +20,13 @@ fn panic(_info: &PanicInfo) -> ! { } // Static storage for locks (kernel will manage allocation) -static mut SPINLOCK_STORAGE: [SpinLock; 64] = [const { SpinLock::new() }; 64]; -static mut SPINLOCK_USED: [bool; 64] = [false; 64]; +static mut SPINLOCK_STORAGE: [SpinLock; 256] = [const { SpinLock::new() }; 256]; +static mut SPINLOCK_USED: [bool; 256] = [false; 256]; #[no_mangle] pub extern "C" fn rust_spinlock_new() -> *mut SpinLock { unsafe { - for i in 0..64 { + for i in 0..256 { if !SPINLOCK_USED[i] { SPINLOCK_USED[i] = true; return &mut SPINLOCK_STORAGE[i] as *mut SpinLock; @@ -103,7 +103,7 @@ pub extern "C" fn rust_spinlock_owner_cpu(lock: *mut SpinLock) -> u32 { #[no_mangle] pub extern "C" fn rust_spinlock_new_with_order(order: u32) -> *mut SpinLock { unsafe { - for i in 0..64 { + for i in 0..256 { if !SPINLOCK_USED[i] { SPINLOCK_USED[i] = true; SPINLOCK_STORAGE[i] = SpinLock::new_with_order(order); @@ -115,15 +115,15 @@ pub extern "C" fn rust_spinlock_new_with_order(order: u32) -> *mut SpinLock { } // Static storage for MCS locks and nodes -static mut MCS_LOCK_STORAGE: [McsLock; 32] = [const { McsLock::new() }; 32]; -static mut MCS_LOCK_USED: [bool; 32] = [false; 32]; -static mut MCS_NODE_STORAGE: [McsNode; 128] = [const { McsNode::new() }; 128]; -static mut MCS_NODE_USED: [bool; 128] = [false; 128]; +static mut MCS_LOCK_STORAGE: [McsLock; 128] = [const { McsLock::new() }; 128]; +static mut MCS_LOCK_USED: [bool; 128] = [false; 128]; +static mut MCS_NODE_STORAGE: [McsNode; 512] = [const { McsNode::new() }; 512]; +static mut MCS_NODE_USED: [bool; 512] = [false; 512]; #[no_mangle] pub extern "C" fn rust_mcs_lock_new() -> *mut McsLock { unsafe { - for i in 0..32 { + for i in 0..128 { if !MCS_LOCK_USED[i] { MCS_LOCK_USED[i] = true; return &mut MCS_LOCK_STORAGE[i] as *mut McsLock; @@ -150,7 +150,7 @@ pub extern "C" fn rust_mcs_lock_free(lock: *mut McsLock) { #[no_mangle] pub extern "C" fn rust_mcs_node_new() -> *mut McsNode { unsafe { - for i in 0..128 { + for i in 0..512 { if !MCS_NODE_USED[i] { MCS_NODE_USED[i] = true; return &mut MCS_NODE_STORAGE[i] as *mut McsNode; diff --git a/kernel/sched/EEVDF.c b/kernel/sched/EEVDF.c index 3cf43db..b31af73 100644 --- a/kernel/sched/EEVDF.c +++ b/kernel/sched/EEVDF.c @@ -52,40 +52,40 @@ const uint32_t eevdf_nice_to_wmult[40] = { /* 15 */ 119304647, 148102320, 186737708, 238609294, 286331153, }; -// Global state +// Per-process locks for fine-grained locking +static RustSpinLock* process_locks[EEVDF_MAX_PROCESSES] ALIGNED_CACHE; + +// Global state with atomic operations static EEVDFProcessControlBlock processes[EEVDF_MAX_PROCESSES] ALIGNED_CACHE; -static volatile uint32_t next_pid = 1; static uint64_t pid_bitmap[EEVDF_MAX_PROCESSES / 64 + 1] = {0}; static volatile uint32_t current_process = 0; static volatile uint32_t process_count = 0; static volatile int need_schedule = 0; static RustSpinLock* pid_lock = NULL; -static RustSpinLock* eevdf_lock = NULL; -static RustRwLock* process_table_rwlock_eevdf = NULL; +static RustSpinLock* runqueue_lock = NULL; // Only for RB tree operations // Security subsystem uint32_t eevdf_security_manager_pid = 0; -static uint32_t security_violation_count = 0; -static uint64_t last_security_check = 0; +static volatile uint32_t security_violation_count = 0; -// Fast bitmap operations for process slots -static uint64_t active_process_bitmap = 0; -static uint64_t ready_process_bitmap = 0; +// Lockless bitmaps with atomic operations +static volatile uint64_t active_process_bitmap = 0; +static volatile uint64_t ready_process_bitmap = 0; // Main scheduler instance static EEVDFScheduler eevdf_scheduler ALIGNED_CACHE; static EEVDFRBNode rb_node_pool[EEVDF_MAX_PROCESSES] ALIGNED_CACHE; -static uint32_t rb_node_pool_bitmap[(EEVDF_MAX_PROCESSES + 31) / 32]; +static volatile uint32_t rb_node_pool_bitmap[(EEVDF_MAX_PROCESSES + 31) / 32]; -// Lockless termination queue +// Lockless termination queue with atomic operations static volatile uint32_t termination_queue[EEVDF_MAX_PROCESSES]; static volatile uint32_t term_queue_head = 0; static volatile uint32_t term_queue_tail = 0; static volatile uint32_t term_queue_count = 0; -// Performance counters -static uint64_t context_switches = 0; -static uint64_t scheduler_calls = 0; +// Performance counters (atomic) +static volatile uint64_t context_switches = 0; +static volatile uint64_t scheduler_calls = 0; extern volatile uint32_t APIC_HZ; extern volatile uint32_t APICticks; @@ -94,18 +94,17 @@ extern volatile uint32_t APICticks; static void EEVDFASTerminate(uint32_t pid, const char* reason); static void EEVDFCleanupTerminatedProcessInternal(void); static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32_t exit_code); -static inline int EEVDFPostflightCheck(uint32_t slot); -static inline int EEVDFPreflightCheck(uint32_t slot); +static int EEVDFPostflightCheck(uint32_t slot); +static int EEVDFPreflightCheck(uint32_t slot); // ============================================================================= // Utility Functions // ============================================================================= -static inline int FastFFS(const uint64_t value) { +static int FastFFS(const uint64_t value) { return __builtin_ctzll(value); } - -static inline uint64_t GetNS(void) { +static uint64_t GetNS(void) { return (APICticks * 1000000000ULL) / APIC_HZ; } @@ -139,7 +138,7 @@ void EEVDFSetTaskNice(EEVDFProcessControlBlock* p, int nice) { if (nice < EEVDF_MIN_NICE) nice = EEVDF_MIN_NICE; if (nice > EEVDF_MAX_NICE) nice = EEVDF_MAX_NICE; - p->nice = nice; + p->nice = (int8_t)nice; p->weight = EEVDFNiceToWeight(nice); p->inv_weight = EEVDFNiceToWmult(nice); } @@ -617,11 +616,12 @@ static uint64_t EEVDFCalculateSecureChecksum(const EEVDFSecurityToken* token, ui } static inline int FindFreeSlotFast(void) { - if (UNLIKELY(active_process_bitmap == ~1ULL)) { + uint64_t current = AtomicRead64(&active_process_bitmap); + if (UNLIKELY(current == ~1ULL)) { return -1; } - uint64_t available = ~active_process_bitmap; + uint64_t available = ~current; available &= ~1ULL; // Clear bit 0 if (UNLIKELY(available == 0)) { @@ -629,13 +629,21 @@ static inline int FindFreeSlotFast(void) { } int slot = FastFFS(available); - active_process_bitmap |= (1ULL << slot); - return slot; + uint64_t mask = 1ULL << slot; + + // Atomic compare-and-swap to claim the slot + if (AtomicCmpxchg64(&active_process_bitmap, current, current | mask) == current) { + return slot; + } + + // Retry if CAS failed + return FindFreeSlotFast(); } static inline void FreeSlotFast(int slot) { if (LIKELY(slot > 0 && slot < 64)) { - active_process_bitmap &= ~(1ULL << slot); + uint64_t mask = 1ULL << slot; + AtomicFetchAnd64(&active_process_bitmap, ~mask); } } @@ -701,10 +709,16 @@ void EEVDFUpdateClock(EEVDFRunqueue* rq) { } void EEVDFSchedule(Registers* regs) { - uint64_t flags = rust_spinlock_lock_irqsave(eevdf_lock); - - AtomicInc(&scheduler_calls); + // Pre-compute values outside lock + uint64_t now = GetNS(); + uint32_t old_slot = eevdf_scheduler.rq.current_slot; + + AtomicInc64(&scheduler_calls); AtomicInc(&eevdf_scheduler.tick_counter); + + // Only lock runqueue for tree operations, not the entire scheduler + uint64_t flags = 0; + int need_rq_lock = 0; #ifdef VF_CONFIG_USE_CERBERUS static uint64_t cerberus_tick_counter = 0; @@ -712,49 +726,49 @@ void EEVDFSchedule(Registers* regs) { CerberusTick(); } #endif - + EEVDFRunqueue* rq = &eevdf_scheduler.rq; - uint32_t old_slot = rq->current_slot; EEVDFProcessControlBlock* prev = NULL; - - // Update clock - EEVDFUpdateClock(rq); + rq->clock = now; + rq->exec_clock = now; - // Handle current task + // Handle current task without global lock if (LIKELY(old_slot != 0 && old_slot < EEVDF_MAX_PROCESSES)) { prev = &processes[old_slot]; - if (UNLIKELY(prev->state == PROC_DYING || prev->state == PROC_ZOMBIE || prev->state == PROC_TERMINATED)) { + ProcessState state = AtomicRead((volatile uint32_t*)&prev->state); + if (UNLIKELY(state == PROC_DYING || state == PROC_ZOMBIE || state == PROC_TERMINATED)) { goto pick_next; } if (UNLIKELY(!EEVDFPostflightCheck(old_slot))) { - // Post-flight check failed, process is corrupt and already terminated. - // Do not re-queue. goto pick_next; } - // Save context + // Save context (lockless) FastMemcpy(&prev->context, regs, sizeof(Registers)); - // Update runtime statistics + // Update runtime statistics (lockless) EEVDFUpdateCurr(rq, prev); - // Check if task should continue running - if (LIKELY(prev->state == PROC_RUNNING)) { - prev->state = PROC_READY; - ready_process_bitmap |= (1ULL << old_slot); - - // Re-enqueue the task (it was dequeued when it started running) - EEVDFEnqueueTask(rq, prev); + // Atomic state transition + if (LIKELY(AtomicCmpxchg((volatile uint32_t*)&prev->state, PROC_RUNNING, PROC_READY) == PROC_RUNNING)) { + AtomicFetchOr64(&ready_process_bitmap, 1ULL << old_slot); + need_rq_lock = 1; } } pick_next:; - // Safety counter to prevent infinite loops when cleaning invalid processes - int retry_count = 0; + // Lock runqueue only when needed for tree operations + if (need_rq_lock || prev) { + flags = rust_spinlock_lock_irqsave(runqueue_lock); + + // Re-enqueue previous task if needed + if (prev && prev->state == PROC_READY) { + EEVDFEnqueueTask(rq, prev); + } + } -pick_retry:; EEVDFProcessControlBlock* next = EEVDFPickNext(rq); uint32_t next_slot; @@ -765,68 +779,65 @@ pick_retry:; if (UNLIKELY(!EEVDFPreflightCheck(next_slot))) { EEVDFDequeueTask(rq, next); - goto pick_retry; // Pick another process + next = EEVDFPickNext(rq); // Try again + next_slot = next ? (next - processes) : 0; } - if (UNLIKELY(next_slot >= EEVDF_MAX_PROCESSES || next->state != PROC_READY)) { - // Remove invalid process from tree to prevent infinite loop + if (LIKELY(next_slot < EEVDF_MAX_PROCESSES && next && next->state == PROC_READY)) { EEVDFDequeueTask(rq, next); - - retry_count++; - if (retry_count > 10) { - PrintKernelWarning("EEVDF: Too many invalid processes detected, falling back to idle\n"); - next_slot = 0; - } else { - goto pick_retry; - } } else { - // Dequeue the selected task - EEVDFDequeueTask(rq, next); + next_slot = 0; // Fall back to idle } } + + if (need_rq_lock || prev) { + rust_spinlock_unlock_irqrestore(runqueue_lock, flags); + } - // Context switch + // Context switch (lockless) rq->current_slot = next_slot; - current_process = next_slot; + AtomicStore(¤t_process, next_slot); if (LIKELY(next_slot != 0)) { EEVDFProcessControlBlock* new_proc = &processes[next_slot]; // Validate process before switching if (UNLIKELY(!new_proc->stack || new_proc->context.rip == 0)) { - // Invalid process, fall back to idle next_slot = 0; goto switch_to_idle; } - new_proc->state = PROC_RUNNING; - ready_process_bitmap &= ~(1ULL << next_slot); + AtomicStore((volatile uint32_t*)&new_proc->state, PROC_RUNNING); + AtomicFetchAnd64(&ready_process_bitmap, ~(1ULL << next_slot)); new_proc->exec_start = GetNS(); new_proc->slice_ns = EEVDFCalcSlice(rq, new_proc); FastMemcpy(regs, &new_proc->context, sizeof(Registers)); - AtomicInc(&context_switches); - eevdf_scheduler.switch_count++; + AtomicInc64(&context_switches); + AtomicInc(&eevdf_scheduler.switch_count); } -switch_to_idle: +switch_to_idle:; - // Periodic cleanup of terminated processes (every 100 schedule calls) + // Cleanup outside lock to reduce critical section if (UNLIKELY((scheduler_calls % 100) == 0)) { - EEVDFCleanupTerminatedProcessInternal(); + EEVDFCleanupTerminatedProcess(); } - - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); } int EEVDFSchedInit(void) { - if (!eevdf_lock && !pid_lock && !process_table_rwlock_eevdf) { // All initialized as NULL so redundant check actually - eevdf_lock = rust_spinlock_new(); + if (!runqueue_lock && !pid_lock) { + runqueue_lock = rust_spinlock_new(); pid_lock = rust_spinlock_new(); - process_table_rwlock_eevdf = rust_rwlock_new(); - if (!eevdf_lock || !pid_lock || !process_table_rwlock_eevdf) PANIC("EEVDFSchedInit: Failed to allocate locks"); + if (!runqueue_lock || !pid_lock) PANIC("EEVDFSchedInit: Failed to allocate locks"); + + // Initialize per-process locks + for (int i = 0; i < EEVDF_MAX_PROCESSES; i++) { + process_locks[i] = rust_spinlock_new(); + if (!process_locks[i]) PANIC("EEVDFSchedInit: Failed to allocate process locks"); + } } PrintKernel("System: Initializing EEVDF scheduler...\n"); // Initialize process array @@ -906,17 +917,13 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u PANIC("EEVDFCreateProcess: NULL entry point"); } - uint64_t flags = rust_spinlock_lock_irqsave(eevdf_lock); - - if (UNLIKELY(process_count >= EEVDF_MAX_PROCESSES)) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + if (UNLIKELY(AtomicRead(&process_count) >= EEVDF_MAX_PROCESSES)) { PANIC("EEVDFCreateProcess: Too many processes"); } - // Find free slot + // Find free slot (lockless) int slot = FindFreeSlotFast(); if (UNLIKELY(slot == -1)) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); PANIC("EEVDFCreateProcess: No free process slots"); } // Allocate PID @@ -935,7 +942,6 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u if (new_pid == 0) { FreeSlotFast(slot); - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); PANIC("EEVDFCreateProcess: PID exhaustion"); } @@ -946,7 +952,12 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u void* stack = VMemAllocStack(EEVDF_STACK_SIZE); if (UNLIKELY(!stack)) { FreeSlotFast(slot); - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + // Free PID + rust_spinlock_lock(pid_lock); + int idx = new_pid / 64; + int bit = new_pid % 64; + pid_bitmap[idx] &= ~(1ULL << bit); + rust_spinlock_unlock(pid_lock); PANIC("EEVDFCreateProcess: Failed to allocate stack"); } @@ -1006,15 +1017,15 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u ProcFSRegisterProcess(new_pid, stack); - // Update counters + // Update counters (atomic) AtomicInc(&process_count); - ready_process_bitmap |= (1ULL << slot); - eevdf_scheduler.total_processes++; + AtomicFetchOr64(&ready_process_bitmap, 1ULL << slot); + AtomicInc(&eevdf_scheduler.total_processes); - // Add to scheduler + // Add to scheduler (requires runqueue lock) + uint64_t rq_flags = rust_spinlock_lock_irqsave(runqueue_lock); EEVDFEnqueueTask(&eevdf_scheduler.rq, proc); - - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + rust_spinlock_unlock_irqrestore(runqueue_lock, rq_flags); return new_pid; } @@ -1031,15 +1042,13 @@ EEVDFProcessControlBlock* EEVDFGetCurrentProcess(void) { } EEVDFProcessControlBlock* EEVDFGetCurrentProcessByPID(uint32_t pid) { - rust_rwlock_read_lock(process_table_rwlock_eevdf, pid); + // Lockless search using atomic reads for (int i = 0; i < EEVDF_MAX_PROCESSES; i++) { - if (processes[i].pid == pid && processes[i].state != PROC_TERMINATED) { - EEVDFProcessControlBlock* found = &processes[i]; - rust_rwlock_read_unlock(process_table_rwlock_eevdf, pid); - return found; + if (AtomicRead(&processes[i].pid) == pid && + AtomicRead((volatile uint32_t*)&processes[i].state) != PROC_TERMINATED) { + return &processes[i]; } } - rust_rwlock_read_unlock(process_table_rwlock_eevdf, pid); return NULL; } @@ -1114,21 +1123,22 @@ static inline int EEVDFPostflightCheck(uint32_t slot) { // ============================================================================= static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32_t exit_code) { - uint64_t flags = rust_spinlock_lock_irqsave(eevdf_lock); EEVDFProcessControlBlock* proc = EEVDFGetCurrentProcessByPID(pid); - if (UNLIKELY(!proc || proc->state == PROC_DYING || - proc->state == PROC_ZOMBIE || proc->state == PROC_TERMINATED)) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + if (UNLIKELY(!proc)) return; + + uint32_t slot = proc - processes; + if (slot >= EEVDF_MAX_PROCESSES) return; + + // Lock this specific process + uint64_t flags = rust_spinlock_lock_irqsave(process_locks[slot]); + + ProcessState state = AtomicRead((volatile uint32_t*)&proc->state); + if (UNLIKELY(state == PROC_DYING || state == PROC_ZOMBIE || state == PROC_TERMINATED)) { + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); return; } EEVDFProcessControlBlock* caller = EEVDFGetCurrentProcess(); - uint32_t slot = proc - processes; - - if (slot >= EEVDF_MAX_PROCESSES) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); - return; - } // Enhanced security checks if (reason != TERM_SECURITY) { @@ -1139,13 +1149,12 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 if (proc->privilege_level == EEVDF_PROC_PRIV_SYSTEM) { // Only system processes can kill system processes if (caller->privilege_level != EEVDF_PROC_PRIV_SYSTEM) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); PrintKernelError("[EEVDF-SECURITY] Process "); PrintKernelInt(caller->pid); PrintKernel(" tried to kill system process "); PrintKernelInt(proc->pid); PrintKernel("\n"); - // Use ASTerminate to avoid recursive deadlock EEVDFASTerminate(caller->pid, "Unauthorized system process termination"); return; } @@ -1153,14 +1162,14 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 // Cannot terminate immune processes if (UNLIKELY(proc->token.capabilities & EEVDF_CAP_IMMUNE)) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); EEVDFASTerminate(caller->pid, "Attempted termination of immune process"); return; } // Cannot terminate critical system processes if (UNLIKELY(proc->token.capabilities & EEVDF_CAP_CRITICAL)) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); EEVDFASTerminate(caller->pid, "Attempted termination of critical process"); return; } @@ -1168,16 +1177,15 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 // Validate caller's token before allowing termination if (UNLIKELY(!EEVDFValidateToken(&caller->token, caller))) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); EEVDFASTerminate(caller->pid, "Token validation failed"); return; } } // Atomic state transition - ProcessState old_state = proc->state; - if (UNLIKELY(AtomicCmpxchg((volatile uint32_t*)&proc->state, old_state, PROC_DYING) != old_state)) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + if (UNLIKELY(AtomicCmpxchg((volatile uint32_t*)&proc->state, state, PROC_DYING) != state)) { + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); return; // Race condition, another thread is handling termination } @@ -1191,20 +1199,25 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 proc->exit_code = exit_code; proc->termination_time = EEVDFGetSystemTicks(); - // Remove from EEVDF scheduler - EEVDFDequeueTask(&eevdf_scheduler.rq, proc); - - // Clear from ready bitmap - ready_process_bitmap &= ~(1ULL << slot); + // Clear from ready bitmap (atomic) + AtomicFetchAnd64(&ready_process_bitmap, ~(1ULL << slot)); // Request immediate reschedule if current process if (UNLIKELY(slot == eevdf_scheduler.rq.current_slot)) { - need_schedule = 1; + AtomicStore(&need_schedule, 1); } - proc->state = PROC_ZOMBIE; // Set state FIRST + AtomicStore((volatile uint32_t*)&proc->state, PROC_ZOMBIE); __atomic_thread_fence(__ATOMIC_SEQ_CST); - AddToTerminationQueueAtomic(slot); // Then add to queue + + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); + + // Remove from scheduler (requires runqueue lock) + uint64_t rq_flags = rust_spinlock_lock_irqsave(runqueue_lock); + EEVDFDequeueTask(&eevdf_scheduler.rq, proc); + rust_spinlock_unlock_irqrestore(runqueue_lock, rq_flags); + + AddToTerminationQueueAtomic(slot); // Free PID rust_spinlock_lock(pid_lock); @@ -1213,15 +1226,11 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 pid_bitmap[idx] &= ~(1ULL << bit); rust_spinlock_unlock(pid_lock); - // Update scheduler statistics - if (eevdf_scheduler.total_processes > 0) { - eevdf_scheduler.total_processes--; - } + // Update scheduler statistics (atomic) + AtomicDec(&eevdf_scheduler.total_processes); ProcFSUnregisterProcess(pid); - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); - #ifdef VF_CONFIG_USE_CERBERUS CerberusUnregisterProcess(proc->pid); #endif @@ -1229,38 +1238,42 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 // EEVDF's deadly termination function - bypasses all protections static void EEVDFASTerminate(uint32_t pid, const char* reason) { - uint64_t flags = rust_spinlock_lock_irqsave(eevdf_lock); EEVDFProcessControlBlock* proc = EEVDFGetCurrentProcessByPID(pid); - - if (!proc || proc->state == PROC_TERMINATED) { - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); + if (!proc) return; + + uint32_t slot = proc - processes; + if (slot >= EEVDF_MAX_PROCESSES) return; + + // AS overrides ALL protections - even immune and critical + uint64_t flags = rust_spinlock_lock_irqsave(process_locks[slot]); + + if (AtomicRead((volatile uint32_t*)&proc->state) == PROC_TERMINATED) { + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); return; } - - // AS overrides ALL protections - even immune and critical - uint32_t slot = proc - processes; - proc->state = PROC_DYING; + + AtomicStore((volatile uint32_t*)&proc->state, PROC_DYING); proc->term_reason = TERM_SECURITY; proc->exit_code = 666; // AS signature proc->termination_time = EEVDFGetSystemTicks(); - EEVDFDequeueTask(&eevdf_scheduler.rq, proc); - ready_process_bitmap &= ~(1ULL << slot); + AtomicFetchAnd64(&ready_process_bitmap, ~(1ULL << slot)); if (slot == eevdf_scheduler.rq.current_slot) { - need_schedule = 1; + AtomicStore(&need_schedule, 1); } + AtomicStore((volatile uint32_t*)&proc->state, PROC_ZOMBIE); + rust_spinlock_unlock_irqrestore(process_locks[slot], flags); + + // Remove from scheduler + uint64_t rq_flags = rust_spinlock_lock_irqsave(runqueue_lock); + EEVDFDequeueTask(&eevdf_scheduler.rq, proc); + rust_spinlock_unlock_irqrestore(runqueue_lock, rq_flags); + AddToTerminationQueueAtomic(slot); - proc->state = PROC_ZOMBIE; - - if (eevdf_scheduler.total_processes > 0) { - eevdf_scheduler.total_processes--; - } - + AtomicDec(&eevdf_scheduler.total_processes); ProcFSUnregisterProcess(pid); - - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); #ifdef VF_CONFIG_USE_CERBERUS CerberusUnregisterProcess(proc->pid); @@ -1274,7 +1287,7 @@ static void EEVDFSecurityViolationHandler(uint32_t violator_pid, const char* rea PrintKernelError(reason); PrintKernelError("\n"); - security_violation_count++; + AtomicInc(&security_violation_count); if (security_violation_count >= EEVDF_MAX_SECURITY_VIOLATIONS) { PANIC("EEVDF: Maximum security violations exceeded"); } @@ -1363,7 +1376,7 @@ static void EEVDFCleanupTerminatedProcessInternal(void) { // Free the slot FreeSlotFast(slot); - process_count--; + AtomicDec(&process_count); cleanup_count++; PrintKernel("EEVDF: Process PID "); @@ -1373,9 +1386,8 @@ static void EEVDFCleanupTerminatedProcessInternal(void) { } void EEVDFCleanupTerminatedProcess(void) { - uint64_t flags = rust_spinlock_lock_irqsave(eevdf_lock); + // Cleanup is now lockless except for individual process locks EEVDFCleanupTerminatedProcessInternal(); - rust_spinlock_unlock_irqrestore(eevdf_lock, flags); } // ============================================================================= @@ -1435,20 +1447,18 @@ void EEVDFListProcesses(void) { } void EEVDFGetProcessStats(uint32_t pid, uint32_t* cpu_time, uint32_t* wait_time, uint32_t* preemptions) { - rust_rwlock_read_lock(process_table_rwlock_eevdf, pid); EEVDFProcessControlBlock* proc = EEVDFGetCurrentProcessByPID(pid); if (!proc) { if (cpu_time) *cpu_time = 0; if (wait_time) *wait_time = 0; if (preemptions) *preemptions = 0; - rust_rwlock_read_unlock(process_table_rwlock_eevdf, pid); return; } - if (cpu_time) *cpu_time = (uint32_t)proc->cpu_time_accumulated; - if (wait_time) *wait_time = (uint32_t)proc->wait_sum; - if (preemptions) *preemptions = proc->preemption_count; - rust_rwlock_read_unlock(process_table_rwlock_eevdf, pid); + // Atomic reads for statistics + if (cpu_time) *cpu_time = (uint32_t)AtomicRead64(&proc->cpu_time_accumulated); + if (wait_time) *wait_time = (uint32_t)AtomicRead64(&proc->wait_sum); + if (preemptions) *preemptions = AtomicRead(&proc->preemption_count); } void EEVDFDumpPerformanceStats(void) { From 4e3d097547ad0a150bb053a6388196df99960e83 Mon Sep 17 00:00:00 2001 From: Atheria Date: Sun, 2 Nov 2025 17:14:54 +0700 Subject: [PATCH 4/5] EEVDF SIS --- kernel/sched/EEVDF.c | 178 +++++++++++++++++++++++++------------------ kernel/sched/EEVDF.h | 1 + 2 files changed, 104 insertions(+), 75 deletions(-) diff --git a/kernel/sched/EEVDF.c b/kernel/sched/EEVDF.c index b31af73..32fb1d2 100644 --- a/kernel/sched/EEVDF.c +++ b/kernel/sched/EEVDF.c @@ -15,6 +15,7 @@ #include #include #include +#include #define offsetof(type, member) ((uint64_t)&(((type*)0)->member)) @@ -24,10 +25,15 @@ #define CACHE_LINE_SIZE 64 #define ALIGNED_CACHE __attribute__((aligned(CACHE_LINE_SIZE))) -// Security constants -static const uint64_t EEVDF_SECURITY_MAGIC = 0x5EC0DE4D41474943ULL; -static const uint64_t EEVDF_SECURITY_SALT = 0xDEADBEEFCAFEBABEULL; -static const uint32_t EEVDF_MAX_SECURITY_VIOLATIONS = EEVDF_SECURITY_VIOLATION_LIMIT; +// SIS (Scheduler Integrated Security) constants +static const uint64_t SIS_MAGIC = 0x5EC0DE4D41474943ULL; +static const uint64_t SIS_SALT_BASE = 0xDEADBEEFCAFEBABEULL; +static const uint32_t SIS_MAX_VIOLATIONS = EEVDF_SECURITY_VIOLATION_LIMIT; + +// SIS runtime state +static volatile uint64_t sis_global_nonce = 0x1337C0DEDEADBEEFULL; +static volatile uint64_t sis_boot_entropy = 0; +static uint64_t sis_process_keys[EEVDF_MAX_PROCESSES] ALIGNED_CACHE; // Nice-to-weight conversion tables (based on Linux CFS) const uint32_t eevdf_nice_to_weight[40] = { @@ -90,6 +96,43 @@ static volatile uint64_t scheduler_calls = 0; extern volatile uint32_t APIC_HZ; extern volatile uint32_t APICticks; +// ============================================================================= +// SIS (Scheduler Integrated Security) - Ultra Low Overhead +// ============================================================================= + +// Fast CRC32 hash using existing crypto/CRC32.h +static inline uint64_t SISFastHash(uint64_t a, uint64_t b) { + uint64_t combined[2] = {a, b}; + return CRC32(combined, sizeof(combined)); +} + +// Generate process-specific key (called once at creation) +static uint64_t SISGenerateProcessKey(uint32_t slot, uint32_t pid) { + AtomicInc64(&sis_global_nonce); + uint64_t entropy = sis_global_nonce; + uint64_t key = SISFastHash(SIS_SALT_BASE ^ entropy, (uint64_t)pid << 32 | slot); + sis_process_keys[slot] = key; + return key; +} + +// Ultra-fast PCB seal (3-4 instructions) +static inline uint64_t SISSealPCB(const EEVDFProcessControlBlock* pcb, uint32_t slot) { + uint64_t critical = (uint64_t)pcb->pid << 32 | pcb->privilege_level << 16 | pcb->state; + return SISFastHash(critical, sis_process_keys[slot]); +} + +// Ultra-fast PCB verification (2-3 instructions) +static inline int SISVerifyPCB(const EEVDFProcessControlBlock* pcb, uint32_t slot) { + if (UNLIKELY(slot >= EEVDF_MAX_PROCESSES)) return 0; + uint64_t expected = SISSealPCB(pcb, slot); + return LIKELY(pcb->sis_seal == expected); +} + +// Update seal after legitimate state change +static inline void SISUpdateSeal(EEVDFProcessControlBlock* pcb, uint32_t slot) { + pcb->sis_seal = SISSealPCB(pcb, slot); +} + // Foward declaration static void EEVDFASTerminate(uint32_t pid, const char* reason); static void EEVDFCleanupTerminatedProcessInternal(void); @@ -579,40 +622,13 @@ EEVDFProcessControlBlock* EEVDFPickNext(EEVDFRunqueue* rq) { // Process Management (same security model as MLFQ) // ============================================================================= -static uint64_t EEVDFSecureHash(const void* data, const uint64_t len, uint64_t salt) { - const uint8_t* bytes = data; - uint64_t hash = salt; - - for (uint64_t i = 0; i < len; i++) { - hash ^= bytes[i]; - hash *= 0x100000001b3ULL; // FNV-1a prime - } - - return hash; -} - +// Legacy compatibility functions (minimal overhead) static uint64_t EEVDFCalculateTokenChecksum(const EEVDFSecurityToken* token) { - return EEVDFSecureHash(token, offsetof(EEVDFSecurityToken, checksum), EEVDF_SECURITY_SALT); + return SISFastHash(token->magic, token->capabilities); } 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->initial_entry_point, sizeof(pcb->initial_entry_point), 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; + return pcb->sis_seal; } static inline int FindFreeSlotFast(void) { @@ -751,8 +767,9 @@ void EEVDFSchedule(Registers* regs) { // Update runtime statistics (lockless) EEVDFUpdateCurr(rq, prev); - // Atomic state transition + // Atomic state transition with SIS update if (LIKELY(AtomicCmpxchg((volatile uint32_t*)&prev->state, PROC_RUNNING, PROC_READY) == PROC_RUNNING)) { + SISUpdateSeal(prev, old_slot); // Update seal after state change AtomicFetchOr64(&ready_process_bitmap, 1ULL << old_slot); need_rq_lock = 1; } @@ -808,6 +825,7 @@ pick_next:; } AtomicStore((volatile uint32_t*)&new_proc->state, PROC_RUNNING); + SISUpdateSeal(new_proc, next_slot); // Update seal after state change AtomicFetchAnd64(&ready_process_bitmap, ~(1ULL << next_slot)); new_proc->exec_start = GetNS(); @@ -840,6 +858,10 @@ int EEVDFSchedInit(void) { } } PrintKernel("System: Initializing EEVDF scheduler...\n"); + + // Initialize SIS crypto (CRC32 auto-initializes) + CRC32Init(); + // Initialize process array FastMemset(processes, 0, sizeof(EEVDFProcessControlBlock) * EEVDF_MAX_PROCESSES); @@ -875,15 +897,21 @@ int EEVDFSchedInit(void) { idle_proc->exec_start = GetNS(); idle_proc->initial_entry_point = 0; // Idle process has no specific entry point - // Initialize idle process security token + // Initialize SIS for idle process + sis_boot_entropy = GetNS() ^ (uint64_t)&idle_proc; // Boot-time entropy + SISGenerateProcessKey(0, 0); + EEVDFSecurityToken* token = &idle_proc->token; - token->magic = EEVDF_SECURITY_MAGIC; + token->magic = SIS_MAGIC; token->creator_pid = 0; token->privilege = EEVDF_PROC_PRIV_SYSTEM; token->capabilities = EEVDF_CAP_CORE; token->creation_tick = idle_proc->creation_time; token->checksum = EEVDFCalculateTokenChecksum(token); - token->pcb_hash = EEVDFCalculatePCBHash(idle_proc); + token->pcb_hash = 0; // Will be set by SIS seal + + // Seal idle process + SISUpdateSeal(idle_proc, 0); snprintf(idle_proc->ProcessRuntimePath, sizeof(idle_proc->ProcessRuntimePath), "%s/%d", RuntimeServices, idle_proc->pid); @@ -978,9 +1006,11 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u proc->vruntime = eevdf_scheduler.rq.min_vruntime; proc->exec_start = GetNS(); - // Initialize security token + // Generate SIS key and initialize security token + SISGenerateProcessKey(slot, new_pid); + EEVDFSecurityToken* token = &proc->token; - token->magic = EEVDF_SECURITY_MAGIC; + token->magic = SIS_MAGIC; token->creator_pid = creator->pid; token->privilege = priv; token->capabilities = capabilities; @@ -1008,8 +1038,9 @@ uint32_t EEVDFCreateSecureProcess(const char* name, void (*entry_point)(void), u snprintf(proc->ProcessRuntimePath, sizeof(proc->ProcessRuntimePath), "%s/%d", RuntimeProcesses, new_pid); - // Recalculate PCB hash after all relevant fields are set - token->pcb_hash = EEVDFCalculatePCBHash(proc); + // Seal process with SIS after all fields are set + SISUpdateSeal(proc, slot); + token->pcb_hash = proc->sis_seal; #ifdef VF_CONFIG_USE_CERBERUS CerberusRegisterProcess(new_pid, (uint64_t)stack, EEVDF_STACK_SIZE); @@ -1061,61 +1092,56 @@ void EEVDFYield(void) { // Security and Validation Functions // ============================================================================= -static int EEVDFValidateToken(const EEVDFSecurityToken* token, const EEVDFProcessControlBlock* pcb) { - if (UNLIKELY(!token || !pcb)) return 0; - if (UNLIKELY(token->magic != EEVDF_SECURITY_MAGIC)) return 0; - - // 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; - } +// SIS validation - ultra-fast path +static inline int SISValidateProcess(const EEVDFProcessControlBlock* pcb, uint32_t slot) { + if (UNLIKELY(!pcb || slot >= EEVDF_MAX_PROCESSES)) return 0; + if (UNLIKELY(pcb->token.magic != SIS_MAGIC)) return 0; + return SISVerifyPCB(pcb, slot); +} - return 1; +// Legacy token validation (compatibility) +static int EEVDFValidateToken(const EEVDFSecurityToken* token, const EEVDFProcessControlBlock* pcb) { + uint32_t slot = pcb - processes; + return SISValidateProcess(pcb, slot); } static inline int EEVDFPreflightCheck(uint32_t slot) { - if (slot == 0) return 1; // Idle process is always safe. + if (slot == 0) return 1; // Idle process is always safe EEVDFProcessControlBlock* proc = &processes[slot]; - if (UNLIKELY(!EEVDFValidateToken(&proc->token, proc))) { - EEVDFASTerminate(proc->pid, "Pre-flight token validation failure"); - return 0; // Do not schedule this process. + // Ultra-fast SIS check (2-3 instructions) + if (UNLIKELY(!SISVerifyPCB(proc, slot))) { + EEVDFASTerminate(proc->pid, "SIS integrity violation"); + return 0; } + // Fast privilege check if (UNLIKELY(proc->privilege_level == EEVDF_PROC_PRIV_SYSTEM && !(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. + EEVDFASTerminate(proc->pid, "Privilege escalation detected"); + return 0; } #ifdef VF_CONFIG_USE_CERBERUS CerberusPreScheduleCheck(slot); #endif - return 1; // Process appears safe to run. + return 1; } static inline int EEVDFPostflightCheck(uint32_t slot) { - if (slot == 0) return 1; // Idle process is always safe. + if (slot == 0) return 1; // Idle process is always safe EEVDFProcessControlBlock* proc = &processes[slot]; - if (UNLIKELY(!EEVDFValidateToken(&proc->token, proc))) { - EEVDFASTerminate(proc->pid, "Post-execution token corruption"); - return 0; // Do not re-queue this process + // Ultra-fast SIS integrity check + if (UNLIKELY(!SISVerifyPCB(proc, slot))) { + EEVDFASTerminate(proc->pid, "Runtime PCB corruption detected"); + return 0; } - return 1; // Process is still safe. + return 1; } // ============================================================================= @@ -1208,6 +1234,7 @@ static void EEVDFTerminateProcess(uint32_t pid, TerminationReason reason, uint32 } AtomicStore((volatile uint32_t*)&proc->state, PROC_ZOMBIE); + SISUpdateSeal(proc, slot); // Update seal after state change __atomic_thread_fence(__ATOMIC_SEQ_CST); rust_spinlock_unlock_irqrestore(process_locks[slot], flags); @@ -1264,6 +1291,7 @@ static void EEVDFASTerminate(uint32_t pid, const char* reason) { } AtomicStore((volatile uint32_t*)&proc->state, PROC_ZOMBIE); + SISUpdateSeal(proc, slot); // Update seal for AS termination rust_spinlock_unlock_irqrestore(process_locks[slot], flags); // Remove from scheduler @@ -1286,10 +1314,10 @@ static void EEVDFSecurityViolationHandler(uint32_t violator_pid, const char* rea PrintKernelError(": "); PrintKernelError(reason); PrintKernelError("\n"); - AtomicInc(&security_violation_count); - if (security_violation_count >= EEVDF_MAX_SECURITY_VIOLATIONS) { - PANIC("EEVDF: Maximum security violations exceeded"); + uint32_t violations = security_violation_count; + if (violations >= SIS_MAX_VIOLATIONS) { + PANIC("SIS: Maximum security violations exceeded"); } EEVDFASTerminate(violator_pid, reason); diff --git a/kernel/sched/EEVDF.h b/kernel/sched/EEVDF.h index 7cdb876..065c056 100644 --- a/kernel/sched/EEVDF.h +++ b/kernel/sched/EEVDF.h @@ -139,6 +139,7 @@ typedef struct { uint64_t termination_time; EEVDFSecurityToken token; + uint64_t sis_seal; // SIS cryptographic seal MessageQueue ipc_queue; EEVDFProcessContext context; char ProcessRuntimePath[256]; From 5f78c619659fc46f9c8b60e948e2c34959fb7e58 Mon Sep 17 00:00:00 2001 From: Atheria Date: Sun, 2 Nov 2025 18:30:04 +0700 Subject: [PATCH 5/5] Remove dead code, minor fixes --- cmake/configuration.cmake | 2 - cmake/features.cmake | 8 ---- cmake/flags.cmake | 2 +- kernel/ipc/Ipc.c | 2 - kernel/sched/EEVDF.c | 7 +++- kernel/sched/MLFQ.c | 1 - mm/security/Cerberus.c | 83 +++++++-------------------------------- vfcompositor/Compositor.c | 4 +- 8 files changed, 21 insertions(+), 88 deletions(-) diff --git a/cmake/configuration.cmake b/cmake/configuration.cmake index 2ab17eb..ff174e7 100644 --- a/cmake/configuration.cmake +++ b/cmake/configuration.cmake @@ -8,8 +8,6 @@ option(STACK_PROTECTION "Enable stack protection" ON) option(SILENT_BUILD "Enable silent build (suppress warnings)" OFF) option(VF_CONFIG_ENABLE_VMWARE_SVGA_II "Enable VMware SVGA II support" OFF) -option(VF_CONFIG_ENABLE_CERBERUS_VFS_LOGGING "Enable Cerberus VFS logging" OFF) -option(VF_CONFIG_CERBERUS_THREAT_REPORTING "Enable Cerberus threat reporting" OFF) option(VF_CONFIG_PANIC_OVERRIDE "Enable panic override" OFF) option(VF_CONFIG_LOAD_MB_MODULES "Enable multiboot module loading" OFF) diff --git a/cmake/features.cmake b/cmake/features.cmake index d166346..9275ebc 100644 --- a/cmake/features.cmake +++ b/cmake/features.cmake @@ -73,14 +73,6 @@ if(VF_CONFIG_ENABLE_VMWARE_SVGA_II) add_compile_definitions(VF_CONFIG_ENABLE_VMWARE_SVGA_II) endif() -if(VF_CONFIG_ENABLE_CERBERUS_VFS_LOGGING) - add_compile_definitions(VF_CONFIG_ENABLE_CERBERUS_VFS_LOGGING) -endif() - -if(VF_CONFIG_CERBERUS_THREAT_REPORTING) - add_compile_definitions(VF_CONFIG_CERBERUS_THREAT_REPORTING) -endif() - if(VF_CONFIG_PANIC_OVERRIDE) add_compile_definitions(VF_CONFIG_PANIC_OVERRIDE) endif() diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 1228b25..7659e92 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -12,7 +12,7 @@ else() endif() if(STACK_PROTECTION) - string(APPEND C_FLAGS " -fstack-protector-strong -D_FORTIFY_SOURCE=2") + string(APPEND C_FLAGS " -fstack-protector-all -D_FORTIFY_SOURCE=2") endif() if(DEBUG_SYMBOLS) diff --git a/kernel/ipc/Ipc.c b/kernel/ipc/Ipc.c index 9964c40..dbbeff4 100644 --- a/kernel/ipc/Ipc.c +++ b/kernel/ipc/Ipc.c @@ -133,7 +133,6 @@ IpcResult IpcReceiveMessage(IpcMessage* msg_buffer) { current->state = PROC_BLOCKED; rust_spinlock_unlock(queue->lock); - Yield(); } } @@ -174,7 +173,6 @@ IpcResult IpcReceiveMessageType(IpcMessage* msg_buffer, IpcMessageType type) { // Mark blocked while still holding the lock to avoid a wakeup‐before‐block race current->state = PROC_BLOCKED; rust_spinlock_unlock(queue->lock); - Yield(); } } diff --git a/kernel/sched/EEVDF.c b/kernel/sched/EEVDF.c index 32fb1d2..c33d979 100644 --- a/kernel/sched/EEVDF.c +++ b/kernel/sched/EEVDF.c @@ -859,8 +859,10 @@ int EEVDFSchedInit(void) { } PrintKernel("System: Initializing EEVDF scheduler...\n"); - // Initialize SIS crypto (CRC32 auto-initializes) - CRC32Init(); +#ifdef VF_CONFIG_USE_CERBERUS + // Initialize Cerberus + CerberusInit(); +#endif // Initialize process array FastMemset(processes, 0, sizeof(EEVDFProcessControlBlock) * EEVDF_MAX_PROCESSES); @@ -920,6 +922,7 @@ int EEVDFSchedInit(void) { process_count = 1; active_process_bitmap |= 1ULL; + #ifdef VF_CONFIG_USE_VFSHELL // Create shell process PrintKernel("System: Creating shell process...\n"); diff --git a/kernel/sched/MLFQ.c b/kernel/sched/MLFQ.c index 5ad49de..fea8350 100644 --- a/kernel/sched/MLFQ.c +++ b/kernel/sched/MLFQ.c @@ -2,7 +2,6 @@ #include #include #include -#include #ifdef VF_CONFIG_USE_CERBERUS #include #endif diff --git a/mm/security/Cerberus.c b/mm/security/Cerberus.c index 985f05a..d38b5ff 100644 --- a/mm/security/Cerberus.c +++ b/mm/security/Cerberus.c @@ -5,9 +5,8 @@ #include #include #include -#include -#include #include + static CerberusState g_cerberus_state = {0}; static RustSpinLock* cerberus_lock = NULL; static uint64_t system_ticks = 0; @@ -27,18 +26,8 @@ void CerberusLogViolation(CerberusViolationReport* report) { rust_spinlock_unlock(cerberus_lock); // Console logging - PrintKernelErrorF("[Cerberus] VIOLATION PID=%d: %s\n", + PrintKernelErrorF("Cerberus: VIOLATION PID=%d: %s\n", report->process_id, report->description); -#ifdef VF_CONFIG_CERBERUS_VFS_LOGGING - // VFS logging - char log_entry[256]; - snprintf(log_entry, sizeof(log_entry), - "TICK=%lu PID=%d TYPE=%d ADDR=0x%lx RIP=0x%lx DESC=%s\n", - system_ticks, report->process_id, report->violation_type, - report->fault_address, report->rip, report->description); - - VfsAppendFile("/ProcINFO/Cerberus/violations.log", log_entry, StringLength(log_entry)); -#endif } @@ -65,12 +54,6 @@ void CerberusInit(void) { g_cerberus_state.monitored_processes = 0; g_cerberus_state.total_violations = 0; g_cerberus_state.is_initialized = true; -#ifdef VF_CONFIG_CERBERUS_VFS_LOGGING - // Create logging directories in VFS - VfsCreateDir(FormatS("%s/Cerberus", RuntimeServices)); - VfsCreateFile(FormatS("%s/Cerberus/violations.log", RuntimeServices)); - VfsCreateFile(FormatS("%s/Cerberus/watchlist.log", RuntimeServices)); -#endif PrintKernelSuccess("Cerberus initialized\n"); } @@ -103,7 +86,7 @@ int CerberusRegisterProcess(uint32_t pid, uint64_t stack_base, uint64_t stack_si g_cerberus_state.monitored_processes++; rust_spinlock_unlock(cerberus_lock); - PrintKernelF("[Cerberus] Process %d registered\n", pid); + PrintKernelF("Cerberus: Process %d registered\n", pid); return 0; } @@ -130,7 +113,7 @@ void CerberusUnregisterProcess(uint32_t pid) { } rust_spinlock_unlock(cerberus_lock); - PrintKernelF("[Cerberus] Process %d unregistered\n", pid); + PrintKernelF("Cerberus: Process %d unregistered\n", pid); } int CerberusInstallStackCanary(uint32_t pid, uint64_t stack_top, uint64_t stack_size) { @@ -141,13 +124,13 @@ int CerberusInstallStackCanary(uint32_t pid, uint64_t stack_top, uint64_t stack_ // Leave some space for initial stack usage uint64_t canary_addr = stack_top - 0x100; // 256 bytes from top - PrintKernelF("[Cerberus] Installing canary: stack_top=0x%lx, size=0x%lx, canary=0x%lx\n", + PrintKernelF("Cerberus: Installing canary: stack_top=0x%lx, size=0x%lx, canary=0x%lx\n", stack_top, stack_size, canary_addr); // Validate memory is accessible and writable uint64_t phys_addr = VMemGetPhysAddr(canary_addr); if (phys_addr == 0) { - PrintKernelWarningF("[Cerberus] Canary address not mapped: 0x%lx\n", canary_addr); + PrintKernelWarningF("Cerberus: Canary address not mapped: 0x%lx\n", canary_addr); return -1; } @@ -156,7 +139,7 @@ int CerberusInstallStackCanary(uint32_t pid, uint64_t stack_top, uint64_t stack_ uint64_t original = *test_ptr; // Read first *test_ptr = 0x1234567890ABCDEF; // Test write if (*test_ptr != 0x1234567890ABCDEF) { - PrintKernelWarningF("[Cerberus] Canary address not writable: 0x%lx\n", canary_addr); + PrintKernelWarningF("Cerberus: Canary address not writable: 0x%lx\n", canary_addr); return -1; } @@ -167,7 +150,7 @@ int CerberusInstallStackCanary(uint32_t pid, uint64_t stack_top, uint64_t stack_ CerberusProcessInfo* proc_info = &g_cerberus_state.process_info[pid]; proc_info->stack_canary_addr = canary_addr; - PrintKernelSuccessF("[Cerberus] Stack canary installed for PID %d at 0x%lx\n", pid, canary_addr); + PrintKernelSuccessF("Cerberus: Stack canary installed for PID %d at 0x%lx\n", pid, canary_addr); return 0; } @@ -180,13 +163,13 @@ int CerberusCheckStackCanary(uint32_t pid) { // Validate canary address is still mapped uint64_t phys_addr = VMemGetPhysAddr(proc_info->stack_canary_addr); if (phys_addr == 0) { - PrintKernelWarningF("[Cerberus] Canary address unmapped for PID %d\n", pid); + PrintKernelWarningF("Cerberus: Canary address unmapped for PID %d\n", pid); return -1; } volatile uint64_t* canary_ptr = (volatile uint64_t*)proc_info->stack_canary_addr; uint64_t canary_value = *canary_ptr; - + if (canary_value != STACK_CANARY_VALUE) { // Stack canary corrupted! CerberusViolationReport violation = { @@ -216,27 +199,18 @@ void CerberusPreScheduleCheck(uint32_t pid) { // Block compromised processes if (proc_info->is_compromised) { - PrintKernelErrorF("[Cerberus] BLOCKED compromised sched %d\n", pid); -#ifdef VF_CONFIG_CERBERUS_THREAT_REPORTING - CerberusReportThreat(pid, MEM_VIOLATION_STACK_CORRUPTION); -#endif + PrintKernelErrorF("Cerberus: BLOCKED compromised sched %d\n", pid); return; } // Check stack canary if (CerberusCheckStackCanary(pid) != 0) { - PrintKernelErrorF("[Cerberus] Stack canary violation in PID %d\n", pid); -#ifdef VF_CONFIG_CERBERUS_THREAT_REPORTING - CerberusReportThreat(pid, MEM_VIOLATION_CANARY_CORRUPT); -#endif + PrintKernelErrorF("Cerberus: Stack canary violation in PID %d\n", pid); } // Check violation threshold if (proc_info->violation_count >= CERBERUS_VIOLATION_THRESHOLD) { - PrintKernelWarningF("[Cerberus] PID %d exceeded violation threshold\n", pid); -#ifdef VF_CONFIG_CERBERUS_THREAT_REPORTING - CerberusReportThreat(pid, MEM_VIOLATION_BOUNDS_CHECK); -#endif + PrintKernelWarningF("Cerberus: PID %d exceeded violation threshold\n", pid); } } @@ -258,7 +232,7 @@ void CerberusTick(void) { !proc_info->is_compromised) { proc_info->is_compromised = true; - PrintKernelWarningF("[Cerberus] Process %d marked as compromised\n", i); + PrintKernelWarningF("Cerberus: Process %d marked as compromised\n", i); } } } @@ -299,35 +273,6 @@ int CerberusAnalyzeFault(uint64_t fault_addr, uint64_t error_code, uint32_t pid, return 0; // No violation } -#ifdef VF_CONFIG_CERBERUS_THREAT_REPORTING -void CerberusReportThreat(uint32_t pid, MemorySecurityViolation violation) { - if (!g_cerberus_state.is_initialized) return; - - extern uint32_t security_manager_pid; // From MLFQ.c - if (security_manager_pid == 0) return; // Astra not available - - // Create IPC message with threat data - IpcMessage threat_msg = { - .sender_pid = 0, // Kernel/Cerberus - .type = IPC_TYPE_DATA, - .size = sizeof(CerberusThreatReport) - }; - - CerberusThreatReport* report = (CerberusThreatReport*)threat_msg.payload.data; - report->pid = pid; - report->violation_type = violation; - report->fault_address = 0; // Can be populated from context - report->rip = 0; - report->severity = (violation >= MEM_VIOLATION_STACK_CORRUPTION) ? 3 : 2; - report->timestamp = system_ticks; - - // Send directly to Astra via IPC - no VFS operations! - IpcSendMessage(security_manager_pid, &threat_msg); - - PrintKernelWarningF("[Cerberus] Threat reported to Astra via IPC: PID=%d\n", pid); -} -#endif - int CerberusTrackAlloc(uint64_t addr, uint64_t size, uint32_t pid) { if (!g_cerberus_state.is_initialized) return -1; diff --git a/vfcompositor/Compositor.c b/vfcompositor/Compositor.c index d8ba6f6..42420a3 100644 --- a/vfcompositor/Compositor.c +++ b/vfcompositor/Compositor.c @@ -434,9 +434,7 @@ void VFCompositor(void) { if (!VBEIsInitialized()) { PrintKernel("VFCompositor: VBE not initialized, waiting...\n"); - while (!VBEIsInitialized()) { - MLFQYield(); - } + return; } CompositorInit(&g_compositor_ctx);