diff --git a/drivers/audio/ihdad/src/main.rs b/drivers/audio/ihdad/src/main.rs index 31a2add737..681b73e963 100755 --- a/drivers/audio/ihdad/src/main.rs +++ b/drivers/audio/ihdad/src/main.rs @@ -1,3 +1,4 @@ +use common::MemoryType; use redox_scheme::scheme::register_sync_scheme; use redox_scheme::Socket; use scheme_utils::ReadinessBased; @@ -38,7 +39,10 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { log::info!("IHDA {}", pci_config.func.display()); - let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize; + let address = unsafe { pcid_handle.map_bar(0, MemoryType::Uncacheable) } + .ptr + .as_ptr() + .expose_provenance(); let irq_file = pci_allocate_interrupt_vector(&mut pcid_handle, "ihdad"); diff --git a/drivers/common/src/lib.rs b/drivers/common/src/lib.rs index b6661e3aaa..87f8f29bbb 100644 --- a/drivers/common/src/lib.rs +++ b/drivers/common/src/lib.rs @@ -67,7 +67,7 @@ pub fn memory_root_fd() -> &'static libredox::Fd { /// aarch64 and x86 have very different cache-coherency rules, so this API as written is likely /// not sufficient to describe the memory caching behavior in a cross-platform manner. As such, /// consider this API unstable. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum MemoryType { /// A region of memory that implements Write-back caching. /// diff --git a/drivers/graphics/ihdgd/src/device/mod.rs b/drivers/graphics/ihdgd/src/device/mod.rs index 3649dd7292..07fb98e02c 100644 --- a/drivers/graphics/ihdgd/src/device/mod.rs +++ b/drivers/graphics/ihdgd/src/device/mod.rs @@ -120,15 +120,26 @@ pub struct Interrupter { #[derive(Debug)] pub struct MmioRegion { - phys: usize, virt: usize, size: usize, } impl MmioRegion { - fn new(phys: usize, size: usize, memory_type: common::MemoryType) -> Result { + unsafe fn new(phys: usize, size: usize, memory_type: common::MemoryType) -> Result { let virt = unsafe { common::physmap(phys, size, common::Prot::RW, memory_type)? as usize }; - Ok(Self { phys, virt, size }) + Ok(Self { virt, size }) + } + + unsafe fn new_pci_bar( + pcid_handle: &mut PciFunctionHandle, + bir: u8, + memory_type: common::MemoryType, + ) -> Result { + let mapped_bar = unsafe { pcid_handle.map_bar(bir, memory_type) }; + Ok(Self { + virt: mapped_bar.ptr.expose_provenance().get(), + size: mapped_bar.bar_size, + }) } unsafe fn mmio(&self, offset: usize) -> Result> { @@ -249,18 +260,13 @@ impl Device { }; let gttmm = { - let (phys, size) = func.bars[0].expect_mem(); - Arc::new(MmioRegion::new( - phys, - size, - common::MemoryType::Uncacheable, - )?) + Arc::new(unsafe { + MmioRegion::new_pci_bar(pcid_handle, 0, common::MemoryType::Uncacheable) + }?) }; log::info!("GTTMM {:X?}", gttmm); - let gm = { - let (phys, size) = func.bars[2].expect_mem(); - MmioRegion::new(phys, size, common::MemoryType::WriteCombining)? - }; + let gm = + unsafe { MmioRegion::new_pci_bar(pcid_handle, 2, common::MemoryType::WriteCombining) }?; log::info!("GM {:X?}", gm); /* IOBAR not used, not present on all generations let iobar = func.bars[4].expect_port(); @@ -273,11 +279,13 @@ impl Device { log::info!("BIOS {:X?}", bios_base); // This is the default BIOS size let bios_size = 8 * 1024; - match MmioRegion::new( - bios_base as usize, - bios_size, - common::MemoryType::Uncacheable, - ) { + match unsafe { + MmioRegion::new( + bios_base as usize, + bios_size, + common::MemoryType::Uncacheable, + ) + } { Ok(region) => match Bios::new(region) { Ok(bios) => Some(bios), Err(err) => { diff --git a/drivers/net/e1000d/src/main.rs b/drivers/net/e1000d/src/main.rs index 373ea9b38b..d48781bab6 100644 --- a/drivers/net/e1000d/src/main.rs +++ b/drivers/net/e1000d/src/main.rs @@ -1,6 +1,7 @@ use std::io::{Read, Write}; use std::os::unix::io::AsRawFd; +use common::MemoryType; use driver_network::NetworkScheme; use event::{user_data, EventQueue}; use pcid_interface::PciFunctionHandle; @@ -34,7 +35,10 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { let mut irq_file = irq.irq_handle("e1000d"); - let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize; + let address = unsafe { pcid_handle.map_bar(0, MemoryType::Uncacheable) } + .ptr + .as_ptr() + .expose_provenance(); let mut scheme = NetworkScheme::new( move || unsafe { diff --git a/drivers/net/ixgbed/src/main.rs b/drivers/net/ixgbed/src/main.rs index 4a6ce74dcd..e0d705ef39 100644 --- a/drivers/net/ixgbed/src/main.rs +++ b/drivers/net/ixgbed/src/main.rs @@ -1,6 +1,7 @@ use std::io::{Read, Write}; use std::os::unix::io::AsRawFd; +use common::MemoryType; use driver_network::NetworkScheme; use event::{user_data, EventQueue}; use pcid_interface::PciFunctionHandle; @@ -28,7 +29,7 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { let mut irq_file = irq.irq_handle("ixgbed"); - let mapped_bar = unsafe { pcid_handle.map_bar(0) }; + let mapped_bar = unsafe { pcid_handle.map_bar(0, MemoryType::Uncacheable) }; let address = mapped_bar.ptr.as_ptr(); let size = mapped_bar.bar_size; diff --git a/drivers/net/rtl8139d/src/main.rs b/drivers/net/rtl8139d/src/main.rs index d470e814df..b10d871c31 100644 --- a/drivers/net/rtl8139d/src/main.rs +++ b/drivers/net/rtl8139d/src/main.rs @@ -1,6 +1,7 @@ use std::io::{Read, Write}; use std::os::unix::io::AsRawFd; +use common::MemoryType; use driver_network::NetworkScheme; use event::{user_data, EventQueue}; use pcid_interface::irq_helpers::pci_allocate_interrupt_vector; @@ -27,7 +28,10 @@ fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 { for &barnum in &[2, 1] { match config.func.bars[usize::from(barnum)] { pcid_interface::PciBar::Memory32 { .. } | pcid_interface::PciBar::Memory64 { .. } => unsafe { - return pcid_handle.map_bar(barnum).ptr.as_ptr(); + return pcid_handle + .map_bar(barnum, MemoryType::Uncacheable) + .ptr + .as_ptr(); }, other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other), } diff --git a/drivers/net/rtl8168d/src/main.rs b/drivers/net/rtl8168d/src/main.rs index 1d9963a3ad..c660bef781 100644 --- a/drivers/net/rtl8168d/src/main.rs +++ b/drivers/net/rtl8168d/src/main.rs @@ -1,6 +1,7 @@ use std::io::{Read, Write}; use std::os::unix::io::AsRawFd; +use common::MemoryType; use driver_network::NetworkScheme; use event::{user_data, EventQueue}; use pcid_interface::irq_helpers::pci_allocate_interrupt_vector; @@ -27,7 +28,10 @@ fn map_bar(pcid_handle: &mut PciFunctionHandle) -> *mut u8 { for &barnum in &[2, 1] { match config.func.bars[usize::from(barnum)] { pcid_interface::PciBar::Memory32 { .. } | pcid_interface::PciBar::Memory64 { .. } => unsafe { - return pcid_handle.map_bar(barnum).ptr.as_ptr(); + return pcid_handle + .map_bar(barnum, MemoryType::Uncacheable) + .ptr + .as_ptr(); }, other => log::warn!("BAR {} is {:?} instead of memory BAR", barnum, other), } diff --git a/drivers/pcid/src/driver_interface/mod.rs b/drivers/pcid/src/driver_interface/mod.rs index bbc7304ee5..1328b0259d 100644 --- a/drivers/pcid/src/driver_interface/mod.rs +++ b/drivers/pcid/src/driver_interface/mod.rs @@ -6,6 +6,7 @@ use std::ptr::NonNull; use std::{env, io}; use std::{fmt, process}; +use common::MemoryType; use daemon::Daemon; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -268,6 +269,7 @@ pub enum PcidClientResponse { pub struct MappedBar { pub ptr: NonNull, pub bar_size: usize, + pub memory_type: MemoryType, } /// A handle from a `pcid` client (e.g. `ahcid`) to `pcid`. @@ -452,22 +454,16 @@ impl PciFunctionHandle { } } } - pub unsafe fn map_bar(&mut self, bir: u8) -> &MappedBar { + pub unsafe fn map_bar(&mut self, bir: u8, memory_type: MemoryType) -> &MappedBar { let mapped_bar = &mut self.mapped_bars[bir as usize]; if let Some(mapped_bar) = mapped_bar { + assert_eq!(mapped_bar.memory_type, memory_type); mapped_bar } else { let (bar, bar_size) = self.config.func.bars[bir as usize].expect_mem(); - let ptr = match unsafe { - common::physmap( - bar, - bar_size, - common::Prot::RW, - // FIXME once the kernel supports this use write-through for prefetchable BAR - common::MemoryType::Uncacheable, - ) - } { + let ptr = match unsafe { common::physmap(bar, bar_size, common::Prot::RW, memory_type) } + { Ok(ptr) => ptr, Err(err) => { log::error!("failed to map BAR at {bar:016X}: {err}"); @@ -478,6 +474,7 @@ impl PciFunctionHandle { mapped_bar.insert(MappedBar { ptr: NonNull::new(ptr.cast::()).expect("Mapping a BAR resulted in a nullptr"), bar_size, + memory_type, }) } } diff --git a/drivers/pcid/src/driver_interface/msi.rs b/drivers/pcid/src/driver_interface/msi.rs index 0ca68ec556..e2b2416284 100644 --- a/drivers/pcid/src/driver_interface/msi.rs +++ b/drivers/pcid/src/driver_interface/msi.rs @@ -5,6 +5,7 @@ use crate::driver_interface::PciBar; use crate::PciFunctionHandle; use common::io::{Io, Mmio}; +use common::MemoryType; use serde::{Deserialize, Serialize}; /// The address and data to use for MSI and MSI-X. @@ -39,7 +40,7 @@ impl MsixInfo { let virt_table_base = unsafe { pcid_handle - .map_bar(self.table_bar) + .map_bar(self.table_bar, MemoryType::Uncacheable) .ptr .as_ptr() .byte_add(self.table_offset as usize) diff --git a/drivers/storage/ahcid/src/main.rs b/drivers/storage/ahcid/src/main.rs index 1f130a2974..bcd66a3a94 100644 --- a/drivers/storage/ahcid/src/main.rs +++ b/drivers/storage/ahcid/src/main.rs @@ -5,6 +5,7 @@ use std::os::fd::AsRawFd; use std::usize; use common::io::Io; +use common::MemoryType; use driver_block::{DiskScheme, ExecutorTrait, FuturesExecutor}; use event::{EventFlags, RawEventQueue}; use pcid_interface::PciFunctionHandle; @@ -38,7 +39,10 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { info!("AHCI {}", pci_config.func.display()); - let address = unsafe { pcid_handle.map_bar(5) }.ptr.as_ptr() as usize; + let address = unsafe { pcid_handle.map_bar(5, MemoryType::Uncacheable) } + .ptr + .as_ptr() + .expose_provenance(); { let (hba_mem, disks) = ahci::disks(address as usize, &name); diff --git a/drivers/storage/nvmed/src/main.rs b/drivers/storage/nvmed/src/main.rs index beb1b68940..658af32731 100644 --- a/drivers/storage/nvmed/src/main.rs +++ b/drivers/storage/nvmed/src/main.rs @@ -6,6 +6,7 @@ use std::rc::Rc; use std::sync::Arc; use std::usize; +use common::MemoryType; use driver_block::{Disk, DiskScheme}; use pcid_interface::{irq_helpers, PciFunctionHandle}; @@ -75,7 +76,7 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { log::debug!("NVME PCI CONFIG: {:?}", pci_config); - let address = unsafe { pcid_handle.map_bar(0).ptr }; + let address = unsafe { pcid_handle.map_bar(0, MemoryType::Uncacheable).ptr }; let interrupt_vector = irq_helpers::pci_allocate_interrupt_vector(&mut pcid_handle, "nvmed"); let iv = interrupt_vector.vector(); diff --git a/drivers/usb/xhcid/src/main.rs b/drivers/usb/xhcid/src/main.rs index d345a52fc4..c1dcba7ad1 100644 --- a/drivers/usb/xhcid/src/main.rs +++ b/drivers/usb/xhcid/src/main.rs @@ -30,6 +30,7 @@ extern crate bitflags; use std::fs::File; use std::sync::Arc; +use common::MemoryType; use pcid_interface::irq_helpers::read_bsp_apic_id; #[cfg(target_arch = "x86_64")] use pcid_interface::irq_helpers::{ @@ -136,7 +137,10 @@ fn daemon_with_context_size( log::debug!("XHCI PCI CONFIG: {:?}", pci_config); - let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize; + let address = unsafe { pcid_handle.map_bar(0, MemoryType::Uncacheable) } + .ptr + .as_ptr() + .expose_provenance(); let (irq_file, interrupt_method) = (None, InterruptMethod::Polling); //get_int_method(&mut pcid_handle); //TODO: Fix interrupts. @@ -171,7 +175,10 @@ fn main() { } fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { - let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize; + let address = unsafe { pcid_handle.map_bar(0, MemoryType::Uncacheable) } + .ptr + .as_ptr() + .expose_provenance(); let cap = unsafe { &mut *(address as *mut xhci::CapabilityRegs) }; if cap.csz() { daemon_with_context_size::<{ xhci::CONTEXT_64 }>(daemon, pcid_handle) diff --git a/drivers/vboxd/src/main.rs b/drivers/vboxd/src/main.rs index bcb9bb157d..65386cf591 100644 --- a/drivers/vboxd/src/main.rs +++ b/drivers/vboxd/src/main.rs @@ -1,5 +1,6 @@ //#![deny(warnings)] +use common::MemoryType; use event::{user_data, EventQueue}; use std::fs::File; use std::io::{Read, Write}; @@ -235,7 +236,9 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! { let mut irq_file = irq.irq_handle("vboxd"); - let address = unsafe { pcid_handle.map_bar(1) }.ptr.as_ptr(); + let address = unsafe { pcid_handle.map_bar(1, MemoryType::Uncacheable) } + .ptr + .as_ptr(); #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { let mut port = common::io::Pio::::new(bar0 as u16); diff --git a/drivers/virtio-core/src/probe.rs b/drivers/virtio-core/src/probe.rs index 5631ef676c..1729c9dcfa 100644 --- a/drivers/virtio-core/src/probe.rs +++ b/drivers/virtio-core/src/probe.rs @@ -1,11 +1,11 @@ use std::fs::File; use std::sync::Arc; +use common::MemoryType; use pcid_interface::*; use crate::spec::*; use crate::transport::{Error, StandardTransport, Transport}; -use crate::utils::align_down; pub struct Device { pub transport: Arc, @@ -55,26 +55,8 @@ pub fn probe_device(pcid_handle: &mut PciFunctionHandle) -> Result continue, } - let (addr, _) = pci_config.func.bars[capability.bar as usize].expect_mem(); - - let address = unsafe { - let addr = addr + capability.offset as usize; - - // XXX: physmap() requires the address to be page aligned. - let aligned_addr = align_down(addr); - let offset = addr - aligned_addr; - - let size = offset + capability.length as usize; - - let addr = common::physmap( - aligned_addr, - size, - common::Prot::RW, - common::MemoryType::Uncacheable, - )? as usize; - - addr + offset - }; + let mapped_bar = unsafe { pcid_handle.map_bar(capability.bar, MemoryType::Uncacheable) }; + let address = mapped_bar.ptr.expose_provenance().get() + capability.offset as usize; match capability.cfg_type { CfgType::Common => { diff --git a/drivers/virtio-core/src/utils.rs b/drivers/virtio-core/src/utils.rs index 76d8ff7eb7..8039dd2379 100644 --- a/drivers/virtio-core/src/utils.rs +++ b/drivers/virtio-core/src/utils.rs @@ -74,7 +74,3 @@ impl IncompleteArrayField { pub const fn align(val: usize, align: usize) -> usize { (val + align) & !align } - -pub const fn align_down(addr: usize) -> usize { - addr & !(syscall::PAGE_SIZE - 1) -}