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