1 // Copyright © 2019 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 4 // 5 // Copyright © 2020, Microsoft Corporation 6 // 7 // Copyright 2018-2019 CrowdStrike, Inc. 8 // 9 // 10 11 use crate::arch::x86::{msr_index, SegmentRegisterOps, MTRR_ENABLE, MTRR_MEM_TYPE_WB}; 12 use crate::kvm::{Cap, Kvm, KvmError, KvmResult}; 13 use serde_derive::{Deserialize, Serialize}; 14 15 /// 16 /// Export generically-named wrappers of kvm-bindings for Unix-based platforms 17 /// 18 pub use { 19 kvm_bindings::kvm_cpuid_entry2 as CpuIdEntry, kvm_bindings::kvm_dtable as DescriptorTable, 20 kvm_bindings::kvm_fpu as FpuState, kvm_bindings::kvm_lapic_state as LapicState, 21 kvm_bindings::kvm_mp_state as MpState, kvm_bindings::kvm_msr_entry as MsrEntry, 22 kvm_bindings::kvm_regs as StandardRegisters, kvm_bindings::kvm_segment as SegmentRegister, 23 kvm_bindings::kvm_sregs as SpecialRegisters, kvm_bindings::kvm_vcpu_events as VcpuEvents, 24 kvm_bindings::kvm_xcrs as ExtendedControlRegisters, kvm_bindings::kvm_xsave as Xsave, 25 kvm_bindings::CpuId, kvm_bindings::MsrList, kvm_bindings::Msrs as MsrEntries, 26 kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX as CPUID_FLAG_VALID_INDEX, 27 }; 28 29 impl SegmentRegisterOps for SegmentRegister { 30 fn segment_type(&self) -> u8 { 31 self.type_ 32 } 33 fn set_segment_type(&mut self, val: u8) { 34 self.type_ = val; 35 } 36 37 fn dpl(&self) -> u8 { 38 self.dpl 39 } 40 41 fn set_dpl(&mut self, val: u8) { 42 self.dpl = val; 43 } 44 45 fn present(&self) -> u8 { 46 self.present 47 } 48 49 fn set_present(&mut self, val: u8) { 50 self.present = val; 51 } 52 53 fn long(&self) -> u8 { 54 self.l 55 } 56 57 fn set_long(&mut self, val: u8) { 58 self.l = val; 59 } 60 61 fn avl(&self) -> u8 { 62 self.avl 63 } 64 65 fn set_avl(&mut self, val: u8) { 66 self.avl = val; 67 } 68 69 fn desc_type(&self) -> u8 { 70 self.s 71 } 72 73 fn set_desc_type(&mut self, val: u8) { 74 self.s = val; 75 } 76 77 fn granularity(&self) -> u8 { 78 self.g 79 } 80 81 fn set_granularity(&mut self, val: u8) { 82 self.g = val; 83 } 84 85 fn db(&self) -> u8 { 86 self.db 87 } 88 89 fn set_db(&mut self, val: u8) { 90 self.db = val; 91 } 92 } 93 94 pub fn boot_msr_entries() -> MsrEntries { 95 MsrEntries::from_entries(&[ 96 msr!(msr_index::MSR_IA32_SYSENTER_CS), 97 msr!(msr_index::MSR_IA32_SYSENTER_ESP), 98 msr!(msr_index::MSR_IA32_SYSENTER_EIP), 99 msr!(msr_index::MSR_STAR), 100 msr!(msr_index::MSR_CSTAR), 101 msr!(msr_index::MSR_LSTAR), 102 msr!(msr_index::MSR_KERNEL_GS_BASE), 103 msr!(msr_index::MSR_SYSCALL_MASK), 104 msr!(msr_index::MSR_IA32_TSC), 105 msr_data!( 106 msr_index::MSR_IA32_MISC_ENABLE, 107 msr_index::MSR_IA32_MISC_ENABLE_FAST_STRING as u64 108 ), 109 msr_data!(msr_index::MSR_MTRRdefType, MTRR_ENABLE | MTRR_MEM_TYPE_WB), 110 ]) 111 .unwrap() 112 } 113 114 /// 115 /// Check KVM extension for Linux 116 /// 117 pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> { 118 if !kvm.check_extension(Cap::SignalMsi) { 119 return Err(KvmError::CapabilityMissing(Cap::SignalMsi)); 120 } 121 if !kvm.check_extension(Cap::TscDeadlineTimer) { 122 return Err(KvmError::CapabilityMissing(Cap::TscDeadlineTimer)); 123 } 124 if !kvm.check_extension(Cap::SplitIrqchip) { 125 return Err(KvmError::CapabilityMissing(Cap::SplitIrqchip)); 126 } 127 if !kvm.check_extension(Cap::SetIdentityMapAddr) { 128 return Err(KvmError::CapabilityMissing(Cap::SetIdentityMapAddr)); 129 } 130 if !kvm.check_extension(Cap::SetTssAddr) { 131 return Err(KvmError::CapabilityMissing(Cap::SetTssAddr)); 132 } 133 if !kvm.check_extension(Cap::ImmediateExit) { 134 return Err(KvmError::CapabilityMissing(Cap::ImmediateExit)); 135 } 136 Ok(()) 137 } 138 #[derive(Clone, Serialize, Deserialize)] 139 pub struct VcpuKvmState { 140 pub cpuid: CpuId, 141 pub msrs: MsrEntries, 142 pub vcpu_events: VcpuEvents, 143 pub regs: StandardRegisters, 144 pub sregs: SpecialRegisters, 145 pub fpu: FpuState, 146 pub lapic_state: LapicState, 147 pub xsave: Xsave, 148 pub xcrs: ExtendedControlRegisters, 149 pub mp_state: MpState, 150 } 151