rustkernelosdevahci

AHCI: Is it normal to have 0xFFFFFFFF across the board?


After using Redox's ahcid as a reference implementation for writing an AHCI driver (which isn't an exact clone of that implementation but it's close) that is compatible with a kernel that began life by following Philipp Oppermann's Rust OS development tutorial and has since diverged greatly therefrom due to further research on my part, I attempted to initialize it like so, making use of the ACPI crate to attempt to find the AHCI controller address:

// snip
entry_point!(maink);

fn maink(boot_info: &'static mut BootInfo) -> ! {
// snip
    let rsdp = boot_info.rsdp_addr.clone().into_option().unwrap();
// snip

    info!("RSDP address: {:#x}", rsdp.clone());
// snip

    let tables = unsafe { AcpiTables::from_rsdp(KernelAcpi, rsdp.clone() as usize).unwrap() };
    let mcfg = match PciConfigRegions::new(&tables) {
        Ok(mcfg) => Some(mcfg),
        Err(_) => None,
    };
// snip
    let sata_ctrl = match mcfg {
        Some(mcfg) => mcfg.physical_address(0x0, 0x1, 0x6, 0x1),
        None => None,
    };
// snip
   if let Some(addr) = sata_ctrl {
        map_page!(
            addr,
            addr,
            Size2MiB,
            PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::NO_CACHE
        );
        let (_, disks) = ahci::disks(addr as usize);
        info!("Found {:#?} disks", disks.len());
    }
// snip

Actually trying to run this returns this output ― note the 0xffffffff across the board:

QEMU output

Curiously, Googling AHCI did reveal that 0xffffffff is normal port behavior for disconnected drives, but I'm curious as to why cap, ghc, is, pi, vs, cap2, and bohc are all also 0xffffffff. What is masking these values and why? It shouldn't have these register masks all the way down to the ABAR root, and what must be done to get rid of them?


Solution

  • As Brendan hinted at, the virtual address mapping needs to be properly page-aligned. The following, therefore, worked:

    // snip
        if let Some(addr) = sata_ctrl {
            let test_page = Page::<Size2MiB>::containing_address(VirtAddr::new(addr + boot_info.physical_memory_offset.clone().into_option().unwrap().clone()));
            let virt = test_page.start_address().as_u64();
            map_page!(
                addr,
                virt,
                Size2MiB,
                PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::NO_CACHE
            );
            let (_, disks) = ahci::disks(virt as usize);
            info!("Found {:#?} disks", disks.len());
        }
    // snip