diff --git a/local/recipes/drivers/redox-driver-sys/source/src/memory.rs b/local/recipes/drivers/redox-driver-sys/source/src/memory.rs index 6292649a8e..ae7279404b 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/memory.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/memory.rs @@ -81,6 +81,8 @@ fn ensure_memory_root() -> Result { pub struct MmioRegion { ptr: *mut u8, size: usize, + map_ptr: *mut u8, + map_size: usize, } impl MmioRegion { @@ -89,7 +91,13 @@ impl MmioRegion { return Err(DriverError::InvalidAddress(phys_addr)); } - let aligned_size = size.next_multiple_of(PAGE_SIZE); + // Align physical address down to page boundary for physmap compatibility. + // The kernel requires page-aligned addresses; VirtIO capabilities can + // start at non-page-aligned offsets within BARs. + let page_offset = (phys_addr as usize) % PAGE_SIZE; + let aligned_phys = phys_addr - page_offset as u64; + let adjusted_size = size + page_offset; + let aligned_size = adjusted_size.next_multiple_of(PAGE_SIZE); let path = format!("physical@{}", cache.suffix()); let mode = if prot.contains(MmioProt::READ | MmioProt::WRITE) { @@ -112,7 +120,7 @@ impl MmioRegion { let mem_fd = root_fd.openat(&path, (O_CLOEXEC | mode) as i32, 0)?; let map = Map { - offset: phys_addr as usize, + offset: aligned_phys as usize, size: aligned_size, flags: mmap_prot | redox_syscall::MapFlags::from_bits_truncate(MAP_SHARED.bits()), address: 0, @@ -127,8 +135,10 @@ impl MmioRegion { })?; Ok(Self { - ptr: ptr as *mut u8, - size: aligned_size, + ptr: unsafe { (ptr as *mut u8).add(page_offset) }, + size, + map_ptr: ptr as *mut u8, + map_size: aligned_size, }) } @@ -290,8 +300,8 @@ impl MmioRegion { impl Drop for MmioRegion { fn drop(&mut self) { - if !self.ptr.is_null() { - let _ = unsafe { libredox::call::munmap(self.ptr as *mut (), self.size) }; + if !self.map_ptr.is_null() { + let _ = unsafe { libredox::call::munmap(self.map_ptr as *mut (), self.map_size) }; } } }