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