Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/aarch64/src/hal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ unsafe impl Hal for HalImpl {
}

fn virt_to_phys(vaddr: usize) -> PhysAddr {
vaddr
vaddr as _
}
8 changes: 4 additions & 4 deletions examples/riscv/src/virtio_impl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::{
ptr::NonNull,
sync::atomic::{AtomicUsize, Ordering},
sync::atomic::{AtomicU64, Ordering},
};
use lazy_static::lazy_static;
use log::trace;
Expand All @@ -11,14 +11,14 @@ extern "C" {
}

lazy_static! {
static ref DMA_PADDR: AtomicUsize = AtomicUsize::new(end as usize);
static ref DMA_PADDR: AtomicU64 = AtomicU64::new(end as u64);
}

pub struct HalImpl;

unsafe impl Hal for HalImpl {
fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull<u8>) {
let paddr = DMA_PADDR.fetch_add(PAGE_SIZE * pages, Ordering::SeqCst);
let paddr = DMA_PADDR.fetch_add((PAGE_SIZE * pages) as u64, Ordering::SeqCst);
trace!("alloc DMA: paddr={:#x}, pages={}", paddr, pages);
let vaddr = NonNull::new(paddr as _).unwrap();
(paddr, vaddr)
Expand Down Expand Up @@ -46,5 +46,5 @@ unsafe impl Hal for HalImpl {
}

fn virt_to_phys(vaddr: usize) -> PhysAddr {
vaddr
vaddr as _
}
9 changes: 4 additions & 5 deletions examples/x86_64/src/hal.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::{
ptr::NonNull,
sync::atomic::{AtomicUsize, Ordering},
sync::atomic::{AtomicU64, Ordering},
};
use lazy_static::lazy_static;
use log::trace;
Expand All @@ -11,15 +11,14 @@ extern "C" {
}

lazy_static! {
static ref DMA_PADDR: AtomicUsize =
AtomicUsize::new(unsafe { &dma_region as *const u8 as usize });
static ref DMA_PADDR: AtomicU64 = AtomicU64::new(unsafe { &dma_region as *const u8 as u64 });
}

pub struct HalImpl;

unsafe impl Hal for HalImpl {
fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull<u8>) {
let paddr = DMA_PADDR.fetch_add(PAGE_SIZE * pages, Ordering::SeqCst);
let paddr = DMA_PADDR.fetch_add((PAGE_SIZE * pages) as u64, Ordering::SeqCst);
trace!("alloc DMA: paddr={:#x}, pages={}", paddr, pages);
let vaddr = NonNull::new(paddr as _).unwrap();
(paddr, vaddr)
Expand Down Expand Up @@ -47,5 +46,5 @@ unsafe impl Hal for HalImpl {
}

fn virt_to_phys(vaddr: usize) -> PhysAddr {
vaddr
vaddr as _
}
1 change: 0 additions & 1 deletion examples/x86_64/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
#![feature(asm_const)]
#![feature(abi_x86_interrupt)]

#[macro_use]
Expand Down
6 changes: 3 additions & 3 deletions src/hal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ use crate::{Error, Result, PAGE_SIZE};
use core::{marker::PhantomData, ptr::NonNull};

/// A physical address as used for virtio.
pub type PhysAddr = usize;
pub type PhysAddr = u64;

/// A region of contiguous physical memory used for DMA.
#[derive(Debug)]
pub struct Dma<H: Hal> {
paddr: usize,
paddr: PhysAddr,
vaddr: NonNull<u8>,
pages: usize,
_hal: PhantomData<H>,
Expand Down Expand Up @@ -42,7 +42,7 @@ impl<H: Hal> Dma<H> {
}

/// Returns the physical address of the start of the DMA region, as seen by devices.
pub fn paddr(&self) -> usize {
pub fn paddr(&self) -> PhysAddr {
self.paddr
}

Expand Down
4 changes: 2 additions & 2 deletions src/hal/fake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ unsafe impl Hal for FakeHal {
}

fn virt_to_phys(vaddr: usize) -> PhysAddr {
vaddr
vaddr as _
}

fn phys_to_virt(paddr: PhysAddr) -> usize {
paddr
paddr as _
}
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub use safe_mmio::UniqueMmioPointer;
/// The page size in bytes supported by the library (4 KiB).
pub const PAGE_SIZE: usize = 0x1000;

const PAGE_SIZE_PHYS: PhysAddr = PAGE_SIZE as PhysAddr;

/// The type returned by driver methods.
pub type Result<T = ()> = core::result::Result<T, Error>;

Expand Down Expand Up @@ -119,6 +121,11 @@ fn align_up(size: usize) -> usize {
(size + PAGE_SIZE) & !(PAGE_SIZE - 1)
}

/// Align `size` up to a page.
fn align_up_phys(size: PhysAddr) -> PhysAddr {
(size + PAGE_SIZE_PHYS) & !(PAGE_SIZE_PHYS - 1)
}

/// The number of pages required to store `size` bytes, rounded up to a whole number of pages.
fn pages(size: usize) -> usize {
size.div_ceil(PAGE_SIZE)
Expand Down
16 changes: 8 additions & 8 deletions src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
pub fn new<T: Transport>(
transport: &mut T,
idx: u16,
indirect: bool,

Check warning on line 80 in src/queue.rs

View workflow job for this annotation

GitHub Actions / build

unused variable: `indirect`

Check warning on line 80 in src/queue.rs

View workflow job for this annotation

GitHub Actions / build

unused variable: `indirect`
event_idx: bool,
) -> Result<Self> {
#[allow(clippy::let_unit_value)]
Expand Down Expand Up @@ -443,7 +443,7 @@
// `indirect_list` is owned by this function and is not accessed from any other threads.
unsafe {
H::unshare(
paddr as usize,
paddr,
indirect_list.as_mut_bytes().into(),
BufferDirection::DriverToDevice,
);
Expand All @@ -459,7 +459,7 @@
unsafe {
// Unshare the buffer (and perhaps copy its contents back to the original
// buffer).
H::unshare(indirect_list[i].addr as usize, buffer, direction);
H::unshare(indirect_list[i].addr, buffer, direction);
}
}
drop(indirect_list);
Expand Down Expand Up @@ -487,7 +487,7 @@
// from which we got `paddr`.
unsafe {
// Unshare the buffer (and perhaps copy its contents back to the original buffer).
H::unshare(paddr as usize, buffer, direction);
H::unshare(paddr, buffer, direction);
}
}

Expand Down Expand Up @@ -640,12 +640,12 @@
match self {
Self::Legacy {
dma, avail_offset, ..
} => dma.paddr() + avail_offset,
} => dma.paddr() + *avail_offset as u64,
Self::Modern {
driver_to_device_dma,
avail_offset,
..
} => driver_to_device_dma.paddr() + avail_offset,
} => driver_to_device_dma.paddr() + *avail_offset as u64,
}
}

Expand All @@ -668,7 +668,7 @@
match self {
Self::Legacy {
used_offset, dma, ..
} => dma.paddr() + used_offset,
} => dma.paddr() + *used_offset as u64,
Self::Modern {
device_to_driver_dma,
..
Expand Down Expand Up @@ -699,7 +699,7 @@
queue_size.is_power_of_two(),
"queue size should be a power of 2"
);
let queue_size = queue_size as usize;
let queue_size = usize::from(queue_size);
let desc = size_of::<Descriptor>() * queue_size;
let avail = size_of::<u16>() * (3 + queue_size);
let used = size_of::<u16>() * 3 + size_of::<UsedElem>() * queue_size;
Expand Down Expand Up @@ -729,7 +729,7 @@
) {
// SAFETY: Our caller promises that the buffer is valid.
unsafe {
self.addr = H::share(buf, direction) as u64;
self.addr = H::share(buf, direction);
}
self.len = buf.len().try_into().unwrap();
self.flags = extra_flags
Expand Down
17 changes: 10 additions & 7 deletions src/transport/mmio.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
//! MMIO transport for VirtIO.

use super::{DeviceStatus, DeviceType, DeviceTypeError, Transport};
use crate::{align_up, queue::Descriptor, transport::InterruptStatus, Error, PhysAddr, PAGE_SIZE};
use crate::{
align_up_phys, queue::Descriptor, transport::InterruptStatus, Error, PhysAddr, PAGE_SIZE,
PAGE_SIZE_PHYS,
};
use core::{
convert::{TryFrom, TryInto},
mem::{align_of, size_of},
Expand Down Expand Up @@ -403,18 +406,18 @@ impl Transport for MmioTransport<'_> {
MmioVersion::Legacy => {
assert_eq!(
driver_area - descriptors,
size_of::<Descriptor>() * size as usize
size_of::<Descriptor>() as u64 * u64::from(size)
);
assert_eq!(
device_area - descriptors,
align_up(
size_of::<Descriptor>() * size as usize
+ size_of::<u16>() * (size as usize + 3)
align_up_phys(
size_of::<Descriptor>() as u64 * u64::from(size)
+ size_of::<u16>() as u64 * (u64::from(size) + 3)
)
);
let align = PAGE_SIZE as u32;
let pfn = (descriptors / PAGE_SIZE) as u32;
assert_eq!(pfn as usize * PAGE_SIZE, descriptors);
let pfn = (descriptors / PAGE_SIZE_PHYS).try_into().unwrap();
assert_eq!(u64::from(pfn) * PAGE_SIZE_PHYS, descriptors);
field!(self.header, queue_sel).write(queue.into());
field!(self.header, queue_num).write(size);
field!(self.header, legacy_queue_align).write(align);
Expand Down
12 changes: 3 additions & 9 deletions src/transport/pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,9 @@ impl Transport for PciTransport {
) {
field!(self.common_cfg, queue_select).write(queue);
field!(self.common_cfg, queue_size).write(size as u16);
field!(self.common_cfg, queue_desc).write(descriptors as u64);
field!(self.common_cfg, queue_driver).write(driver_area as u64);
field!(self.common_cfg, queue_device).write(device_area as u64);
field!(self.common_cfg, queue_desc).write(descriptors);
field!(self.common_cfg, queue_driver).write(driver_area);
field!(self.common_cfg, queue_device).write(device_area);
field!(self.common_cfg, queue_enable).write(1);
}

Expand Down Expand Up @@ -506,12 +506,6 @@ impl From<PciError> for VirtioPciError {
}
}

// SAFETY: The `vaddr` field of `VirtioPciError::Misaligned` is only used for debug output.
unsafe impl Send for VirtioPciError {}

// SAFETY: The `vaddr` field of `VirtioPciError::Misaligned` is only used for debug output.
unsafe impl Sync for VirtioPciError {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion src/transport/pci/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ impl<C: ConfigurationAccess> PciRoot<C> {
}

/// Gets an iterator over the capabilities of the given device function.
pub fn capabilities(&self, device_function: DeviceFunction) -> CapabilityIterator<C> {
pub fn capabilities(&self, device_function: DeviceFunction) -> CapabilityIterator<'_, C> {
CapabilityIterator {
configuration_access: &self.configuration_access,
device_function,
Expand Down
10 changes: 5 additions & 5 deletions src/transport/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,9 @@ impl Transport for HypPciTransport {
) {
configwrite!(self.common_cfg, queue_select, queue);
configwrite!(self.common_cfg, queue_size, size as u16);
configwrite!(self.common_cfg, queue_desc, descriptors as u64);
configwrite!(self.common_cfg, queue_driver, driver_area as u64);
configwrite!(self.common_cfg, queue_device, device_area as u64);
configwrite!(self.common_cfg, queue_desc, descriptors);
configwrite!(self.common_cfg, queue_driver, driver_area);
configwrite!(self.common_cfg, queue_device, device_area);
configwrite!(self.common_cfg, queue_enable, 1u16);
}

Expand Down Expand Up @@ -301,9 +301,9 @@ fn get_bar_region<T, C: ConfigurationAccess>(
return Err(VirtioPciError::BarOffsetOutOfRange);
}
let paddr = bar_address as PhysAddr + struct_info.offset as PhysAddr;
if paddr % align_of::<T>() != 0 {
if paddr % (align_of::<T>() as u64) != 0 {
return Err(VirtioPciError::Misaligned {
address: paddr,
address: paddr as usize,
alignment: align_of::<T>(),
});
}
Expand Down
13 changes: 8 additions & 5 deletions src/transport/x86_64/cam.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
use super::hypercalls::{cpuid_signature, hyp_io_read, hyp_io_write};
use crate::transport::pci::bus::{Cam, ConfigurationAccess, DeviceFunction};
use crate::{
hal::PhysAddr,
transport::pci::bus::{Cam, ConfigurationAccess, DeviceFunction},
};

const PKVM_SIGNATURE: &[u8] = b"PKVM";

/// A PCI configuration access mechanism using hypercalls implemented by the x86-64 pKVM hypervisor.
pub struct HypCam {
/// The physical base address of the PCI root complex.
phys_base: usize,
phys_base: PhysAddr,
cam: Cam,
}

impl HypCam {
/// Creates a new `HypCam` for the PCI root complex at the given physical base address.
pub fn new(phys_base: usize, cam: Cam) -> Self {
pub fn new(phys_base: PhysAddr, cam: Cam) -> Self {
Self { phys_base, cam }
}

Expand All @@ -25,12 +28,12 @@ impl HypCam {
impl ConfigurationAccess for HypCam {
fn read_word(&self, device_function: DeviceFunction, register_offset: u8) -> u32 {
let address = self.cam.cam_offset(device_function, register_offset);
hyp_io_read(self.phys_base + (address as usize), 4) as u32
hyp_io_read(self.phys_base + u64::from(address), 4) as u32
}

fn write_word(&mut self, device_function: DeviceFunction, register_offset: u8, data: u32) {
let address = self.cam.cam_offset(device_function, register_offset);
hyp_io_write(self.phys_base + (address as usize), 4, data.into());
hyp_io_write(self.phys_base + u64::from(address), 4, data.into());
}

unsafe fn unsafe_clone(&self) -> Self {
Expand Down
10 changes: 5 additions & 5 deletions src/transport/x86_64/hypercalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn cpuid_signature() -> [u8; 4] {
}

/// Asks the hypervisor to perform an IO read at the given physical address.
pub fn hyp_io_read(address: usize, size: usize) -> u64 {
pub fn hyp_io_read(address: u64, size: usize) -> u64 {
let data;

// SAFETY: Assembly call. Arguments for vmcall are passed via rax, rbx, rcx and rdx. Ideally
Expand All @@ -66,7 +66,7 @@ pub fn hyp_io_read(address: usize, size: usize) -> u64 {
}

/// Asks the hypervisor to perform an IO write at the given physical address.
pub fn hyp_io_write(address: usize, size: usize, data: u64) {
pub fn hyp_io_write(address: u64, size: usize, data: u64) {
// SAFETY: Assembly call. Arguments for vmcall are passed via rax, rbx, rcx and rdx. Ideally
// using a named argument in the inline asm for rbx would be more straightforward but when
// "rbx" is used directly used LLVM complains that it is used internally.
Expand All @@ -90,7 +90,7 @@ pub fn hyp_io_write(address: usize, size: usize, data: u64) {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HypIoRegion {
/// The physical address of the start of the IO region.
pub paddr: usize,
pub paddr: u64,
/// The size of the IO region in bytes.
pub size: usize,
}
Expand All @@ -100,7 +100,7 @@ impl HypIoRegion {
assert!(offset + size_of::<T>() <= self.size);
assert!(size_of::<T>() <= HYP_IO_MAX);

let data = hyp_io_read(self.paddr + offset, size_of::<T>());
let data = hyp_io_read(self.paddr + offset as u64, size_of::<T>());
T::read_from_prefix(data.as_bytes()).unwrap().0
}

Expand All @@ -110,6 +110,6 @@ impl HypIoRegion {

let mut data = 0;
data.as_mut_bytes()[..size_of::<T>()].copy_from_slice(value.as_bytes());
hyp_io_write(self.paddr + offset, size_of::<T>(), data);
hyp_io_write(self.paddr + offset as u64, size_of::<T>(), data);
}
}
Loading