diff --git a/src/transport/x86_64.rs b/src/transport/x86_64.rs index cbd1850c..f12f7f91 100644 --- a/src/transport/x86_64.rs +++ b/src/transport/x86_64.rs @@ -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)) @@ -318,31 +315,3 @@ fn get_bar_region( 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(self, offset: usize) -> T { - assert!(offset + size_of::() <= self.size); - assert!(size_of::() < HYP_IO_MAX); - - let data = hyp_io_read(self.paddr + offset, size_of::()); - T::read_from_prefix(data.as_bytes()).unwrap().0 - } - - fn write(self, offset: usize, value: T) { - assert!(offset + size_of::() <= self.size); - assert!(size_of::() < HYP_IO_MAX); - - let mut data = 0; - data.as_mut_bytes()[..size_of::()].copy_from_slice(value.as_bytes()); - hyp_io_write(self.paddr + offset, size_of::(), data); - } -} diff --git a/src/transport/x86_64/hypercalls.rs b/src/transport/x86_64/hypercalls.rs index 5b5b686a..38962a29 100644 --- a/src/transport/x86_64/hypercalls.rs +++ b/src/transport/x86_64/hypercalls.rs @@ -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`. @@ -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; @@ -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(self, offset: usize) -> T { + assert!(offset + size_of::() <= self.size); + assert!(size_of::() < HYP_IO_MAX); + + let data = hyp_io_read(self.paddr + offset, size_of::()); + T::read_from_prefix(data.as_bytes()).unwrap().0 + } + + pub fn write(self, offset: usize, value: T) { + assert!(offset + size_of::() <= self.size); + assert!(size_of::() < HYP_IO_MAX); + + let mut data = 0; + data.as_mut_bytes()[..size_of::()].copy_from_slice(value.as_bytes()); + hyp_io_write(self.paddr + offset, size_of::(), data); + } +}