diff --git a/kernel/src/cpu/vc.rs b/kernel/src/cpu/vc.rs index de135ae68..b8721a357 100644 --- a/kernel/src/cpu/vc.rs +++ b/kernel/src/cpu/vc.rs @@ -21,7 +21,7 @@ use crate::sev::ghcb::GHCB; use core::fmt; #[cfg(test)] -use crate::testing::is_qemu_test_env; +use crate::testing::{is_qemu_test_env, is_test_platform_type}; pub const SVM_EXIT_EXCP_BASE: usize = 0x40; pub const SVM_EXIT_LAST_EXCP: usize = 0x5f; @@ -308,6 +308,7 @@ mod tests { use crate::cpu::msr::{rdtsc, rdtscp, read_msr, write_msr, RdtscpOut}; use crate::sev::ghcb::GHCB; use crate::sev::utils::{get_dr7, raw_vmmcall, set_dr7}; + use bootlib::platform::SvsmPlatformType; use core::arch::asm; use core::arch::x86_64::__cpuid_count; @@ -323,15 +324,17 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_has_amd_cpuid() { - const CPUID_VENDOR_INFO: u32 = 0; + if is_test_platform_type(SvsmPlatformType::Snp) { + const CPUID_VENDOR_INFO: u32 = 0; - let vendor_info = unsafe { __cpuid_count(CPUID_VENDOR_INFO, 0) }; + let vendor_info = unsafe { __cpuid_count(CPUID_VENDOR_INFO, 0) }; - let vendor_name_bytes = [vendor_info.ebx, vendor_info.edx, vendor_info.ecx] - .map(|v| v.to_le_bytes()) - .concat(); + let vendor_name_bytes = [vendor_info.ebx, vendor_info.edx, vendor_info.ecx] + .map(|v| v.to_le_bytes()) + .concat(); - assert_eq!(core::str::from_utf8(&vendor_name_bytes), Ok("AuthenticAMD")); + assert_eq!(core::str::from_utf8(&vendor_name_bytes), Ok("AuthenticAMD")); + } } const GHCB_FILL_TEST_VALUE: u8 = b'1'; @@ -445,7 +448,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_port_io_8() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const TEST_VAL: u8 = 0x12; verify_ghcb_gets_altered(|| outb(TESTDEV_ECHO_LAST_PORT, TEST_VAL)); assert_eq!( @@ -458,7 +461,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_port_io_16() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const TEST_VAL: u16 = 0x4321; verify_ghcb_gets_altered(|| outw(TESTDEV_ECHO_LAST_PORT, TEST_VAL)); assert_eq!( @@ -471,7 +474,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_port_io_32() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const TEST_VAL: u32 = 0xabcd1234; verify_ghcb_gets_altered(|| outl(TESTDEV_ECHO_LAST_PORT, TEST_VAL)); assert_eq!( @@ -484,7 +487,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_port_io_8_hardcoded() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const TEST_VAL: u8 = 0x12; verify_ghcb_gets_altered(|| outb_to_testdev_echo(TEST_VAL)); assert_eq!(TEST_VAL, verify_ghcb_gets_altered(inb_from_testdev_echo)); @@ -494,7 +497,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_port_io_16_hardcoded() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const TEST_VAL: u16 = 0x4321; verify_ghcb_gets_altered(|| outw_to_testdev_echo(TEST_VAL)); assert_eq!(TEST_VAL, verify_ghcb_gets_altered(inw_from_testdev_echo)); @@ -504,7 +507,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_port_io_32_hardcoded() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const TEST_VAL: u32 = 0xabcd1234; verify_ghcb_gets_altered(|| outl_to_testdev_echo(TEST_VAL)); assert_eq!(TEST_VAL, verify_ghcb_gets_altered(inl_from_testdev_echo)); @@ -514,7 +517,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_port_io_string_16_get_last() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const TEST_DATA: &[u16] = &[0x1234, 0x5678, 0x9abc, 0xdef0]; verify_ghcb_gets_altered(|| rep_outsw(TESTDEV_ECHO_LAST_PORT, TEST_DATA)); assert_eq!( @@ -533,11 +536,13 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_sev_snp_enablement_msr() { - const MSR_SEV_STATUS: u32 = 0xc0010131; - const MSR_SEV_STATUS_SEV_SNP_ENABLED: u64 = 0b10; + if is_test_platform_type(SvsmPlatformType::Snp) { + const MSR_SEV_STATUS: u32 = 0xc0010131; + const MSR_SEV_STATUS_SEV_SNP_ENABLED: u64 = 0b10; - let sev_status = read_msr(MSR_SEV_STATUS); - assert_ne!(sev_status & MSR_SEV_STATUS_SEV_SNP_ENABLED, 0); + let sev_status = read_msr(MSR_SEV_STATUS); + assert_ne!(sev_status & MSR_SEV_STATUS_SEV_SNP_ENABLED, 0); + } } const MSR_APIC_BASE: u32 = 0x1b; @@ -548,7 +553,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_rdmsr_apic() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { let apic_base = verify_ghcb_gets_altered(|| read_msr(MSR_APIC_BASE)); assert_eq!(apic_base & APIC_BASE_PHYS_ADDR_MASK, APIC_DEFAULT_PHYS_BASE); } @@ -557,7 +562,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_rdmsr_debug_ctl() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const MSR_DEBUG_CTL: u32 = 0x1d9; let apic_base = verify_ghcb_gets_altered(|| read_msr(MSR_DEBUG_CTL)); assert_eq!(apic_base, 0); @@ -569,7 +574,7 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_wrmsr_tsc_aux() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { let test_val = 0x1234; verify_ghcb_gets_altered(|| write_msr(MSR_TSC_AUX, test_val)); let readback = verify_ghcb_gets_altered(|| read_msr(MSR_TSC_AUX)); @@ -589,7 +594,7 @@ mod tests { // #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] #[ignore = "Currently unhandled by #VC handler"] fn test_vmmcall_vapic_poll_irq() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const VMMCALL_HC_VAPIC_POLL_IRQ: u32 = 1; let res = verify_ghcb_gets_altered(|| unsafe { @@ -603,7 +608,7 @@ mod tests { // #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] #[ignore = "Currently unhandled by #VC handler"] fn test_read_write_dr7() { - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { const DR7_DEFAULT: u64 = 0x400; const DR7_TEST: u64 = 0x401; @@ -630,21 +635,23 @@ mod tests { #[test] #[cfg_attr(not(test_in_svsm), ignore = "Can only be run inside guest")] fn test_rdtscp() { - let expected_pid = u32::try_from(verify_ghcb_gets_altered(|| read_msr(MSR_TSC_AUX))) - .expect("pid should be 32 bits"); - let RdtscpOut { - timestamp: mut prev, - pid, - } = rdtscp(); - assert_eq!(pid, expected_pid); - for _ in 0..50 { + if is_test_platform_type(SvsmPlatformType::Snp) { + let expected_pid = u32::try_from(verify_ghcb_gets_altered(|| read_msr(MSR_TSC_AUX))) + .expect("pid should be 32 bits"); let RdtscpOut { - timestamp: cur, + timestamp: mut prev, pid, } = rdtscp(); assert_eq!(pid, expected_pid); - assert!(cur > prev); - prev = cur; + for _ in 0..50 { + let RdtscpOut { + timestamp: cur, + pid, + } = rdtscp(); + assert_eq!(pid, expected_pid); + assert!(cur > prev); + prev = cur; + } } } diff --git a/kernel/src/greq/services.rs b/kernel/src/greq/services.rs index 87a489a60..946bccdae 100644 --- a/kernel/src/greq/services.rs +++ b/kernel/src/greq/services.rs @@ -120,11 +120,14 @@ mod tests { extern crate alloc; use crate::serial::Terminal; - use crate::testing::{assert_eq_warn, is_qemu_test_env, svsm_test_io, IORequest}; + use crate::testing::{ + assert_eq_warn, is_qemu_test_env, is_test_platform_type, svsm_test_io, IORequest, + }; use alloc::vec; + use bootlib::platform::SvsmPlatformType; - if is_qemu_test_env() { + if is_qemu_test_env() && is_test_platform_type(SvsmPlatformType::Snp) { let sp = svsm_test_io().unwrap(); sp.put_byte(IORequest::GetLaunchMeasurement as u8); diff --git a/kernel/src/platform/mod.rs b/kernel/src/platform/mod.rs index 890b5e3a0..a1557f077 100644 --- a/kernel/src/platform/mod.rs +++ b/kernel/src/platform/mod.rs @@ -60,6 +60,9 @@ pub enum PageValidateOp { /// This defines a platform abstraction to permit the SVSM to run on different /// underlying architectures. pub trait SvsmPlatform { + #[cfg(test)] + fn platform_type(&self) -> SvsmPlatformType; + /// Halts the system as required by the platform. fn halt() where diff --git a/kernel/src/platform/native.rs b/kernel/src/platform/native.rs index b90fb24e9..cefcc3ec7 100644 --- a/kernel/src/platform/native.rs +++ b/kernel/src/platform/native.rs @@ -20,6 +20,9 @@ use crate::utils::MemoryRegion; #[cfg(debug_assertions)] use crate::mm::virt_to_phys; +#[cfg(test)] +use bootlib::platform::SvsmPlatformType; + const APIC_MSR_EOI: u32 = 0x80B; const APIC_MSR_ICR: u32 = 0x830; @@ -43,6 +46,11 @@ impl Default for NativePlatform { } impl SvsmPlatform for NativePlatform { + #[cfg(test)] + fn platform_type(&self) -> SvsmPlatformType { + SvsmPlatformType::Native + } + fn env_setup(&mut self, debug_serial_port: u16, _vtom: usize) -> Result<(), SvsmError> { // In the native platform, console output does not require the use of // any platform services, so it can be initialized immediately. diff --git a/kernel/src/platform/snp.rs b/kernel/src/platform/snp.rs index 4f734f5bb..ee4ae66ce 100644 --- a/kernel/src/platform/snp.rs +++ b/kernel/src/platform/snp.rs @@ -35,6 +35,9 @@ use crate::utils::MemoryRegion; use core::sync::atomic::{AtomicBool, AtomicU32, Ordering}; +#[cfg(test)] +use bootlib::platform::SvsmPlatformType; + static SVSM_ENV_INITIALIZED: AtomicBool = AtomicBool::new(false); static GHCB_IO_DRIVER: GHCBIOPort = GHCBIOPort::new(); @@ -93,6 +96,11 @@ impl Default for SnpPlatform { } impl SvsmPlatform for SnpPlatform { + #[cfg(test)] + fn platform_type(&self) -> SvsmPlatformType { + SvsmPlatformType::Snp + } + fn env_setup(&mut self, _debug_serial_port: u16, vtom: usize) -> Result<(), SvsmError> { sev_status_init(); VTOM.init(&vtom).map_err(|_| SvsmError::PlatformInit)?; diff --git a/kernel/src/platform/tdp.rs b/kernel/src/platform/tdp.rs index 7ad4f43d0..8fde2f872 100644 --- a/kernel/src/platform/tdp.rs +++ b/kernel/src/platform/tdp.rs @@ -21,6 +21,9 @@ use crate::types::{PageSize, PAGE_SIZE}; use crate::utils::immut_after_init::ImmutAfterInitCell; use crate::utils::{is_aligned, MemoryRegion}; +#[cfg(test)] +use bootlib::platform::SvsmPlatformType; + static GHCI_IO_DRIVER: GHCIIOPort = GHCIIOPort::new(); static VTOM: ImmutAfterInitCell = ImmutAfterInitCell::uninit(); @@ -40,6 +43,11 @@ impl Default for TdpPlatform { } impl SvsmPlatform for TdpPlatform { + #[cfg(test)] + fn platform_type(&self) -> SvsmPlatformType { + SvsmPlatformType::Tdp + } + fn halt() { tdvmcall_halt(); } diff --git a/kernel/src/testing.rs b/kernel/src/testing.rs index b8f9108fb..a14e793a8 100644 --- a/kernel/src/testing.rs +++ b/kernel/src/testing.rs @@ -1,3 +1,4 @@ +use bootlib::platform::SvsmPlatformType; use core::arch::asm; use core::sync::atomic::{AtomicBool, Ordering}; use log::info; @@ -36,6 +37,10 @@ pub fn is_qemu_test_env() -> bool { QEMU_TEST_ENV.load(Ordering::Acquire) } +pub fn is_test_platform_type(platform_type: SvsmPlatformType) -> bool { + SVSM_PLATFORM.platform_type() == platform_type +} + pub fn set_qemu_test_env() { QEMU_TEST_ENV.store(true, Ordering::Release) }