Skip to content

Developer_Onboarding

Zikithezikit edited this page Mar 2, 2026 · 2 revisions

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
  2. Project Overview
  3. Development Workflow
  4. Code Structure
  5. Key Concepts
  6. Testing
  7. Debugging
  8. Common Tasks
  9. Best Practices
  10. 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

    git clone https://github.com/your-org/rust-kernel.git
    cd rust-kernel
  2. Build the Docker environment

    cd buildenv
    docker build -t rust-kernel-env .
  3. Start a development container

    cd buildenv
    docker run --rm -it -v $(pwd)/..:/root/env rust-kernel-env bash
  4. Build the kernel

    cd /root/env
    make build
  5. Run the kernel in QEMU

    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:

# 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:

use crate::error::{KernelError, KernelResult};

fn some_operation() -> KernelResult<T> {
    // 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:

use spin::Mutex;

static GLOBAL_DATA: Mutex<GlobalData> = Mutex::new(GlobalData::default());

Testing

Test Framework

The kernel has a built-in test framework that runs in QEMU:

# 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:

use crate::drivers::serial::write_string;

write_string("Debug message\n");

QEMU Debugging

Run QEMU with serial output for debugging:

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<T, KernelError> 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