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