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