Skip to content

Commit 0579572

Browse files
committed
Reapply "openhcl_boot: set aside private pool memory based on heuristics (microsoft#2215)" (microsoft#2339)
This reverts commit c552f9a.
1 parent 096c3a4 commit 0579572

File tree

15 files changed

+715
-81
lines changed

15 files changed

+715
-81
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5021,7 +5021,9 @@ dependencies = [
50215021
"sidecar_defs",
50225022
"string_page_buf",
50235023
"tdcall",
5024+
"test_with_tracing",
50245025
"thiserror 2.0.16",
5026+
"tracing",
50255027
"underhill_confidentiality",
50265028
"x86defs",
50275029
"zerocopy 0.8.25",

openhcl/openhcl_boot/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ safe_intrinsics.workspace = true
3737
tdcall.workspace = true
3838
x86defs.workspace = true
3939

40+
[dev-dependencies]
41+
test_with_tracing.workspace = true
42+
tracing.workspace = true
43+
4044
[build-dependencies]
4145
minimal_rt_build.workspace = true
4246

openhcl/openhcl_boot/src/cmdline.rs

Lines changed: 131 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,23 @@
33

44
//! Command line arguments and parsing for openhcl_boot.
55
6+
use crate::boot_logger::log;
67
use underhill_confidentiality::OPENHCL_CONFIDENTIAL_DEBUG_ENV_VAR_NAME;
78

8-
/// Enable the private VTL2 GPA pool for page allocations. This is only enabled
9-
/// via the command line, because in order to support the VTL2 GPA pool
10-
/// generically, the boot shim must read serialized data from the previous
11-
/// OpenHCL instance on a servicing boot in order to guarantee the same memory
12-
/// layout is presented.
9+
/// Enable the private VTL2 GPA pool for page allocations.
1310
///
14-
/// The value specified is the number of 4K pages to reserve for the pool.
11+
/// Possible values:
12+
/// * `release`: Use the release version of the lookup table (default), or device tree.
13+
/// * `debug`: Use the debug version of the lookup table, or device tree.
14+
/// * `off`: Disable the VTL2 GPA pool.
15+
/// * `<num_pages>`: Explicitly specify the size of the VTL2 GPA pool.
1516
///
16-
/// TODO: Remove this commandline once support for reading saved state is
17-
/// supported in openhcl_boot.
17+
/// See `Vtl2GpaPoolConfig` for more details.
18+
const IGVM_VTL2_GPA_POOL_CONFIG: &str = "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=";
19+
20+
/// Test-legacy/test-compat override for `OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG`.
21+
/// (otherwise, tests cannot modify the VTL2 GPA pool config different from what
22+
/// may be in the manifest).
1823
const ENABLE_VTL2_GPA_POOL: &str = "OPENHCL_ENABLE_VTL2_GPA_POOL=";
1924

2025
/// Options controlling sidecar.
@@ -29,10 +34,59 @@ const SIDECAR: &str = "OPENHCL_SIDECAR=";
2934
/// Disable NVME keep alive regardless if the host supports it.
3035
const DISABLE_NVME_KEEP_ALIVE: &str = "OPENHCL_DISABLE_NVME_KEEP_ALIVE=";
3136

37+
/// Lookup table to use for VTL2 GPA pool size heuristics.
38+
#[derive(Debug, PartialEq, Clone, Copy)]
39+
pub enum Vtl2GpaPoolLookupTable {
40+
Release,
41+
Debug,
42+
}
43+
44+
#[derive(Debug, PartialEq, Clone, Copy)]
45+
pub enum Vtl2GpaPoolConfig {
46+
/// Use heuristics to determine the VTL2 GPA pool size.
47+
/// Reserve a default size based on the amount of VTL2 ram and
48+
/// number of vCPUs. The point of this method is to account for cases where
49+
/// we retrofit the private pool into existing deployments that do not
50+
/// specify it explicitly.
51+
///
52+
/// If the host specifies a size via the device tree, that size will be used
53+
/// instead.
54+
///
55+
/// The lookup table specifies whether to use the debug or release
56+
/// heuristics (as the dev manifests provide different amounts of VTL2 RAM).
57+
Heuristics(Vtl2GpaPoolLookupTable),
58+
59+
/// Explicitly disable the VTL2 private pool.
60+
Off,
61+
62+
/// Explicitly specify the size of the VTL2 GPA pool in pages.
63+
Pages(u64),
64+
}
65+
66+
impl<S: AsRef<str>> From<S> for Vtl2GpaPoolConfig {
67+
fn from(arg: S) -> Self {
68+
match arg.as_ref() {
69+
"debug" => Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Debug),
70+
"release" => Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release),
71+
"off" => Vtl2GpaPoolConfig::Off,
72+
_ => {
73+
let num = arg.as_ref().parse::<u64>().unwrap_or(0);
74+
// A size of 0 or failure to parse is treated as disabling
75+
// the pool.
76+
if num == 0 {
77+
Vtl2GpaPoolConfig::Off
78+
} else {
79+
Vtl2GpaPoolConfig::Pages(num)
80+
}
81+
}
82+
}
83+
}
84+
}
85+
3286
#[derive(Debug, PartialEq)]
3387
pub struct BootCommandLineOptions {
3488
pub confidential_debug: bool,
35-
pub enable_vtl2_gpa_pool: Option<u64>,
89+
pub enable_vtl2_gpa_pool: Vtl2GpaPoolConfig,
3690
pub sidecar: bool,
3791
pub sidecar_logging: bool,
3892
pub disable_nvme_keep_alive: bool,
@@ -42,7 +96,7 @@ impl BootCommandLineOptions {
4296
pub const fn new() -> Self {
4397
BootCommandLineOptions {
4498
confidential_debug: false,
45-
enable_vtl2_gpa_pool: None,
99+
enable_vtl2_gpa_pool: Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release), // use the release config by default
46100
sidecar: true, // sidecar is enabled by default
47101
sidecar_logging: false,
48102
disable_nvme_keep_alive: false,
@@ -53,19 +107,25 @@ impl BootCommandLineOptions {
53107
impl BootCommandLineOptions {
54108
/// Parse arguments from a command line.
55109
pub fn parse(&mut self, cmdline: &str) {
110+
let mut override_vtl2_gpa_pool: Option<Vtl2GpaPoolConfig> = None;
56111
for arg in cmdline.split_whitespace() {
57112
if arg.starts_with(OPENHCL_CONFIDENTIAL_DEBUG_ENV_VAR_NAME) {
58113
let arg = arg.split_once('=').map(|(_, arg)| arg);
59114
if arg.is_some_and(|a| a != "0") {
60115
self.confidential_debug = true;
61116
}
117+
} else if arg.starts_with(IGVM_VTL2_GPA_POOL_CONFIG) {
118+
if let Some((_, arg)) = arg.split_once('=') {
119+
self.enable_vtl2_gpa_pool = Vtl2GpaPoolConfig::from(arg);
120+
} else {
121+
log!("WARNING: Missing value for IGVM_VTL2_GPA_POOL_CONFIG argument");
122+
}
62123
} else if arg.starts_with(ENABLE_VTL2_GPA_POOL) {
63-
self.enable_vtl2_gpa_pool = arg.split_once('=').and_then(|(_, arg)| {
64-
let num = arg.parse::<u64>().unwrap_or(0);
65-
// A size of 0 or failure to parse is treated as disabling
66-
// the pool.
67-
if num == 0 { None } else { Some(num) }
68-
});
124+
if let Some((_, arg)) = arg.split_once('=') {
125+
override_vtl2_gpa_pool = Some(Vtl2GpaPoolConfig::from(arg));
126+
} else {
127+
log!("WARNING: Missing value for ENABLE_VTL2_GPA_POOL argument");
128+
}
69129
} else if arg.starts_with(SIDECAR) {
70130
if let Some((_, arg)) = arg.split_once('=') {
71131
for arg in arg.split(',') {
@@ -84,6 +144,14 @@ impl BootCommandLineOptions {
84144
}
85145
}
86146
}
147+
148+
if let Some(override_config) = override_vtl2_gpa_pool {
149+
self.enable_vtl2_gpa_pool = override_config;
150+
log!(
151+
"INFO: Overriding VTL2 GPA pool config to {:?} from command line",
152+
override_config
153+
);
154+
}
87155
}
88156
}
89157

@@ -99,34 +167,53 @@ mod tests {
99167

100168
#[test]
101169
fn test_vtl2_gpa_pool_parsing() {
102-
assert_eq!(
103-
parse_boot_command_line("OPENHCL_ENABLE_VTL2_GPA_POOL=1"),
104-
BootCommandLineOptions {
105-
enable_vtl2_gpa_pool: Some(1),
106-
..BootCommandLineOptions::new()
107-
}
108-
);
109-
assert_eq!(
110-
parse_boot_command_line("OPENHCL_ENABLE_VTL2_GPA_POOL=0"),
111-
BootCommandLineOptions {
112-
enable_vtl2_gpa_pool: None,
113-
..BootCommandLineOptions::new()
114-
}
115-
);
116-
assert_eq!(
117-
parse_boot_command_line("OPENHCL_ENABLE_VTL2_GPA_POOL=asdf"),
118-
BootCommandLineOptions {
119-
enable_vtl2_gpa_pool: None,
120-
..BootCommandLineOptions::new()
121-
}
122-
);
123-
assert_eq!(
124-
parse_boot_command_line("OPENHCL_ENABLE_VTL2_GPA_POOL=512"),
125-
BootCommandLineOptions {
126-
enable_vtl2_gpa_pool: Some(512),
127-
..BootCommandLineOptions::new()
128-
}
129-
);
170+
for (cmdline, expected) in [
171+
(
172+
// default
173+
"",
174+
Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release),
175+
),
176+
(
177+
"OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=1",
178+
Vtl2GpaPoolConfig::Pages(1),
179+
),
180+
(
181+
"OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=0",
182+
Vtl2GpaPoolConfig::Off,
183+
),
184+
(
185+
"OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=asdf",
186+
Vtl2GpaPoolConfig::Off,
187+
),
188+
(
189+
"OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=512",
190+
Vtl2GpaPoolConfig::Pages(512),
191+
),
192+
(
193+
"OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=off",
194+
Vtl2GpaPoolConfig::Off,
195+
),
196+
(
197+
"OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=debug",
198+
Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Debug),
199+
),
200+
(
201+
"OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=release",
202+
Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release),
203+
),
204+
(
205+
// OPENHCL_ENABLE_VTL2_GPA_POOL= takes precedence over OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=
206+
"OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=release OPENHCL_ENABLE_VTL2_GPA_POOL=debug",
207+
Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Debug),
208+
),
209+
] {
210+
assert_eq!(
211+
parse_boot_command_line(cmdline).enable_vtl2_gpa_pool,
212+
expected,
213+
"Failed parsing VTL2 GPA pool config from command line: {}",
214+
cmdline
215+
);
216+
}
130217
}
131218

132219
#[test]

0 commit comments

Comments
 (0)