kernel/
main.rs

1//! # Scarlet Kernel
2//!
3//! Scarlet is an operating system kernel written in Rust that implements a transparent ABI 
4//! conversion layer for executing binaries across different operating systems and architectures. 
5//! The kernel provides a universal container runtime environment with strong isolation capabilities 
6//! and comprehensive filesystem support.
7//!
8//! ## Multi-ABI Execution System
9//!
10//! The core innovation of Scarlet is its ability to run binaries from different operating systems
11//! transparently within the same runtime environment:
12//!
13//! ### ABI Module Architecture
14//!
15//! - **Modular ABI Implementation**: Each ABI module implements its own complete syscall interface
16//!   using shared kernel APIs, rather than translating between syscalls
17//! - **Binary Detection**: Automatic identification of binary format and target ABI through
18//!   ELF header analysis and magic number detection
19//! - **Shared Kernel Resources**: All ABIs operate on common kernel objects (VFS, memory, devices)
20//!   ensuring consistent behavior and efficient resource utilization
21//! - **Native Implementation**: Each ABI provides full syscall implementation using underlying
22//!   kernel abstractions, enabling complete OS compatibility
23//!
24//! ### Supported ABIs
25//!
26//! - **Scarlet Native ABI**: Direct kernel interface with optimal performance, featuring:
27//!   - Handle-based resource management with capability-based security
28//!   - Modern VFS operations with namespace isolation
29//!   - Advanced IPC mechanisms including pipes and shared memory
30//!   - Container-native filesystem operations
31//!
32//! - **Linux Compatibility ABI** *(in development)*: Full POSIX syscall implementation
33//! - **xv6 Compatibility ABI** *(in development)*: Educational OS syscall implementation
34//!
35//! ## Container Runtime Environment
36//!
37//! Scarlet provides enterprise-grade containerization features:
38//!
39//! ### Filesystem Isolation
40//!
41//! - **Mount Namespace Isolation**: Per-task filesystem namespaces enabling complete isolation
42//! - **Bind Mount Operations**: Selective resource sharing between containers
43//! - **Overlay Filesystem**: Copy-on-write semantics with whiteout support for efficient layering
44//! - **Device File Management**: Controlled access to hardware through DevFS integration
45//!
46//! ### Resource Management
47//!
48//! - **Handle-Based Security**: Capability-based access control with fine-grained permissions
49//! - **Memory Isolation**: Per-task memory spaces with controlled sharing mechanisms
50//! - **Task Lifecycle Management**: Complete process management with environment variable support
51//! - **IPC Mechanisms**: Pipes, shared memory, and other inter-process communication primitives
52//!
53//! ## Virtual File System v2
54//!
55//! Scarlet implements a modern VFS architecture designed for container environments:
56//!
57//! ### Core Architecture
58//!
59//! - **VfsEntry**: Path hierarchy cache providing fast O(1) path resolution with automatic cleanup
60//! - **VfsNode**: Abstract file entity interface with metadata access and clean downcasting
61//! - **FileSystemOperations**: Unified driver API consolidating all filesystem operations
62//! - **Mount Tree Management**: Hierarchical mount point management with O(log n) resolution
63//!
64//! ### Filesystem Drivers
65//!
66//! - **TmpFS**: High-performance memory-based filesystem with configurable size limits
67//! - **CpioFS**: Read-only CPIO archive filesystem optimized for initramfs and embedded data
68//! - **OverlayFS**: Advanced union filesystem with copy-up semantics and whiteout support
69//! - **DevFS**: Device file system providing controlled hardware access
70//!
71//! - **Memory Safety**: Prevention of use-after-free, double-free, and data races at compile time:
72//!   - The type system ensures resources are not used after being freed
73//!   - Mutable references are exclusive, preventing data races
74//!   - Lifetimes ensure references do not outlive the data they point to
75//!
76//! - **Trait-based Abstractions**: Common interfaces for device drivers and subsystems enabling modularity:
77//!   - The `BlockDevice` trait defines operations for block-based storage
78//!   - The `SerialDevice` trait provides a common interface for UART and console devices
79//!   - The `FileSystem` trait provides unified filesystem operations for VFS v2 integration
80//!
81//! ## Boot Process
82//!
83//! Scarlet follows a structured initialization sequence:
84//!
85//! 1. **Early Architecture Init**: CPU feature detection, interrupt vector setup
86//! 2. **FDT Parsing**: Hardware discovery from Flattened Device Tree
87//! 3. **Memory Subsystem**: Heap allocator initialization, virtual memory setup
88//! 4. **Device Discovery**: Platform device enumeration and driver binding
89//! 5. **Interrupt Setup**: CLINT/PLIC initialization for timer and external interrupts
90//! 6. **VFS Initialization**: Mount root filesystem, initialize global VFS manager
91//! 7. **Task System**: Scheduler setup, initial task creation
92//! 8. **User Space Transition**: Load initial programs and switch to user mode
93//!
94//! Each stage validates successful completion before proceeding, with detailed logging
95//! available through the early console interface.
96//!
97//! ## System Integration
98//!
99//! ### Core Subsystems
100//!
101//! - **Task Management**: Complete process lifecycle with environment variables and IPC
102//! - **Memory Management**: Virtual memory with per-task address spaces and shared regions
103//! - **Device Framework**: Unified device interface supporting block, character, and platform devices
104//! - **Interrupt Handling**: Event-driven architecture with proper context switching
105//! - **Handle System**: Capability-based resource access with fine-grained permissions
106//!
107//! ### ABI Module Integration
108//!
109//! Each ABI module integrates with the kernel through standardized interfaces:
110//!
111//! - **Binary Loading**: ELF loader with format detection and validation
112//! - **Syscall Dispatch**: Per-ABI syscall tables with transparent routing
113//! - **Resource Management**: Shared kernel object access through common APIs
114//! - **Environment Setup**: ABI-specific process initialization and cleanup
115//! - **Mount Operations**: `mount()`, `umount()`, `pivot_root()` for dynamic filesystem management
116//! - **Process Management**: `execve()`, `fork()`, `wait()`, `exit()` with proper cleanup
117//! - **IPC Operations**: Pipe creation, communication, and resource sharing
118//!
119//! ## Architecture Support
120//!
121//! Currently implemented for RISC-V 64-bit architecture with comprehensive hardware support:
122//!
123//! - **Interrupt Handling**: Complete trap frame management with timer and external interrupts
124//! - **Memory Management**: Virtual memory with page tables and memory protection
125//! - **SBI Interface**: Supervisor Binary Interface for firmware communication
126//! - **Instruction Abstractions**: RISC-V specific optimizations with compressed instruction support
127//!
128//! ## Rust Language Features
129//!
130//! Scarlet leverages Rust's advanced features for safe and efficient kernel development:
131//!
132//! ### Memory Safety
133//!
134//! - **Zero-cost Abstractions**: High-level constructs compile to efficient machine code
135//! - **Ownership System**: Automatic memory management without garbage collection overhead
136//! - **Lifetime Validation**: Compile-time prevention of use-after-free and dangling pointer errors
137//! - **Borrowing Rules**: Exclusive mutable access prevents data races at compile time
138//! - **No Buffer Overflows**: Array bounds checking and safe pointer arithmetic
139//!
140//! ### Type System Features
141//!
142//! - **Trait-based Design**: Generic programming with zero-cost abstractions for device drivers
143//! - **Pattern Matching**: Exhaustive matching prevents unhandled error cases
144//! - **Option/Result Types**: Explicit error handling without exceptions or null pointer errors
145//! - **Custom Test Framework**: `#[test_case]` attribute for no-std kernel testing
146//! - **Const Generics**: Compile-time array sizing and type-level programming
147//!
148//! ### No-std Environment
149//!
150//! - **Embedded-first Design**: No standard library dependency for minimal kernel footprint
151//! - **Custom Allocators**: Direct control over memory allocation strategies
152//! - **Inline Assembly**: Direct hardware access when needed with type safety
153//! - **Custom Panic Handler**: Controlled kernel panic behavior for debugging
154//! - **Boot-time Initialization**: Static initialization and controlled startup sequence
155//!
156//! ## Development Framework
157//!
158//! ### Testing Infrastructure
159//!
160//! Scarlet provides a comprehensive testing framework designed for kernel development:
161//!
162//! ```rust
163//! #[test_case]
164//! fn test_vfs_operations() {
165//!     // Kernel unit tests run in privileged mode
166//!     let vfs = VfsManager::new();
167//!     // ... test implementation
168//! }
169//! ```
170//!
171//! - **Custom Test Runner**: `#[test_case]` attribute for kernel-specific testing
172//! - **No-std Testing**: Tests run directly in kernel mode without standard library
173//! - **Integration Tests**: Full subsystem testing including multi-ABI scenarios
174//! - **Hardware-in-the-Loop**: Testing on real hardware and QEMU emulation
175//! - **Performance Benchmarks**: Kernel performance measurement and regression testing
176//!
177//! ### Debugging Support
178//!
179//! - **Early Console**: Serial output available from early boot stages
180//! - **Panic Handler**: Detailed panic information with stack traces
181//! - **GDB Integration**: Full debugging support through QEMU's GDB stub
182//! - **Memory Debugging**: Allocation tracking and leak detection
183//! - **Tracing**: Event tracing for performance analysis and debugging
184//!
185//! ### Build System Integration
186//!
187//! The kernel integrates with `cargo-make` for streamlined development:
188//!
189//! - `cargo make build`: Full kernel build with user programs
190//! - `cargo make test`: Run all kernel tests
191//! - `cargo make debug`: Launch kernel with GDB support
192//! - `cargo make run`: Quick development cycle execution
193//!
194//! ## Entry Points
195//!
196//! The kernel provides multiple entry points for different scenarios:
197//!
198//! - **`start_kernel()`**: Main bootstrap processor initialization
199//! - **`start_ap()`**: Application processor startup for multicore systems
200//! - **`test_main()`**: Test framework entry point when built with testing enabled
201//!
202//! ## Module Organization
203//!
204//! Core kernel modules provide focused functionality:
205//!
206//! - **`abi/`**: Multi-ABI implementation modules (Scarlet Native, Linux, xv6)
207//! - **`arch/`**: Architecture-specific code (currently RISC-V 64-bit)
208//! - **`drivers/`**: Hardware device drivers (UART, block devices, VirtIO)
209//! - **`fs/`**: Filesystem implementations and VFS v2 core
210//! - **`task/`**: Task management, scheduling, and process lifecycle
211//! - **`mem/`**: Memory management, allocators, and virtual memory
212//! - **`syscall/`**: System call dispatch and implementation
213//! - **`object/`**: Kernel object system with handle management
214//! - **`interrupt/`**: Interrupt handling and controller support
215//!
216//! *Note: Currently, Scarlet Native ABI is fully implemented. Linux and xv6 ABI support 
217//! are under development and will be available in future releases.*
218
219#![no_std]
220#![no_main]
221#![feature(used_with_arg)]
222#![feature(custom_test_frameworks)]
223#![test_runner(crate::test::test_runner)]
224#![reexport_test_harness_main = "test_main"]
225
226pub mod abi;
227pub mod arch;
228pub mod drivers;
229pub mod interrupt;
230pub mod timer;
231pub mod time;
232pub mod library;
233pub mod mem;
234pub mod traits;
235pub mod sched;
236pub mod sync;
237pub mod earlycon;
238pub mod environment;
239pub mod vm;
240pub mod task;
241pub mod initcall;
242pub mod syscall;
243pub mod device;
244pub mod fs;
245pub mod object;
246pub mod ipc;
247pub mod executor;
248
249#[cfg(test)]
250pub mod test;
251
252extern crate alloc;
253use alloc::string::ToString;
254use device::{fdt::{init_fdt, relocate_fdt, FdtManager}, manager::DeviceManager};
255use environment::PAGE_SIZE;
256use initcall::{call_initcalls, driver::driver_initcall_call, early::early_initcall_call};
257use slab_allocator_rs::MIN_HEAP_SIZE;
258
259use arch::{get_cpu, init_arch};
260use task::{elf_loader::load_elf_into_task, new_user_task};
261use vm::{kernel_vm_init, vmem::MemoryArea};
262use sched::scheduler::get_scheduler;
263use mem::{allocator::init_heap, init_bss, __FDT_RESERVED_START, __KERNEL_SPACE_END, __KERNEL_SPACE_START};
264use timer::get_kernel_timer;
265use core::{panic::PanicInfo, sync::atomic::{fence, Ordering}};
266use crate::{fs::vfs_v2::manager::init_global_vfs_manager, interrupt::InterruptManager};
267use crate::fs::vfs_v2::drivers::initramfs::{init_initramfs, relocate_initramfs};
268
269
270/// A panic handler is required in Rust, this is probably the most basic one possible
271#[cfg(not(test))]
272#[panic_handler]
273fn panic(info: &PanicInfo) -> ! {
274    use arch::instruction::idle;
275
276    crate::early_println!("[Scarlet Kernel] panic: {}", info);
277    loop {
278        idle();
279    }
280}
281
282#[unsafe(no_mangle)]
283pub extern "C" fn start_kernel(cpu_id: usize) -> ! {
284    early_println!("Hello, I'm Scarlet kernel!");
285    early_println!("[Scarlet Kernel] Boot on CPU {}", cpu_id);
286    early_println!("[Scarlet Kernel] Initializing .bss section...");
287    init_bss();
288    early_println!("[Scarlet Kernel] Initializing arch...");
289    init_arch(cpu_id);
290    /* Initializing FDT subsystem */
291    early_println!("[Scarlet Kernel] Initializing FDT...");
292    init_fdt();
293    /* Get DRAM area from FDT */
294    let dram_area = FdtManager::get_manager().get_dram_memoryarea().expect("Memory area not found");
295    early_println!("[Scarlet Kernel] DRAM area          : {:#x} - {:#x}", dram_area.start, dram_area.end);
296    /* Relocate FDT to usable memory area */
297    early_println!("[Scarlet Kernel] Relocating FDT...");
298    let fdt_reloc_start = unsafe { &__FDT_RESERVED_START as *const usize as usize };
299    let dest_ptr = fdt_reloc_start as *mut u8;
300    relocate_fdt(dest_ptr);
301    /* Calculate usable memory area */
302    let kernel_end =  unsafe { &__KERNEL_SPACE_END as *const usize as usize };
303    let mut usable_area = MemoryArea::new(kernel_end, dram_area.end);
304    early_println!("[Scarlet Kernel] Usable memory area : {:#x} - {:#x}", usable_area.start, usable_area.end);
305    /* Relocate initramfs to usable memory area */
306    early_println!("[Scarlet Kernel] Relocating initramfs...");
307    if let Err(e) = relocate_initramfs(&mut usable_area) {
308        early_println!("[Scarlet Kernel] Failed to relocate initramfs: {}", e);
309    }
310    early_println!("[Scarlet Kernel] Updated Usable memory area : {:#x} - {:#x}", usable_area.start, usable_area.end);
311    /* Initialize heap with the usable memory area after FDT */
312    early_println!("[Scarlet Kernel] Initializing heap...");
313    let heap_start = (usable_area.start + PAGE_SIZE - 1) & !(PAGE_SIZE - 1);
314    let heap_size = ((usable_area.end - heap_start + 1) / MIN_HEAP_SIZE) * MIN_HEAP_SIZE;
315    let heap_end = heap_start + heap_size - 1;
316    init_heap(MemoryArea::new(heap_start, heap_end));
317
318    fence(Ordering::SeqCst);
319    early_println!("[Scarlet Kernel] Heap initialized at {:#x} - {:#x}", heap_start, heap_end);
320    
321    {
322        let test_vec = alloc::vec::Vec::<u8>::with_capacity(1024);
323        drop(test_vec);
324        early_println!("[Scarlet Kernel] Heap allocation test passed");
325    }
326    
327    fence(Ordering::Release);
328
329    /* After this point, we can use the heap */
330    early_initcall_call();
331    fence(Ordering::SeqCst); // Ensure early initcalls are completed before proceeding
332    driver_initcall_call();
333
334    #[cfg(test)]
335    test_main();
336
337    early_println!("[Scarlet Kernel] Initializing Virtual Memory...");
338    let kernel_start =  unsafe { &__KERNEL_SPACE_START as *const usize as usize };
339    kernel_vm_init(MemoryArea::new(kernel_start, usable_area.end));
340    /* After this point, we can use the heap and virtual memory */
341    /* We will also be restricted to the kernel address space */
342
343    /* Initialize (populate) devices */
344    early_println!("[Scarlet Kernel] Initializing devices...");
345    DeviceManager::get_mut_manager().populate_devices();
346    /* After this point, we can use the device manager */
347    /* Serial console also works */
348    
349    /* Initcalls */
350    call_initcalls();
351
352    /* Initialize interrupt management system */
353    println!("[Scarlet Kernel] Initializing interrupt system...");
354    InterruptManager::get_manager().init();
355
356    /* Initialize timer */
357    println!("[Scarlet Kernel] Initializing timer...");
358    get_kernel_timer().init();
359
360    /* Initialize scheduler */
361    println!("[Scarlet Kernel] Initializing scheduler...");
362    let scheduler = get_scheduler();
363    /* Initialize global VFS */
364    println!("[Scarlet Kernel] Initializing global VFS...");
365    let manager = init_global_vfs_manager();
366    /* Initialize initramfs */
367    println!("[Scarlet Kernel] Initializing initramfs...");
368    init_initramfs(&manager);
369    /* Make init task */
370    println!("[Scarlet Kernel] Creating initial user task...");
371    let mut task = new_user_task("init".to_string(), 0);
372
373    task.init();
374    task.vfs = Some(manager.clone());
375    task.cwd = Some("/".to_string());
376    let file_obj = match task.vfs.as_ref().unwrap().open("/system/scarlet/bin/init", 0) {
377        Ok(kernel_obj) => kernel_obj,
378        Err(e) => {
379            panic!("Failed to open init file: {:?}", e);
380        },
381    };
382    // file_obj is already a KernelObject::File
383    let file_ref = match file_obj.as_file() {
384        Some(file) => file,
385        None => panic!("Failed to get file reference"),
386    };
387
388    match load_elf_into_task(file_ref, &mut task) {
389        Ok(_) => {
390            for map in task.vm_manager.get_memmap() {
391                early_println!("[Scarlet Kernel] Task memory map: {:#x} - {:#x}", map.vmarea.start, map.vmarea.end);
392            }
393            early_println!("[Scarlet Kernel] Successfully loaded init ELF into task");
394            get_scheduler().add_task(task, get_cpu().get_cpuid());
395        }
396        Err(e) => early_println!("[Scarlet Kernel] Error loading ELF into task: {:?}", e),
397    }
398
399    println!("[Scarlet Kernel] Scheduler will start...");
400    scheduler.start_scheduler();
401    loop {} 
402}
403
404#[unsafe(no_mangle)]
405pub extern "C" fn start_ap(cpu_id: usize) {
406    println!("[Scarlet Kernel] CPU {} is up and running", cpu_id);
407    println!("[Scarlet Kernel] Initializing arch...");
408    init_arch(cpu_id);
409    loop {}
410}