1#![cfg(target_os = "linux")]
8#![forbid(unsafe_code)]
9
10use anyhow::Context;
11use hcl::ioctl::MshvVtlLow;
12use inspect::Inspect;
13use page_pool_alloc::PoolSource;
14use std::os::fd::AsFd;
15
16#[derive(Inspect)]
18pub struct HclMapper {
19 #[inspect(skip)]
20 fd: MshvVtlLow,
21 gpa_bias: u64,
22 is_shared: bool,
23}
24
25impl HclMapper {
26 pub fn new_shared(vtom: u64) -> anyhow::Result<Self> {
29 Self::new_inner(vtom, true)
30 }
31
32 pub fn new_private() -> anyhow::Result<Self> {
34 Self::new_inner(0, false)
35 }
36
37 fn new_inner(gpa_bias: u64, is_shared: bool) -> anyhow::Result<Self> {
38 let fd = MshvVtlLow::new().context("failed to open gpa fd")?;
39 Ok(Self {
40 fd,
41 gpa_bias,
42 is_shared,
43 })
44 }
45}
46
47impl PoolSource for HclMapper {
48 fn address_bias(&self) -> u64 {
49 self.gpa_bias
50 }
51
52 fn file_offset(&self, address: u64) -> u64 {
53 address.wrapping_add(if self.is_shared {
54 MshvVtlLow::SHARED_MEMORY_FLAG
55 } else {
56 0
57 })
58 }
59
60 fn mappable(&self) -> sparse_mmap::MappableRef<'_> {
61 self.fd.get().as_fd()
62 }
63}