xref: /cloud-hypervisor/hypervisor/src/kvm/x86_64/mod.rs (revision 68468b8519fe25ad68e6a1fffb86aa534c8f8a72)
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::{
12     CpuIdEntry, DescriptorTable, FpuState, LapicState, MsrEntry, SegmentRegister, SpecialRegisters,
13     XsaveState, CPUID_FLAG_VALID_INDEX,
14 };
15 use crate::kvm::{Cap, Kvm, KvmError, KvmResult};
16 use serde::{Deserialize, Serialize};
17 
18 ///
19 /// Export generically-named wrappers of kvm-bindings for Unix-based platforms
20 ///
21 pub use {
22     kvm_bindings::kvm_cpuid_entry2, kvm_bindings::kvm_dtable, kvm_bindings::kvm_fpu,
23     kvm_bindings::kvm_lapic_state, kvm_bindings::kvm_mp_state as MpState,
24     kvm_bindings::kvm_msr_entry, kvm_bindings::kvm_regs, kvm_bindings::kvm_segment,
25     kvm_bindings::kvm_sregs, kvm_bindings::kvm_vcpu_events as VcpuEvents,
26     kvm_bindings::kvm_xcrs as ExtendedControlRegisters, kvm_bindings::kvm_xsave,
27     kvm_bindings::CpuId, kvm_bindings::MsrList, kvm_bindings::Msrs as MsrEntries,
28     kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX,
29 };
30 
31 ///
32 /// Check KVM extension for Linux
33 ///
34 pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> {
35     macro_rules! check_extension {
36         ($cap:expr) => {
37             if !kvm.check_extension($cap) {
38                 return Err(KvmError::CapabilityMissing($cap));
39             }
40         };
41     }
42 
43     // DeviceCtrl, EnableCap, and SetGuestDebug are also required, but some kernels have
44     // the features implemented without the capability flags.
45     check_extension!(Cap::AdjustClock);
46     check_extension!(Cap::ExtCpuid);
47     check_extension!(Cap::GetTscKhz);
48     check_extension!(Cap::ImmediateExit);
49     check_extension!(Cap::Ioeventfd);
50     check_extension!(Cap::Irqchip);
51     check_extension!(Cap::Irqfd);
52     check_extension!(Cap::IrqRouting);
53     check_extension!(Cap::MpState);
54     check_extension!(Cap::SetIdentityMapAddr);
55     check_extension!(Cap::SetTssAddr);
56     check_extension!(Cap::SplitIrqchip);
57     check_extension!(Cap::TscDeadlineTimer);
58     check_extension!(Cap::UserMemory);
59     check_extension!(Cap::UserNmi);
60     check_extension!(Cap::VcpuEvents);
61     check_extension!(Cap::Xcrs);
62     check_extension!(Cap::Xsave);
63     Ok(())
64 }
65 
66 #[derive(Clone, Serialize, Deserialize)]
67 pub struct VcpuKvmState {
68     pub cpuid: Vec<CpuIdEntry>,
69     pub msrs: Vec<MsrEntry>,
70     pub vcpu_events: VcpuEvents,
71     pub regs: kvm_regs,
72     pub sregs: kvm_sregs,
73     pub fpu: FpuState,
74     pub lapic_state: LapicState,
75     pub xsave: XsaveState,
76     pub xcrs: ExtendedControlRegisters,
77     pub mp_state: MpState,
78     pub tsc_khz: Option<u32>,
79 }
80 
81 impl From<SegmentRegister> for kvm_segment {
82     fn from(s: SegmentRegister) -> Self {
83         Self {
84             base: s.base,
85             limit: s.limit,
86             selector: s.selector,
87             type_: s.type_,
88             present: s.present,
89             dpl: s.dpl,
90             db: s.db,
91             s: s.s,
92             l: s.l,
93             g: s.g,
94             avl: s.avl,
95             unusable: s.unusable,
96             ..Default::default()
97         }
98     }
99 }
100 
101 impl From<kvm_segment> for SegmentRegister {
102     fn from(s: kvm_segment) -> Self {
103         Self {
104             base: s.base,
105             limit: s.limit,
106             selector: s.selector,
107             type_: s.type_,
108             present: s.present,
109             dpl: s.dpl,
110             db: s.db,
111             s: s.s,
112             l: s.l,
113             g: s.g,
114             avl: s.avl,
115             unusable: s.unusable,
116         }
117     }
118 }
119 
120 impl From<DescriptorTable> for kvm_dtable {
121     fn from(dt: DescriptorTable) -> Self {
122         Self {
123             base: dt.base,
124             limit: dt.limit,
125             ..Default::default()
126         }
127     }
128 }
129 
130 impl From<kvm_dtable> for DescriptorTable {
131     fn from(dt: kvm_dtable) -> Self {
132         Self {
133             base: dt.base,
134             limit: dt.limit,
135         }
136     }
137 }
138 
139 impl From<SpecialRegisters> for kvm_sregs {
140     fn from(s: SpecialRegisters) -> Self {
141         Self {
142             cs: s.cs.into(),
143             ds: s.ds.into(),
144             es: s.es.into(),
145             fs: s.fs.into(),
146             gs: s.gs.into(),
147             ss: s.ss.into(),
148             tr: s.tr.into(),
149             ldt: s.ldt.into(),
150             gdt: s.gdt.into(),
151             idt: s.idt.into(),
152             cr0: s.cr0,
153             cr2: s.cr2,
154             cr3: s.cr3,
155             cr4: s.cr4,
156             cr8: s.cr8,
157             efer: s.efer,
158             apic_base: s.apic_base,
159             interrupt_bitmap: s.interrupt_bitmap,
160         }
161     }
162 }
163 
164 impl From<kvm_sregs> for SpecialRegisters {
165     fn from(s: kvm_sregs) -> Self {
166         Self {
167             cs: s.cs.into(),
168             ds: s.ds.into(),
169             es: s.es.into(),
170             fs: s.fs.into(),
171             gs: s.gs.into(),
172             ss: s.ss.into(),
173             tr: s.tr.into(),
174             ldt: s.ldt.into(),
175             gdt: s.gdt.into(),
176             idt: s.idt.into(),
177             cr0: s.cr0,
178             cr2: s.cr2,
179             cr3: s.cr3,
180             cr4: s.cr4,
181             cr8: s.cr8,
182             efer: s.efer,
183             apic_base: s.apic_base,
184             interrupt_bitmap: s.interrupt_bitmap,
185         }
186     }
187 }
188 
189 impl From<CpuIdEntry> for kvm_cpuid_entry2 {
190     fn from(e: CpuIdEntry) -> Self {
191         let flags = if e.flags & CPUID_FLAG_VALID_INDEX != 0 {
192             KVM_CPUID_FLAG_SIGNIFCANT_INDEX
193         } else {
194             0
195         };
196         Self {
197             function: e.function,
198             index: e.index,
199             flags,
200             eax: e.eax,
201             ebx: e.ebx,
202             ecx: e.ecx,
203             edx: e.edx,
204             ..Default::default()
205         }
206     }
207 }
208 
209 impl From<kvm_cpuid_entry2> for CpuIdEntry {
210     fn from(e: kvm_cpuid_entry2) -> Self {
211         let flags = if e.flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX != 0 {
212             CPUID_FLAG_VALID_INDEX
213         } else {
214             0
215         };
216         Self {
217             function: e.function,
218             index: e.index,
219             flags,
220             eax: e.eax,
221             ebx: e.ebx,
222             ecx: e.ecx,
223             edx: e.edx,
224         }
225     }
226 }
227 
228 impl From<kvm_fpu> for FpuState {
229     fn from(s: kvm_fpu) -> Self {
230         Self {
231             fpr: s.fpr,
232             fcw: s.fcw,
233             fsw: s.fsw,
234             ftwx: s.ftwx,
235             last_opcode: s.last_opcode,
236             last_ip: s.last_ip,
237             last_dp: s.last_dp,
238             xmm: s.xmm,
239             mxcsr: s.mxcsr,
240         }
241     }
242 }
243 
244 impl From<FpuState> for kvm_fpu {
245     fn from(s: FpuState) -> Self {
246         Self {
247             fpr: s.fpr,
248             fcw: s.fcw,
249             fsw: s.fsw,
250             ftwx: s.ftwx,
251             last_opcode: s.last_opcode,
252             last_ip: s.last_ip,
253             last_dp: s.last_dp,
254             xmm: s.xmm,
255             mxcsr: s.mxcsr,
256             ..Default::default()
257         }
258     }
259 }
260 
261 impl From<LapicState> for kvm_lapic_state {
262     fn from(s: LapicState) -> Self {
263         Self { regs: s.regs }
264     }
265 }
266 
267 impl From<kvm_lapic_state> for LapicState {
268     fn from(s: kvm_lapic_state) -> Self {
269         Self { regs: s.regs }
270     }
271 }
272 
273 impl From<kvm_msr_entry> for MsrEntry {
274     fn from(e: kvm_msr_entry) -> Self {
275         Self {
276             index: e.index,
277             data: e.data,
278         }
279     }
280 }
281 
282 impl From<MsrEntry> for kvm_msr_entry {
283     fn from(e: MsrEntry) -> Self {
284         Self {
285             index: e.index,
286             data: e.data,
287             ..Default::default()
288         }
289     }
290 }
291 
292 impl From<kvm_xsave> for XsaveState {
293     fn from(s: kvm_xsave) -> Self {
294         Self { region: s.region }
295     }
296 }
297 
298 impl From<XsaveState> for kvm_xsave {
299     fn from(s: XsaveState) -> Self {
300         Self {
301             region: s.region,
302             extra: Default::default(),
303         }
304     }
305 }
306