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