somehal

Crates.iosomehal
lib.rssomehal
version0.4.4
created_at2025-07-22 09:07:18.224868+00
updated_at2025-09-22 08:23:15.595129+00
descriptionBoot kernel code with mmu.
homepage
repositoryhttps://github.com/rcore-os/somehal
max_upload_size
id1763247
size145,917
周睿 (ZR233)

documentation

README

SomeHAL

Test Crates.io License

SomeHAL is a hardware abstraction layer library designed specifically for AArch64 chips with MMU functionality. It provides bootloader capabilities to complete MMU initialization and run code at specified virtual addresses.

Features

  • 🚀 Dynamic MMU Initialization: Automatically configures page tables, enables MMU, and redirects to virtual addresses
  • 📱 Multi-Privilege Level Support: Supports both EL1 and EL2 (hypervisor) privilege levels
  • 🔧 Position Independent Boot: Uses PIE (Position Independent Executable) bootloader
  • 💾 Memory Management: Automatically parses device tree and manages memory regions
  • 🐛 Early Debug Support: Provides early debug output functionality
  • Multi-Core Support: Supports multi-core CPU boot

Architecture Support

  • AArch64: ✅ Full support
    • EL1 (Exception Level 1)
    • EL2 (Exception Level 2, Hypervisor)

Getting Started

Adding Dependencies

Add to your Cargo.toml:

[dependencies]
somehal = "0.3"

Basic Usage

#![no_std]
#![no_main]

use somehal::{entry, BootInfo};

#[entry]
fn main(boot_info: &BootInfo) -> ! {
    // Your kernel main function
    println!("Hello from virtual address!");
    
    // Access boot information
    println!("FDT address: {:p}", boot_info.fdt);
    println!("Memory regions: {}", boot_info.memory_regions.len());
    
    // Your kernel logic
    loop {}
}

Multi-Core Support

use somehal::{entry, secondary_entry, BootInfo};

#[entry]
fn main(boot_info: &BootInfo) -> ! {
    // Primary CPU startup logic
    println!("Primary CPU started");
    
    // Start other cores
    let secondary_addr = somehal::secondary_entry_addr();
    // Start other cores through your method...
    
    loop {}
}

#[secondary_entry]
fn secondary_main(cpu_id: usize) -> ! {
    // Secondary CPU startup logic
    println!("Secondary CPU {} started", cpu_id);
    loop {}
}

Core Concepts

Boot Process

  1. Kernel Entry (_start) - Save boot parameters
  2. PIE Bootloader - Position-independent bootloader responsible for:
    • Parsing device tree (FDT)
    • Configuring page table mappings
    • Enabling MMU
    • Redirecting to virtual addresses
  3. Virtual Entry - Call user's main function

Memory Layout

Virtual Address Space:
0xffff_0000_0000_0000  +----------------+
                       |   Kernel Space |
                       |                |
0xffff_8000_0000_0000  +----------------+
                       |  Linear Mapping|
                       | (Physical Mem) |
0xffff_0000_0000_0000  +----------------+

BootInfo Structure

BootInfo provides important boot-time information:

pub struct BootInfo {
    pub fdt: Option<NonNull<u8>>,           // Device tree pointer
    pub memory_regions: MemoryRegions,      // Memory region list
    pub kimage_start_lma: u64,              // Kernel load address
    pub kimage_start_vma: u64,              // Kernel virtual address
    pub free_memory_start: *mut u8,         // Free memory start address
    pub pg_start: u64,                      // Page table start address
    pub cpu_id: usize,                      // CPU ID
}

Feature Flags

  • hv: Enable hypervisor mode (EL2) support

Hypervisor Mode Example

[dependencies]
somehal = { version = "0.3", features = ["hv"] }

Memory Management

Getting Memory Region Information

use somehal::{BootInfo, MemoryRegionKind};

#[entry]
fn main(boot_info: &BootInfo) -> ! {
    for region in boot_info.memory_regions.iter() {
        match region.kind {
            MemoryRegionKind::Ram => {
                println!("RAM: {:#x} - {:#x}", region.start, region.end);
            }
            MemoryRegionKind::Reserved => {
                println!("Reserved: {:#x} - {:#x}", region.start, region.end);
            }
        }
    }
    
    loop {}
}

I/O Memory Mapping

use somehal::mem::iomap;

// Map I/O device memory
let device_base = 0x1000_0000;
let device_size = 0x1000;

match iomap(device_base, device_size) {
    Ok(virt_addr) => {
        println!("Device mapped at {:p}", virt_addr);
        // Use virtual address to access device
    }
    Err(e) => {
        println!("Failed to map device: {:?}", e);
    }
}

Debug Features

Early Debug Output

use somehal::*;

println!("Early boot message");

Build Configuration

Linker Script

SomeHAL requires specific linker script configuration. Create link.ld in your project:

STACK_SIZE = 0x40000;

INCLUDE "somehal.x"

SECTIONS
{
   # other sections...
}

Build Script

In build.rs:

fn main() {
    // SomeHAL will automatically configure necessary linking parameters
    println!("cargo:rustc-link-arg=-Tlink.ld");
}

Platform Testing

The project provides test configurations for multiple platforms:

# Test runtime
cargo test --target aarch64-unknown-none-softfloat -p test-some-rt

# Test configuration with VM functionality
cargo test --target aarch64-unknown-none-softfloat -p test-some-rt --features hv

Example Projects

Check the tests/test-some-rt directory for complete usage examples.

Important Notes

  1. Target Architecture: Currently only supports aarch64-unknown-none-softfloat target
  2. no_std: This is a no_std library for bare-metal environments
  3. MMU Requirement: Requires hardware MMU support
  4. Device Tree: Requires a valid device tree (FDT) to obtain hardware information

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Issues and pull requests are welcome!

Commit count: 253

cargo fmt