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 use crate::MpState; 23 use thiserror::Error; 24 #[cfg(target_arch = "x86_64")] 25 use vm_memory::GuestAddress; 26 27 #[derive(Error, Debug)] 28 /// 29 /// Enum for CPU error 30 pub enum HypervisorCpuError { 31 /// 32 /// Setting standard registers error 33 /// 34 #[error("Failed to set standard register: {0}")] 35 SetStandardRegs(#[source] anyhow::Error), 36 /// 37 /// Setting standard registers error 38 /// 39 #[error("Failed to get standard registers: {0}")] 40 GetStandardRegs(#[source] anyhow::Error), 41 /// 42 /// Setting special register error 43 /// 44 #[error("Failed to set special registers: {0}")] 45 SetSpecialRegs(#[source] anyhow::Error), 46 /// 47 /// Getting standard register error 48 /// 49 #[error("Failed to get special registers: {0}")] 50 GetSpecialRegs(#[source] anyhow::Error), 51 /// 52 /// Setting floating point registers error 53 /// 54 #[error("Failed to set special register: {0}")] 55 SetFloatingPointRegs(#[source] anyhow::Error), 56 /// 57 /// Getting floating point register error 58 /// 59 #[error("Failed to get special register: {0}")] 60 GetFloatingPointRegs(#[source] anyhow::Error), 61 /// 62 /// Setting Cpuid error 63 /// 64 #[error("Failed to set Cpuid: {0}")] 65 SetCpuid(#[source] anyhow::Error), 66 /// 67 /// Getting Cpuid error 68 /// 69 #[error("Failed to get Cpuid: {0}")] 70 GetCpuid(#[source] anyhow::Error), 71 /// 72 /// Setting lapic state error 73 /// 74 #[error("Failed to set Lapic state: {0}")] 75 SetLapicState(#[source] anyhow::Error), 76 /// 77 /// Getting Lapic state error 78 /// 79 #[error("Failed to get Lapic state: {0}")] 80 GetlapicState(#[source] anyhow::Error), 81 /// 82 /// Setting MSR entries error 83 /// 84 #[error("Failed to set Msr entries: {0}")] 85 SetMsrEntries(#[source] anyhow::Error), 86 /// 87 /// Getting Msr entries error 88 /// 89 #[error("Failed to get Msr entries: {0}")] 90 GetMsrEntries(#[source] anyhow::Error), 91 /// 92 /// Setting MSR entries error 93 /// 94 #[error("Failed to set MP state: {0}")] 95 SetMpState(#[source] anyhow::Error), 96 /// 97 /// Getting Msr entries error 98 /// 99 #[error("Failed to get MP state: {0}")] 100 GetMpState(#[source] anyhow::Error), 101 /// 102 /// Setting Saved Processor Extended States error 103 /// 104 #[error("Failed to set Saved Processor Extended States: {0}")] 105 SetXsaveState(#[source] anyhow::Error), 106 /// 107 /// Getting Saved Processor Extended States error 108 /// 109 #[error("Failed to get Saved Processor Extended States: {0}")] 110 GetXsaveState(#[source] anyhow::Error), 111 /// 112 /// Setting Extended Control Registers error 113 /// 114 #[error("Failed to set Extended Control Registers: {0}")] 115 SetXcsr(#[source] anyhow::Error), 116 /// 117 /// Getting Extended Control Registers error 118 /// 119 #[error("Failed to get Extended Control Registers: {0}")] 120 GetXcsr(#[source] anyhow::Error), 121 /// 122 /// Running Vcpu error 123 /// 124 #[error("Failed to run vcpu: {0}")] 125 RunVcpu(#[source] anyhow::Error), 126 /// 127 /// Getting Vcpu events error 128 /// 129 #[error("Failed to get Vcpu events: {0}")] 130 GetVcpuEvents(#[source] anyhow::Error), 131 /// 132 /// Setting Vcpu events error 133 /// 134 #[error("Failed to set Vcpu events: {0}")] 135 SetVcpuEvents(#[source] anyhow::Error), 136 /// 137 /// Vcpu Init error 138 /// 139 #[error("Failed to init vcpu: {0}")] 140 VcpuInit(#[source] anyhow::Error), 141 /// 142 /// Setting one reg error 143 /// 144 #[error("Failed to init vcpu: {0}")] 145 SetRegister(#[source] anyhow::Error), 146 /// 147 /// Getting one reg error 148 /// 149 #[error("Failed to init vcpu: {0}")] 150 GetRegister(#[source] anyhow::Error), 151 /// 152 /// Getting guest clock paused error 153 /// 154 #[error("Failed to notify guest its clock was paused: {0}")] 155 NotifyGuestClockPaused(#[source] anyhow::Error), 156 /// 157 /// Setting debug register error 158 /// 159 #[error("Failed to set debug registers: {0}")] 160 SetDebugRegs(#[source] anyhow::Error), 161 /// 162 /// Getting debug register error 163 /// 164 #[error("Failed to get debug registers: {0}")] 165 GetDebugRegs(#[source] anyhow::Error), 166 /// 167 /// Setting misc register error 168 /// 169 #[error("Failed to set misc registers: {0}")] 170 SetMiscRegs(#[source] anyhow::Error), 171 /// 172 /// Getting misc register error 173 /// 174 #[error("Failed to get misc registers: {0}")] 175 GetMiscRegs(#[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 /// Set cpu attribute error 217 /// 218 #[error("Failed to set vcpu attribute: {0}")] 219 SetVcpuAttribute(#[source] anyhow::Error), 220 /// 221 /// Check if cpu has a certain attribute error 222 /// 223 #[error("Failed to check if vcpu has attribute: {0}")] 224 HasVcpuAttribute(#[source] anyhow::Error), 225 /// 226 /// Failed to initialize TDX on CPU 227 /// 228 #[cfg(feature = "tdx")] 229 #[error("Failed to initialize TDX: {0}")] 230 InitializeTdx(#[source] std::io::Error), 231 /// 232 /// Unknown TDX VM call 233 /// 234 #[cfg(feature = "tdx")] 235 #[error("Unknown TDX VM call")] 236 UnknownTdxVmCall, 237 #[cfg(target_arch = "aarch64")] 238 /// 239 /// Failed to intialize PMU 240 /// 241 #[error("Failed to initialize PMU")] 242 InitializePmu, 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 #[cfg(feature = "tdx")] 260 Tdx, 261 #[cfg(feature = "kvm")] 262 Debug, 263 } 264 265 /// 266 /// Result type for returning from a function 267 /// 268 pub type Result<T> = anyhow::Result<T, HypervisorCpuError>; 269 /// 270 /// Trait to represent a generic Vcpu 271 /// 272 pub trait Vcpu: Send + Sync { 273 /// 274 /// Returns the vCPU general purpose registers. 275 /// 276 fn get_regs(&self) -> Result<StandardRegisters>; 277 /// 278 /// Sets the vCPU general purpose registers. 279 /// 280 fn set_regs(&self, regs: &StandardRegisters) -> Result<()>; 281 #[cfg(target_arch = "x86_64")] 282 /// 283 /// Returns the vCPU special registers. 284 /// 285 fn get_sregs(&self) -> Result<SpecialRegisters>; 286 #[cfg(target_arch = "x86_64")] 287 /// 288 /// Sets the vCPU special registers 289 /// 290 fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>; 291 #[cfg(target_arch = "x86_64")] 292 /// 293 /// Returns the floating point state (FPU) from the vCPU. 294 /// 295 fn get_fpu(&self) -> Result<FpuState>; 296 #[cfg(target_arch = "x86_64")] 297 /// 298 /// Set the floating point state (FPU) of a vCPU 299 /// 300 fn set_fpu(&self, fpu: &FpuState) -> Result<()>; 301 #[cfg(target_arch = "x86_64")] 302 /// 303 /// X86 specific call to setup the CPUID registers. 304 /// 305 fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> Result<()>; 306 #[cfg(target_arch = "x86_64")] 307 /// 308 /// X86 specific call to enable HyperV SynIC 309 /// 310 fn enable_hyperv_synic(&self) -> Result<()>; 311 #[cfg(target_arch = "x86_64")] 312 /// 313 /// X86 specific call to retrieve the CPUID registers. 314 /// 315 fn get_cpuid2(&self, num_entries: usize) -> Result<Vec<CpuIdEntry>>; 316 #[cfg(target_arch = "x86_64")] 317 /// 318 /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 319 /// 320 fn get_lapic(&self) -> Result<LapicState>; 321 #[cfg(target_arch = "x86_64")] 322 /// 323 /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 324 /// 325 fn set_lapic(&self, lapic: &LapicState) -> Result<()>; 326 #[cfg(target_arch = "x86_64")] 327 /// 328 /// Returns the model-specific registers (MSR) for this vCPU. 329 /// 330 fn get_msrs(&self, msrs: &mut Vec<MsrEntry>) -> Result<usize>; 331 #[cfg(target_arch = "x86_64")] 332 /// 333 /// Setup the model-specific registers (MSR) for this vCPU. 334 /// 335 fn set_msrs(&self, msrs: &[MsrEntry]) -> Result<usize>; 336 /// 337 /// Returns the vcpu's current "multiprocessing state". 338 /// 339 fn get_mp_state(&self) -> Result<MpState>; 340 /// 341 /// Sets the vcpu's current "multiprocessing state". 342 /// 343 fn set_mp_state(&self, mp_state: MpState) -> Result<()>; 344 #[cfg(target_arch = "x86_64")] 345 /// 346 /// Let the guest know that it has been paused, which prevents from 347 /// potential soft lockups when being resumed. 348 /// 349 fn notify_guest_clock_paused(&self) -> Result<()> { 350 Ok(()) 351 } 352 #[cfg(target_arch = "x86_64")] 353 /// 354 /// Sets debug registers to set hardware breakpoints and/or enable single step. 355 /// 356 fn set_guest_debug(&self, _addrs: &[GuestAddress], _singlestep: bool) -> Result<()> { 357 Err(HypervisorCpuError::SetDebugRegs(anyhow!("unimplemented"))) 358 } 359 /// 360 /// Sets the type of CPU to be exposed to the guest and optional features. 361 /// 362 #[cfg(target_arch = "aarch64")] 363 fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>; 364 /// 365 /// Sets the value of one register for this vCPU. 366 /// 367 #[cfg(target_arch = "aarch64")] 368 fn set_reg(&self, reg_id: u64, data: u64) -> Result<()>; 369 /// 370 /// Sets the value of one register for this vCPU. 371 /// 372 #[cfg(target_arch = "aarch64")] 373 fn get_reg(&self, reg_id: u64) -> Result<u64>; 374 /// 375 /// Gets a list of the guest registers that are supported for the 376 /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 377 /// 378 #[cfg(target_arch = "aarch64")] 379 fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>; 380 /// 381 /// Save the state of the system registers. 382 /// 383 #[cfg(target_arch = "aarch64")] 384 fn get_sys_regs(&self) -> Result<Vec<Register>>; 385 /// 386 /// Restore the state of the system registers. 387 /// 388 #[cfg(target_arch = "aarch64")] 389 fn set_sys_regs(&self, state: &[Register]) -> Result<()>; 390 /// 391 /// Read the MPIDR - Multiprocessor Affinity Register. 392 /// 393 #[cfg(target_arch = "aarch64")] 394 fn read_mpidr(&self) -> Result<u64>; 395 /// 396 /// Configure core registers for a given CPU. 397 /// 398 #[cfg(target_arch = "aarch64")] 399 fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> Result<()>; 400 /// 401 /// Check if the CPU supports PMU 402 /// 403 #[cfg(target_arch = "aarch64")] 404 fn has_pmu_support(&self) -> bool; 405 /// 406 /// Initialize PMU 407 /// 408 #[cfg(target_arch = "aarch64")] 409 fn init_pmu(&self, irq: u32) -> Result<()>; 410 /// 411 /// Retrieve the vCPU state. 412 /// This function is necessary to snapshot the VM 413 /// 414 fn state(&self) -> Result<CpuState>; 415 /// 416 /// Set the vCPU state. 417 /// This function is required when restoring the VM 418 /// 419 fn set_state(&self, state: &CpuState) -> Result<()>; 420 /// 421 /// Triggers the running of the current virtual CPU returning an exit reason. 422 /// 423 fn run(&self) -> std::result::Result<VmExit, HypervisorCpuError>; 424 #[cfg(target_arch = "x86_64")] 425 /// 426 /// Translate guest virtual address to guest physical address 427 /// 428 fn translate_gva(&self, gva: u64, flags: u64) -> Result<(u64, u32)>; 429 /// 430 /// Initialize TDX support on the vCPU 431 /// 432 #[cfg(feature = "tdx")] 433 fn tdx_init(&self, hob_address: u64) -> Result<()>; 434 /// 435 /// Set the "immediate_exit" state 436 /// 437 fn set_immediate_exit(&self, _exit: bool) {} 438 #[cfg(feature = "tdx")] 439 /// 440 /// Returns the details about TDX exit reason 441 /// 442 fn get_tdx_exit_details(&mut self) -> Result<TdxExitDetails>; 443 #[cfg(feature = "tdx")] 444 /// 445 /// Set the status code for TDX exit 446 /// 447 fn set_tdx_status(&mut self, status: TdxExitStatus); 448 #[cfg(target_arch = "x86_64")] 449 /// 450 /// Return the list of initial MSR entries for a VCPU 451 /// 452 fn boot_msr_entries(&self) -> Vec<MsrEntry>; 453 } 454