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//! comprehensive filesystem support, dynamic linking, and modern graphics capabilities.
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//! - **Dynamic Linking**: Native dynamic linker support for shared libraries and position-independent executables
24//!
25//! ### Supported ABIs
26//!
27//! - **Scarlet Native ABI**: Direct kernel interface with optimal performance, featuring:
28//!   - Handle-based resource management with capability-based security
29//!   - Modern VFS operations with namespace isolation
30//!   - Advanced IPC mechanisms including pipes and event-driven communication
31//!   - Container-native filesystem operations
32//!   - Dynamic linking support
33//!
34//! - **Linux Compatibility ABI** *(in development)*: Full POSIX syscall implementation
35//! - **xv6 Compatibility ABI** *(in development)*: Educational OS syscall implementation
36//!
37//! ## Container Runtime Environment
38//!
39//! Scarlet provides enterprise-grade containerization features:
40//!
41//! ### Filesystem Isolation
42//!
43//! - **Mount Namespace Isolation**: Per-task filesystem namespaces enabling complete isolation
44//! - **Bind Mount Operations**: Selective resource sharing between containers
45//! - **Overlay Filesystem**: Copy-on-write semantics with whiteout support for efficient layering
46//! - **Device File Management**: Controlled access to hardware through DevFS integration
47//!
48//! ### Resource Management
49//!
50//! - **Handle-Based Security**: Capability-based access control with fine-grained permissions
51//! - **Memory Isolation**: Per-task memory spaces with controlled sharing mechanisms
52//! - **Task Lifecycle Management**: Complete process management with environment variable support
53//! - **IPC Mechanisms**: Pipes, shared memory, and other inter-process communication primitives
54//!
55//! ## Virtual File System v2
56//!
57//! Scarlet implements a modern VFS architecture designed for container environments:
58//!
59//! ### Core Architecture
60//!
61//! - **VfsEntry**: Path hierarchy cache providing fast O(1) path resolution with automatic cleanup
62//! - **VfsNode**: Abstract file entity interface with metadata access and clean downcasting
63//! - **FileSystemOperations**: Unified driver API consolidating all filesystem operations
64//! - **Mount Tree Management**: Hierarchical mount point management with O(log n) resolution
65//!
66//! ### Filesystem Drivers
67//!
68//! - **TmpFS**: High-performance memory-based filesystem with configurable size limits
69//! - **CpioFS**: Read-only CPIO archive filesystem optimized for initramfs and embedded data
70//! - **ext2**: Full ext2 filesystem implementation with complete read/write support for persistent storage
71//! - **FAT32**: Complete FAT32 filesystem implementation with directory and file operations
72//! - **OverlayFS**: Advanced union filesystem with copy-up semantics and whiteout support
73//! - **DevFS**: Device file system providing controlled hardware access
74//!
75//! - **Memory Safety**: Prevention of use-after-free, double-free, and data races at compile time:
76//!   - The type system ensures resources are not used after being freed
77//!   - Mutable references are exclusive, preventing data races
78//!   - Lifetimes ensure references do not outlive the data they point to
79//!
80//! - **Trait-based Abstractions**: Common interfaces for device drivers and subsystems enabling modularity:
81//!   - The `BlockDevice` trait defines operations for block-based storage
82//!   - The `SerialDevice` trait provides a common interface for UART and console devices
83//!   - The `FileSystem` trait provides unified filesystem operations for VFS v2 integration
84//!
85//! ## Boot Process
86//!
87//! Scarlet follows a structured, architecture-agnostic initialization sequence
88//! built around the BootInfo structure for unified system startup:
89//!
90//! ### Architecture-Specific Boot Phase
91//!
92//! 1. **Low-level Initialization**: CPU feature detection, trap vector setup
93//! 2. **Hardware Discovery**: Parse firmware-provided hardware description (FDT/UEFI/ACPI)
94//! 3. **Memory Layout**: Determine usable memory areas and relocate critical data
95//! 4. **BootInfo Creation**: Consolidate boot parameters into unified structure
96//! 5. **Kernel Handoff**: Call `start_kernel()` with complete BootInfo
97//!
98//! ### Unified Kernel Initialization
99//!
100//! 6. **Early Memory Setup**: Heap allocator initialization using BootInfo memory areas
101//! 7. **Early Subsystems**: Critical kernel subsystem initialization via early initcalls
102//! 8. **Driver Framework**: Device driver registration and basic driver initcalls
103//! 9. **Virtual Memory**: Kernel virtual memory management and address space setup
104//! 10. **Device Discovery**: Hardware enumeration from BootInfo device source
105//! 11. **Graphics Subsystem**: Framebuffer and graphics device initialization
106//! 12. **Interrupt Infrastructure**: Interrupt controller setup and handler registration
107//! 13. **Timer Subsystem**: Kernel timer initialization for scheduling and timekeeping
108//! 14. **Virtual File System**: VFS initialization and root filesystem mounting
109//! 15. **Initial Filesystem**: Initramfs processing if provided in BootInfo
110//! 16. **Initial Process**: Create and load first userspace task (/system/scarlet/bin/init)
111//! 17. **Scheduler Activation**: Begin task scheduling and enter normal operation
112//!
113//! ### BootInfo Integration Benefits
114//!
115//! - **Architecture Abstraction**: Unified interface across RISC-V, ARM, x86 platforms
116//! - **Modular Design**: Clean separation between arch-specific and generic initialization
117//! - **Memory Safety**: Structured memory area management prevents overlaps and corruption
118//! - **Extensibility**: Easy addition of new boot parameters without breaking existing code
119//! - **Debugging**: Centralized boot information for diagnostics and troubleshooting
120//!
121//! Each stage validates successful completion before proceeding, with comprehensive
122//! logging available through the early console interface. The BootInfo structure
123//! ensures all necessary information is available throughout the initialization process.
124//!
125//! ## System Integration
126//!
127//! ### Core Subsystems
128//!
129//! - **Task Management**: Complete process lifecycle with environment variables and IPC
130//! - **Memory Management**: Virtual memory with per-task address spaces and shared regions
131//! - **Device Framework**: Unified device interface supporting block, character, and platform devices
132//! - **Interrupt Handling**: Event-driven architecture with proper context switching
133//! - **Handle System**: Capability-based resource access with fine-grained permissions
134//!
135//! ### ABI Module Integration
136//!
137//! Each ABI module integrates with the kernel through standardized interfaces:
138//!
139//! - **Binary Loading**: ELF loader with format detection and validation
140//! - **Syscall Dispatch**: Per-ABI syscall tables with transparent routing
141//! - **Resource Management**: Shared kernel object access through common APIs
142//! - **Environment Setup**: ABI-specific process initialization and cleanup
143//! - **Mount Operations**: `mount()`, `umount()`, `pivot_root()` for dynamic filesystem management
144//! - **Process Management**: `execve()`, `fork()`, `wait()`, `exit()` with proper cleanup
145//! - **IPC Operations**: Pipe creation, communication, and resource sharing
146//!
147//! ## Architecture Support
148//!
149//! Currently implemented for RISC-V 64-bit architecture with comprehensive hardware support:
150//!
151//! - **Interrupt Handling**: Complete trap frame management with timer and external interrupts
152//! - **Memory Management**: Virtual memory with page tables and memory protection
153//! - **SBI Interface**: Supervisor Binary Interface for firmware communication
154//! - **Instruction Abstractions**: RISC-V specific optimizations with compressed instruction support
155//!
156//! ## Rust Language Features
157//!
158//! Scarlet leverages Rust's advanced features for safe and efficient kernel development:
159//!
160//! ### Memory Safety
161//!
162//! - **Zero-cost Abstractions**: High-level constructs compile to efficient machine code
163//! - **Ownership System**: Automatic memory management without garbage collection overhead
164//! - **Lifetime Validation**: Compile-time prevention of use-after-free and dangling pointer errors
165//! - **Borrowing Rules**: Exclusive mutable access prevents data races at compile time
166//! - **No Buffer Overflows**: Array bounds checking and safe pointer arithmetic
167//!
168//! ### Type System Features
169//!
170//! - **Trait-based Design**: Generic programming with zero-cost abstractions for device drivers
171//! - **Pattern Matching**: Exhaustive matching prevents unhandled error cases
172//! - **Option/Result Types**: Explicit error handling without exceptions or null pointer errors
173//! - **Custom Test Framework**: `#[test_case]` attribute for no-std kernel testing
174//! - **Const Generics**: Compile-time array sizing and type-level programming
175//!
176//! ### No-std Environment
177//!
178//! - **Embedded-first Design**: No standard library dependency for minimal kernel footprint
179//! - **Custom Allocators**: Direct control over memory allocation strategies
180//! - **Inline Assembly**: Direct hardware access when needed with type safety
181//! - **Custom Panic Handler**: Controlled kernel panic behavior for debugging
182//! - **Boot-time Initialization**: Static initialization and controlled startup sequence
183//!
184//! ## Development Framework
185//!
186//! ### Testing Infrastructure
187//!
188//! Scarlet provides a comprehensive testing framework designed for kernel development:
189//!
190//! ```rust
191//! #[test_case]
192//! fn test_vfs_operations() {
193//!     // Kernel unit tests run in privileged mode
194//!     let vfs = VfsManager::new();
195//!     // ... test implementation
196//! }
197//! ```
198//!
199//! - **Custom Test Runner**: `#[test_case]` attribute for kernel-specific testing
200//! - **No-std Testing**: Tests run directly in kernel mode without standard library
201//! - **Integration Tests**: Full subsystem testing including multi-ABI scenarios
202//! - **Hardware-in-the-Loop**: Testing on real hardware and QEMU emulation
203//! - **Performance Benchmarks**: Kernel performance measurement and regression testing
204//!
205//! ### Debugging Support
206//!
207//! - **Early Console**: Serial output available from early boot stages
208//! - **Panic Handler**: Detailed panic information with stack traces
209//! - **GDB Integration**: Full debugging support through QEMU's GDB stub
210//! - **Memory Debugging**: Allocation tracking and leak detection
211//! - **Tracing**: Event tracing for performance analysis and debugging
212//!
213//! ### Build System Integration
214//!
215//! The kernel integrates with `cargo-make` for streamlined development:
216//!
217//! - `cargo make build-debug-riscv64` / `cargo make build-debug-aarch64`: Full build with user programs
218//! - `cargo make test-riscv64` / `cargo make test-aarch64`: Run kernel tests
219//! - `cargo make debug-riscv64` / `cargo make debug-aarch64`: Launch kernel with GDB support
220//! - `cargo make run-riscv64` / `cargo make run-aarch64`: Quick development cycle execution
221//!
222//! ## Entry Points
223//!
224//! The kernel provides multiple entry points for different scenarios:
225//!
226//! - **`start_kernel()`**: Main bootstrap processor initialization
227//! - **`start_ap()`**: Application processor startup for multicore systems
228//! - **`test_main()`**: Test framework entry point when built with testing enabled
229//!
230//! ## Module Organization
231//!
232//! Core kernel modules provide focused functionality:
233//!
234//! - **`abi/`**: Multi-ABI implementation modules (Scarlet Native, Linux, xv6)
235//! - **`arch/`**: Architecture-specific code (currently RISC-V 64-bit)
236//! - **`drivers/`**: Hardware device drivers (UART, block devices, VirtIO)
237//! - **`fs/`**: Filesystem implementations and VFS v2 core
238//! - **`task/`**: Task management, scheduling, and process lifecycle
239//! - **`mem/`**: Memory management, allocators, and virtual memory
240//! - **`syscall/`**: System call dispatch and implementation
241//! - **`object/`**: Kernel object system with handle management
242//! - **`interrupt/`**: Interrupt handling and controller support
243//!
244//! *Note: Currently, Scarlet Native ABI is fully implemented. Linux and xv6 ABI support
245//! are under development and will be available in future releases.*
246
247#![no_std]
248#![no_main]
249#![feature(used_with_arg)]
250#![feature(custom_test_frameworks)]
251#![test_runner(crate::test::test_runner)]
252#![reexport_test_harness_main = "test_main"]
253
254pub mod abi;
255pub mod arch;
256pub mod device;
257pub mod drivers;
258pub mod earlycon;
259pub mod environment;
260pub mod executor;
261pub mod fs;
262pub mod initcall;
263pub mod interrupt;
264pub mod ipc;
265pub mod library;
266pub mod mem;
267#[cfg(feature = "network")]
268pub mod network;
269pub mod object;
270pub mod profiler;
271pub mod random;
272pub mod sched;
273pub mod sync;
274pub mod syscall;
275pub mod task;
276pub mod time;
277pub mod timer;
278pub mod traits;
279pub mod vm;
280
281#[cfg(test)]
282pub mod test;
283
284extern crate alloc;
285use alloc::string::ToString;
286use device::manager::{DeviceManager, DriverPriority};
287use environment::PAGE_SIZE;
288use initcall::{call_initcalls, driver::driver_initcall_call, early::early_initcall_call};
289use slab_allocator_rs::MIN_HEAP_SIZE;
290
291use crate::{
292    device::graphics::manager::GraphicsManager,
293    fs::{drivers::initramfs::init_initramfs, vfs_v2::manager::init_global_vfs_manager},
294    interrupt::InterruptManager,
295};
296use arch::get_cpu;
297use core::sync::atomic::{Ordering, fence};
298use mem::{__KERNEL_SPACE_START, allocator::init_heap};
299use sched::scheduler::get_scheduler;
300use task::{elf_loader::load_elf_into_task, new_user_task};
301use timer::get_kernel_timer;
302use vm::{kernel_vm_init, vmem::MemoryArea};
303
304/// A panic handler is required in Rust, this is probably the most basic one possible
305#[cfg(not(test))]
306#[panic_handler]
307fn panic(info: &core::panic::PanicInfo) -> ! {
308    use arch::instruction::idle;
309
310    crate::early_println!("[Scarlet Kernel] panic: {}", info);
311
312    // if let Some(task) = get_scheduler().get_current_task(get_cpu().get_cpuid()) {
313    //     task.exit(1); // Exit the task with error code 1
314    //     get_scheduler().schedule(get_cpu());
315    // }
316
317    loop {
318        idle();
319    }
320}
321
322/// Represents the source of device information during boot
323///
324/// Different boot protocols provide hardware information through various mechanisms.
325/// This enum captures the source and relevant parameters for device discovery.
326#[derive(Debug, Clone, Copy)]
327pub enum DeviceSource {
328    /// Flattened Device Tree (FDT) source with relocated FDT address
329    /// Used by RISC-V, ARM, and other architectures that support device trees
330    Fdt(usize),
331    /// Unified Extensible Firmware Interface (UEFI) source
332    /// Modern firmware interface providing comprehensive hardware information  
333    Uefi,
334    /// Advanced Configuration and Power Interface (ACPI) source
335    /// x86/x86_64 standard for hardware configuration and power management
336    Acpi,
337    /// No device information available
338    /// Fallback when no hardware description is provided by firmware
339    None,
340}
341
342/// Boot information structure containing essential system parameters
343///
344/// This structure is created during the early boot process and contains
345/// all necessary information for kernel initialization. It abstracts
346/// architecture-specific boot protocols into a common interface.
347///
348/// # Architecture Integration
349///
350/// Different architectures populate this structure from their respective
351/// boot protocols:
352/// - **RISC-V**: Created from FDT (Flattened Device Tree) data
353/// - **ARM/AArch64**: Created from FDT or UEFI
354/// - **x86/x86_64**: Created from ACPI tables or legacy BIOS structures
355///
356/// # Usage
357///
358/// The BootInfo is passed to `start_kernel()` as the primary parameter
359/// and provides all essential information needed for kernel initialization:
360///
361/// ```rust
362/// #[no_mangle]
363/// pub extern "C" fn start_kernel(boot_info: &BootInfo) -> ! {
364///     // Use boot_info for system initialization
365///     let memory = boot_info.usable_memory;
366///     let cpu_id = boot_info.cpu_id;
367///     // ...
368/// }
369/// ```
370pub struct BootInfo {
371    /// CPU/Hart ID of the boot processor
372    /// Used for multicore initialization and per-CPU data structures
373    pub cpu_id: usize,
374    /// Number of CPUs detected at runtime (from FDT)
375    /// Used to drive SMP initialization and per-CPU resource sizing
376    pub cpu_count: usize,
377    /// Usable memory area available for kernel allocation
378    /// Excludes reserved regions, firmware areas, and kernel image
379    pub usable_memory: MemoryArea,
380    /// Optional initramfs memory area if available
381    /// Contains initial root filesystem for early userspace programs
382    pub initramfs: Option<MemoryArea>,
383    /// Optional kernel command line parameters
384    /// Boot arguments passed by bootloader for kernel configuration
385    pub cmdline: Option<&'static str>,
386    /// Source of device information for hardware discovery
387    /// Determines how the kernel will enumerate and initialize devices
388    pub device_source: DeviceSource,
389}
390
391impl BootInfo {
392    /// Creates a new BootInfo instance with the specified parameters
393    ///
394    /// # Arguments
395    ///
396    /// * `cpu_id` - ID of the boot processor/hart
397    /// * `usable_memory` - Memory area available for kernel allocation
398    /// * `initramfs` - Optional initramfs memory area
399    /// * `cmdline` - Optional kernel command line parameters
400    /// * `device_source` - Source of device information for hardware discovery
401    ///
402    /// # Returns
403    ///
404    /// A new BootInfo instance containing the specified boot parameters
405    pub fn new(
406        cpu_id: usize,
407        cpu_count: usize,
408        usable_memory: MemoryArea,
409        initramfs: Option<MemoryArea>,
410        cmdline: Option<&'static str>,
411        device_source: DeviceSource,
412    ) -> Self {
413        Self {
414            cpu_id,
415            cpu_count,
416            usable_memory,
417            initramfs,
418            cmdline,
419            device_source,
420        }
421    }
422
423    /// Returns the kernel command line arguments
424    ///
425    /// Provides access to boot parameters passed by the bootloader.
426    /// Returns an empty string if no command line was provided.
427    ///
428    /// # Returns
429    ///
430    /// Command line string slice, or empty string if none available
431    pub fn get_cmdline(&self) -> &str {
432        if let Some(cmdline) = self.cmdline {
433            cmdline
434        } else {
435            ""
436        }
437    }
438
439    /// Returns the initramfs memory area if available
440    ///
441    /// The initramfs contains an initial root filesystem that can be used
442    /// during early boot before mounting the real root filesystem.
443    ///
444    /// # Returns
445    ///
446    /// Optional memory area containing the initramfs data
447    pub fn get_initramfs(&self) -> Option<MemoryArea> {
448        self.initramfs
449    }
450}
451
452/// Main kernel entry point for the boot processor
453///
454/// This function is called by architecture-specific boot code and performs
455/// the complete kernel initialization sequence using information provided
456/// in the BootInfo structure.
457///
458/// # Boot Sequence
459///
460/// The kernel initialization follows this structured sequence:
461///
462/// 1. **Early System Setup**: Extract boot parameters from BootInfo
463/// 2. **Memory Initialization**: Set up heap allocator with usable memory
464/// 3. **Early Initcalls**: Initialize critical early subsystems
465/// 4. **Driver Initcalls**: Load and initialize device drivers
466/// 5. **Virtual Memory**: Set up kernel virtual memory management
467/// 6. **Device Discovery**: Enumerate hardware from BootInfo device source
468/// 7. **Graphics Initialization**: Initialize graphics subsystem and framebuffer
469/// 8. **Interrupt System**: Set up interrupt controllers and handlers
470/// 9. **Timer Subsystem**: Initialize kernel timer and scheduling infrastructure
471/// 10. **VFS Setup**: Initialize virtual filesystem and mount root
472/// 11. **Initramfs Processing**: Mount initramfs if provided in BootInfo
473/// 12. **Initial Task**: Create and load initial userspace process
474/// 13. **Scheduler Start**: Begin task scheduling and enter normal operation
475///
476/// # Architecture Integration
477///
478/// This function is architecture-agnostic and relies on the BootInfo structure
479/// to abstract hardware-specific details. Architecture-specific boot code is
480/// responsible for creating a properly initialized BootInfo before calling
481/// this function.
482///
483/// # Arguments
484///
485/// * `boot_info` - Comprehensive boot information structure containing:
486///   - CPU ID for multicore initialization
487///   - Usable memory area for heap allocation
488///   - Optional initramfs location and size
489///   - Kernel command line parameters
490///   - Device information source (FDT/UEFI/ACPI)
491///
492/// # Memory Layout
493///
494/// The function expects the following memory layout:
495/// - Kernel image loaded and executable
496/// - BootInfo.usable_memory available for allocation
497/// - Hardware description (FDT/ACPI) accessible via device_source
498/// - Optional initramfs data at specified location
499///
500/// # Safety
501///
502/// This function assumes:
503/// - Architecture-specific initialization has completed successfully
504/// - BootInfo contains valid memory areas and addresses
505/// - Basic CPU features (MMU, interrupts) are available
506/// - Memory protection allows kernel operation
507///
508/// # Returns
509///
510/// This function never returns - it transitions to the scheduler and
511/// enters normal kernel operation mode.
512#[unsafe(no_mangle)]
513pub extern "C" fn start_kernel(boot_info: &BootInfo) -> ! {
514    let cpu_id = boot_info.cpu_id;
515    let cpu_count = boot_info.cpu_count;
516
517    early_println!("[Scarlet Kernel] Hello, I'm Scarlet kernel!");
518    early_println!("[Scarlet Kernel] Boot on CPU {}", cpu_id);
519    early_println!("[Scarlet Kernel] Detected {} CPU(s)", cpu_count);
520    /* Use usable memory area from BootInfo */
521    let usable_area = boot_info.usable_memory;
522    early_println!(
523        "[Scarlet Kernel] Usable memory area : {:#x} - {:#x}",
524        usable_area.start,
525        usable_area.end
526    );
527
528    /* Handle initramfs if available in BootInfo */
529    if let Some(initramfs_area) = boot_info.initramfs {
530        early_println!(
531            "[Scarlet Kernel] InitramFS available: {:#x} - {:#x}",
532            initramfs_area.start,
533            initramfs_area.end
534        );
535        // Note: initramfs already relocated by arch-specific boot code
536    } else {
537        early_println!("[Scarlet Kernel] No initramfs found");
538    }
539
540    /* Initialize heap with the usable memory area */
541    early_println!("[Scarlet Kernel] Initializing heap...");
542    let heap_start = (usable_area.start + PAGE_SIZE - 1) & !(PAGE_SIZE - 1);
543    let heap_size = ((usable_area.end - heap_start + 1) / MIN_HEAP_SIZE) * MIN_HEAP_SIZE;
544    let heap_end = heap_start + heap_size - 1;
545    init_heap(MemoryArea::new(heap_start, heap_end));
546
547    fence(Ordering::SeqCst);
548    early_println!(
549        "[Scarlet Kernel] Heap initialized at {:#x} - {:#x}",
550        heap_start,
551        heap_end
552    );
553
554    {
555        let test_vec = alloc::vec::Vec::<u8>::with_capacity(1024);
556        drop(test_vec);
557        early_println!("[Scarlet Kernel] Heap allocation test passed");
558    }
559
560    fence(Ordering::Release);
561
562    /* After this point, we can use the heap */
563    early_initcall_call();
564    fence(Ordering::SeqCst); // Ensure early initcalls are completed before proceeding
565    driver_initcall_call();
566
567    early_println!("[Scarlet Kernel] Initializing Virtual Memory...");
568    let kernel_start = unsafe { &__KERNEL_SPACE_START as *const usize as usize };
569    kernel_vm_init(MemoryArea::new(kernel_start, usable_area.end));
570    /* After this point, we can use the heap and virtual memory */
571    /* We will also be restricted to the kernel address space */
572
573    /* Populate devices from BootInfo device source */
574    early_println!("[Scarlet Kernel] Populating devices...");
575    let device_manager = DeviceManager::get_manager();
576    // Two-phase interrupt bring-up:
577    // 1) Discover critical interrupt controllers (PLIC/CLINT) first.
578    // 2) Initialize interrupt controllers.
579    // 3) Discover remaining devices (which may enable specific IRQ lines).
580    device_manager
581        .populate_devices_from_source(&boot_info.device_source, Some(&[DriverPriority::Critical]));
582    fence(Ordering::SeqCst); // Ensure device population is complete before proceeding
583
584    /* Initialize interrupt controllers (stage 1) */
585    early_println!("[Scarlet Kernel] Initializing interrupt controllers...");
586    InterruptManager::get_manager().init_controllers();
587
588    fence(Ordering::SeqCst); // Ensure interrupt controllers are initialized before proceeding
589
590    /* Initialize NetworkManager before device discovery so protocol layers are ready */
591    #[cfg(feature = "network")]
592    {
593        early_println!("[NetworkManager] Initializing NetworkLayers...");
594        let _network_manager = crate::network::NetworkManager::init();
595        fence(Ordering::SeqCst);
596    }
597
598    /* Discover remaining devices */
599    early_println!("[Scarlet Kernel] Populating remaining devices...");
600    device_manager.populate_devices_from_source(
601        &boot_info.device_source,
602        Some(&[
603            DriverPriority::Core,
604            DriverPriority::Standard,
605            DriverPriority::Late,
606        ]),
607    );
608    fence(Ordering::SeqCst);
609
610    /* After this point, we can use the device manager */
611    /* Serial console also works */
612
613    /* Initialize Graphics Manager and discover graphics devices */
614    early_println!("[Scarlet Kernel] Initializing graphics subsystem...");
615
616    // Add extra safety measures for optimized builds
617    fence(Ordering::SeqCst); // Ensure device population is complete before proceeding
618
619    // Verify that devices are actually registered before attempting graphics initialization
620    let device_count = DeviceManager::get_manager().get_devices_count();
621    early_println!(
622        "[Scarlet Kernel] Found {} devices before graphics initialization",
623        device_count
624    );
625
626    if device_count > 0 {
627        GraphicsManager::get_manager().discover_graphics_devices();
628    } else {
629        early_println!(
630            "[Scarlet Kernel] Warning: No devices found, skipping graphics initialization"
631        );
632    }
633
634    fence(Ordering::SeqCst); // Ensure graphics devices are discovered before proceeding
635
636    #[cfg(test)]
637    test_main();
638
639    /* Initcalls */
640    early_println!("[boot] entering initcalls");
641    call_initcalls();
642    early_println!("[boot] leaving initcalls");
643
644    fence(Ordering::SeqCst); // Ensure all initcalls are completed before proceeding
645
646    /* Enable CPU interrupt reception (stage 2) */
647    println!("[Scarlet Kernel] Enabling CPU interrupts...");
648    InterruptManager::get_manager().enable_cpu_interrupts();
649
650    fence(Ordering::SeqCst); // Ensure interrupt manager is initialized before proceeding
651
652    /* Initialize timer */
653    early_println!("[boot] Initializing timer...");
654    // Initialize timer for the boot CPU (from BootInfo)
655    get_kernel_timer().init(boot_info.cpu_id);
656
657    fence(Ordering::SeqCst); // Ensure timer is initialized before proceeding
658
659    /* Initialize scheduler */
660    early_println!("[boot] Initializing scheduler...");
661    let scheduler = get_scheduler();
662    fence(Ordering::SeqCst); // Ensure scheduler is initialized before proceeding
663
664    /* Initialize global VFS */
665    early_println!("[boot] Initializing global VFS...");
666    let manager = init_global_vfs_manager();
667
668    /* Initialize initramfs from BootInfo if available */
669    if let Some(initramfs_area) = boot_info.initramfs {
670        println!("[Scarlet Kernel] Initializing initramfs from BootInfo...");
671        if let Err(e) = init_initramfs(&manager, initramfs_area) {
672            println!(
673                "[Scarlet Kernel] Warning: Failed to initialize initramfs: {}",
674                e
675            );
676        }
677    } else {
678        println!("[Scarlet Kernel] No initramfs found in BootInfo");
679    }
680
681    fence(Ordering::SeqCst); // Ensure VFS and initramfs are initialized before proceeding
682
683    /* Apply network configuration from cmdline */
684    #[cfg(feature = "network")]
685    {
686        let cmdline = boot_info.get_cmdline();
687        if !cmdline.is_empty() {
688            crate::network::config::apply_cmdline_config(cmdline);
689        }
690    }
691
692    /* Make init task */
693    early_println!("[boot] Creating initial user task...");
694    let mut task = new_user_task("init".to_string(), 0);
695
696    task.init();
697    *task.vfs.write() = Some(manager.clone());
698    task.vfs
699        .read()
700        .as_ref()
701        .unwrap()
702        .set_cwd_by_path("/")
703        .expect("Failed to set initial working directory");
704    let file_obj = match task
705        .vfs
706        .read()
707        .as_ref()
708        .unwrap()
709        .open("/system/scarlet/bin/init", 0)
710    {
711        Ok(kernel_obj) => kernel_obj,
712        Err(e) => {
713            panic!("Failed to open init file: {:?}", e);
714        }
715    };
716    // file_obj is already a KernelObject::File
717    let file_ref = match file_obj.as_file() {
718        Some(file) => file,
719        None => panic!("Failed to get file reference"),
720    };
721
722    match load_elf_into_task(file_ref, &mut task) {
723        Ok(entry_point) => {
724            task.vm_manager.memmaps_iter_with(|maps| {
725                for map in maps {
726                    early_println!(
727                        "[Scarlet Kernel] Task memory map: {:#x} - {:#x}",
728                        map.vmarea.start,
729                        map.vmarea.end
730                    );
731                }
732            });
733            early_println!(
734                "[Scarlet Kernel] Init ELF loaded with entry point at {:#x}",
735                entry_point
736            );
737            early_println!("[Scarlet Kernel] Successfully loaded init ELF into task");
738            early_println!("[Scarlet Kernel] Adding init task to scheduler...");
739            let cpu_id = get_cpu().get_cpuid();
740            early_println!("[Scarlet Kernel] cpu_id for init task: {}", cpu_id);
741            get_scheduler().add_task(task, cpu_id);
742            early_println!("[Scarlet Kernel] Init task added to scheduler");
743        }
744        Err(e) => early_println!("[Scarlet Kernel] Error loading ELF into task: {:?}", e),
745    }
746
747    early_println!("[Scarlet Kernel] About to fence before scheduler start...");
748    fence(Ordering::SeqCst); // Ensure task is added to scheduler before proceeding
749    early_println!("[Scarlet Kernel] Fence complete; about to print scheduler start...");
750
751    // Use early_println here to avoid any potential console lock issues.
752    early_println!("[Scarlet Kernel] Scheduler will start...");
753    early_println!("[Scarlet Kernel] Calling start_scheduler()...");
754
755    let next_task_id = scheduler.start_scheduler();
756    if let Some(next_task_id) = next_task_id {
757        let next_task = scheduler
758            .get_task_by_id(next_task_id)
759            .expect("First runnable task must exist");
760        crate::arch::first_switch_to_user(next_task);
761    }
762
763    early_println!("[Scarlet Kernel] No runnable task; entering idle loop");
764    loop {
765        crate::arch::instruction::idle();
766    }
767}
768
769#[unsafe(no_mangle)]
770pub extern "C" fn start_ap(cpu_id: usize) {
771    println!("[Scarlet Kernel] CPU {} is up and running", cpu_id);
772
773    loop {}
774}