1use underhill_confidentiality::OPENHCL_CONFIDENTIAL_DEBUG_ENV_VAR_NAME;
7
8const IGVM_VTL2_GPA_POOL_CONFIG: &str = "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=";
18
19const ENABLE_VTL2_GPA_POOL: &str = "OPENHCL_ENABLE_VTL2_GPA_POOL=";
23
24const SIDECAR: &str = "OPENHCL_SIDECAR=";
32
33const DISABLE_NVME_KEEP_ALIVE: &str = "OPENHCL_DISABLE_NVME_KEEP_ALIVE=";
35
36#[derive(Debug, PartialEq, Clone, Copy)]
38pub enum Vtl2GpaPoolLookupTable {
39 Release,
40 Debug,
41}
42
43#[derive(Debug, PartialEq, Clone, Copy)]
44pub enum Vtl2GpaPoolConfig {
45 Heuristics(Vtl2GpaPoolLookupTable),
57
58 Off,
60
61 Pages(u64),
63}
64
65impl<S: AsRef<str>> From<S> for Vtl2GpaPoolConfig {
66 fn from(arg: S) -> Self {
67 match arg.as_ref() {
68 "debug" => Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Debug),
69 "release" => Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release),
70 "off" => Vtl2GpaPoolConfig::Off,
71 _ => {
72 let num = arg.as_ref().parse::<u64>().unwrap_or(0);
73 if num == 0 {
76 Vtl2GpaPoolConfig::Off
77 } else {
78 Vtl2GpaPoolConfig::Pages(num)
79 }
80 }
81 }
82 }
83}
84
85#[derive(Debug, PartialEq)]
86pub enum SidecarOptions {
87 Enabled {
91 enable_logging: bool,
92 cpu_threshold: Option<u32>,
93 },
94 DisabledServicing,
97 DisabledCommandLine,
99}
100
101impl SidecarOptions {
102 pub const DEFAULT_CPU_THRESHOLD: Option<u32> = Some(100);
103 pub const fn default() -> Self {
104 SidecarOptions::Enabled {
105 enable_logging: false,
106 cpu_threshold: Self::DEFAULT_CPU_THRESHOLD,
107 }
108 }
109}
110
111#[derive(Debug, PartialEq)]
112pub struct BootCommandLineOptions {
113 pub confidential_debug: bool,
114 pub enable_vtl2_gpa_pool: Vtl2GpaPoolConfig,
115 pub sidecar: SidecarOptions,
116 pub disable_nvme_keep_alive: bool,
117}
118
119impl BootCommandLineOptions {
120 pub const fn new() -> Self {
121 BootCommandLineOptions {
122 confidential_debug: false,
123 enable_vtl2_gpa_pool: Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release), sidecar: SidecarOptions::default(),
125 disable_nvme_keep_alive: true,
126 }
127 }
128}
129
130impl BootCommandLineOptions {
131 pub fn parse(&mut self, cmdline: &str) {
133 self.disable_nvme_keep_alive = true;
135
136 let mut override_vtl2_gpa_pool: Option<Vtl2GpaPoolConfig> = None;
137 for arg in cmdline.split_whitespace() {
138 if arg.starts_with(OPENHCL_CONFIDENTIAL_DEBUG_ENV_VAR_NAME) {
139 let arg = arg.split_once('=').map(|(_, arg)| arg);
140 if arg.is_some_and(|a| a != "0") {
141 self.confidential_debug = true;
142 }
143 } else if arg.starts_with(IGVM_VTL2_GPA_POOL_CONFIG) {
144 if let Some((_, arg)) = arg.split_once('=') {
145 self.enable_vtl2_gpa_pool = Vtl2GpaPoolConfig::from(arg);
146 } else {
147 log::warn!("Missing value for IGVM_VTL2_GPA_POOL_CONFIG argument");
148 }
149 } else if arg.starts_with(ENABLE_VTL2_GPA_POOL) {
150 if let Some((_, arg)) = arg.split_once('=') {
151 override_vtl2_gpa_pool = Some(Vtl2GpaPoolConfig::from(arg));
152 } else {
153 log::warn!("Missing value for ENABLE_VTL2_GPA_POOL argument");
154 }
155 } else if arg.starts_with(SIDECAR) {
156 if let Some((_, arg)) = arg.split_once('=') {
157 for arg in arg.split(',') {
158 match arg {
159 "off" => self.sidecar = SidecarOptions::DisabledCommandLine,
160 "on" => {
161 self.sidecar = SidecarOptions::Enabled {
162 enable_logging: false,
163 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
164 }
165 }
166 "log" => {
167 self.sidecar = SidecarOptions::Enabled {
168 enable_logging: true,
169 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
170 }
171 }
172 _ => {}
173 }
174 }
175 }
176 } else if arg.starts_with(DISABLE_NVME_KEEP_ALIVE) {
177 let arg = arg.split_once('=').map(|(_, arg)| arg);
178 if arg.is_some_and(|a| a == "0") {
179 self.disable_nvme_keep_alive = false;
180 }
181 }
182 }
183
184 if let Some(override_config) = override_vtl2_gpa_pool {
185 self.enable_vtl2_gpa_pool = override_config;
186 log::info!(
187 "Overriding VTL2 GPA pool config to {:?} from command line",
188 override_config
189 );
190 }
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197
198 fn parse_boot_command_line(cmdline: &str) -> BootCommandLineOptions {
199 let mut options = BootCommandLineOptions::new();
200 options.parse(cmdline);
201 options
202 }
203
204 #[test]
205 fn test_vtl2_gpa_pool_parsing() {
206 for (cmdline, expected) in [
207 (
208 "",
210 Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release),
211 ),
212 (
213 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=1",
214 Vtl2GpaPoolConfig::Pages(1),
215 ),
216 (
217 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=0",
218 Vtl2GpaPoolConfig::Off,
219 ),
220 (
221 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=asdf",
222 Vtl2GpaPoolConfig::Off,
223 ),
224 (
225 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=512",
226 Vtl2GpaPoolConfig::Pages(512),
227 ),
228 (
229 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=off",
230 Vtl2GpaPoolConfig::Off,
231 ),
232 (
233 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=debug",
234 Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Debug),
235 ),
236 (
237 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=release",
238 Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release),
239 ),
240 (
241 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=release OPENHCL_ENABLE_VTL2_GPA_POOL=debug",
243 Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Debug),
244 ),
245 ] {
246 assert_eq!(
247 parse_boot_command_line(cmdline).enable_vtl2_gpa_pool,
248 expected,
249 "Failed parsing VTL2 GPA pool config from command line: {}",
250 cmdline
251 );
252 }
253 }
254
255 #[test]
256 fn test_sidecar_parsing() {
257 assert_eq!(
258 parse_boot_command_line("OPENHCL_SIDECAR=on"),
259 BootCommandLineOptions {
260 sidecar: SidecarOptions::Enabled {
261 enable_logging: false,
262 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
263 },
264 ..BootCommandLineOptions::new()
265 }
266 );
267 assert_eq!(
268 parse_boot_command_line("OPENHCL_SIDECAR=off"),
269 BootCommandLineOptions {
270 sidecar: SidecarOptions::DisabledCommandLine,
271 ..BootCommandLineOptions::new()
272 }
273 );
274 assert_eq!(
275 parse_boot_command_line("OPENHCL_SIDECAR=on,off"),
276 BootCommandLineOptions {
277 sidecar: SidecarOptions::DisabledCommandLine,
278 ..BootCommandLineOptions::new()
279 }
280 );
281 assert_eq!(
282 parse_boot_command_line("OPENHCL_SIDECAR=on,log"),
283 BootCommandLineOptions {
284 sidecar: SidecarOptions::Enabled {
285 enable_logging: true,
286 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
287 },
288 ..BootCommandLineOptions::new()
289 }
290 );
291 assert_eq!(
292 parse_boot_command_line("OPENHCL_SIDECAR=log"),
293 BootCommandLineOptions {
294 sidecar: SidecarOptions::Enabled {
295 enable_logging: true,
296 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
297 },
298 ..BootCommandLineOptions::new()
299 }
300 );
301 }
302}