From a5d47f75103425790ca093bc9952811a1094e71f Mon Sep 17 00:00:00 2001 From: Trevor Jones Date: Thu, 10 Apr 2025 15:56:37 -0700 Subject: [PATCH 1/4] use com3 for kmsg in petri --- .../src/init_hyperv_tests.rs | 8 ++++++- petri/src/vm/hyperv/mod.rs | 23 +++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs b/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs index 5c7466278e..194208c161 100644 --- a/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs +++ b/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs @@ -28,12 +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()?; + // Allow loading IGVM from file (to run custom OpenHCL firmware) 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()?; + // Enable COM3 and COM4 for Hyper-V VMs so we can get the OpenHCL KMSG logs over serial + xshell::cmd!(sh, "Enable-VelocityFeature -Feature 21938063").run()?; + Ok(()) } }); diff --git a/petri/src/vm/hyperv/mod.rs b/petri/src/vm/hyperv/mod.rs index 4e6d7f2c37..84d4a90521 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 @@ -357,20 +357,19 @@ impl PetriVmConfigHyperV { })); let openhcl_diag_handler = if self.openhcl_igvm.is_some() { + let openhcl_serial_pipe_path = vm.set_vm_com_port(3)?; 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?, - ) - .await? - } + let serial = diag_client::hyperv::open_serial_port( + &driver, + diag_client::hyperv::ComPortAccessInfo::PortPipePath( + &openhcl_serial_pipe_path, + ), + ) + .await?; + crate::log_stream(openhcl_log_file, PolledPipe::new(&driver, serial)?).await } })); Some(OpenHclDiagHandler::new( From 893716537e140d3ff0284e3fb42f8f13664fa5c7 Mon Sep 17 00:00:00 2001 From: Trevor Jones Date: Thu, 10 Apr 2025 16:36:25 -0700 Subject: [PATCH 2/4] use reg --- flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs b/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs index 194208c161..81fcff2147 100644 --- a/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs +++ b/flowey/flowey_lib_hvlite/src/init_hyperv_tests.rs @@ -33,12 +33,13 @@ impl FlowNode for Node { // Install the Hyper-V Powershell commands xshell::cmd!(sh, "DISM /Online /Norestart /Enable-Feature /All /FeatureName:Microsoft-Hyper-V-Management-PowerShell").run()?; + let virt_reg_path = r#"HKLM\Software\Microsoft\Windows NT\CurrentVersion\Virtualization"#; + // Allow loading IGVM from file (to run custom OpenHCL firmware) - 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()?; + 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, "Enable-VelocityFeature -Feature 21938063").run()?; + xshell::cmd!(sh, "reg add {virt_reg_path} /v EnableAdditionalComPorts /t REG_DWORD /d 1 /f").run()?; Ok(()) } From ce0c907f1826b1db4c6cd40ff8f90aec9a9afcb0 Mon Sep 17 00:00:00 2001 From: Trevor Jones Date: Wed, 23 Apr 2025 15:06:09 -0700 Subject: [PATCH 3/4] only use it when it works. --- petri/src/vm/hyperv/mod.rs | 55 +++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/petri/src/vm/hyperv/mod.rs b/petri/src/vm/hyperv/mod.rs index 84d4a90521..57d8eeaef0 100644 --- a/petri/src/vm/hyperv/mod.rs +++ b/petri/src/vm/hyperv/mod.rs @@ -357,21 +357,50 @@ impl PetriVmConfigHyperV { })); let openhcl_diag_handler = if self.openhcl_igvm.is_some() { - let openhcl_serial_pipe_path = vm.set_vm_com_port(3)?; let openhcl_log_file = self.log_source.log_file("openhcl")?; - 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?; - crate::log_stream(openhcl_log_file, PolledPipe::new(&driver, serial)?).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. + match (self.guest_state_isolation_type, vm.set_vm_com_port(3)) { + (powershell::HyperVGuestStateIsolationType::Vbs, _) | (_, Err(_)) => { + 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? + } + } + })); + } + (_, Ok(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?; + crate::log_stream(openhcl_log_file, PolledPipe::new(&driver, serial)?) + .await + } + })); } - })); + } + Some(OpenHclDiagHandler::new( diag_client::DiagClient::from_hyperv_id(self.driver.clone(), *vm.vmid()), )) From 2ca60d1843270074d6890e16ccb699b1d5fe9294 Mon Sep 17 00:00:00 2001 From: Trevor Jones Date: Wed, 23 Apr 2025 15:52:39 -0700 Subject: [PATCH 4/4] don't add the com port if its gonna fail --- petri/src/vm/hyperv/mod.rs | 71 ++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/petri/src/vm/hyperv/mod.rs b/petri/src/vm/hyperv/mod.rs index 57d8eeaef0..098a7ee047 100644 --- a/petri/src/vm/hyperv/mod.rs +++ b/petri/src/vm/hyperv/mod.rs @@ -363,42 +363,45 @@ impl PetriVmConfigHyperV { // fall back to use diag_client. // // Hyper-V VBS VMs don't work with COM3 enabled for some reason. - match (self.guest_state_isolation_type, vm.set_vm_com_port(3)) { - (powershell::HyperVGuestStateIsolationType::Vbs, _) | (_, Err(_)) => { - 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? - } - } - })); - } - (_, Ok(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, - ), + 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?; + 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?; - crate::log_stream(openhcl_log_file, PolledPipe::new(&driver, serial)?) - .await + .await? } - })); - } + } + })); } Some(OpenHclDiagHandler::new(