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