• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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