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: false,
126 }
127 }
128}
129
130impl BootCommandLineOptions {
131 pub fn parse(&mut self, cmdline: &str) {
133 let mut override_vtl2_gpa_pool: Option<Vtl2GpaPoolConfig> = None;
134 for arg in cmdline.split_whitespace() {
135 if arg.starts_with(OPENHCL_CONFIDENTIAL_DEBUG_ENV_VAR_NAME) {
136 let arg = arg.split_once('=').map(|(_, arg)| arg);
137 if arg.is_some_and(|a| a != "0") {
138 self.confidential_debug = true;
139 }
140 } else if arg.starts_with(IGVM_VTL2_GPA_POOL_CONFIG) {
141 if let Some((_, arg)) = arg.split_once('=') {
142 self.enable_vtl2_gpa_pool = Vtl2GpaPoolConfig::from(arg);
143 } else {
144 log::warn!("Missing value for IGVM_VTL2_GPA_POOL_CONFIG argument");
145 }
146 } else if arg.starts_with(ENABLE_VTL2_GPA_POOL) {
147 if let Some((_, arg)) = arg.split_once('=') {
148 override_vtl2_gpa_pool = Some(Vtl2GpaPoolConfig::from(arg));
149 } else {
150 log::warn!("Missing value for ENABLE_VTL2_GPA_POOL argument");
151 }
152 } else if arg.starts_with(SIDECAR) {
153 if let Some((_, arg)) = arg.split_once('=') {
154 for arg in arg.split(',') {
155 match arg {
156 "off" => self.sidecar = SidecarOptions::DisabledCommandLine,
157 "on" => {
158 self.sidecar = SidecarOptions::Enabled {
159 enable_logging: false,
160 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
161 }
162 }
163 "log" => {
164 self.sidecar = SidecarOptions::Enabled {
165 enable_logging: true,
166 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
167 }
168 }
169 _ => {}
170 }
171 }
172 }
173 } else if arg.starts_with(DISABLE_NVME_KEEP_ALIVE) {
174 let arg = arg.split_once('=').map(|(_, arg)| arg);
175 if arg.is_some_and(|a| a != "0") {
176 self.disable_nvme_keep_alive = true;
177 }
178 }
179 }
180
181 if let Some(override_config) = override_vtl2_gpa_pool {
182 self.enable_vtl2_gpa_pool = override_config;
183 log::info!(
184 "Overriding VTL2 GPA pool config to {:?} from command line",
185 override_config
186 );
187 }
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 fn parse_boot_command_line(cmdline: &str) -> BootCommandLineOptions {
196 let mut options = BootCommandLineOptions::new();
197 options.parse(cmdline);
198 options
199 }
200
201 #[test]
202 fn test_vtl2_gpa_pool_parsing() {
203 for (cmdline, expected) in [
204 (
205 "",
207 Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release),
208 ),
209 (
210 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=1",
211 Vtl2GpaPoolConfig::Pages(1),
212 ),
213 (
214 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=0",
215 Vtl2GpaPoolConfig::Off,
216 ),
217 (
218 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=asdf",
219 Vtl2GpaPoolConfig::Off,
220 ),
221 (
222 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=512",
223 Vtl2GpaPoolConfig::Pages(512),
224 ),
225 (
226 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=off",
227 Vtl2GpaPoolConfig::Off,
228 ),
229 (
230 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=debug",
231 Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Debug),
232 ),
233 (
234 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=release",
235 Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Release),
236 ),
237 (
238 "OPENHCL_IGVM_VTL2_GPA_POOL_CONFIG=release OPENHCL_ENABLE_VTL2_GPA_POOL=debug",
240 Vtl2GpaPoolConfig::Heuristics(Vtl2GpaPoolLookupTable::Debug),
241 ),
242 ] {
243 assert_eq!(
244 parse_boot_command_line(cmdline).enable_vtl2_gpa_pool,
245 expected,
246 "Failed parsing VTL2 GPA pool config from command line: {}",
247 cmdline
248 );
249 }
250 }
251
252 #[test]
253 fn test_sidecar_parsing() {
254 assert_eq!(
255 parse_boot_command_line("OPENHCL_SIDECAR=on"),
256 BootCommandLineOptions {
257 sidecar: SidecarOptions::Enabled {
258 enable_logging: false,
259 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
260 },
261 ..BootCommandLineOptions::new()
262 }
263 );
264 assert_eq!(
265 parse_boot_command_line("OPENHCL_SIDECAR=off"),
266 BootCommandLineOptions {
267 sidecar: SidecarOptions::DisabledCommandLine,
268 ..BootCommandLineOptions::new()
269 }
270 );
271 assert_eq!(
272 parse_boot_command_line("OPENHCL_SIDECAR=on,off"),
273 BootCommandLineOptions {
274 sidecar: SidecarOptions::DisabledCommandLine,
275 ..BootCommandLineOptions::new()
276 }
277 );
278 assert_eq!(
279 parse_boot_command_line("OPENHCL_SIDECAR=on,log"),
280 BootCommandLineOptions {
281 sidecar: SidecarOptions::Enabled {
282 enable_logging: true,
283 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
284 },
285 ..BootCommandLineOptions::new()
286 }
287 );
288 assert_eq!(
289 parse_boot_command_line("OPENHCL_SIDECAR=log"),
290 BootCommandLineOptions {
291 sidecar: SidecarOptions::Enabled {
292 enable_logging: true,
293 cpu_threshold: SidecarOptions::DEFAULT_CPU_THRESHOLD,
294 },
295 ..BootCommandLineOptions::new()
296 }
297 );
298 }
299}