Skip to content

Commit

Permalink
Merge pull request #202 from msft-jlange/ghcb_features
Browse files Browse the repository at this point in the history
Query hypervisor GHCB features during SVSM startup
  • Loading branch information
joergroedel authored Jan 10, 2024
2 parents 02953a0 + f645156 commit 5e09a94
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 @@ -390,6 +390,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 5e09a94

Please sign in to comment.