drivers: Use map_bar instead of physmap where possible

Physmap requires root, while map_bar in the future could be run as
unprivileged process given a pcid handle for the target device.
This commit is contained in:
bjorn3
2026-05-09 20:12:41 +02:00
parent 0f2291ed8b
commit d528fb73b4
15 changed files with 81 additions and 65 deletions
+5 -1
View File
@@ -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");
+1 -1
View File
@@ -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.
///
+26 -18
View File
@@ -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<Self> {
unsafe fn new(phys: usize, size: usize, memory_type: common::MemoryType) -> Result<Self> {
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<Self> {
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<MmioPtr<u32>> {
@@ -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) => {
+5 -1
View File
@@ -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 {
+2 -1
View File
@@ -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;
+5 -1
View File
@@ -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),
}
+5 -1
View File
@@ -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),
}
+7 -10
View File
@@ -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<u8>,
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::<u8>()).expect("Mapping a BAR resulted in a nullptr"),
bar_size,
memory_type,
})
}
}
+2 -1
View File
@@ -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)
+5 -1
View File
@@ -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);
+2 -1
View File
@@ -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();
+9 -2
View File
@@ -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<const N: usize>(
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)
+4 -1
View File
@@ -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::<u32>::new(bar0 as u16);
+3 -21
View File
@@ -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<dyn Transport>,
@@ -55,26 +55,8 @@ pub fn probe_device(pcid_handle: &mut PciFunctionHandle) -> Result<Device, Error
_ => 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 => {
-4
View File
@@ -74,7 +74,3 @@ impl<T> IncompleteArrayField<T> {
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)
}