-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ghcb: disable interrupts around VMGEXIT
Issuing a GHCB call via VMGEXIT requires setting and potentially reading the GHCB MSR. Since GHCB calls can be issued by interrupt routines, interrupts must be disabled during each set-exit-read sequence to prevent possible tearing due to preemption during such a sequence. Signed-off-by: Jon Lange <[email protected]>
- Loading branch information
1 parent
619f93e
commit db2d8cf
Showing
3 changed files
with
49 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,9 @@ | |
// Author: Joerg Roedel <[email protected]> | ||
|
||
use crate::address::{Address, PhysAddr}; | ||
use crate::cpu::irq_state::raw_irqs_disable; | ||
use crate::cpu::msr::{read_msr, write_msr, SEV_GHCB}; | ||
use crate::cpu::{irqs_enabled, IrqGuard}; | ||
use crate::error::SvsmError; | ||
use crate::utils::halt; | ||
use crate::utils::immut_after_init::ImmutAfterInitCell; | ||
|
@@ -71,9 +73,15 @@ static GHCB_HV_FEATURES: ImmutAfterInitCell<GHCBHvFeatures> = ImmutAfterInitCell | |
|
||
/// Check that we support the hypervisor's advertised GHCB versions. | ||
pub fn verify_ghcb_version() { | ||
// This function is normally only called early during initializtion before | ||
// interrupts have been enabled, and before interrupt guards can safely be | ||
// used. | ||
assert!(!irqs_enabled()); | ||
// Request SEV information. | ||
write_msr(SEV_GHCB, GHCBMsr::SEV_INFO_REQ); | ||
raw_vmgexit(); | ||
unsafe { | ||
raw_vmgexit(); | ||
} | ||
let sev_info = read_msr(SEV_GHCB); | ||
|
||
// Parse the results. | ||
|
@@ -100,9 +108,13 @@ pub fn hypervisor_ghcb_features() -> GHCBHvFeatures { | |
} | ||
|
||
pub fn init_hypervisor_ghcb_features() -> Result<(), GhcbMsrError> { | ||
let guard = IrqGuard::new(); | ||
write_msr(SEV_GHCB, GHCBMsr::SNP_HV_FEATURES_REQ); | ||
raw_vmgexit(); | ||
unsafe { | ||
raw_vmgexit(); | ||
} | ||
let result = read_msr(SEV_GHCB); | ||
drop(guard); | ||
if (result & 0xFFF) == GHCBMsr::SNP_HV_FEATURES_RESP { | ||
let features = GHCBHvFeatures::from_bits_truncate(result >> 12); | ||
|
||
|
@@ -134,9 +146,13 @@ pub fn register_ghcb_gpa_msr(addr: PhysAddr) -> Result<(), GhcbMsrError> { | |
let mut info = addr.bits() as u64; | ||
|
||
info |= GHCBMsr::SNP_REG_GHCB_GPA_REQ; | ||
let guard = IrqGuard::new(); | ||
write_msr(SEV_GHCB, info); | ||
raw_vmgexit(); | ||
unsafe { | ||
raw_vmgexit(); | ||
} | ||
info = read_msr(SEV_GHCB); | ||
drop(guard); | ||
|
||
if (info & 0xfff) != GHCBMsr::SNP_REG_GHCB_GPA_RESP { | ||
return Err(GhcbMsrError::InfoMismatch); | ||
|
@@ -159,9 +175,13 @@ fn set_page_valid_status_msr(addr: PhysAddr, valid: bool) -> Result<(), GhcbMsrE | |
} | ||
|
||
info |= GHCBMsr::SNP_STATE_CHANGE_REQ; | ||
let guard = IrqGuard::new(); | ||
write_msr(SEV_GHCB, info); | ||
raw_vmgexit(); | ||
unsafe { | ||
raw_vmgexit(); | ||
} | ||
let response = read_msr(SEV_GHCB); | ||
drop(guard); | ||
|
||
if (response & 0xfff) != GHCBMsr::SNP_STATE_CHANGE_RESP { | ||
return Err(GhcbMsrError::InfoMismatch); | ||
|
@@ -185,8 +205,16 @@ pub fn invalidate_page_msr(addr: PhysAddr) -> Result<(), GhcbMsrError> { | |
pub fn request_termination_msr() -> ! { | ||
let info: u64 = GHCBMsr::TERM_REQ; | ||
|
||
write_msr(SEV_GHCB, info); | ||
raw_vmgexit(); | ||
// Safety | ||
// | ||
// Since this processor is destined for a fatal termination, there is | ||
// no reason to preserve interrupt state. Interrupts can be disabled | ||
// outright prior to shutdown. | ||
unsafe { | ||
raw_irqs_disable(); | ||
write_msr(SEV_GHCB, info); | ||
raw_vmgexit(); | ||
} | ||
loop { | ||
halt(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters