1 // Copyright © 2024 Institute of Software, CAS. All rights reserved. 2 // 3 // Copyright © 2019 Intel Corporation 4 // 5 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 6 // 7 // Copyright © 2020, Microsoft Corporation 8 // 9 // Copyright 2018-2019 CrowdStrike, Inc. 10 // 11 // 12 13 use thiserror::Error; 14 #[cfg(not(target_arch = "riscv64"))] 15 use vm_memory::GuestAddress; 16 17 #[cfg(target_arch = "aarch64")] 18 use crate::aarch64::{RegList, VcpuInit}; 19 #[cfg(target_arch = "x86_64")] 20 use crate::arch::x86::{CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters}; 21 #[cfg(feature = "tdx")] 22 use crate::kvm::{TdxExitDetails, TdxExitStatus}; 23 #[cfg(target_arch = "riscv64")] 24 use crate::riscv64::RegList; 25 use crate::{CpuState, MpState, StandardRegisters}; 26 27 #[cfg(target_arch = "x86_64")] 28 #[derive(Copy, Clone, Default)] 29 pub enum CpuVendor { 30 #[default] 31 Unknown, 32 Intel, 33 AMD, 34 } 35 36 #[derive(Error, Debug)] 37 /// 38 /// Enum for CPU error 39 pub enum HypervisorCpuError { 40 /// 41 /// Setting standard registers error 42 /// 43 #[error("Failed to set standard register: {0}")] 44 SetStandardRegs(#[source] anyhow::Error), 45 /// 46 /// Setting standard registers error 47 /// 48 #[error("Failed to get standard registers: {0}")] 49 GetStandardRegs(#[source] anyhow::Error), 50 /// 51 /// Setting special register error 52 /// 53 #[error("Failed to set special registers: {0}")] 54 SetSpecialRegs(#[source] anyhow::Error), 55 /// 56 /// Getting standard register error 57 /// 58 #[error("Failed to get special registers: {0}")] 59 GetSpecialRegs(#[source] anyhow::Error), 60 /// 61 /// Setting floating point registers error 62 /// 63 #[error("Failed to set floating point registers: {0}")] 64 SetFloatingPointRegs(#[source] anyhow::Error), 65 /// 66 /// Getting floating point register error 67 /// 68 #[error("Failed to get floating points registers: {0}")] 69 GetFloatingPointRegs(#[source] anyhow::Error), 70 /// 71 /// Setting Cpuid error 72 /// 73 #[error("Failed to set Cpuid: {0}")] 74 SetCpuid(#[source] anyhow::Error), 75 /// 76 /// Getting Cpuid error 77 /// 78 #[error("Failed to get Cpuid: {0}")] 79 GetCpuid(#[source] anyhow::Error), 80 /// 81 /// Setting lapic state error 82 /// 83 #[error("Failed to set Lapic state: {0}")] 84 SetLapicState(#[source] anyhow::Error), 85 /// 86 /// Getting Lapic state error 87 /// 88 #[error("Failed to get Lapic state: {0}")] 89 GetlapicState(#[source] anyhow::Error), 90 /// 91 /// Setting MSR entries error 92 /// 93 #[error("Failed to set Msr entries: {0}")] 94 SetMsrEntries(#[source] anyhow::Error), 95 /// 96 /// Getting Msr entries error 97 /// 98 #[error("Failed to get Msr entries: {0}")] 99 GetMsrEntries(#[source] anyhow::Error), 100 /// 101 /// Setting multi-processing state error 102 /// 103 #[error("Failed to set MP state: {0}")] 104 SetMpState(#[source] anyhow::Error), 105 /// 106 /// Getting multi-processing state error 107 /// 108 #[error("Failed to get MP state: {0}")] 109 GetMpState(#[source] anyhow::Error), 110 /// 111 /// Setting Saved Processor Extended States error 112 /// 113 #[cfg(feature = "kvm")] 114 #[error("Failed to set Saved Processor Extended States: {0}")] 115 SetXsaveState(#[source] anyhow::Error), 116 /// 117 /// Getting Saved Processor Extended States error 118 /// 119 #[cfg(feature = "kvm")] 120 #[error("Failed to get Saved Processor Extended States: {0}")] 121 GetXsaveState(#[source] anyhow::Error), 122 /// 123 /// Getting the VP state components error 124 /// 125 #[cfg(feature = "mshv")] 126 #[error("Failed to get VP State Components: {0}")] 127 GetAllVpStateComponents(#[source] anyhow::Error), 128 /// 129 /// Setting the VP state components error 130 /// 131 #[cfg(feature = "mshv")] 132 #[error("Failed to set VP State Components: {0}")] 133 SetAllVpStateComponents(#[source] anyhow::Error), 134 /// 135 /// Setting Extended Control Registers error 136 /// 137 #[error("Failed to set Extended Control Registers: {0}")] 138 SetXcsr(#[source] anyhow::Error), 139 /// 140 /// Getting Extended Control Registers error 141 /// 142 #[error("Failed to get Extended Control Registers: {0}")] 143 GetXcsr(#[source] anyhow::Error), 144 /// 145 /// Running Vcpu error 146 /// 147 #[error("Failed to run vcpu: {0}")] 148 RunVcpu(#[source] anyhow::Error), 149 /// 150 /// Getting Vcpu events error 151 /// 152 #[error("Failed to get Vcpu events: {0}")] 153 GetVcpuEvents(#[source] anyhow::Error), 154 /// 155 /// Setting Vcpu events error 156 /// 157 #[error("Failed to set Vcpu events: {0}")] 158 SetVcpuEvents(#[source] anyhow::Error), 159 /// 160 /// Vcpu Init error 161 /// 162 #[error("Failed to init vcpu: {0}")] 163 VcpuInit(#[source] anyhow::Error), 164 /// 165 /// Vcpu Finalize error 166 /// 167 #[error("Failed to finalize vcpu: {0}")] 168 VcpuFinalize(#[source] anyhow::Error), 169 /// 170 /// Setting one reg error 171 /// 172 #[error("Failed to set one reg: {0}")] 173 SetRegister(#[source] anyhow::Error), 174 /// 175 /// Getting one reg error 176 /// 177 #[error("Failed to get one reg: {0}")] 178 GetRegister(#[source] anyhow::Error), 179 /// 180 /// Getting guest clock paused error 181 /// 182 #[error("Failed to notify guest its clock was paused: {0}")] 183 NotifyGuestClockPaused(#[source] anyhow::Error), 184 /// 185 /// Setting debug register error 186 /// 187 #[error("Failed to set debug registers: {0}")] 188 SetDebugRegs(#[source] anyhow::Error), 189 /// 190 /// Getting debug register error 191 /// 192 #[error("Failed to get debug registers: {0}")] 193 GetDebugRegs(#[source] anyhow::Error), 194 /// 195 /// Setting misc register error 196 /// 197 #[error("Failed to set misc registers: {0}")] 198 SetMiscRegs(#[source] anyhow::Error), 199 /// 200 /// Getting misc register error 201 /// 202 #[error("Failed to get misc registers: {0}")] 203 GetMiscRegs(#[source] anyhow::Error), 204 /// 205 /// Write to Guest Mem 206 /// 207 #[error("Failed to write to Guest Mem at: {0}")] 208 GuestMemWrite(#[source] anyhow::Error), 209 /// Enabling HyperV SynIC error 210 /// 211 #[error("Failed to enable HyperV SynIC")] 212 EnableHyperVSyncIc(#[source] anyhow::Error), 213 /// 214 /// Getting AArch64 core register error 215 /// 216 #[error("Failed to get aarch64 core register: {0}")] 217 GetAarchCoreRegister(#[source] anyhow::Error), 218 /// 219 /// Setting AArch64 core register error 220 /// 221 #[error("Failed to set aarch64 core register: {0}")] 222 SetAarchCoreRegister(#[source] anyhow::Error), 223 /// 224 /// Getting RISC-V 64-bit core register error 225 /// 226 #[error("Failed to get riscv64 core register: {0}")] 227 GetRiscvCoreRegister(#[source] anyhow::Error), 228 /// 229 /// Setting RISC-V 64-bit core register error 230 /// 231 #[error("Failed to set riscv64 core register: {0}")] 232 SetRiscvCoreRegister(#[source] anyhow::Error), 233 /// 234 /// Getting registers list error 235 /// 236 #[error("Failed to retrieve list of registers: {0}")] 237 GetRegList(#[source] anyhow::Error), 238 /// 239 /// Getting AArch64 system register error 240 /// 241 #[error("Failed to get system register: {0}")] 242 GetSysRegister(#[source] anyhow::Error), 243 /// 244 /// Setting AArch64 system register error 245 /// 246 #[error("Failed to set system register: {0}")] 247 SetSysRegister(#[source] anyhow::Error), 248 /// 249 /// Getting RISC-V 64-bit non-core register error 250 /// 251 #[error("Failed to get non-core register: {0}")] 252 GetNonCoreRegister(#[source] anyhow::Error), 253 /// 254 /// Setting RISC-V 64-bit non-core register error 255 /// 256 #[error("Failed to set non-core register: {0}")] 257 SetNonCoreRegister(#[source] anyhow::Error), 258 /// 259 /// GVA translation error 260 /// 261 #[error("Failed to translate GVA: {0}")] 262 TranslateVirtualAddress(#[source] anyhow::Error), 263 /// 264 /// Set cpu attribute error 265 /// 266 #[error("Failed to set vcpu attribute: {0}")] 267 SetVcpuAttribute(#[source] anyhow::Error), 268 /// 269 /// Check if cpu has a certain attribute error 270 /// 271 #[error("Failed to check if vcpu has attribute: {0}")] 272 HasVcpuAttribute(#[source] anyhow::Error), 273 /// 274 /// Failed to initialize TDX on CPU 275 /// 276 #[cfg(feature = "tdx")] 277 #[error("Failed to initialize TDX: {0}")] 278 InitializeTdx(#[source] std::io::Error), 279 /// 280 /// Unknown TDX VM call 281 /// 282 #[cfg(feature = "tdx")] 283 #[error("Unknown TDX VM call")] 284 UnknownTdxVmCall, 285 #[cfg(target_arch = "aarch64")] 286 /// 287 /// Failed to initialize PMU 288 /// 289 #[error("Failed to initialize PMU")] 290 InitializePmu, 291 #[cfg(target_arch = "x86_64")] 292 /// 293 /// Error getting TSC frequency 294 /// 295 #[error("Failed to get TSC frequency: {0}")] 296 GetTscKhz(#[source] anyhow::Error), 297 /// 298 /// Error setting TSC frequency 299 /// 300 #[error("Failed to set TSC frequency: {0}")] 301 SetTscKhz(#[source] anyhow::Error), 302 /// 303 /// Error reading value at given GPA 304 /// 305 #[error("Failed to read from GPA: {0}")] 306 GpaRead(#[source] anyhow::Error), 307 /// 308 /// Error writing value at given GPA 309 /// 310 #[error("Failed to write to GPA: {0}")] 311 GpaWrite(#[source] anyhow::Error), 312 /// 313 /// Error getting CPUID leaf 314 /// 315 #[error("Failed to get CPUID entries: {0}")] 316 GetCpuidVales(#[source] anyhow::Error), 317 /// 318 /// Setting SEV control register error 319 /// 320 #[cfg(feature = "sev_snp")] 321 #[error("Failed to set sev control register: {0}")] 322 SetSevControlRegister(#[source] anyhow::Error), 323 324 /// Error injecting NMI 325 /// 326 #[error("Failed to inject NMI")] 327 Nmi(#[source] anyhow::Error), 328 } 329 330 #[derive(Debug)] 331 pub enum VmExit { 332 #[cfg(target_arch = "x86_64")] 333 IoapicEoi(u8 /* vector */), 334 Ignore, 335 Reset, 336 Shutdown, 337 Hyperv, 338 #[cfg(feature = "tdx")] 339 Tdx, 340 #[cfg(feature = "kvm")] 341 Debug, 342 } 343 344 /// 345 /// Result type for returning from a function 346 /// 347 pub type Result<T> = anyhow::Result<T, HypervisorCpuError>; 348 /// 349 /// Trait to represent a generic Vcpu 350 /// 351 pub trait Vcpu: Send + Sync { 352 /// 353 /// Returns StandardRegisters with default value set 354 /// 355 fn create_standard_regs(&self) -> StandardRegisters { 356 unimplemented!(); 357 } 358 /// 359 /// Returns the vCPU general purpose registers. 360 /// 361 fn get_regs(&self) -> Result<StandardRegisters>; 362 /// 363 /// Sets the vCPU general purpose registers. 364 /// 365 fn set_regs(&self, regs: &StandardRegisters) -> Result<()>; 366 #[cfg(target_arch = "x86_64")] 367 /// 368 /// Returns the vCPU special registers. 369 /// 370 fn get_sregs(&self) -> Result<SpecialRegisters>; 371 #[cfg(target_arch = "x86_64")] 372 /// 373 /// Sets the vCPU special registers 374 /// 375 fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>; 376 #[cfg(target_arch = "x86_64")] 377 /// 378 /// Returns the floating point state (FPU) from the vCPU. 379 /// 380 fn get_fpu(&self) -> Result<FpuState>; 381 #[cfg(target_arch = "x86_64")] 382 /// 383 /// Set the floating point state (FPU) of a vCPU 384 /// 385 fn set_fpu(&self, fpu: &FpuState) -> Result<()>; 386 #[cfg(target_arch = "x86_64")] 387 /// 388 /// X86 specific call to setup the CPUID registers. 389 /// 390 fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> Result<()>; 391 #[cfg(target_arch = "x86_64")] 392 /// 393 /// X86 specific call to enable HyperV SynIC 394 /// 395 fn enable_hyperv_synic(&self) -> Result<()>; 396 #[cfg(target_arch = "x86_64")] 397 /// 398 /// X86 specific call to retrieve the CPUID registers. 399 /// 400 fn get_cpuid2(&self, num_entries: usize) -> Result<Vec<CpuIdEntry>>; 401 #[cfg(target_arch = "x86_64")] 402 /// 403 /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 404 /// 405 fn get_lapic(&self) -> Result<LapicState>; 406 #[cfg(target_arch = "x86_64")] 407 /// 408 /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 409 /// 410 fn set_lapic(&self, lapic: &LapicState) -> Result<()>; 411 #[cfg(target_arch = "x86_64")] 412 /// 413 /// Returns the model-specific registers (MSR) for this vCPU. 414 /// 415 fn get_msrs(&self, msrs: &mut Vec<MsrEntry>) -> Result<usize>; 416 #[cfg(target_arch = "x86_64")] 417 /// 418 /// Setup the model-specific registers (MSR) for this vCPU. 419 /// 420 fn set_msrs(&self, msrs: &[MsrEntry]) -> Result<usize>; 421 /// 422 /// Returns the vcpu's current "multiprocessing state". 423 /// 424 fn get_mp_state(&self) -> Result<MpState>; 425 /// 426 /// Sets the vcpu's current "multiprocessing state". 427 /// 428 fn set_mp_state(&self, mp_state: MpState) -> Result<()>; 429 #[cfg(target_arch = "x86_64")] 430 /// 431 /// Let the guest know that it has been paused, which prevents from 432 /// potential soft lockups when being resumed. 433 /// 434 fn notify_guest_clock_paused(&self) -> Result<()> { 435 Ok(()) 436 } 437 /// 438 /// Sets debug registers to set hardware breakpoints and/or enable single step. 439 /// 440 #[cfg(not(target_arch = "riscv64"))] 441 fn set_guest_debug(&self, _addrs: &[GuestAddress], _singlestep: bool) -> Result<()> { 442 Err(HypervisorCpuError::SetDebugRegs(anyhow!("unimplemented"))) 443 } 444 /// 445 /// Sets the type of CPU to be exposed to the guest and optional features. 446 /// 447 #[cfg(target_arch = "aarch64")] 448 fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>; 449 450 #[cfg(target_arch = "aarch64")] 451 fn vcpu_finalize(&self, feature: i32) -> Result<()>; 452 453 /// 454 /// Gets a list of the guest registers that are supported for the 455 /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 456 /// 457 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] 458 fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>; 459 /// 460 /// Gets the value of a system register 461 /// 462 #[cfg(target_arch = "aarch64")] 463 fn get_sys_reg(&self, sys_reg: u32) -> Result<u64>; 464 /// 465 /// Gets the value of a non-core register on RISC-V 64-bit 466 /// 467 #[cfg(target_arch = "riscv64")] 468 fn get_non_core_reg(&self, non_core_reg: u32) -> Result<u64>; 469 /// 470 /// Configure core registers for a given CPU. 471 /// 472 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] 473 fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> Result<()>; 474 /// 475 /// Check if the CPU supports PMU 476 /// 477 #[cfg(target_arch = "aarch64")] 478 fn has_pmu_support(&self) -> bool; 479 /// 480 /// Initialize PMU 481 /// 482 #[cfg(target_arch = "aarch64")] 483 fn init_pmu(&self, irq: u32) -> Result<()>; 484 /// 485 /// Retrieve the vCPU state. 486 /// This function is necessary to snapshot the VM 487 /// 488 fn state(&self) -> Result<CpuState>; 489 /// 490 /// Set the vCPU state. 491 /// This function is required when restoring the VM 492 /// 493 fn set_state(&self, state: &CpuState) -> Result<()>; 494 /// 495 /// Triggers the running of the current virtual CPU returning an exit reason. 496 /// 497 fn run(&self) -> std::result::Result<VmExit, HypervisorCpuError>; 498 #[cfg(target_arch = "x86_64")] 499 /// 500 /// Translate guest virtual address to guest physical address 501 /// 502 fn translate_gva(&self, gva: u64, flags: u64) -> Result<(u64, u32)>; 503 /// 504 /// Initialize TDX support on the vCPU 505 /// 506 #[cfg(feature = "tdx")] 507 fn tdx_init(&self, _hob_address: u64) -> Result<()> { 508 unimplemented!() 509 } 510 /// 511 /// Set the "immediate_exit" state 512 /// 513 fn set_immediate_exit(&self, _exit: bool) {} 514 #[cfg(feature = "tdx")] 515 /// 516 /// Returns the details about TDX exit reason 517 /// 518 fn get_tdx_exit_details(&mut self) -> Result<TdxExitDetails> { 519 unimplemented!() 520 } 521 #[cfg(feature = "tdx")] 522 /// 523 /// Set the status code for TDX exit 524 /// 525 fn set_tdx_status(&mut self, _status: TdxExitStatus) { 526 unimplemented!() 527 } 528 #[cfg(target_arch = "x86_64")] 529 /// 530 /// Return the list of initial MSR entries for a VCPU 531 /// 532 fn boot_msr_entries(&self) -> Vec<MsrEntry>; 533 534 #[cfg(target_arch = "x86_64")] 535 /// 536 /// Get the frequency of the TSC if available 537 /// 538 fn tsc_khz(&self) -> Result<Option<u32>> { 539 Ok(None) 540 } 541 #[cfg(target_arch = "x86_64")] 542 /// 543 /// Set the frequency of the TSC if available 544 /// 545 fn set_tsc_khz(&self, _freq: u32) -> Result<()> { 546 Ok(()) 547 } 548 #[cfg(target_arch = "x86_64")] 549 /// 550 /// X86 specific call to retrieve cpuid leaf 551 /// 552 fn get_cpuid_values( 553 &self, 554 _function: u32, 555 _index: u32, 556 _xfem: u64, 557 _xss: u64, 558 ) -> Result<[u32; 4]> { 559 unimplemented!() 560 } 561 #[cfg(feature = "mshv")] 562 fn set_sev_control_register(&self, _reg: u64) -> Result<()> { 563 unimplemented!() 564 } 565 566 #[cfg(target_arch = "x86_64")] 567 /// 568 /// Trigger NMI interrupt 569 /// 570 fn nmi(&self) -> Result<()>; 571 } 572