From 348def9dfb1243a0538e4432bc48dae691abf68b Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Fri, 3 Dec 2021 14:46:30 +0000 Subject: [PATCH] arch, hypervisor, vmm: Explicitly place the TSS in the 32-bit space Place the 3 page TSS at an explicit location in the 32-bit address space to avoid conflicting with the loaded raw firmware. Signed-off-by: Rob Bradford --- arch/src/x86_64/layout.rs | 7 ++++--- hypervisor/src/kvm/mod.rs | 10 +--------- hypervisor/src/kvm/x86_64/mod.rs | 6 +++--- vmm/src/vm.rs | 22 +++++++++++++++++++--- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/arch/src/x86_64/layout.rs b/arch/src/x86_64/layout.rs index a0e59d0a0..2242f749f 100644 --- a/arch/src/x86_64/layout.rs +++ b/arch/src/x86_64/layout.rs @@ -94,6 +94,10 @@ pub const PCI_MMCONFIG_START: GuestAddress = GuestAddress(MEM_32BIT_DEVICES_START.0 + MEM_32BIT_DEVICES_SIZE); pub const PCI_MMCONFIG_SIZE: u64 = 256 << 20; +// TSS is 3 pages after the PCI MMCONFIG space +pub const KVM_TSS_START: GuestAddress = GuestAddress(PCI_MMCONFIG_START.0 + PCI_MMCONFIG_SIZE); +pub const KVM_TSS_SIZE: u64 = (3 * 4) << 10; + // IOAPIC pub const IOAPIC_START: GuestAddress = GuestAddress(0xfec0_0000); pub const IOAPIC_SIZE: u64 = 0x20; @@ -101,9 +105,6 @@ pub const IOAPIC_SIZE: u64 = 0x20; // APIC pub const APIC_START: GuestAddress = GuestAddress(0xfee0_0000); -/// Address for the TSS setup. -pub const KVM_TSS_ADDRESS: GuestAddress = GuestAddress(0xfffb_d000); - // == End of "32-bit reserved" range. == // ** 64-bit RAM start (start: 4GiB, length: varies) ** diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index f26dc88b3..3c6d5912e 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -32,8 +32,6 @@ use std::result; #[cfg(target_arch = "x86_64")] use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, RwLock}; -#[cfg(target_arch = "x86_64")] -use vm_memory::Address; use vmm_sys_util::eventfd::EventFd; // x86_64 dependencies #[cfg(target_arch = "x86_64")] @@ -47,9 +45,7 @@ use kvm_bindings::{ kvm_enable_cap, kvm_msr_entry, MsrList, KVM_CAP_HYPERV_SYNIC, KVM_CAP_SPLIT_IRQCHIP, }; #[cfg(target_arch = "x86_64")] -use x86_64::{ - check_required_kvm_extensions, FpuState, SpecialRegisters, StandardRegisters, KVM_TSS_ADDRESS, -}; +use x86_64::{check_required_kvm_extensions, FpuState, SpecialRegisters, StandardRegisters}; #[cfg(target_arch = "x86_64")] pub use x86_64::{ CpuId, CpuIdEntry, ExtendedControlRegisters, LapicState, MsrEntries, VcpuKvmState as CpuState, @@ -353,10 +349,6 @@ impl vm::Vm for KvmVm { } #[cfg(target_arch = "x86_64")] fn enable_split_irq(&self) -> vm::Result<()> { - // Set TSS - self.fd - .set_tss_address(KVM_TSS_ADDRESS.raw_value() as usize) - .map_err(|e| vm::HypervisorVmError::EnableSplitIrq(e.into()))?; // Create split irqchip // Only the local APIC is emulated in kernel, both PICs and IOAPIC // are not. diff --git a/hypervisor/src/kvm/x86_64/mod.rs b/hypervisor/src/kvm/x86_64/mod.rs index aa8840d52..3b9973ef3 100644 --- a/hypervisor/src/kvm/x86_64/mod.rs +++ b/hypervisor/src/kvm/x86_64/mod.rs @@ -11,7 +11,6 @@ use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB}; use crate::kvm::{Cap, Kvm, KvmError, KvmResult}; use serde_derive::{Deserialize, Serialize}; -use vm_memory::GuestAddress; /// /// Export generically-named wrappers of kvm-bindings for Unix-based platforms @@ -92,8 +91,6 @@ impl SegmentRegisterOps for SegmentRegister { } } -pub const KVM_TSS_ADDRESS: GuestAddress = GuestAddress(0xfffb_d000); - pub fn boot_msr_entries() -> MsrEntries { MsrEntries::from_entries(&[ msr!(msr_index::MSR_IA32_SYSENTER_CS), @@ -127,6 +124,9 @@ pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> { if !kvm.check_extension(Cap::SplitIrqchip) { return Err(KvmError::CapabilityMissing(Cap::SplitIrqchip)); } + if !kvm.check_extension(Cap::SetTssAddr) { + return Err(KvmError::CapabilityMissing(Cap::SetTssAddr)); + } Ok(()) } #[derive(Clone, Serialize, Deserialize)] diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 03e8681b3..0866d3eb8 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -31,6 +31,8 @@ use crate::{ }; use anyhow::anyhow; use arch::get_host_cpu_phys_bits; +#[cfg(target_arch = "x86_64")] +use arch::layout::KVM_TSS_START; #[cfg(all(feature = "tdx", feature = "acpi"))] use arch::x86_64::tdx::TdVmmDataRegionType; #[cfg(feature = "tdx")] @@ -753,7 +755,11 @@ impl Vm { let vm = hypervisor.create_vm().unwrap(); #[cfg(target_arch = "x86_64")] - vm.enable_split_irq().unwrap(); + { + vm.set_tss_address(KVM_TSS_START.0 as usize).unwrap(); + vm.enable_split_irq().unwrap(); + } + let phys_bits = physical_bits(config.lock().unwrap().cpus.max_phys_bits); #[cfg(target_arch = "x86_64")] @@ -810,8 +816,13 @@ impl Vm { ) -> Result { hypervisor.check_required_extensions().unwrap(); let vm = hypervisor.create_vm().unwrap(); + #[cfg(target_arch = "x86_64")] - vm.enable_split_irq().unwrap(); + { + vm.set_tss_address(KVM_TSS_START.0 as usize).unwrap(); + vm.enable_split_irq().unwrap(); + } + let vm_snapshot = get_vm_snapshot(snapshot).map_err(Error::Restore)?; let config = vm_snapshot.config; if let Some(state) = vm_snapshot.state { @@ -864,8 +875,13 @@ impl Vm { ) -> Result { hypervisor.check_required_extensions().unwrap(); let vm = hypervisor.create_vm().unwrap(); + #[cfg(target_arch = "x86_64")] - vm.enable_split_irq().unwrap(); + { + vm.set_tss_address(KVM_TSS_START.0 as usize).unwrap(); + vm.enable_split_irq().unwrap(); + } + let phys_bits = physical_bits(config.lock().unwrap().cpus.max_phys_bits); let memory_manager = MemoryManager::new(