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