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 thiserror::Error; 12 use vm_memory::GuestAddress; 13 14 #[cfg(target_arch = "aarch64")] 15 use crate::aarch64::{RegList, VcpuInit}; 16 #[cfg(target_arch = "x86_64")] 17 use crate::arch::x86::{CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters}; 18 #[cfg(feature = "tdx")] 19 use crate::kvm::{TdxExitDetails, TdxExitStatus}; 20 use crate::CpuState; 21 use crate::MpState; 22 use crate::StandardRegisters; 23 24 #[cfg(target_arch = "x86_64")] 25 #[derive(Copy, Clone, Default)] 26 pub enum CpuVendor { 27 #[default] 28 Unknown, 29 Intel, 30 AMD, 31 } 32 33 #[derive(Error, Debug)] 34 /// 35 /// Enum for CPU error 36 pub enum HypervisorCpuError { 37 /// 38 /// Setting standard registers error 39 /// 40 #[error("Failed to set standard register: {0}")] 41 SetStandardRegs(#[source] anyhow::Error), 42 /// 43 /// Setting standard registers error 44 /// 45 #[error("Failed to get standard registers: {0}")] 46 GetStandardRegs(#[source] anyhow::Error), 47 /// 48 /// Setting special register error 49 /// 50 #[error("Failed to set special registers: {0}")] 51 SetSpecialRegs(#[source] anyhow::Error), 52 /// 53 /// Getting standard register error 54 /// 55 #[error("Failed to get special registers: {0}")] 56 GetSpecialRegs(#[source] anyhow::Error), 57 /// 58 /// Setting floating point registers error 59 /// 60 #[error("Failed to set floating point registers: {0}")] 61 SetFloatingPointRegs(#[source] anyhow::Error), 62 /// 63 /// Getting floating point register error 64 /// 65 #[error("Failed to get floating points registers: {0}")] 66 GetFloatingPointRegs(#[source] anyhow::Error), 67 /// 68 /// Setting Cpuid error 69 /// 70 #[error("Failed to set Cpuid: {0}")] 71 SetCpuid(#[source] anyhow::Error), 72 /// 73 /// Getting Cpuid error 74 /// 75 #[error("Failed to get Cpuid: {0}")] 76 GetCpuid(#[source] anyhow::Error), 77 /// 78 /// Setting lapic state error 79 /// 80 #[error("Failed to set Lapic state: {0}")] 81 SetLapicState(#[source] anyhow::Error), 82 /// 83 /// Getting Lapic state error 84 /// 85 #[error("Failed to get Lapic state: {0}")] 86 GetlapicState(#[source] anyhow::Error), 87 /// 88 /// Setting MSR entries error 89 /// 90 #[error("Failed to set Msr entries: {0}")] 91 SetMsrEntries(#[source] anyhow::Error), 92 /// 93 /// Getting Msr entries error 94 /// 95 #[error("Failed to get Msr entries: {0}")] 96 GetMsrEntries(#[source] anyhow::Error), 97 /// 98 /// Setting multi-processing state error 99 /// 100 #[error("Failed to set MP state: {0}")] 101 SetMpState(#[source] anyhow::Error), 102 /// 103 /// Getting multi-processing state error 104 /// 105 #[error("Failed to get MP state: {0}")] 106 GetMpState(#[source] anyhow::Error), 107 /// 108 /// Setting Saved Processor Extended States error 109 /// 110 #[cfg(feature = "kvm")] 111 #[error("Failed to set Saved Processor Extended States: {0}")] 112 SetXsaveState(#[source] anyhow::Error), 113 /// 114 /// Getting Saved Processor Extended States error 115 /// 116 #[cfg(feature = "kvm")] 117 #[error("Failed to get Saved Processor Extended States: {0}")] 118 GetXsaveState(#[source] anyhow::Error), 119 /// 120 /// Getting the VP state components error 121 /// 122 #[cfg(feature = "mshv")] 123 #[error("Failed to get VP State Components: {0}")] 124 GetAllVpStateComponents(#[source] anyhow::Error), 125 /// 126 /// Setting the VP state components error 127 /// 128 #[cfg(feature = "mshv")] 129 #[error("Failed to set VP State Components: {0}")] 130 SetAllVpStateComponents(#[source] anyhow::Error), 131 /// 132 /// Setting Extended Control Registers error 133 /// 134 #[error("Failed to set Extended Control Registers: {0}")] 135 SetXcsr(#[source] anyhow::Error), 136 /// 137 /// Getting Extended Control Registers error 138 /// 139 #[error("Failed to get Extended Control Registers: {0}")] 140 GetXcsr(#[source] anyhow::Error), 141 /// 142 /// Running Vcpu error 143 /// 144 #[error("Failed to run vcpu: {0}")] 145 RunVcpu(#[source] anyhow::Error), 146 /// 147 /// Getting Vcpu events error 148 /// 149 #[error("Failed to get Vcpu events: {0}")] 150 GetVcpuEvents(#[source] anyhow::Error), 151 /// 152 /// Setting Vcpu events error 153 /// 154 #[error("Failed to set Vcpu events: {0}")] 155 SetVcpuEvents(#[source] anyhow::Error), 156 /// 157 /// Vcpu Init error 158 /// 159 #[error("Failed to init vcpu: {0}")] 160 VcpuInit(#[source] anyhow::Error), 161 /// 162 /// Vcpu Finalize error 163 /// 164 #[error("Failed to finalize vcpu: {0}")] 165 VcpuFinalize(#[source] anyhow::Error), 166 /// 167 /// Setting one reg error 168 /// 169 #[error("Failed to set one reg: {0}")] 170 SetRegister(#[source] anyhow::Error), 171 /// 172 /// Getting one reg error 173 /// 174 #[error("Failed to get one reg: {0}")] 175 GetRegister(#[source] anyhow::Error), 176 /// 177 /// Getting guest clock paused error 178 /// 179 #[error("Failed to notify guest its clock was paused: {0}")] 180 NotifyGuestClockPaused(#[source] anyhow::Error), 181 /// 182 /// Setting debug register error 183 /// 184 #[error("Failed to set debug registers: {0}")] 185 SetDebugRegs(#[source] anyhow::Error), 186 /// 187 /// Getting debug register error 188 /// 189 #[error("Failed to get debug registers: {0}")] 190 GetDebugRegs(#[source] anyhow::Error), 191 /// 192 /// Setting misc register error 193 /// 194 #[error("Failed to set misc registers: {0}")] 195 SetMiscRegs(#[source] anyhow::Error), 196 /// 197 /// Getting misc register error 198 /// 199 #[error("Failed to get misc registers: {0}")] 200 GetMiscRegs(#[source] anyhow::Error), 201 /// 202 /// Write to Guest Mem 203 /// 204 #[error("Failed to write to Guest Mem at: {0}")] 205 GuestMemWrite(#[source] anyhow::Error), 206 /// Enabling HyperV SynIC error 207 /// 208 #[error("Failed to enable HyperV SynIC")] 209 EnableHyperVSyncIc(#[source] anyhow::Error), 210 /// 211 /// Getting AArch64 core register error 212 /// 213 #[error("Failed to get aarch64 core register: {0}")] 214 GetAarchCoreRegister(#[source] anyhow::Error), 215 /// 216 /// Setting AArch64 core register error 217 /// 218 #[error("Failed to set aarch64 core register: {0}")] 219 SetAarchCoreRegister(#[source] anyhow::Error), 220 /// 221 /// Getting registers list error 222 /// 223 #[error("Failed to retrieve list of registers: {0}")] 224 GetRegList(#[source] anyhow::Error), 225 /// 226 /// Getting AArch64 system register error 227 /// 228 #[error("Failed to get system register: {0}")] 229 GetSysRegister(#[source] anyhow::Error), 230 /// 231 /// Setting AArch64 system register error 232 /// 233 #[error("Failed to set system register: {0}")] 234 SetSysRegister(#[source] anyhow::Error), 235 /// 236 /// GVA translation error 237 /// 238 #[error("Failed to translate GVA: {0}")] 239 TranslateVirtualAddress(#[source] anyhow::Error), 240 /// 241 /// Set cpu attribute error 242 /// 243 #[error("Failed to set vcpu attribute: {0}")] 244 SetVcpuAttribute(#[source] anyhow::Error), 245 /// 246 /// Check if cpu has a certain attribute error 247 /// 248 #[error("Failed to check if vcpu has attribute: {0}")] 249 HasVcpuAttribute(#[source] anyhow::Error), 250 /// 251 /// Failed to initialize TDX on CPU 252 /// 253 #[cfg(feature = "tdx")] 254 #[error("Failed to initialize TDX: {0}")] 255 InitializeTdx(#[source] std::io::Error), 256 /// 257 /// Unknown TDX VM call 258 /// 259 #[cfg(feature = "tdx")] 260 #[error("Unknown TDX VM call")] 261 UnknownTdxVmCall, 262 #[cfg(target_arch = "aarch64")] 263 /// 264 /// Failed to initialize PMU 265 /// 266 #[error("Failed to initialize PMU")] 267 InitializePmu, 268 #[cfg(target_arch = "x86_64")] 269 /// 270 /// Error getting TSC frequency 271 /// 272 #[error("Failed to get TSC frequency: {0}")] 273 GetTscKhz(#[source] anyhow::Error), 274 /// 275 /// Error setting TSC frequency 276 /// 277 #[error("Failed to set TSC frequency: {0}")] 278 SetTscKhz(#[source] anyhow::Error), 279 /// 280 /// Error reading value at given GPA 281 /// 282 #[error("Failed to read from GPA: {0}")] 283 GpaRead(#[source] anyhow::Error), 284 /// 285 /// Error writing value at given GPA 286 /// 287 #[error("Failed to write to GPA: {0}")] 288 GpaWrite(#[source] anyhow::Error), 289 /// 290 /// Error getting CPUID leaf 291 /// 292 #[error("Failed to get CPUID entries: {0}")] 293 GetCpuidVales(#[source] anyhow::Error), 294 /// 295 /// Setting SEV control register error 296 /// 297 #[cfg(feature = "sev_snp")] 298 #[error("Failed to set sev control register: {0}")] 299 SetSevControlRegister(#[source] anyhow::Error), 300 301 /// Error injecting NMI 302 /// 303 #[error("Failed to inject NMI")] 304 Nmi(#[source] anyhow::Error), 305 } 306 307 #[derive(Debug)] 308 pub enum VmExit { 309 #[cfg(target_arch = "x86_64")] 310 IoapicEoi(u8 /* vector */), 311 Ignore, 312 Reset, 313 Shutdown, 314 Hyperv, 315 #[cfg(feature = "tdx")] 316 Tdx, 317 #[cfg(feature = "kvm")] 318 Debug, 319 } 320 321 /// 322 /// Result type for returning from a function 323 /// 324 pub type Result<T> = anyhow::Result<T, HypervisorCpuError>; 325 /// 326 /// Trait to represent a generic Vcpu 327 /// 328 pub trait Vcpu: Send + Sync { 329 /// 330 /// Returns StandardRegisters with default value set 331 /// 332 fn create_standard_regs(&self) -> StandardRegisters { 333 unimplemented!(); 334 } 335 /// 336 /// Returns the vCPU general purpose registers. 337 /// 338 fn get_regs(&self) -> Result<StandardRegisters>; 339 /// 340 /// Sets the vCPU general purpose registers. 341 /// 342 fn set_regs(&self, regs: &StandardRegisters) -> Result<()>; 343 #[cfg(target_arch = "x86_64")] 344 /// 345 /// Returns the vCPU special registers. 346 /// 347 fn get_sregs(&self) -> Result<SpecialRegisters>; 348 #[cfg(target_arch = "x86_64")] 349 /// 350 /// Sets the vCPU special registers 351 /// 352 fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>; 353 #[cfg(target_arch = "x86_64")] 354 /// 355 /// Returns the floating point state (FPU) from the vCPU. 356 /// 357 fn get_fpu(&self) -> Result<FpuState>; 358 #[cfg(target_arch = "x86_64")] 359 /// 360 /// Set the floating point state (FPU) of a vCPU 361 /// 362 fn set_fpu(&self, fpu: &FpuState) -> Result<()>; 363 #[cfg(target_arch = "x86_64")] 364 /// 365 /// X86 specific call to setup the CPUID registers. 366 /// 367 fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> Result<()>; 368 #[cfg(target_arch = "x86_64")] 369 /// 370 /// X86 specific call to enable HyperV SynIC 371 /// 372 fn enable_hyperv_synic(&self) -> Result<()>; 373 #[cfg(target_arch = "x86_64")] 374 /// 375 /// X86 specific call to retrieve the CPUID registers. 376 /// 377 fn get_cpuid2(&self, num_entries: usize) -> Result<Vec<CpuIdEntry>>; 378 #[cfg(target_arch = "x86_64")] 379 /// 380 /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 381 /// 382 fn get_lapic(&self) -> Result<LapicState>; 383 #[cfg(target_arch = "x86_64")] 384 /// 385 /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 386 /// 387 fn set_lapic(&self, lapic: &LapicState) -> Result<()>; 388 #[cfg(target_arch = "x86_64")] 389 /// 390 /// Returns the model-specific registers (MSR) for this vCPU. 391 /// 392 fn get_msrs(&self, msrs: &mut Vec<MsrEntry>) -> Result<usize>; 393 #[cfg(target_arch = "x86_64")] 394 /// 395 /// Setup the model-specific registers (MSR) for this vCPU. 396 /// 397 fn set_msrs(&self, msrs: &[MsrEntry]) -> Result<usize>; 398 /// 399 /// Returns the vcpu's current "multiprocessing state". 400 /// 401 fn get_mp_state(&self) -> Result<MpState>; 402 /// 403 /// Sets the vcpu's current "multiprocessing state". 404 /// 405 fn set_mp_state(&self, mp_state: MpState) -> Result<()>; 406 #[cfg(target_arch = "x86_64")] 407 /// 408 /// Let the guest know that it has been paused, which prevents from 409 /// potential soft lockups when being resumed. 410 /// 411 fn notify_guest_clock_paused(&self) -> Result<()> { 412 Ok(()) 413 } 414 /// 415 /// Sets debug registers to set hardware breakpoints and/or enable single step. 416 /// 417 fn set_guest_debug(&self, _addrs: &[GuestAddress], _singlestep: bool) -> Result<()> { 418 Err(HypervisorCpuError::SetDebugRegs(anyhow!("unimplemented"))) 419 } 420 /// 421 /// Sets the type of CPU to be exposed to the guest and optional features. 422 /// 423 #[cfg(target_arch = "aarch64")] 424 fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>; 425 426 #[cfg(target_arch = "aarch64")] 427 fn vcpu_finalize(&self, feature: i32) -> Result<()>; 428 429 /// 430 /// Gets a list of the guest registers that are supported for the 431 /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 432 /// 433 #[cfg(target_arch = "aarch64")] 434 fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>; 435 /// 436 /// Gets the value of a system register 437 /// 438 #[cfg(target_arch = "aarch64")] 439 fn get_sys_reg(&self, sys_reg: u32) -> Result<u64>; 440 /// 441 /// Configure core registers for a given CPU. 442 /// 443 #[cfg(target_arch = "aarch64")] 444 fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> Result<()>; 445 /// 446 /// Check if the CPU supports PMU 447 /// 448 #[cfg(target_arch = "aarch64")] 449 fn has_pmu_support(&self) -> bool; 450 /// 451 /// Initialize PMU 452 /// 453 #[cfg(target_arch = "aarch64")] 454 fn init_pmu(&self, irq: u32) -> Result<()>; 455 /// 456 /// Retrieve the vCPU state. 457 /// This function is necessary to snapshot the VM 458 /// 459 fn state(&self) -> Result<CpuState>; 460 /// 461 /// Set the vCPU state. 462 /// This function is required when restoring the VM 463 /// 464 fn set_state(&self, state: &CpuState) -> Result<()>; 465 /// 466 /// Triggers the running of the current virtual CPU returning an exit reason. 467 /// 468 fn run(&self) -> std::result::Result<VmExit, HypervisorCpuError>; 469 #[cfg(target_arch = "x86_64")] 470 /// 471 /// Translate guest virtual address to guest physical address 472 /// 473 fn translate_gva(&self, gva: u64, flags: u64) -> Result<(u64, u32)>; 474 /// 475 /// Initialize TDX support on the vCPU 476 /// 477 #[cfg(feature = "tdx")] 478 fn tdx_init(&self, _hob_address: u64) -> Result<()> { 479 unimplemented!() 480 } 481 /// 482 /// Set the "immediate_exit" state 483 /// 484 fn set_immediate_exit(&self, _exit: bool) {} 485 #[cfg(feature = "tdx")] 486 /// 487 /// Returns the details about TDX exit reason 488 /// 489 fn get_tdx_exit_details(&mut self) -> Result<TdxExitDetails> { 490 unimplemented!() 491 } 492 #[cfg(feature = "tdx")] 493 /// 494 /// Set the status code for TDX exit 495 /// 496 fn set_tdx_status(&mut self, _status: TdxExitStatus) { 497 unimplemented!() 498 } 499 #[cfg(target_arch = "x86_64")] 500 /// 501 /// Return the list of initial MSR entries for a VCPU 502 /// 503 fn boot_msr_entries(&self) -> Vec<MsrEntry>; 504 505 #[cfg(target_arch = "x86_64")] 506 /// 507 /// Get the frequency of the TSC if available 508 /// 509 fn tsc_khz(&self) -> Result<Option<u32>> { 510 Ok(None) 511 } 512 #[cfg(target_arch = "x86_64")] 513 /// 514 /// Set the frequency of the TSC if available 515 /// 516 fn set_tsc_khz(&self, _freq: u32) -> Result<()> { 517 Ok(()) 518 } 519 #[cfg(target_arch = "x86_64")] 520 /// 521 /// X86 specific call to retrieve cpuid leaf 522 /// 523 fn get_cpuid_values( 524 &self, 525 _function: u32, 526 _index: u32, 527 _xfem: u64, 528 _xss: u64, 529 ) -> Result<[u32; 4]> { 530 unimplemented!() 531 } 532 #[cfg(feature = "mshv")] 533 fn set_sev_control_register(&self, _reg: u64) -> Result<()> { 534 unimplemented!() 535 } 536 537 #[cfg(target_arch = "x86_64")] 538 /// 539 /// Trigger NMI interrupt 540 /// 541 fn nmi(&self) -> Result<()>; 542 } 543