Skip to content

Commit e74f61e

Browse files
authored
page_pool_alloc: create mappings via trait, move to vm directory (#780)
Allow reusing the page pool in other places with mapping support by specifying mapping via a trait, and move the crate to the vm directory. This may be used for some driver unittests in the future. Move the OpenHCL specific mapping code to a new crate. As a plus, now this crate works on Windows too.
1 parent b89b569 commit e74f61e

File tree

10 files changed

+258
-74
lines changed

10 files changed

+258
-74
lines changed

Cargo.lock

+14-1
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,19 @@ dependencies = [
26762676
"zerocopy 0.8.14",
26772677
]
26782678

2679+
[[package]]
2680+
name = "hcl_mapper"
2681+
version = "0.0.0"
2682+
dependencies = [
2683+
"anyhow",
2684+
"hcl",
2685+
"hvdef",
2686+
"inspect",
2687+
"page_pool_alloc",
2688+
"sparse_mmap",
2689+
"tracing",
2690+
]
2691+
26792692
[[package]]
26802693
name = "heck"
26812694
version = "0.4.1"
@@ -4873,7 +4886,6 @@ name = "page_pool_alloc"
48734886
version = "0.0.0"
48744887
dependencies = [
48754888
"anyhow",
4876-
"hcl",
48774889
"hvdef",
48784890
"inspect",
48794891
"memory_range",
@@ -7067,6 +7079,7 @@ dependencies = [
70677079
"guestmem",
70687080
"guid",
70697081
"hcl_compat_uefi_nvram_storage",
7082+
"hcl_mapper",
70707083
"hvdef",
70717084
"hyperv_ic_guest",
70727085
"hyperv_ic_resources",

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,12 @@ diag_proto = { path = "openhcl/diag_proto" }
153153
diag_server = { path = "openhcl/diag_server" }
154154
get_lower_vtl = { path = "openhcl/get_lower_vtl" }
155155
hcl = { path = "openhcl/hcl" }
156+
hcl_mapper = { path = "openhcl/hcl_mapper" }
156157
host_fdt_parser = { path = "openhcl/host_fdt_parser" }
157158
kmsg_defs = { path = "openhcl/kmsg_defs" }
158159
lower_vtl_permissions_guard = { path = "openhcl/lower_vtl_permissions_guard" }
159160
minimal_rt = { path = "openhcl/minimal_rt" }
160161
minimal_rt_build = { path = "openhcl/minimal_rt_build" }
161-
page_pool_alloc = { path = "openhcl/page_pool_alloc" }
162162
sidecar_client = { path = "openhcl/sidecar_client" }
163163
sidecar_defs = { path = "openhcl/sidecar_defs" }
164164
underhill_attestation = { path = "openhcl/underhill_attestation" }
@@ -327,6 +327,7 @@ loader = { path = "vm/loader" }
327327
igvmfilegen_config = { path = "vm/loader/igvmfilegen_config" }
328328
loader_defs = { path = "vm/loader/loader_defs" }
329329
page_table = { path = "vm/loader/page_table" }
330+
page_pool_alloc = { path = "vm/page_pool_alloc" }
330331
vbs_defs = { path = "vm/vbs_defs" }
331332
vmgs = { path = "vm/vmgs/vmgs" }
332333
vmgs_broker = { path = "vm/vmgs/vmgs_broker" }

openhcl/hcl_mapper/Cargo.toml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
[package]
5+
name = "hcl_mapper"
6+
rust-version.workspace = true
7+
edition.workspace = true
8+
9+
[dependencies]
10+
hcl.workspace = true
11+
12+
hvdef.workspace = true
13+
page_pool_alloc.workspace = true
14+
15+
inspect.workspace = true
16+
sparse_mmap.workspace = true
17+
18+
anyhow.workspace = true
19+
tracing.workspace = true
20+
21+
[lints]
22+
workspace = true

openhcl/hcl_mapper/src/lib.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
//! Provides a mapper implementation for the page pool that uses the hcl ioctl
5+
//! crate to map guest memory.
6+
7+
#![cfg(target_os = "linux")]
8+
#![warn(missing_docs)]
9+
10+
use anyhow::Context;
11+
use hcl::ioctl::MshvVtlLow;
12+
use hvdef::HV_PAGE_SIZE;
13+
use inspect::Inspect;
14+
use inspect::Response;
15+
use page_pool_alloc::Mapper;
16+
use page_pool_alloc::PoolType;
17+
use sparse_mmap::SparseMapping;
18+
19+
/// A mapper that uses [`MshvVtlLow`] to map pages.
20+
#[derive(Inspect)]
21+
#[inspect(extra = "HclMapper::inspect_extra")]
22+
pub struct HclMapper {
23+
#[inspect(skip)]
24+
fd: MshvVtlLow,
25+
}
26+
27+
impl HclMapper {
28+
/// Creates a new [`HclMapper`].
29+
pub fn new() -> Result<Self, anyhow::Error> {
30+
let fd = MshvVtlLow::new().context("failed to open gpa fd")?;
31+
Ok(Self { fd })
32+
}
33+
34+
fn inspect_extra(&self, resp: &mut Response<'_>) {
35+
resp.field("type", "hcl_mapper");
36+
}
37+
}
38+
39+
impl Mapper for HclMapper {
40+
fn map(
41+
&self,
42+
base_pfn: u64,
43+
size_pages: u64,
44+
pool_type: PoolType,
45+
) -> Result<SparseMapping, anyhow::Error> {
46+
let len = (size_pages * HV_PAGE_SIZE) as usize;
47+
let mapping = SparseMapping::new(len).context("failed to create mapping")?;
48+
let gpa = base_pfn * HV_PAGE_SIZE;
49+
50+
// When the pool references shared memory, on hardware isolated
51+
// platforms the file_offset must have the shared bit set as these
52+
// are decrypted pages. Setting this bit is okay on non-hardware
53+
// isolated platforms, as it does nothing.
54+
let file_offset = match pool_type {
55+
PoolType::Private => gpa,
56+
PoolType::Shared => {
57+
tracing::trace!("setting MshvVtlLow::SHARED_MEMORY_FLAG");
58+
gpa | MshvVtlLow::SHARED_MEMORY_FLAG
59+
}
60+
};
61+
62+
tracing::trace!(gpa, file_offset, len, "mapping allocation");
63+
64+
mapping
65+
.map_file(0, len, self.fd.get(), file_offset, true)
66+
.context("unable to map allocation")?;
67+
68+
Ok(mapping)
69+
}
70+
}

openhcl/underhill_core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ hyperv_secure_boot_templates.workspace = true
5858
hyperv_uefi_custom_vars_json.workspace = true
5959
framebuffer.workspace = true
6060
hcl_compat_uefi_nvram_storage = { workspace = true, features = ["inspect"] }
61+
hcl_mapper.workspace = true
6162
get_helpers.workspace = true
6263
get_lower_vtl.workspace = true
6364
get_protocol.workspace = true

openhcl/underhill_core/src/worker.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ use guest_emulation_transport::GuestEmulationTransportClient;
7373
use guestmem::GuestMemory;
7474
use guid::Guid;
7575
use hcl_compat_uefi_nvram_storage::HclCompatNvramQuirks;
76+
use hcl_mapper::HclMapper;
7677
use hvdef::hypercall::HvGuestOsId;
7778
use hvdef::HvRegisterValue;
7879
use hvdef::Vtl;
@@ -1515,6 +1516,7 @@ async fn new_underhill_vm(
15151516
.vtom_offset_bit
15161517
.map(|bit| 1 << bit)
15171518
.unwrap_or(0),
1519+
HclMapper::new().context("failed to create hcl mapper")?,
15181520
)
15191521
.context("failed to create shared vis page pool")?;
15201522

@@ -1541,8 +1543,11 @@ async fn new_underhill_vm(
15411543
use vmcore::save_restore::SaveRestore;
15421544

15431545
let ranges = runtime_params.private_pool_ranges();
1544-
let mut pool =
1545-
PagePool::new_private_pool(ranges).context("failed to create private pool")?;
1546+
let mut pool = PagePool::new_private_pool(
1547+
ranges,
1548+
HclMapper::new().context("failed to create hcl mapper")?,
1549+
)
1550+
.context("failed to create private pool")?;
15461551

15471552
if let Some(pool_state) = servicing_state.private_pool_state.flatten() {
15481553
pool.restore(pool_state)

openhcl/virt_mshv_vtl/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ gdb = []
1313
aarch64emu.workspace = true
1414
aarch64defs.workspace = true
1515
hcl.workspace = true
16-
page_pool_alloc = { workspace = true, features = ["hcl_mapping"] }
16+
page_pool_alloc.workspace = true
1717
virt.workspace = true
1818
virt_support_aarch64emu.workspace = true
1919
virt_support_apic.workspace = true

openhcl/page_pool_alloc/Cargo.toml renamed to vm/page_pool_alloc/Cargo.toml

+1-6
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ edition.workspace = true
77
rust-version.workspace = true
88

99
[features]
10-
# Enable mapping support, using the MshvVtlLow.
11-
hcl_mapping = ["hcl"]
1210
# Enable user_driver vfio trait support.
13-
vfio = ["hcl_mapping", "user_driver/vfio"]
11+
vfio = ["user_driver/vfio"]
1412

1513
[dependencies]
1614
user_driver.workspace = true
@@ -28,8 +26,5 @@ thiserror.workspace = true
2826
anyhow.workspace = true
2927
tracing.workspace = true
3028

31-
[target.'cfg(target_os = "linux")'.dependencies]
32-
hcl = { workspace = true, optional = true}
33-
3429
[lints]
3530
workspace = true

0 commit comments

Comments
 (0)