arch, hypervisor, vmm: Patch CPUID subleaves to expose EPC sections

The support for SGX is exposed to the guest through CPUID 0x12. KVM
passes static subleaves 0 and 1 from the host to the guest, without
needing any modification from the VMM itself.

But SGX also relies on dynamic subleaves 2 through N, used for
describing each EPC section. This is not handled by KVM, which means
the VMM is in charge of setting each subleaf starting from index 2
up to index N, depending on the number of EPC sections.

These subleaves 2 through N are not listed as part of the supported
CPUID entries from KVM. But it's important to set them as long as index
0 and 1 are present and indicate that SGX is supported.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2020-07-08 16:58:10 +02:00
committed by Samuel Ortiz
parent 1603786374
commit e10d9b13d4
7 changed files with 156 additions and 13 deletions

View File

@@ -22,6 +22,8 @@ use acpi_tables::{aml, aml::Aml, sdt::SDT};
use anyhow::anyhow;
#[cfg(feature = "acpi")]
use arch::layout;
#[cfg(target_arch = "x86_64")]
use arch::x86_64::SgxEpcSection;
use arch::EntryPoint;
#[cfg(target_arch = "x86_64")]
use arch::{CpuidPatch, CpuidReg};
@@ -589,9 +591,17 @@ impl CpuManager {
let mut vcpu_states = Vec::with_capacity(usize::from(config.max_vcpus));
vcpu_states.resize_with(usize::from(config.max_vcpus), VcpuState::default);
let device_manager = device_manager.lock().unwrap();
#[cfg(target_arch = "x86_64")]
let cpuid = CpuManager::patch_cpuid(hypervisor, &config.topology)?;
let sgx_epc_sections =
if let Some(sgx_epc_region) = memory_manager.lock().unwrap().sgx_epc_region() {
Some(sgx_epc_region.epc_sections().clone())
} else {
None
};
#[cfg(target_arch = "x86_64")]
let cpuid = CpuManager::patch_cpuid(hypervisor, &config.topology, sgx_epc_sections)?;
let device_manager = device_manager.lock().unwrap();
let cpu_manager = Arc::new(Mutex::new(CpuManager {
config: config.clone(),
#[cfg(target_arch = "x86_64")]
@@ -633,6 +643,7 @@ impl CpuManager {
fn patch_cpuid(
hypervisor: Arc<dyn hypervisor::Hypervisor>,
topology: &Option<CpuTopology>,
sgx_epc_sections: Option<Vec<SgxEpcSection>>,
) -> Result<CpuId> {
let mut cpuid_patches = Vec::new();
@@ -674,6 +685,10 @@ impl CpuManager {
);
}
if let Some(sgx_epc_sections) = sgx_epc_sections {
arch::x86_64::update_cpuid_sgx(&mut cpuid, sgx_epc_sections).unwrap();
}
Ok(cpuid)
}