xref: /cloud-hypervisor/hypervisor/src/kvm/x86_64/mod.rs (revision 3ce0fef7fd546467398c914dbc74d8542e45cf6f)
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     StandardRegisters, 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     if !kvm.check_extension(Cap::SignalMsi) {
36         return Err(KvmError::CapabilityMissing(Cap::SignalMsi));
37     }
38     if !kvm.check_extension(Cap::TscDeadlineTimer) {
39         return Err(KvmError::CapabilityMissing(Cap::TscDeadlineTimer));
40     }
41     if !kvm.check_extension(Cap::SplitIrqchip) {
42         return Err(KvmError::CapabilityMissing(Cap::SplitIrqchip));
43     }
44     if !kvm.check_extension(Cap::SetIdentityMapAddr) {
45         return Err(KvmError::CapabilityMissing(Cap::SetIdentityMapAddr));
46     }
47     if !kvm.check_extension(Cap::SetTssAddr) {
48         return Err(KvmError::CapabilityMissing(Cap::SetTssAddr));
49     }
50     if !kvm.check_extension(Cap::ImmediateExit) {
51         return Err(KvmError::CapabilityMissing(Cap::ImmediateExit));
52     }
53     if !kvm.check_extension(Cap::GetTscKhz) {
54         return Err(KvmError::CapabilityMissing(Cap::GetTscKhz));
55     }
56     Ok(())
57 }
58 #[derive(Clone, Serialize, Deserialize)]
59 pub struct VcpuKvmState {
60     pub cpuid: Vec<CpuIdEntry>,
61     pub msrs: Vec<MsrEntry>,
62     pub vcpu_events: VcpuEvents,
63     pub regs: kvm_regs,
64     pub sregs: kvm_sregs,
65     pub fpu: FpuState,
66     pub lapic_state: LapicState,
67     pub xsave: XsaveState,
68     pub xcrs: ExtendedControlRegisters,
69     pub mp_state: MpState,
70     pub tsc_khz: Option<u32>,
71 }
72 
73 impl From<StandardRegisters> for kvm_regs {
74     fn from(regs: StandardRegisters) -> Self {
75         Self {
76             rax: regs.rax,
77             rbx: regs.rbx,
78             rcx: regs.rcx,
79             rdx: regs.rdx,
80             rsi: regs.rsi,
81             rdi: regs.rdi,
82             rsp: regs.rsp,
83             rbp: regs.rbp,
84             r8: regs.r8,
85             r9: regs.r9,
86             r10: regs.r10,
87             r11: regs.r11,
88             r12: regs.r12,
89             r13: regs.r13,
90             r14: regs.r14,
91             r15: regs.r15,
92             rip: regs.rip,
93             rflags: regs.rflags,
94         }
95     }
96 }
97 
98 impl From<kvm_regs> for StandardRegisters {
99     fn from(regs: kvm_regs) -> Self {
100         Self {
101             rax: regs.rax,
102             rbx: regs.rbx,
103             rcx: regs.rcx,
104             rdx: regs.rdx,
105             rsi: regs.rsi,
106             rdi: regs.rdi,
107             rsp: regs.rsp,
108             rbp: regs.rbp,
109             r8: regs.r8,
110             r9: regs.r9,
111             r10: regs.r10,
112             r11: regs.r11,
113             r12: regs.r12,
114             r13: regs.r13,
115             r14: regs.r14,
116             r15: regs.r15,
117             rip: regs.rip,
118             rflags: regs.rflags,
119         }
120     }
121 }
122 
123 impl From<SegmentRegister> for kvm_segment {
124     fn from(s: SegmentRegister) -> Self {
125         Self {
126             base: s.base,
127             limit: s.limit,
128             selector: s.selector,
129             type_: s.type_,
130             present: s.present,
131             dpl: s.dpl,
132             db: s.db,
133             s: s.s,
134             l: s.l,
135             g: s.g,
136             avl: s.avl,
137             unusable: s.unusable,
138             ..Default::default()
139         }
140     }
141 }
142 
143 impl From<kvm_segment> for SegmentRegister {
144     fn from(s: kvm_segment) -> Self {
145         Self {
146             base: s.base,
147             limit: s.limit,
148             selector: s.selector,
149             type_: s.type_,
150             present: s.present,
151             dpl: s.dpl,
152             db: s.db,
153             s: s.s,
154             l: s.l,
155             g: s.g,
156             avl: s.avl,
157             unusable: s.unusable,
158         }
159     }
160 }
161 
162 impl From<DescriptorTable> for kvm_dtable {
163     fn from(dt: DescriptorTable) -> Self {
164         Self {
165             base: dt.base,
166             limit: dt.limit,
167             ..Default::default()
168         }
169     }
170 }
171 
172 impl From<kvm_dtable> for DescriptorTable {
173     fn from(dt: kvm_dtable) -> Self {
174         Self {
175             base: dt.base,
176             limit: dt.limit,
177         }
178     }
179 }
180 
181 impl From<SpecialRegisters> for kvm_sregs {
182     fn from(s: SpecialRegisters) -> Self {
183         Self {
184             cs: s.cs.into(),
185             ds: s.ds.into(),
186             es: s.es.into(),
187             fs: s.fs.into(),
188             gs: s.gs.into(),
189             ss: s.ss.into(),
190             tr: s.tr.into(),
191             ldt: s.ldt.into(),
192             gdt: s.gdt.into(),
193             idt: s.idt.into(),
194             cr0: s.cr0,
195             cr2: s.cr2,
196             cr3: s.cr3,
197             cr4: s.cr4,
198             cr8: s.cr8,
199             efer: s.efer,
200             apic_base: s.apic_base,
201             interrupt_bitmap: s.interrupt_bitmap,
202         }
203     }
204 }
205 
206 impl From<kvm_sregs> for SpecialRegisters {
207     fn from(s: kvm_sregs) -> Self {
208         Self {
209             cs: s.cs.into(),
210             ds: s.ds.into(),
211             es: s.es.into(),
212             fs: s.fs.into(),
213             gs: s.gs.into(),
214             ss: s.ss.into(),
215             tr: s.tr.into(),
216             ldt: s.ldt.into(),
217             gdt: s.gdt.into(),
218             idt: s.idt.into(),
219             cr0: s.cr0,
220             cr2: s.cr2,
221             cr3: s.cr3,
222             cr4: s.cr4,
223             cr8: s.cr8,
224             efer: s.efer,
225             apic_base: s.apic_base,
226             interrupt_bitmap: s.interrupt_bitmap,
227         }
228     }
229 }
230 
231 impl From<CpuIdEntry> for kvm_cpuid_entry2 {
232     fn from(e: CpuIdEntry) -> Self {
233         let flags = if e.flags & CPUID_FLAG_VALID_INDEX != 0 {
234             KVM_CPUID_FLAG_SIGNIFCANT_INDEX
235         } else {
236             0
237         };
238         Self {
239             function: e.function,
240             index: e.index,
241             flags,
242             eax: e.eax,
243             ebx: e.ebx,
244             ecx: e.ecx,
245             edx: e.edx,
246             ..Default::default()
247         }
248     }
249 }
250 
251 impl From<kvm_cpuid_entry2> for CpuIdEntry {
252     fn from(e: kvm_cpuid_entry2) -> Self {
253         let flags = if e.flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX != 0 {
254             CPUID_FLAG_VALID_INDEX
255         } else {
256             0
257         };
258         Self {
259             function: e.function,
260             index: e.index,
261             flags,
262             eax: e.eax,
263             ebx: e.ebx,
264             ecx: e.ecx,
265             edx: e.edx,
266         }
267     }
268 }
269 
270 impl From<kvm_fpu> for FpuState {
271     fn from(s: kvm_fpu) -> Self {
272         Self {
273             fpr: s.fpr,
274             fcw: s.fcw,
275             fsw: s.fsw,
276             ftwx: s.ftwx,
277             last_opcode: s.last_opcode,
278             last_ip: s.last_ip,
279             last_dp: s.last_dp,
280             xmm: s.xmm,
281             mxcsr: s.mxcsr,
282         }
283     }
284 }
285 
286 impl From<FpuState> for kvm_fpu {
287     fn from(s: FpuState) -> Self {
288         Self {
289             fpr: s.fpr,
290             fcw: s.fcw,
291             fsw: s.fsw,
292             ftwx: s.ftwx,
293             last_opcode: s.last_opcode,
294             last_ip: s.last_ip,
295             last_dp: s.last_dp,
296             xmm: s.xmm,
297             mxcsr: s.mxcsr,
298             ..Default::default()
299         }
300     }
301 }
302 
303 impl From<LapicState> for kvm_lapic_state {
304     fn from(s: LapicState) -> Self {
305         Self { regs: s.regs }
306     }
307 }
308 
309 impl From<kvm_lapic_state> for LapicState {
310     fn from(s: kvm_lapic_state) -> Self {
311         Self { regs: s.regs }
312     }
313 }
314 
315 impl From<kvm_msr_entry> for MsrEntry {
316     fn from(e: kvm_msr_entry) -> Self {
317         Self {
318             index: e.index,
319             data: e.data,
320         }
321     }
322 }
323 
324 impl From<MsrEntry> for kvm_msr_entry {
325     fn from(e: MsrEntry) -> Self {
326         Self {
327             index: e.index,
328             data: e.data,
329             ..Default::default()
330         }
331     }
332 }
333 
334 impl From<kvm_xsave> for XsaveState {
335     fn from(s: kvm_xsave) -> Self {
336         Self { region: s.region }
337     }
338 }
339 
340 impl From<XsaveState> for kvm_xsave {
341     fn from(s: XsaveState) -> Self {
342         Self {
343             region: s.region,
344             extra: Default::default(),
345         }
346     }
347 }
348