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