Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions petri/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,20 @@ impl<T: PetriVmmBackend> PetriVmBuilder<T> {
self
}

/// Sets the UEFI diagnostics log level filter.
///
/// By default only ERROR and WARN level entries are forwarded to the
/// host tracing infrastructure. Use this to also surface INFO (or all)
/// entries when a test needs to observe them.
pub fn with_efi_diagnostics_log_level(mut self, level: EfiDiagnosticsLogLevel) -> Self {
self.config
.firmware
.uefi_config_mut()
.expect("EFI diagnostics log level is only supported for UEFI firmware.")
.efi_diagnostics_log_level = level;
Comment thread
maheeraeron marked this conversation as resolved.
self
}

/// Sets whether UEFI should always attempt a default boot.
pub fn with_default_boot_always_attempt(mut self, enable: bool) -> Self {
self.config
Expand Down Expand Up @@ -2158,6 +2172,8 @@ pub struct UefiConfig {
pub default_boot_always_attempt: bool,
/// Enable vPCI boot (for NVMe)
pub enable_vpci_boot: bool,
/// EFI diagnostics log level filter
pub efi_diagnostics_log_level: EfiDiagnosticsLogLevel,
}

impl Default for UefiConfig {
Expand All @@ -2168,10 +2184,26 @@ impl Default for UefiConfig {
disable_frontpage: true,
default_boot_always_attempt: false,
enable_vpci_boot: false,
efi_diagnostics_log_level: EfiDiagnosticsLogLevel::Default,
}
}
}

/// EFI diagnostics log level filter.
///
/// Controls which UEFI diagnostics log entries are forwarded to the host
/// tracing infrastructure (and thus visible via kmsg / test output).
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum EfiDiagnosticsLogLevel {
/// Default log level (ERROR and WARN only).
#[default]
Default,
/// Include INFO logs (ERROR, WARN, and INFO).
Info,
/// All log levels.
Full,
}

/// Control the logging configuration of OpenVMM/OpenHCL.
#[derive(Debug, Clone)]
pub enum OpenvmmLogConfig {
Expand Down
31 changes: 29 additions & 2 deletions petri/src/vm/openvmm/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use super::PetriVmConfigOpenVmm;
use super::PetriVmResourcesOpenVmm;
use crate::Drive;
use crate::EfiDiagnosticsLogLevel;
use crate::Firmware;
use crate::IsolationType;
use crate::MemoryConfig;
Expand Down Expand Up @@ -552,7 +553,21 @@ impl PetriVmConfigOpenVmm {
debugger_rpc: None,
generation_id_recv: None,
rtc_delta_milliseconds: 0,
efi_diagnostics_log_level: Default::default(), // TODO: Add config for tests
efi_diagnostics_log_level: match firmware
.uefi_config()
.map(|c| c.efi_diagnostics_log_level)
.unwrap_or_default()
{
EfiDiagnosticsLogLevel::Default => {
openvmm_defs::config::EfiDiagnosticsLogLevelType::Default
}
EfiDiagnosticsLogLevel::Info => {
openvmm_defs::config::EfiDiagnosticsLogLevelType::Info
}
EfiDiagnosticsLogLevel::Full => {
openvmm_defs::config::EfiDiagnosticsLogLevelType::Full
}
},
};

// Make the pipette connection listener.
Expand Down Expand Up @@ -774,6 +789,7 @@ impl PetriVmConfigSetupCore<'_> {
disable_frontpage,
default_boot_always_attempt,
enable_vpci_boot,
efi_diagnostics_log_level: _, // applied to top-level Config below
},
},
) => {
Expand Down Expand Up @@ -933,6 +949,7 @@ impl PetriVmConfigSetupCore<'_> {
disable_frontpage,
default_boot_always_attempt,
enable_vpci_boot,
efi_diagnostics_log_level,
},
OpenHclConfig { vmbus_redirect, .. },
) = match self.firmware {
Expand Down Expand Up @@ -985,7 +1002,17 @@ impl PetriVmConfigSetupCore<'_> {
no_persistent_secrets: self.tpm_config.as_ref().is_some_and(|c| c.no_persistent_secrets),
igvm_attest_test_config: None,
test_gsp_by_id,
efi_diagnostics_log_level: Default::default(), // TODO: make configurable
efi_diagnostics_log_level: match efi_diagnostics_log_level {
EfiDiagnosticsLogLevel::Default => {
get_resources::ged::EfiDiagnosticsLogLevelType::Default
}
EfiDiagnosticsLogLevel::Info => {
get_resources::ged::EfiDiagnosticsLogLevelType::Info
}
EfiDiagnosticsLogLevel::Full => {
get_resources::ged::EfiDiagnosticsLogLevelType::Full
}
},
hv_sint_enabled: false,
};

Expand Down
28 changes: 28 additions & 0 deletions vmm_tests/vmm_tests/tests/tests/multiarch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use anyhow::Context;
use futures::StreamExt;
use petri::EfiDiagnosticsLogLevel;
use petri::MemoryConfig;
use petri::PetriHaltReason;
use petri::PetriVmBuilder;
Expand Down Expand Up @@ -480,6 +481,33 @@ async fn efi_diagnostics_no_boot<T: PetriVmmBackend>(
anyhow::bail!("Did not find expected message in kmsg");
}

/// Test EFI diagnostics with INFO-level logging enabled
#[vmm_test_with(noagent(openvmm_openhcl_uefi_x64(none)))]
async fn efi_diagnostics_info_level<T: PetriVmmBackend>(
config: PetriVmBuilder<T>,
) -> anyhow::Result<()> {
let vm = config
.with_uefi_frontpage(true)
.with_efi_diagnostics_log_level(EfiDiagnosticsLogLevel::Info)
.run_without_agent()
.await?;

const INFO_MSG: &str = "DXE IPL Entry";

let mut kmsg = vm.kmsg().await?;

while let Some(data) = kmsg.next().await {
let data = data.context("reading kmsg")?;
let msg = kmsg::KmsgParsedEntry::new(&data).unwrap();
let raw = msg.message.as_raw();
if raw.contains(INFO_MSG) {
return Ok(());
}
}

anyhow::bail!("Did not find expected INFO-level UEFI diagnostics message {INFO_MSG:?} in kmsg");
}

/// Boot our guest-test UEFI image, which will run some tests,
/// and then purposefully triple fault itself via an expiring
/// watchdog timer.
Expand Down
Loading