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