Skip to content

Commit

Permalink
Move HypIoRegion to hypercalls submodule too.
Browse files Browse the repository at this point in the history
  • Loading branch information
qwandor committed Dec 4, 2024
1 parent 93e9831 commit 9168099
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 32 deletions.
33 changes: 1 addition & 32 deletions src/transport/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@ use crate::{
Error,
};
pub use cam::HypCam;
use hypercalls::{hyp_io_read, hyp_io_write};
use hypercalls::HypIoRegion;
use zerocopy::{FromBytes, Immutable, IntoBytes};

/// The maximum number of bytes that can be read or written by a single IO hypercall.
const HYP_IO_MAX: usize = 8;

macro_rules! configread {
($common_cfg:expr, $field:ident) => {
$common_cfg.read(core::mem::offset_of!(CommonCfg, $field))
Expand Down Expand Up @@ -318,31 +315,3 @@ fn get_bar_region<H: Hal, T, C: ConfigurationAccess>(
size: struct_info.length as usize,
})
}

/// A region of physical address space which may be accessed by IO read and/or write hypercalls.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct HypIoRegion {
/// The physical address of the start of the IO region.
paddr: usize,
/// The size of the IO region in bytes.
size: usize,
}

impl HypIoRegion {
fn read<T: FromBytes>(self, offset: usize) -> T {
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>());
T::read_from_prefix(data.as_bytes()).unwrap().0
}

fn write<T: IntoBytes + Immutable>(self, offset: usize, value: T) {
assert!(offset + size_of::<T>() <= self.size);
assert!(size_of::<T>() < HYP_IO_MAX);

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);
}
}
32 changes: 32 additions & 0 deletions src/transport/x86_64/hypercalls.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Hypercalls for x86-64 pKVM.
use core::arch::asm;
use zerocopy::{FromBytes, Immutable, IntoBytes};

/// This CPUID returns the signature and should be used to determine if VM is running under pKVM,
/// KVM or not. See the Linux header `arch/x86/include/uapi/asm/kvm_para.h`.
Expand All @@ -12,6 +13,9 @@ const KVM_HC_PKVM_OP: u32 = 20;
const PKVM_GHC_IOREAD: u32 = KVM_HC_PKVM_OP + 3;
const PKVM_GHC_IOWRITE: u32 = KVM_HC_PKVM_OP + 4;

/// The maximum number of bytes that can be read or written by a single IO hypercall.
const HYP_IO_MAX: usize = 8;

/// Gets the signature CPU ID.
pub fn cpuid_signature() -> [u8; 4] {
let signature: u32;
Expand Down Expand Up @@ -81,3 +85,31 @@ pub fn hyp_io_write(address: usize, size: usize, data: u64) {
);
}
}

/// A region of physical address space which may be accessed by IO read and/or write hypercalls.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HypIoRegion {
/// The physical address of the start of the IO region.
pub paddr: usize,
/// The size of the IO region in bytes.
pub size: usize,
}

impl HypIoRegion {
pub fn read<T: FromBytes>(self, offset: usize) -> T {
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>());
T::read_from_prefix(data.as_bytes()).unwrap().0
}

pub fn write<T: IntoBytes + Immutable>(self, offset: usize, value: T) {
assert!(offset + size_of::<T>() <= self.size);
assert!(size_of::<T>() < HYP_IO_MAX);

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);
}
}

0 comments on commit 9168099

Please sign in to comment.