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