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}