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