# Rust Kernel Development Guide This guide provides comprehensive information for new developers working on the rust-kernel project. It covers everything from initial setup to advanced development practices. ## Table of Contents 1. [Getting Started](#getting-started) 2. [Project Overview](#project-overview) 3. [Development Workflow](#development-workflow) 4. [Code Structure](#code-structure) 5. [Key Concepts](#key-concepts) 6. [Testing](#testing) 7. [Debugging](#debugging) 8. [Common Tasks](#common-tasks) 9. [Best Practices](#best-practices) 10. [Troubleshooting](#troubleshooting) --- ## Getting Started ### Prerequisites Before you begin, ensure you have the following installed: - **Docker** - Required for cross-compilation - **QEMU** - For testing the kernel - **Rust** - Latest stable version - **NASM** - For assembly code compilation - **GNU Make** - For build orchestration ### Initial Setup 1. **Clone the repository** ```bash git clone https://github.com/your-org/rust-kernel.git cd rust-kernel ``` 2. **Build the Docker environment** ```bash cd buildenv docker build -t rust-kernel-env . ``` 3. **Start a development container** ```bash cd buildenv docker run --rm -it -v $(pwd)/..:/root/env rust-kernel-env bash ``` 4. **Build the kernel** ```bash cd /root/env make build ``` 5. **Run the kernel in QEMU** ```bash qemu-system-x86_64 -cdrom dist/x86_64/kernel.iso -serial stdio ``` --- ## Project Overview ### What is this kernel? This is a bare-metal x86_64 operating system kernel written in Rust. It's designed as an educational project to demonstrate modern kernel development practices while maintaining clarity over optimization. ### Key Features - **Rust-based** - Leverages Rust's safety features where possible - **No_std environment** - No standard library, minimal dependencies - **Linux-inspired architecture** - Follows Linux design patterns - **Modular design** - Clear separation of concerns - **Comprehensive testing** - Built-in test framework - **Virtual File System** - Linux-like VFS layer - **Task management** - Process and thread management - **System calls** - Basic syscall interface ### Current Status **Phase 2.4 Complete:** - Context switching - Scheduler (round-robin) - Timer-based preemption - TSS (Task State Segment) - System calls (13 implemented) - VFS inode interface - Initramfs and Tmpfs filesystems - Task structures with state management - Linux-style ID allocator **Next Priorities:** 1. Fix VMM page fault handling 2. Replace bump allocator with slab allocator 3. Complete syscall implementation 4. Add process isolation --- ## Development Workflow ### Build Commands All build commands should be run from the project root: ```bash # Build the kernel make build # Build and run tests in QEMU make run-tests # Build ISO only make iso # Clean build artifacts make clean ``` ### Development Cycle 1. **Make changes** - Edit Rust source files 2. **Build** - Run `make build` to compile 3. **Test** - Run `make run-tests` for comprehensive testing 4. **Debug** - Use QEMU serial output for debugging 5. **Iterate** - Fix issues and repeat ### Common Development Tasks #### Adding a New Module 1. Create the module in the appropriate directory 2. Add it to the `src/implementation/kernel/main.rs` imports 3. Implement initialization in the init sequence 4. Add tests in the corresponding test file #### Modifying Existing Code 1. Understand the module's responsibility 2. Check for existing error handling patterns 3. Add appropriate tests 4. Verify build and test pass --- ## Code Structure ### High-Level Organization ``` rust-kernel/ ├── src/implementation/ │ ├── kernel/ # Main kernel modules │ │ ├── main.rs # Entry point and initialization │ │ ├── error.rs # Unified error handling │ │ ├── kernel.rs # Global kernel state │ │ ├── panic.rs # Panic handler │ │ ├── arch/ # Architecture-specific code │ │ ├── memory/ # Memory management │ │ ├── task/ # Process/thread management │ │ ├── vfs/ # Virtual file system │ │ ├── drivers/ # Hardware drivers │ │ └── tests/ # Kernel tests │ └── x86_64/boot/ # Assembly boot code └── targets/x86_64/ # Target configuration ``` ### Module Responsibilities #### `kernel/` (Core) - **main.rs** - Entry point, module initialization - **error.rs** - Unified error handling with `KernelError` - **kernel.rs** - Global kernel state management - **panic.rs** - Custom panic handler #### `arch/` (Architecture) - **x86/interrupts.rs** - IDT, PIC, interrupt handlers - **x86/tss.rs** - Task State Segment implementation - **init.rs** - Architecture initialization #### `memory/` (Memory Management) - **pmm.rs** - Physical Memory Manager - **vmm.rs** - Virtual Memory Manager - **allocator.rs** - Heap allocator - **init.rs** - Memory subsystem initialization #### `task/` (Process Management) - **task.rs** - Task structure and state - **scheduler.rs** - Round-robin scheduler - **id_allocator.rs** - PID allocation - **switch.rs** - Context switching #### `vfs/` (File System) - **inode.rs** - VFS inode interface - **file.rs** - File abstraction - **mount.rs** - Mount namespace - **initramfs.rs** - Embedded filesystem - **tmpfs.rs** - In-memory filesystem #### `drivers/` (Hardware) - **vga.rs** - VGA text mode driver - **serial.rs** - Serial port driver - **init.rs** - Driver initialization --- ## Key Concepts ### No_std Environment This kernel runs without the Rust standard library. Key implications: - **No heap allocation** until memory manager is initialized - **No standard I/O** - use custom drivers (VGA, serial) - **No panic recovery** - implement custom panic handler - **Limited collections** - only core collections available ### Error Handling All modules use unified error handling: ```rust use crate::error::{KernelError, KernelResult}; fn some_operation() -> KernelResult { // Instead of custom errors: // return Err(MyCustomError::Something); // Use KernelError: Err(KernelError::NotFound) } ``` ### Memory Safety Rust's safety features are used where possible, but unsafe blocks are necessary for: - Hardware access (memory-mapped I/O) - Context switching assembly - Raw pointer manipulation - Inline assembly Every unsafe block must be documented with `// SAFETY:` comments explaining the invariants. ### Concurrency The kernel uses spin locks for synchronization: ```rust use spin::Mutex; static GLOBAL_DATA: Mutex = Mutex::new(GlobalData::default()); ``` --- ## Testing ### Test Framework The kernel has a built-in test framework that runs in QEMU: ```bash # Run all tests make run-tests # Tests output to serial port # Look for "TESTS PASSED" or "TESTS FAILED" messages ``` ### Test Structure Tests are organized by subsystem: - **test_allocator.rs** - Heap allocator tests - **test_pmm.rs** - Physical memory tests - **test_vmm.rs** - Virtual memory tests - **test_task.rs** - Task management tests - **test_vfs.rs** - VFS tests - **test_tss.rs** - TSS tests ### Writing Tests 1. Create test functions in the appropriate test file 2. Use `#[test_case]` or standard test attributes 3. Tests run in kernel context with serial output 4. Test failures cause kernel halt with error message --- ## Debugging ### Serial Output All debugging information goes to the serial port: ```rust use crate::drivers::serial::write_string; write_string("Debug message\n"); ``` ### QEMU Debugging Run QEMU with serial output for debugging: ```bash qemu-system-x86_64 -cdrom dist/x86_64/kernel.iso -serial stdio ``` ### Common Debugging Techniques 1. **Serial logging** - Use `write_string()` for debug messages 2. **VGA output** - Use `vga::println!()` for visual debugging 3. **Panic handler** - Custom panic provides file/line info 4. **Breakpoints** - Use QEMU's debugging features if needed --- ## Common Tasks ### Adding a New System Call 1. Add syscall number to `syscall/numbers.rs` 2. Implement handler in `syscall/handler.rs` 3. Add to syscall dispatch table 4. Write tests in `tests/test_syscall.rs` ### Creating a New Filesystem 1. Create module in `vfs/` directory 2. Implement `Inode` trait 3. Add to VFS mount system 4. Write tests ### Adding Hardware Support 1. Create driver in `drivers/` directory 2. Implement initialization in `drivers/init.rs` 3. Add to driver initialization sequence 4. Write tests --- ## Best Practices ### Code Style - **Naming**: `snake_case` for functions, `PascalCase` for types - **Error handling**: Always use `Result` for high level kernel calls. (= is called in/near `main.rs`) --- ## Troubleshooting ### Common Issues #### "make: command not found" - Install GNU Make - On Ubuntu: `sudo apt-get install make` #### "docker: command not found" - Install Docker Desktop or Docker Engine - Ensure Docker daemon is running #### "qemu-system-x86_64: command not found" - Install QEMU - On Ubuntu: `sudo apt-get install qemu-system-x86` #### "kernel panic" - Check serial output for error message - Verify memory initialization - Check for null pointer dereferences #### "tests cause kernel reset" - Tests may be causing memory corruption - Check for memory leaks in test code - Consider running tests in isolated contexts ### Getting Help 1. **Check serial output** - Most errors print to serial 2. **Review error logs** - Look for specific error messages 3. **Check documentation** - This guide and code comments 4. **Ask questions** - Reach out to me --- ## Next Steps Now that you're familiar with the project structure and development workflow, you can: 1. **Start with small changes** - Fix a bug or add a simple feature 2. **Read the code** - Understand how existing modules work 3. **Run the tests** - Verify everything works as expected 4. **Contribute** - Submit a pull request with your changes