xref: /cloud-hypervisor/hypervisor/src/kvm/x86_64/mod.rs (revision 7d7bfb2034001d4cb15df2ddc56d2d350c8da30f)
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