Skip to content

Commit

Permalink
Query hypervisor GHCB features during SVSM startup
Browse files Browse the repository at this point in the history
This is used to verify that the hypervisor implements all of the GHCB
features required (since not all of them are guaranteed by virtue of
supporting version 2 of the GHCB protocol) and captures any optional
features that may influence SVSM behavior.

Signed-off-by: Jon Lange <jlange@microsoft.com>
  • Loading branch information
msft-jlange committed Jan 3, 2024
1 parent 3ac60e0 commit f645156
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/sev/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod vmsa;

pub mod utils;

pub use msr_protocol::init_hypervisor_ghcb_features;
pub use status::sev_status_init;
pub use status::sev_status_verify;
pub use status::{sev_es_enabled, sev_snp_enabled};
Expand Down
63 changes: 63 additions & 0 deletions src/sev/msr_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ use crate::address::{Address, PhysAddr};
use crate::cpu::msr::{read_msr, write_msr, SEV_GHCB};
use crate::error::SvsmError;
use crate::utils::halt;
use crate::utils::immut_after_init::ImmutAfterInitCell;

use super::utils::raw_vmgexit;

use bitflags::bitflags;
use core::fmt;
use core::fmt::Display;

#[derive(Clone, Copy, Debug)]
pub enum GhcbMsrError {
// The info section of the response did not match our request
Expand All @@ -37,9 +42,32 @@ impl GHCBMsr {
pub const SNP_REG_GHCB_GPA_RESP: u64 = 0x13;
pub const SNP_STATE_CHANGE_REQ: u64 = 0x14;
pub const SNP_STATE_CHANGE_RESP: u64 = 0x15;
pub const SNP_HV_FEATURES_REQ: u64 = 0x80;
pub const SNP_HV_FEATURES_RESP: u64 = 0x81;
pub const TERM_REQ: u64 = 0x100;
}

bitflags! {
#[derive(Clone, Copy, Debug)]
pub struct GHCBHvFeatures: u64 {
const SEV_SNP = 1 << 0;
const SEV_SNP_AP_CREATION = 1 << 1;
const SEV_SNP_RESTR_INJ = 1 << 2;
const SEV_SNP_RESTR_INJ_TIMER = 1 << 3;
const APIC_ID_LIST = 1 << 4;
const SEV_SNP_MULTI_VMPL = 1 << 5;
const SEV_PAGE_STATE_CHANGE = 1 << 6;
}
}

impl Display for GHCBHvFeatures {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_fmt(format_args!("{:#x}", self.bits()))
}
}

static GHCB_HV_FEATURES: ImmutAfterInitCell<GHCBHvFeatures> = ImmutAfterInitCell::uninit();

/// Check that we support the hypervisor's advertised GHCB versions.
pub fn verify_ghcb_version() {
// Request SEV information.
Expand All @@ -66,6 +94,41 @@ pub fn verify_ghcb_version() {
);
}

pub fn hypervisor_ghcb_features() -> GHCBHvFeatures {
*GHCB_HV_FEATURES
}

pub fn init_hypervisor_ghcb_features() -> Result<(), GhcbMsrError> {
write_msr(SEV_GHCB, GHCBMsr::SNP_HV_FEATURES_REQ);
raw_vmgexit();
let result = read_msr(SEV_GHCB);
if (result & 0xFFF) == GHCBMsr::SNP_HV_FEATURES_RESP {
let features = GHCBHvFeatures::from_bits_truncate(result >> 12);

// Verify that the required features are supported.
let required = GHCBHvFeatures::SEV_SNP
| GHCBHvFeatures::SEV_SNP_AP_CREATION
| GHCBHvFeatures::SEV_SNP_MULTI_VMPL;
let missing = !features & required;
if !missing.is_empty() {
log::error!(
"Required hypervisor GHCB features not available: present={:#x}, required={:#x}, missing={:#x}",
features, required, missing
);
// FIXME - enforce this panic once KVM advertises the required
// features.
// panic!("Required hypervisor GHCB features not available");
}

GHCB_HV_FEATURES
.init(&features)
.expect("Already initialized GHCB HV features");
Ok(())
} else {
Err(GhcbMsrError::InfoMismatch)
}
}

pub fn register_ghcb_gpa_msr(addr: PhysAddr) -> Result<(), GhcbMsrError> {
let mut info = addr.bits() as u64;

Expand Down
4 changes: 3 additions & 1 deletion src/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ use svsm::mm::{init_kernel_mapping_info, PerCPUPageMappingGuard};
use svsm::requests::{request_loop, update_mappings};
use svsm::serial::SerialPort;
use svsm::sev::secrets_page::{copy_secrets_page, disable_vmpck0, SecretsPage};
use svsm::sev::sev_status_init;
use svsm::sev::utils::{rmp_adjust, RMPFlags};
use svsm::sev::{init_hypervisor_ghcb_features, sev_status_init};
use svsm::svsm_console::SVSMIOPort;
use svsm::svsm_paging::{init_page_table, invalidate_early_boot_memory};
use svsm::task::{create_task, TASK_FLAG_SHARE_PT};
Expand Down Expand Up @@ -419,6 +419,8 @@ pub extern "C" fn svsm_main() {
// a remote GDB connection
//debug_break();

init_hypervisor_ghcb_features().expect("Failed to obtain hypervisor GHCB features");

let launch_info = &*LAUNCH_INFO;
let config = if launch_info.igvm_params_virt_addr != 0 {
let igvm_params = IgvmParams::new(VirtAddr::from(launch_info.igvm_params_virt_addr));
Expand Down

0 comments on commit f645156

Please sign in to comment.