diff --git a/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs b/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs index 5c7466278e..81fcff2147 100644 --- a/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs +++ b/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs @@ -28,11 +28,18 @@ impl FlowNode for Node { |_| { let sh = xshell::Shell::new()?; - // TODO: add this to the initial CI image (and maybe the reg keys too) + // TODO: perform these operation on the reference CI image + + // Install the Hyper-V Powershell commands xshell::cmd!(sh, "DISM /Online /Norestart /Enable-Feature /All /FeatureName:Microsoft-Hyper-V-Management-PowerShell").run()?; - let firmware_load_path = r#"HKLM\Software\Microsoft\Windows NT\CurrentVersion\Virtualization"#; - xshell::cmd!(sh, "reg add {firmware_load_path} /v AllowFirmwareLoadFromFile /t REG_DWORD /d 1 /f").run()?; + let virt_reg_path = r#"HKLM\Software\Microsoft\Windows NT\CurrentVersion\Virtualization"#; + + // Allow loading IGVM from file (to run custom OpenHCL firmware) + xshell::cmd!(sh, "reg add {virt_reg_path} /v AllowFirmwareLoadFromFile /t REG_DWORD /d 1 /f").run()?; + + // Enable COM3 and COM4 for Hyper-V VMs so we can get the OpenHCL KMSG logs over serial + xshell::cmd!(sh, "reg add {virt_reg_path} /v EnableAdditionalComPorts /t REG_DWORD /d 1 /f").run()?; Ok(()) } diff --git a/petri/src/vm/hyperv/mod.rs b/petri/src/vm/hyperv/mod.rs index 4e6d7f2c37..098a7ee047 100644 --- a/petri/src/vm/hyperv/mod.rs +++ b/petri/src/vm/hyperv/mod.rs @@ -342,14 +342,14 @@ impl PetriVmConfigHyperV { let mut log_tasks = Vec::new(); - let serial_pipe_path = vm.set_vm_com_port(1)?; + let guest_serial_pipe_path = vm.set_vm_com_port(1)?; let serial_log_file = self.log_source.log_file("guest")?; log_tasks.push(self.driver.spawn("guest-log", { let driver = self.driver.clone(); async move { let serial = diag_client::hyperv::open_serial_port( &driver, - diag_client::hyperv::ComPortAccessInfo::PortPipePath(&serial_pipe_path), + diag_client::hyperv::ComPortAccessInfo::PortPipePath(&guest_serial_pipe_path), ) .await?; crate::log_stream(serial_log_file, PolledPipe::new(&driver, serial)?).await @@ -358,21 +358,52 @@ impl PetriVmConfigHyperV { let openhcl_diag_handler = if self.openhcl_igvm.is_some() { let openhcl_log_file = self.log_source.log_file("openhcl")?; - log_tasks.push(self.driver.spawn("openhcl-log", { - let driver = self.driver.clone(); - let vmid = *vm.vmid(); - async move { - let diag_client = diag_client::DiagClient::from_hyperv_id(driver.clone(), vmid); - loop { - diag_client.wait_for_server().await?; - crate::kmsg_log_task( - openhcl_log_file.clone(), - diag_client.kmsg(true).await?, + + // Attempt to enable COM3 and use that to get KMSG logs, otherwise + // fall back to use diag_client. + // + // Hyper-V VBS VMs don't work with COM3 enabled for some reason. + let is_not_vbs = !matches!( + self.guest_state_isolation_type, + powershell::HyperVGuestStateIsolationType::Vbs + ); + let openhcl_serial_pipe_path = is_not_vbs.then(|| vm.set_vm_com_port(3).ok()).flatten(); + + if let Some(openhcl_serial_pipe_path) = openhcl_serial_pipe_path { + log_tasks.push(self.driver.spawn("openhcl-log", { + let driver = self.driver.clone(); + async move { + let serial = diag_client::hyperv::open_serial_port( + &driver, + diag_client::hyperv::ComPortAccessInfo::PortPipePath( + &openhcl_serial_pipe_path, + ), ) - .await? + .await?; + crate::log_stream(openhcl_log_file, PolledPipe::new(&driver, serial)?).await } - } - })); + })); + } else { + tracing::warn!("falling back to getting kmsg logs from diag_client"); + + log_tasks.push(self.driver.spawn("openhcl-log", { + let driver = self.driver.clone(); + let vmid = *vm.vmid(); + async move { + let diag_client = + diag_client::DiagClient::from_hyperv_id(driver.clone(), vmid); + loop { + diag_client.wait_for_server().await?; + crate::kmsg_log_task( + openhcl_log_file.clone(), + diag_client.kmsg(true).await?, + ) + .await? + } + } + })); + } + Some(OpenHclDiagHandler::new( diag_client::DiagClient::from_hyperv_id(self.driver.clone(), *vm.vmid()), ))