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::VcpuInit; 13 #[cfg(target_arch = "aarch64")] 14 use crate::aarch64::{RegList, Register, StandardRegisters}; 15 #[cfg(target_arch = "x86_64")] 16 use crate::x86_64::{CpuId, LapicState}; 17 #[cfg(target_arch = "x86_64")] 18 use crate::x86_64::{ 19 ExtendedControlRegisters, FpuState, MsrEntries, SpecialRegisters, StandardRegisters, VcpuEvents, 20 }; 21 use crate::CpuState; 22 #[cfg(target_arch = "aarch64")] 23 use crate::DeviceAttr; 24 #[cfg(feature = "kvm")] 25 use crate::MpState; 26 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 27 use crate::SuspendRegisters; 28 #[cfg(target_arch = "x86_64")] 29 use crate::Xsave; 30 #[cfg(feature = "tdx")] 31 use crate::{TdxExitDetails, TdxExitStatus}; 32 use thiserror::Error; 33 #[cfg(all(feature = "kvm", target_arch = "x86_64"))] 34 use vm_memory::GuestAddress; 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 /// Getting suspend registers error 52 /// 53 #[error("Failed to get suspend registers: {0}")] 54 GetSuspendRegs(#[source] anyhow::Error), 55 /// 56 /// Setting special register error 57 /// 58 #[error("Failed to set special registers: {0}")] 59 SetSpecialRegs(#[source] anyhow::Error), 60 /// 61 /// Getting standard register error 62 /// 63 #[error("Failed to get special registers: {0}")] 64 GetSpecialRegs(#[source] anyhow::Error), 65 /// 66 /// Setting floating point registers error 67 /// 68 #[error("Failed to set special register: {0}")] 69 SetFloatingPointRegs(#[source] anyhow::Error), 70 /// 71 /// Getting floating point register error 72 /// 73 #[error("Failed to get special register: {0}")] 74 GetFloatingPointRegs(#[source] anyhow::Error), 75 /// 76 /// Setting Cpuid error 77 /// 78 #[error("Failed to set Cpuid: {0}")] 79 SetCpuid(#[source] anyhow::Error), 80 /// 81 /// Getting Cpuid error 82 /// 83 #[error("Failed to get Cpuid: {0}")] 84 GetCpuid(#[source] anyhow::Error), 85 /// 86 /// Setting lapic state error 87 /// 88 #[error("Failed to set Lapic state: {0}")] 89 SetLapicState(#[source] anyhow::Error), 90 /// 91 /// Getting Lapic state error 92 /// 93 #[error("Failed to get Lapic state: {0}")] 94 GetlapicState(#[source] anyhow::Error), 95 /// 96 /// Setting MSR entries error 97 /// 98 #[error("Failed to set Msr entries: {0}")] 99 SetMsrEntries(#[source] anyhow::Error), 100 /// 101 /// Getting Msr entries error 102 /// 103 #[error("Failed to get Msr entries: {0}")] 104 GetMsrEntries(#[source] anyhow::Error), 105 /// 106 /// Setting MSR entries error 107 /// 108 #[error("Failed to set MP state: {0}")] 109 SetMpState(#[source] anyhow::Error), 110 /// 111 /// Getting Msr entries error 112 /// 113 #[error("Failed to get MP state: {0}")] 114 GetMpState(#[source] anyhow::Error), 115 /// 116 /// Setting Saved Processor Extended States error 117 /// 118 #[error("Failed to set Saved Processor Extended States: {0}")] 119 SetXsaveState(#[source] anyhow::Error), 120 /// 121 /// Getting Saved Processor Extended States error 122 /// 123 #[error("Failed to get Saved Processor Extended States: {0}")] 124 GetXsaveState(#[source] anyhow::Error), 125 /// 126 /// Setting Extended Control Registers error 127 /// 128 #[error("Failed to set Extended Control Registers: {0}")] 129 SetXcsr(#[source] anyhow::Error), 130 /// 131 /// Getting Extended Control Registers error 132 /// 133 #[error("Failed to get Extended Control Registers: {0}")] 134 GetXcsr(#[source] anyhow::Error), 135 /// 136 /// Running Vcpu error 137 /// 138 #[error("Failed to run vcpu: {0}")] 139 RunVcpu(#[source] anyhow::Error), 140 /// 141 /// Getting Vcpu events error 142 /// 143 #[error("Failed to get Vcpu events: {0}")] 144 GetVcpuEvents(#[source] anyhow::Error), 145 /// 146 /// Setting Vcpu events error 147 /// 148 #[error("Failed to set Vcpu events: {0}")] 149 SetVcpuEvents(#[source] anyhow::Error), 150 /// 151 /// Vcpu Init error 152 /// 153 #[error("Failed to init vcpu: {0}")] 154 VcpuInit(#[source] anyhow::Error), 155 /// 156 /// Setting one reg error 157 /// 158 #[error("Failed to init vcpu: {0}")] 159 SetRegister(#[source] anyhow::Error), 160 /// 161 /// Getting one reg error 162 /// 163 #[error("Failed to init vcpu: {0}")] 164 GetRegister(#[source] anyhow::Error), 165 /// 166 /// Getting guest clock paused error 167 /// 168 #[error("Failed to notify guest its clock was paused: {0}")] 169 NotifyGuestClockPaused(#[source] anyhow::Error), 170 /// 171 /// Setting debug register error 172 /// 173 #[error("Failed to set debug registers: {0}")] 174 SetDebugRegs(#[source] anyhow::Error), 175 /// 176 /// Getting debug register error 177 /// 178 #[error("Failed to get debug registers: {0}")] 179 GetDebugRegs(#[source] anyhow::Error), 180 /// 181 /// Setting misc register error 182 /// 183 #[error("Failed to set misc registers: {0}")] 184 SetMiscRegs(#[source] anyhow::Error), 185 /// 186 /// Getting misc register error 187 /// 188 #[error("Failed to get misc registers: {0}")] 189 GetMiscRegs(#[source] anyhow::Error), 190 /// 191 /// Write to Guest Mem 192 /// 193 #[error("Failed to write to Guest Mem at: {0}")] 194 GuestMemWrite(#[source] anyhow::Error), 195 /// Enabling HyperV SynIC error 196 /// 197 #[error("Failed to enable HyperV SynIC")] 198 EnableHyperVSyncIc(#[source] anyhow::Error), 199 /// 200 /// Getting AArch64 core register error 201 /// 202 #[error("Failed to get core register: {0}")] 203 GetCoreRegister(#[source] anyhow::Error), 204 /// 205 /// Setting AArch64 core register error 206 /// 207 #[error("Failed to set core register: {0}")] 208 SetCoreRegister(#[source] anyhow::Error), 209 /// 210 /// Getting AArch64 registers list error 211 /// 212 #[error("Failed to retrieve list of registers: {0}")] 213 GetRegList(#[source] anyhow::Error), 214 /// 215 /// Getting AArch64 system register error 216 /// 217 #[error("Failed to get system register: {0}")] 218 GetSysRegister(#[source] anyhow::Error), 219 /// 220 /// Setting AArch64 system register error 221 /// 222 #[error("Failed to set system register: {0}")] 223 SetSysRegister(#[source] anyhow::Error), 224 /// 225 /// GVA translation error 226 /// 227 #[error("Failed to translate GVA: {0}")] 228 TranslateVirtualAddress(#[source] anyhow::Error), 229 /// 230 /// Set cpu attribute error 231 /// 232 #[error("Failed to set vcpu attribute: {0}")] 233 SetVcpuAttribute(#[source] anyhow::Error), 234 /// 235 /// Check if cpu has a certain attribute error 236 /// 237 #[error("Failed to check if vcpu has attribute: {0}")] 238 HasVcpuAttribute(#[source] anyhow::Error), 239 /// 240 /// Failed to initialize TDX on CPU 241 /// 242 #[cfg(feature = "tdx")] 243 #[error("Failed to initialize TDX: {0}")] 244 InitializeTdx(#[source] std::io::Error), 245 /// 246 /// Unknown TDX VM call 247 /// 248 #[cfg(feature = "tdx")] 249 #[error("Unknown TDX VM call")] 250 UnknownTdxVmCall, 251 } 252 253 #[derive(Debug)] 254 pub enum VmExit<'a> { 255 #[cfg(target_arch = "x86_64")] 256 IoOut(u16 /* port */, &'a [u8] /* data */), 257 #[cfg(target_arch = "x86_64")] 258 IoIn(u16 /* port */, &'a mut [u8] /* data */), 259 #[cfg(target_arch = "x86_64")] 260 IoapicEoi(u8 /* vector */), 261 MmioRead(u64 /* address */, &'a mut [u8]), 262 MmioWrite(u64 /* address */, &'a [u8]), 263 Ignore, 264 Reset, 265 Shutdown, 266 Hyperv, 267 #[cfg(feature = "tdx")] 268 Tdx, 269 #[cfg(feature = "kvm")] 270 Debug, 271 } 272 273 /// 274 /// Result type for returning from a function 275 /// 276 pub type Result<T> = anyhow::Result<T, HypervisorCpuError>; 277 /// 278 /// Trait to represent a generic Vcpu 279 /// 280 pub trait Vcpu: Send + Sync { 281 #[cfg(target_arch = "x86_64")] 282 /// 283 /// Returns the vCPU general purpose registers. 284 /// 285 fn get_regs(&self) -> Result<StandardRegisters>; 286 #[cfg(target_arch = "aarch64")] 287 /// 288 /// Sets vcpu attribute 289 /// 290 fn set_vcpu_attr(&self, attr: &DeviceAttr) -> Result<()>; 291 #[cfg(target_arch = "aarch64")] 292 /// 293 /// Check if vcpu has attribute. 294 /// 295 fn has_vcpu_attr(&self, attr: &DeviceAttr) -> Result<()>; 296 #[cfg(target_arch = "x86_64")] 297 /// 298 /// Sets the vCPU general purpose registers. 299 /// 300 fn set_regs(&self, regs: &StandardRegisters) -> Result<()>; 301 #[cfg(target_arch = "x86_64")] 302 /// 303 /// Returns the vCPU special registers. 304 /// 305 fn get_sregs(&self) -> Result<SpecialRegisters>; 306 #[cfg(target_arch = "x86_64")] 307 /// 308 /// Sets the vCPU special registers 309 /// 310 fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>; 311 #[cfg(target_arch = "x86_64")] 312 /// 313 /// Returns the floating point state (FPU) from the vCPU. 314 /// 315 fn get_fpu(&self) -> Result<FpuState>; 316 #[cfg(target_arch = "x86_64")] 317 /// 318 /// Set the floating point state (FPU) of a vCPU 319 /// 320 fn set_fpu(&self, fpu: &FpuState) -> Result<()>; 321 #[cfg(target_arch = "x86_64")] 322 /// 323 /// X86 specific call to setup the CPUID registers. 324 /// 325 fn set_cpuid2(&self, cpuid: &CpuId) -> Result<()>; 326 #[cfg(target_arch = "x86_64")] 327 /// 328 /// X86 specific call to enable HyperV SynIC 329 /// 330 fn enable_hyperv_synic(&self) -> Result<()>; 331 #[cfg(target_arch = "x86_64")] 332 /// 333 /// X86 specific call to retrieve the CPUID registers. 334 /// 335 fn get_cpuid2(&self, num_entries: usize) -> Result<CpuId>; 336 #[cfg(target_arch = "x86_64")] 337 /// 338 /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 339 /// 340 fn get_lapic(&self) -> Result<LapicState>; 341 #[cfg(target_arch = "x86_64")] 342 /// 343 /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 344 /// 345 fn set_lapic(&self, lapic: &LapicState) -> Result<()>; 346 #[cfg(target_arch = "x86_64")] 347 /// 348 /// Returns the model-specific registers (MSR) for this vCPU. 349 /// 350 fn get_msrs(&self, msrs: &mut MsrEntries) -> Result<usize>; 351 #[cfg(target_arch = "x86_64")] 352 /// 353 /// Setup the model-specific registers (MSR) for this vCPU. 354 /// 355 fn set_msrs(&self, msrs: &MsrEntries) -> Result<usize>; 356 #[cfg(feature = "kvm")] 357 /// 358 /// Returns the vcpu's current "multiprocessing state". 359 /// 360 fn get_mp_state(&self) -> Result<MpState>; 361 #[cfg(feature = "kvm")] 362 /// 363 /// Sets the vcpu's current "multiprocessing state". 364 /// 365 fn set_mp_state(&self, mp_state: MpState) -> Result<()>; 366 #[cfg(target_arch = "x86_64")] 367 /// 368 /// X86 specific call that returns the vcpu's current "xsave struct". 369 /// 370 fn get_xsave(&self) -> Result<Xsave>; 371 #[cfg(target_arch = "x86_64")] 372 /// 373 /// X86 specific call that sets the vcpu's current "xsave struct". 374 /// 375 fn set_xsave(&self, xsave: &Xsave) -> Result<()>; 376 #[cfg(target_arch = "x86_64")] 377 /// 378 /// X86 specific call that returns the vcpu's current "xcrs". 379 /// 380 fn get_xcrs(&self) -> Result<ExtendedControlRegisters>; 381 #[cfg(target_arch = "x86_64")] 382 /// 383 /// X86 specific call that sets the vcpu's current "xcrs". 384 /// 385 fn set_xcrs(&self, xcrs: &ExtendedControlRegisters) -> Result<()>; 386 #[cfg(target_arch = "x86_64")] 387 /// 388 /// Returns currently pending exceptions, interrupts, and NMIs as well as related 389 /// states of the vcpu. 390 /// 391 fn get_vcpu_events(&self) -> Result<VcpuEvents>; 392 #[cfg(target_arch = "x86_64")] 393 /// 394 /// Sets pending exceptions, interrupts, and NMIs as well as related states 395 /// of the vcpu. 396 /// 397 fn set_vcpu_events(&self, events: &VcpuEvents) -> Result<()>; 398 #[cfg(all(feature = "kvm", target_arch = "x86_64"))] 399 /// 400 /// Let the guest know that it has been paused, which prevents from 401 /// potential soft lockups when being resumed. 402 /// 403 fn notify_guest_clock_paused(&self) -> Result<()>; 404 #[cfg(all(feature = "kvm", target_arch = "x86_64"))] 405 /// 406 /// Sets debug registers to set hardware breakpoints and/or enable single step. 407 /// 408 fn set_guest_debug(&self, addrs: &[GuestAddress], singlestep: bool) -> Result<()>; 409 /// 410 /// Sets the type of CPU to be exposed to the guest and optional features. 411 /// 412 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 413 fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>; 414 /// 415 /// Sets the value of one register for this vCPU. 416 /// 417 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 418 fn set_reg(&self, reg_id: u64, data: u64) -> Result<()>; 419 /// 420 /// Sets the value of one register for this vCPU. 421 /// 422 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 423 fn get_reg(&self, reg_id: u64) -> Result<u64>; 424 /// 425 /// Gets a list of the guest registers that are supported for the 426 /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 427 /// 428 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 429 fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>; 430 /// 431 /// Save the state of the core registers. 432 /// 433 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 434 fn core_registers(&self, state: &mut StandardRegisters) -> Result<()>; 435 /// 436 /// Restore the state of the core registers. 437 /// 438 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 439 fn set_core_registers(&self, state: &StandardRegisters) -> Result<()>; 440 /// 441 /// Save the state of the system registers. 442 /// 443 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 444 fn system_registers(&self, state: &mut Vec<Register>) -> Result<()>; 445 /// 446 /// Restore the state of the system registers. 447 /// 448 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 449 fn set_system_registers(&self, state: &[Register]) -> Result<()>; 450 /// 451 /// Read the MPIDR - Multiprocessor Affinity Register. 452 /// 453 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 454 fn read_mpidr(&self) -> Result<u64>; 455 /// 456 /// Retrieve the vCPU state. 457 /// This function is necessary to snapshot the VM 458 /// 459 fn state(&self) -> Result<CpuState>; 460 /// 461 /// Set the vCPU state. 462 /// This function is required when restoring the VM 463 /// 464 fn set_state(&self, state: &CpuState) -> Result<()>; 465 /// 466 /// Triggers the running of the current virtual CPU returning an exit reason. 467 /// 468 fn run(&self) -> std::result::Result<VmExit, HypervisorCpuError>; 469 #[cfg(target_arch = "x86_64")] 470 /// 471 /// Translate guest virtual address to guest physical address 472 /// 473 fn translate_gva(&self, gva: u64, flags: u64) -> Result<(u64, u32)>; 474 /// 475 /// Initialize TDX support on the vCPU 476 /// 477 #[cfg(feature = "tdx")] 478 fn tdx_init(&self, hob_address: u64) -> Result<()>; 479 #[cfg(all(feature = "mshv", target_arch = "x86_64"))] 480 /// 481 /// Return suspend registers(explicit and intercept suspend registers) 482 /// 483 fn get_suspend_regs(&self) -> Result<SuspendRegisters>; 484 #[cfg(feature = "kvm")] 485 /// 486 /// Set the "immediate_exit" state 487 /// 488 fn set_immediate_exit(&self, exit: bool); 489 #[cfg(feature = "tdx")] 490 /// 491 /// Returns the details about TDX exit reason 492 /// 493 fn get_tdx_exit_details(&mut self) -> Result<TdxExitDetails>; 494 #[cfg(feature = "tdx")] 495 /// 496 /// Set the status code for TDX exit 497 /// 498 fn set_tdx_status(&mut self, status: TdxExitStatus); 499 } 500