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