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