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