1 use super::hypercalls::{cpuid_signature, hyp_io_read, hyp_io_write}; 2 use crate::transport::pci::bus::{Cam, ConfigurationAccess, DeviceFunction}; 3 4 const PKVM_SIGNATURE: &[u8] = b"PKVM"; 5 6 /// A PCI configuration access mechanism using hypercalls implemented by the x86-64 pKVM hypervisor. 7 pub struct HypCam { 8 /// The physical base address of the PCI root complex. 9 phys_base: usize, 10 cam: Cam, 11 } 12 13 impl HypCam { 14 /// Creates a new `HypCam` for the PCI root complex at the given physical base address. new(phys_base: usize, cam: Cam) -> Self15 pub fn new(phys_base: usize, cam: Cam) -> Self { 16 Self { phys_base, cam } 17 } 18 19 /// Returns whether we are running under pKVM by checking the CPU ID signature. is_pkvm() -> bool20 pub fn is_pkvm() -> bool { 21 cpuid_signature() == PKVM_SIGNATURE 22 } 23 } 24 25 impl ConfigurationAccess for HypCam { read_word(&self, device_function: DeviceFunction, register_offset: u8) -> u3226 fn read_word(&self, device_function: DeviceFunction, register_offset: u8) -> u32 { 27 let address = self.cam.cam_offset(device_function, register_offset); 28 hyp_io_read(self.phys_base + (address as usize), 4) as u32 29 } 30 write_word(&mut self, device_function: DeviceFunction, register_offset: u8, data: u32)31 fn write_word(&mut self, device_function: DeviceFunction, register_offset: u8, data: u32) { 32 let address = self.cam.cam_offset(device_function, register_offset); 33 hyp_io_write(self.phys_base + (address as usize), 4, data.into()); 34 } 35 unsafe_clone(&self) -> Self36 unsafe fn unsafe_clone(&self) -> Self { 37 Self { 38 phys_base: self.phys_base, 39 cam: self.cam, 40 } 41 } 42 } 43