From b67656a3ace7ebf6569f90a4792d0c1b6a7b6aa3 Mon Sep 17 00:00:00 2001 From: Pavel Mores Date: Tue, 4 Mar 2025 14:05:52 +0100 Subject: [PATCH] runtime-rs: get SEV params using CPUID and store them in SevSnpDetails An implementation of cbitpos acquisition is supplied that was missing so far. We also get the physical address reduction value from the same source (CPUID Fn8000_001f function). This has been hardcoded at 1 so far, following the Go runtime example, but it's better to get it from the processor. Signed-off-by: Pavel Mores --- src/libs/kata-sys-util/src/protection.rs | 37 ++++++++++++++++--- .../hypervisor/ch-config/src/convert.rs | 10 ++++- .../crates/hypervisor/ch-config/src/lib.rs | 10 ++++- .../hypervisor/src/ch/inner_hypervisor.rs | 10 ++++- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/libs/kata-sys-util/src/protection.rs b/src/libs/kata-sys-util/src/protection.rs index 223a971e84..15d8dff986 100644 --- a/src/libs/kata-sys-util/src/protection.rs +++ b/src/libs/kata-sys-util/src/protection.rs @@ -6,6 +6,8 @@ #[cfg(any(target_arch = "s390x", target_arch = "x86_64", target_arch = "aarch64"))] use anyhow::Result; use serde::{Deserialize, Serialize}; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64; use std::fmt; #[cfg(all(target_arch = "powerpc64", target_endian = "little"))] use std::fs; @@ -26,6 +28,7 @@ use std::fs; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct SevSnpDetails { pub cbitpos: u32, + pub phys_addr_reduction: u32, } #[allow(dead_code)] @@ -117,17 +120,39 @@ pub fn arch_guest_protection( Ok(false) }; - let retrieve_sev_cbitpos = || -> Result { - Err(ProtectionError::CheckFailed( - "cbitpos retrieval NOT IMPLEMENTED YET".to_owned(), - )) + let retrieve_sev_params = || -> Result<(u32, u32), ProtectionError> { + // The initial checks for AMD and SEV shouldn't be necessary due to + // the context this function is currently called from, however it + // shouldn't hurt to double-check and have better logging if anything + // goes wrong. + + let fn0 = unsafe { x86_64::__cpuid(0) }; + // The values in [ ebx, edx, ecx ] spell out "AuthenticAMD" when + // interpreted byte-wise as ASCII. No need to bother here with an + // actual conversion to string though. + // See also AMD64 Architecture Programmer's Manual pg. 600 + // https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24594.pdf + if fn0.ebx != 0x68747541 || fn0.edx != 0x69746e65 || fn0.ecx != 0x444d4163 { + return Err(ProtectionError::CheckFailed("Not an AMD processor".to_owned())); + } + + // AMD64 Architecture Prgrammer's Manual Fn8000_001f docs on pg. 640 + let fn8000_001f = unsafe { x86_64::__cpuid(0x8000_001f) }; + if fn8000_001f.eax & 0x10 == 0 { + return Err(ProtectionError::CheckFailed("SEV not supported".to_owned())); + } + + let cbitpos = fn8000_001f.ebx & 0b11_1111; + let phys_addr_reduction = (fn8000_001f.ebx & 0b1111_1100_0000) >> 6; + + Ok((cbitpos, phys_addr_reduction)) }; let is_snp_available = check_contents(snp_path)?; let is_sev_available = is_snp_available || check_contents(sev_path)?; if is_snp_available || is_sev_available { - let cbitpos = retrieve_sev_cbitpos()?; - let sev_snp_details = SevSnpDetails { cbitpos }; + let (cbitpos, phys_addr_reduction) = retrieve_sev_params()?; + let sev_snp_details = SevSnpDetails { cbitpos, phys_addr_reduction }; return Ok(if is_snp_available { GuestProtection::Snp(sev_snp_details) } else { diff --git a/src/runtime-rs/crates/hypervisor/ch-config/src/convert.rs b/src/runtime-rs/crates/hypervisor/ch-config/src/convert.rs index 49cdcf4b59..3552e169fe 100644 --- a/src/runtime-rs/crates/hypervisor/ch-config/src/convert.rs +++ b/src/runtime-rs/crates/hypervisor/ch-config/src/convert.rs @@ -2144,7 +2144,15 @@ mod tests { #[test] fn test_check_tdx_rootfs_settings() { - let sev_snp_details = SevSnpDetails { cbitpos: 42 }; + let tdx_details = TDXDetails { + major_version: 1, + minor_version: 0, + }; + + let sev_snp_details = SevSnpDetails { + cbitpos: 42, + phys_addr_reduction: 42, + }; #[derive(Debug)] struct TestData<'a> { diff --git a/src/runtime-rs/crates/hypervisor/ch-config/src/lib.rs b/src/runtime-rs/crates/hypervisor/ch-config/src/lib.rs index 54f74648f1..742aafa7e1 100644 --- a/src/runtime-rs/crates/hypervisor/ch-config/src/lib.rs +++ b/src/runtime-rs/crates/hypervisor/ch-config/src/lib.rs @@ -539,7 +539,15 @@ mod tests { #[test] fn test_guest_protection_is_tdx() { - let sev_snp_details = SevSnpDetails { cbitpos: 42 }; + let tdx_details = TDXDetails { + major_version: 1, + minor_version: 0, + }; + + let sev_snp_details = SevSnpDetails { + cbitpos: 42, + phys_addr_reduction: 42, + }; #[derive(Debug)] struct TestData { diff --git a/src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs b/src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs index 768029608d..fb02ce9c42 100644 --- a/src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs +++ b/src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs @@ -1110,7 +1110,15 @@ mod tests { // available_guest_protection() requires super user privs. skip_if_not_root!(); - let sev_snp_details = SevSnpDetails { cbitpos: 42 }; + let tdx_details = TDXDetails { + major_version: 1, + minor_version: 0, + }; + + let sev_snp_details = SevSnpDetails { + cbitpos: 42, + phys_addr_reduction: 42, + }; #[derive(Debug)] struct TestData {