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