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