Skip to content

Commit

Permalink
testing: restrict SNP tests to SNP platforms
Browse files Browse the repository at this point in the history
Tests specific to the functionality of SNP platforms (such as #VC
handling and guest request messages) should only be performed on SNP
platforms.

Signed-off-by: Jon Lange <[email protected]>
  • Loading branch information
msft-jlange committed Dec 17, 2024
1 parent 3932161 commit 7873cf3
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 36 deletions.
75 changes: 41 additions & 34 deletions kernel/src/cpu/vc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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';
Expand Down Expand Up @@ -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!(
Expand All @@ -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!(
Expand All @@ -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!(
Expand All @@ -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));
Expand All @@ -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));
Expand All @@ -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));
Expand All @@ -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!(
Expand All @@ -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;
Expand All @@ -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);
}
Expand All @@ -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);
Expand All @@ -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));
Expand All @@ -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 {
Expand All @@ -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;

Expand All @@ -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;
}
}
}

Expand Down
7 changes: 5 additions & 2 deletions kernel/src/greq/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions kernel/src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions kernel/src/platform/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions kernel/src/platform/snp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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)?;
Expand Down
8 changes: 8 additions & 0 deletions kernel/src/platform/tdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<usize> = ImmutAfterInitCell::uninit();

Expand All @@ -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();
}
Expand Down
5 changes: 5 additions & 0 deletions kernel/src/testing.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use bootlib::platform::SvsmPlatformType;
use core::arch::asm;
use core::sync::atomic::{AtomicBool, Ordering};
use log::info;
Expand Down Expand Up @@ -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)
}
Expand Down

0 comments on commit 7873cf3

Please sign in to comment.