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