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