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, StandardRegisters, 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 #[cfg(target_arch = "x86_64")] 20 use crate::StandardRegisters; 21 use thiserror::Error; 22 use vm_memory::GuestAddress; 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 /// Setting one reg error 163 /// 164 #[error("Failed to init vcpu: {0}")] 165 SetRegister(#[source] anyhow::Error), 166 /// 167 /// Getting one reg error 168 /// 169 #[error("Failed to init vcpu: {0}")] 170 GetRegister(#[source] anyhow::Error), 171 /// 172 /// Getting guest clock paused error 173 /// 174 #[error("Failed to notify guest its clock was paused: {0}")] 175 NotifyGuestClockPaused(#[source] anyhow::Error), 176 /// 177 /// Setting debug register error 178 /// 179 #[error("Failed to set debug registers: {0}")] 180 SetDebugRegs(#[source] anyhow::Error), 181 /// 182 /// Getting debug register error 183 /// 184 #[error("Failed to get debug registers: {0}")] 185 GetDebugRegs(#[source] anyhow::Error), 186 /// 187 /// Setting misc register error 188 /// 189 #[error("Failed to set misc registers: {0}")] 190 SetMiscRegs(#[source] anyhow::Error), 191 /// 192 /// Getting misc register error 193 /// 194 #[error("Failed to get misc registers: {0}")] 195 GetMiscRegs(#[source] anyhow::Error), 196 /// 197 /// Write to Guest Mem 198 /// 199 #[error("Failed to write to Guest Mem at: {0}")] 200 GuestMemWrite(#[source] anyhow::Error), 201 /// Enabling HyperV SynIC error 202 /// 203 #[error("Failed to enable HyperV SynIC")] 204 EnableHyperVSyncIc(#[source] anyhow::Error), 205 /// 206 /// Getting AArch64 core register error 207 /// 208 #[error("Failed to get core register: {0}")] 209 GetCoreRegister(#[source] anyhow::Error), 210 /// 211 /// Setting AArch64 core register error 212 /// 213 #[error("Failed to set core register: {0}")] 214 SetCoreRegister(#[source] anyhow::Error), 215 /// 216 /// Getting AArch64 registers list error 217 /// 218 #[error("Failed to retrieve list of registers: {0}")] 219 GetRegList(#[source] anyhow::Error), 220 /// 221 /// Getting AArch64 system register error 222 /// 223 #[error("Failed to get system register: {0}")] 224 GetSysRegister(#[source] anyhow::Error), 225 /// 226 /// Setting AArch64 system register error 227 /// 228 #[error("Failed to set system register: {0}")] 229 SetSysRegister(#[source] anyhow::Error), 230 /// 231 /// GVA translation error 232 /// 233 #[error("Failed to translate GVA: {0}")] 234 TranslateVirtualAddress(#[source] anyhow::Error), 235 /// 236 /// Set cpu attribute error 237 /// 238 #[error("Failed to set vcpu attribute: {0}")] 239 SetVcpuAttribute(#[source] anyhow::Error), 240 /// 241 /// Check if cpu has a certain attribute error 242 /// 243 #[error("Failed to check if vcpu has attribute: {0}")] 244 HasVcpuAttribute(#[source] anyhow::Error), 245 /// 246 /// Failed to initialize TDX on CPU 247 /// 248 #[cfg(feature = "tdx")] 249 #[error("Failed to initialize TDX: {0}")] 250 InitializeTdx(#[source] std::io::Error), 251 /// 252 /// Unknown TDX VM call 253 /// 254 #[cfg(feature = "tdx")] 255 #[error("Unknown TDX VM call")] 256 UnknownTdxVmCall, 257 #[cfg(target_arch = "aarch64")] 258 /// 259 /// Failed to initialize PMU 260 /// 261 #[error("Failed to initialize PMU")] 262 InitializePmu, 263 #[cfg(target_arch = "x86_64")] 264 /// 265 /// Error getting TSC frequency 266 /// 267 #[error("Failed to get TSC frequency: {0}")] 268 GetTscKhz(#[source] anyhow::Error), 269 /// 270 /// Error setting TSC frequency 271 /// 272 #[error("Failed to set TSC frequency: {0}")] 273 SetTscKhz(#[source] anyhow::Error), 274 /// 275 /// Error reading value at given GPA 276 /// 277 #[error("Failed to read from GPA: {0}")] 278 GpaRead(#[source] anyhow::Error), 279 /// 280 /// Error writing value at given GPA 281 /// 282 #[error("Failed to write to GPA: {0}")] 283 GpaWrite(#[source] anyhow::Error), 284 /// 285 /// Error getting CPUID leaf 286 /// 287 #[error("Failed to get CPUID entries: {0}")] 288 GetCpuidVales(#[source] anyhow::Error), 289 /// 290 /// Setting SEV control register error 291 /// 292 #[cfg(feature = "sev_snp")] 293 #[error("Failed to set sev control register: {0}")] 294 SetSevControlRegister(#[source] anyhow::Error), 295 296 /// Error injecting NMI 297 /// 298 #[error("Failed to inject NMI")] 299 Nmi(#[source] anyhow::Error), 300 } 301 302 #[derive(Debug)] 303 pub enum VmExit { 304 #[cfg(target_arch = "x86_64")] 305 IoapicEoi(u8 /* vector */), 306 Ignore, 307 Reset, 308 Shutdown, 309 Hyperv, 310 #[cfg(feature = "tdx")] 311 Tdx, 312 #[cfg(feature = "kvm")] 313 Debug, 314 } 315 316 /// 317 /// Result type for returning from a function 318 /// 319 pub type Result<T> = anyhow::Result<T, HypervisorCpuError>; 320 /// 321 /// Trait to represent a generic Vcpu 322 /// 323 pub trait Vcpu: Send + Sync { 324 /// 325 /// Returns StandardRegisters with default value set 326 /// 327 fn create_standard_regs(&self) -> StandardRegisters { 328 unimplemented!(); 329 } 330 /// 331 /// Returns the vCPU general purpose registers. 332 /// 333 fn get_regs(&self) -> Result<StandardRegisters>; 334 /// 335 /// Sets the vCPU general purpose registers. 336 /// 337 fn set_regs(&self, regs: &StandardRegisters) -> Result<()>; 338 #[cfg(target_arch = "x86_64")] 339 /// 340 /// Returns the vCPU special registers. 341 /// 342 fn get_sregs(&self) -> Result<SpecialRegisters>; 343 #[cfg(target_arch = "x86_64")] 344 /// 345 /// Sets the vCPU special registers 346 /// 347 fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>; 348 #[cfg(target_arch = "x86_64")] 349 /// 350 /// Returns the floating point state (FPU) from the vCPU. 351 /// 352 fn get_fpu(&self) -> Result<FpuState>; 353 #[cfg(target_arch = "x86_64")] 354 /// 355 /// Set the floating point state (FPU) of a vCPU 356 /// 357 fn set_fpu(&self, fpu: &FpuState) -> Result<()>; 358 #[cfg(target_arch = "x86_64")] 359 /// 360 /// X86 specific call to setup the CPUID registers. 361 /// 362 fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> Result<()>; 363 #[cfg(target_arch = "x86_64")] 364 /// 365 /// X86 specific call to enable HyperV SynIC 366 /// 367 fn enable_hyperv_synic(&self) -> Result<()>; 368 #[cfg(target_arch = "x86_64")] 369 /// 370 /// X86 specific call to retrieve the CPUID registers. 371 /// 372 fn get_cpuid2(&self, num_entries: usize) -> Result<Vec<CpuIdEntry>>; 373 #[cfg(target_arch = "x86_64")] 374 /// 375 /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 376 /// 377 fn get_lapic(&self) -> Result<LapicState>; 378 #[cfg(target_arch = "x86_64")] 379 /// 380 /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 381 /// 382 fn set_lapic(&self, lapic: &LapicState) -> Result<()>; 383 #[cfg(target_arch = "x86_64")] 384 /// 385 /// Returns the model-specific registers (MSR) for this vCPU. 386 /// 387 fn get_msrs(&self, msrs: &mut Vec<MsrEntry>) -> Result<usize>; 388 #[cfg(target_arch = "x86_64")] 389 /// 390 /// Setup the model-specific registers (MSR) for this vCPU. 391 /// 392 fn set_msrs(&self, msrs: &[MsrEntry]) -> Result<usize>; 393 /// 394 /// Returns the vcpu's current "multiprocessing state". 395 /// 396 fn get_mp_state(&self) -> Result<MpState>; 397 /// 398 /// Sets the vcpu's current "multiprocessing state". 399 /// 400 fn set_mp_state(&self, mp_state: MpState) -> Result<()>; 401 #[cfg(target_arch = "x86_64")] 402 /// 403 /// Let the guest know that it has been paused, which prevents from 404 /// potential soft lockups when being resumed. 405 /// 406 fn notify_guest_clock_paused(&self) -> Result<()> { 407 Ok(()) 408 } 409 /// 410 /// Sets debug registers to set hardware breakpoints and/or enable single step. 411 /// 412 fn set_guest_debug(&self, _addrs: &[GuestAddress], _singlestep: bool) -> Result<()> { 413 Err(HypervisorCpuError::SetDebugRegs(anyhow!("unimplemented"))) 414 } 415 /// 416 /// Sets the type of CPU to be exposed to the guest and optional features. 417 /// 418 #[cfg(target_arch = "aarch64")] 419 fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>; 420 /// 421 /// Gets a list of the guest registers that are supported for the 422 /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 423 /// 424 #[cfg(target_arch = "aarch64")] 425 fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>; 426 /// 427 /// Gets the value of a system register 428 /// 429 #[cfg(target_arch = "aarch64")] 430 fn get_sys_reg(&self, sys_reg: u32) -> Result<u64>; 431 /// 432 /// Configure core registers for a given CPU. 433 /// 434 #[cfg(target_arch = "aarch64")] 435 fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> Result<()>; 436 /// 437 /// Check if the CPU supports PMU 438 /// 439 #[cfg(target_arch = "aarch64")] 440 fn has_pmu_support(&self) -> bool; 441 /// 442 /// Initialize PMU 443 /// 444 #[cfg(target_arch = "aarch64")] 445 fn init_pmu(&self, irq: u32) -> Result<()>; 446 /// 447 /// Retrieve the vCPU state. 448 /// This function is necessary to snapshot the VM 449 /// 450 fn state(&self) -> Result<CpuState>; 451 /// 452 /// Set the vCPU state. 453 /// This function is required when restoring the VM 454 /// 455 fn set_state(&self, state: &CpuState) -> Result<()>; 456 /// 457 /// Triggers the running of the current virtual CPU returning an exit reason. 458 /// 459 fn run(&self) -> std::result::Result<VmExit, HypervisorCpuError>; 460 #[cfg(target_arch = "x86_64")] 461 /// 462 /// Translate guest virtual address to guest physical address 463 /// 464 fn translate_gva(&self, gva: u64, flags: u64) -> Result<(u64, u32)>; 465 /// 466 /// Initialize TDX support on the vCPU 467 /// 468 #[cfg(feature = "tdx")] 469 fn tdx_init(&self, _hob_address: u64) -> Result<()> { 470 unimplemented!() 471 } 472 /// 473 /// Set the "immediate_exit" state 474 /// 475 fn set_immediate_exit(&self, _exit: bool) {} 476 #[cfg(feature = "tdx")] 477 /// 478 /// Returns the details about TDX exit reason 479 /// 480 fn get_tdx_exit_details(&mut self) -> Result<TdxExitDetails> { 481 unimplemented!() 482 } 483 #[cfg(feature = "tdx")] 484 /// 485 /// Set the status code for TDX exit 486 /// 487 fn set_tdx_status(&mut self, _status: TdxExitStatus) { 488 unimplemented!() 489 } 490 #[cfg(target_arch = "x86_64")] 491 /// 492 /// Return the list of initial MSR entries for a VCPU 493 /// 494 fn boot_msr_entries(&self) -> Vec<MsrEntry>; 495 496 #[cfg(target_arch = "x86_64")] 497 /// 498 /// Get the frequency of the TSC if available 499 /// 500 fn tsc_khz(&self) -> Result<Option<u32>> { 501 Ok(None) 502 } 503 #[cfg(target_arch = "x86_64")] 504 /// 505 /// Set the frequency of the TSC if available 506 /// 507 fn set_tsc_khz(&self, _freq: u32) -> Result<()> { 508 Ok(()) 509 } 510 #[cfg(target_arch = "x86_64")] 511 /// 512 /// X86 specific call to retrieve cpuid leaf 513 /// 514 fn get_cpuid_values( 515 &self, 516 _function: u32, 517 _index: u32, 518 _xfem: u64, 519 _xss: u64, 520 ) -> Result<[u32; 4]> { 521 unimplemented!() 522 } 523 #[cfg(feature = "mshv")] 524 fn set_sev_control_register(&self, _reg: u64) -> Result<()> { 525 unimplemented!() 526 } 527 528 #[cfg(target_arch = "x86_64")] 529 /// 530 /// Trigger NMI interrupt 531 /// 532 fn nmi(&self) -> Result<()>; 533 } 534