rust-osdev / bootloader

An experimental pure-Rust x86 bootloader
Apache License 2.0
1.36k stars 206 forks source link

Writing to usable memory regions causes a reboot #440

Closed br0kenpixel closed 4 months ago

br0kenpixel commented 4 months ago

I'm trying to use the MemoryRegions provided by BootInfo to store data. However I have noticed that writing to any region (marked as MemoryRegionKind::Usable) causes QEMU to reboot the VM. I'm assuming it's probably because of some access violation.

My kernel_main():

fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
    let mem = boot_info
        .memory_regions
        .iter()
        .skip(1)
        .find(|region| region.kind == MemoryRegionKind::Usable)
        .unwrap();

    let ptr = mem.start as *mut u8;
    unsafe { *ptr = 9 };

    loop {
        unsafe {
            asm!("NOP");
        }
    }
}
Bootloader config ```rust const CONFIG: bootloader_api::BootloaderConfig = { let mut config = bootloader_api::BootloaderConfig::new_default(); config.kernel_stack_size = 100 * 1024; config.mappings.physical_memory = Some(Mapping::Dynamic); config }; ```

I'd expect this code to simply write 9 to the first address of a usable region. When running the VM, the start address of this regions is 0x3A7000, and the end address is 0x800000.

Things I tried:

I'm using qemu-system-x86_64 v9.0.0 on macOS Monterey. QEMU Flags: Just -drive format=raw,file={uefi_path}

I don't have any experience writing kernels (I'm mostly just exploring out of curiosity). I'm assuming I have to do more than just create a pointer to those addresses to use them.

Freax13 commented 4 months ago

boot_info.memory_regions contains physical addresses, not virtual addresses. In order to access the memory you first have to translate the physical addresses into virtual addresses e.g. by adding boot_info.physical_memory_offset.

br0kenpixel commented 4 months ago

Thanks! That made it work! By the way, is there a way to calculate/get the physical memory size? Adding up the sizes of all usable regions is not even close to the memory given to the VM. I know, some of it will be reserved, but still. I always get 176128 bytes of total usable memory no matter how much I give the VM (using the -m flag).

Freax13 commented 4 months ago

Thanks! That made it work! By the way, is there a way to calculate/get the physical memory size? Adding up the sizes of all usable regions is not even close to the memory given to the VM. I know, some of it will be reserved, but still. I always get 176128 bytes of total usable memory no matter how much I give the VM (using the -m flag).

Adding up all the regions should work. 176128 sounds suspiciously low. If you want to share your code, I can take a look at it.