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::{ 15 CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters, 16 }; 17 #[cfg(feature = "tdx")] 18 use crate::kvm::{TdxExitDetails, TdxExitStatus}; 19 use crate::CpuState; 20 use crate::MpState; 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 the vCPU general purpose registers. 326 /// 327 fn get_regs(&self) -> Result<StandardRegisters>; 328 /// 329 /// Sets the vCPU general purpose registers. 330 /// 331 fn set_regs(&self, regs: &StandardRegisters) -> Result<()>; 332 #[cfg(target_arch = "x86_64")] 333 /// 334 /// Returns the vCPU special registers. 335 /// 336 fn get_sregs(&self) -> Result<SpecialRegisters>; 337 #[cfg(target_arch = "x86_64")] 338 /// 339 /// Sets the vCPU special registers 340 /// 341 fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>; 342 #[cfg(target_arch = "x86_64")] 343 /// 344 /// Returns the floating point state (FPU) from the vCPU. 345 /// 346 fn get_fpu(&self) -> Result<FpuState>; 347 #[cfg(target_arch = "x86_64")] 348 /// 349 /// Set the floating point state (FPU) of a vCPU 350 /// 351 fn set_fpu(&self, fpu: &FpuState) -> Result<()>; 352 #[cfg(target_arch = "x86_64")] 353 /// 354 /// X86 specific call to setup the CPUID registers. 355 /// 356 fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> Result<()>; 357 #[cfg(target_arch = "x86_64")] 358 /// 359 /// X86 specific call to enable HyperV SynIC 360 /// 361 fn enable_hyperv_synic(&self) -> Result<()>; 362 #[cfg(target_arch = "x86_64")] 363 /// 364 /// X86 specific call to retrieve the CPUID registers. 365 /// 366 fn get_cpuid2(&self, num_entries: usize) -> Result<Vec<CpuIdEntry>>; 367 #[cfg(target_arch = "x86_64")] 368 /// 369 /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 370 /// 371 fn get_lapic(&self) -> Result<LapicState>; 372 #[cfg(target_arch = "x86_64")] 373 /// 374 /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 375 /// 376 fn set_lapic(&self, lapic: &LapicState) -> Result<()>; 377 #[cfg(target_arch = "x86_64")] 378 /// 379 /// Returns the model-specific registers (MSR) for this vCPU. 380 /// 381 fn get_msrs(&self, msrs: &mut Vec<MsrEntry>) -> Result<usize>; 382 #[cfg(target_arch = "x86_64")] 383 /// 384 /// Setup the model-specific registers (MSR) for this vCPU. 385 /// 386 fn set_msrs(&self, msrs: &[MsrEntry]) -> Result<usize>; 387 /// 388 /// Returns the vcpu's current "multiprocessing state". 389 /// 390 fn get_mp_state(&self) -> Result<MpState>; 391 /// 392 /// Sets the vcpu's current "multiprocessing state". 393 /// 394 fn set_mp_state(&self, mp_state: MpState) -> Result<()>; 395 #[cfg(target_arch = "x86_64")] 396 /// 397 /// Let the guest know that it has been paused, which prevents from 398 /// potential soft lockups when being resumed. 399 /// 400 fn notify_guest_clock_paused(&self) -> Result<()> { 401 Ok(()) 402 } 403 /// 404 /// Sets debug registers to set hardware breakpoints and/or enable single step. 405 /// 406 fn set_guest_debug(&self, _addrs: &[GuestAddress], _singlestep: bool) -> Result<()> { 407 Err(HypervisorCpuError::SetDebugRegs(anyhow!("unimplemented"))) 408 } 409 /// 410 /// Sets the type of CPU to be exposed to the guest and optional features. 411 /// 412 #[cfg(target_arch = "aarch64")] 413 fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>; 414 /// 415 /// Gets a list of the guest registers that are supported for the 416 /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 417 /// 418 #[cfg(target_arch = "aarch64")] 419 fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>; 420 /// 421 /// Gets the value of a system register 422 /// 423 #[cfg(target_arch = "aarch64")] 424 fn get_sys_reg(&self, sys_reg: u32) -> Result<u64>; 425 /// 426 /// Configure core registers for a given CPU. 427 /// 428 #[cfg(target_arch = "aarch64")] 429 fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> Result<()>; 430 /// 431 /// Check if the CPU supports PMU 432 /// 433 #[cfg(target_arch = "aarch64")] 434 fn has_pmu_support(&self) -> bool; 435 /// 436 /// Initialize PMU 437 /// 438 #[cfg(target_arch = "aarch64")] 439 fn init_pmu(&self, irq: u32) -> Result<()>; 440 /// 441 /// Retrieve the vCPU state. 442 /// This function is necessary to snapshot the VM 443 /// 444 fn state(&self) -> Result<CpuState>; 445 /// 446 /// Set the vCPU state. 447 /// This function is required when restoring the VM 448 /// 449 fn set_state(&self, state: &CpuState) -> Result<()>; 450 /// 451 /// Triggers the running of the current virtual CPU returning an exit reason. 452 /// 453 fn run(&self) -> std::result::Result<VmExit, HypervisorCpuError>; 454 #[cfg(target_arch = "x86_64")] 455 /// 456 /// Translate guest virtual address to guest physical address 457 /// 458 fn translate_gva(&self, gva: u64, flags: u64) -> Result<(u64, u32)>; 459 /// 460 /// Initialize TDX support on the vCPU 461 /// 462 #[cfg(feature = "tdx")] 463 fn tdx_init(&self, _hob_address: u64) -> Result<()> { 464 unimplemented!() 465 } 466 /// 467 /// Set the "immediate_exit" state 468 /// 469 fn set_immediate_exit(&self, _exit: bool) {} 470 #[cfg(feature = "tdx")] 471 /// 472 /// Returns the details about TDX exit reason 473 /// 474 fn get_tdx_exit_details(&mut self) -> Result<TdxExitDetails> { 475 unimplemented!() 476 } 477 #[cfg(feature = "tdx")] 478 /// 479 /// Set the status code for TDX exit 480 /// 481 fn set_tdx_status(&mut self, _status: TdxExitStatus) { 482 unimplemented!() 483 } 484 #[cfg(target_arch = "x86_64")] 485 /// 486 /// Return the list of initial MSR entries for a VCPU 487 /// 488 fn boot_msr_entries(&self) -> Vec<MsrEntry>; 489 490 #[cfg(target_arch = "x86_64")] 491 /// 492 /// Get the frequency of the TSC if available 493 /// 494 fn tsc_khz(&self) -> Result<Option<u32>> { 495 Ok(None) 496 } 497 #[cfg(target_arch = "x86_64")] 498 /// 499 /// Set the frequency of the TSC if available 500 /// 501 fn set_tsc_khz(&self, _freq: u32) -> Result<()> { 502 Ok(()) 503 } 504 #[cfg(target_arch = "x86_64")] 505 /// 506 /// X86 specific call to retrieve cpuid leaf 507 /// 508 fn get_cpuid_values( 509 &self, 510 _function: u32, 511 _index: u32, 512 _xfem: u64, 513 _xss: u64, 514 ) -> Result<[u32; 4]> { 515 unimplemented!() 516 } 517 #[cfg(feature = "mshv")] 518 fn set_sev_control_register(&self, _reg: u64) -> Result<()> { 519 unimplemented!() 520 } 521 522 #[cfg(target_arch = "x86_64")] 523 /// 524 /// Trigger NMI interrupt 525 /// 526 fn nmi(&self) -> Result<()>; 527 } 528