1*f9b51a41SMuminul Islam // Copyright © 2019 Intel Corporation 2*f9b51a41SMuminul Islam // 3*f9b51a41SMuminul Islam // SPDX-License-Identifier: Apache-2.0 4*f9b51a41SMuminul Islam // 5*f9b51a41SMuminul Islam // Copyright © 2020, Microsoft Corporation 6*f9b51a41SMuminul Islam // 7*f9b51a41SMuminul Islam // Copyright 2018-2019 CrowdStrike, Inc. 8*f9b51a41SMuminul Islam // 9*f9b51a41SMuminul Islam // SPDX-License-Identifier: Apache-2.0 OR MIT 10*f9b51a41SMuminul Islam 11*f9b51a41SMuminul Islam #[cfg(target_arch = "aarch64")] 12*f9b51a41SMuminul Islam use crate::aarch64::VcpuInit; 13*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 14*f9b51a41SMuminul Islam pub use crate::x86_64::{CpuId, ExtendedControlRegisters, LapicState, MsrEntries, Xsave}; 15*f9b51a41SMuminul Islam use crate::{FpuState, MpState, SpecialRegisters, StandardRegisters, VcpuEvents, VcpuExit}; 16*f9b51a41SMuminul Islam use thiserror::Error; 17*f9b51a41SMuminul Islam use vmm_sys_util::errno::Error as RunError; 18*f9b51a41SMuminul Islam 19*f9b51a41SMuminul Islam pub struct CpuState {} 20*f9b51a41SMuminul Islam 21*f9b51a41SMuminul Islam #[derive(Error, Debug)] 22*f9b51a41SMuminul Islam /// 23*f9b51a41SMuminul Islam /// Enum for CPU error 24*f9b51a41SMuminul Islam pub enum HypervisorCpuError { 25*f9b51a41SMuminul Islam /// 26*f9b51a41SMuminul Islam /// Setting standard registers error 27*f9b51a41SMuminul Islam /// 28*f9b51a41SMuminul Islam #[error("Failed to set standard register: {0}")] 29*f9b51a41SMuminul Islam SetStandardRegs(#[source] anyhow::Error), 30*f9b51a41SMuminul Islam /// 31*f9b51a41SMuminul Islam /// Setting standard registers error 32*f9b51a41SMuminul Islam /// 33*f9b51a41SMuminul Islam #[error("Failed to get standard registers: {0}")] 34*f9b51a41SMuminul Islam GetStandardRegs(#[source] anyhow::Error), 35*f9b51a41SMuminul Islam /// 36*f9b51a41SMuminul Islam /// Setting special register error 37*f9b51a41SMuminul Islam /// 38*f9b51a41SMuminul Islam #[error("Failed to set special registers: {0}")] 39*f9b51a41SMuminul Islam SetSpecialRegs(#[source] anyhow::Error), 40*f9b51a41SMuminul Islam /// 41*f9b51a41SMuminul Islam /// Getting standard register error 42*f9b51a41SMuminul Islam /// 43*f9b51a41SMuminul Islam #[error("Failed to get special registers: {0}")] 44*f9b51a41SMuminul Islam GetSpecialRegs(#[source] anyhow::Error), 45*f9b51a41SMuminul Islam /// 46*f9b51a41SMuminul Islam /// Setting floating point registers error 47*f9b51a41SMuminul Islam /// 48*f9b51a41SMuminul Islam #[error("Failed to set special register: {0}")] 49*f9b51a41SMuminul Islam SetFloatingPointRegs(#[source] anyhow::Error), 50*f9b51a41SMuminul Islam /// 51*f9b51a41SMuminul Islam /// Getting floating point register error 52*f9b51a41SMuminul Islam /// 53*f9b51a41SMuminul Islam #[error("Failed to get special register: {0}")] 54*f9b51a41SMuminul Islam GetFloatingPointRegs(#[source] anyhow::Error), 55*f9b51a41SMuminul Islam /// 56*f9b51a41SMuminul Islam /// Setting Cpuid error 57*f9b51a41SMuminul Islam /// 58*f9b51a41SMuminul Islam #[error("Failed to set Cpuid: {0}")] 59*f9b51a41SMuminul Islam SetCpuid(#[source] anyhow::Error), 60*f9b51a41SMuminul Islam /// 61*f9b51a41SMuminul Islam /// Getting Cpuid error 62*f9b51a41SMuminul Islam /// 63*f9b51a41SMuminul Islam #[error("Failed to get Cpuid: {0}")] 64*f9b51a41SMuminul Islam GetCpuid(#[source] anyhow::Error), 65*f9b51a41SMuminul Islam /// 66*f9b51a41SMuminul Islam /// Setting lapic state error 67*f9b51a41SMuminul Islam /// 68*f9b51a41SMuminul Islam #[error("Failed to set Lapic state: {0}")] 69*f9b51a41SMuminul Islam SetLapicState(#[source] anyhow::Error), 70*f9b51a41SMuminul Islam /// 71*f9b51a41SMuminul Islam /// Getting Lapic state error 72*f9b51a41SMuminul Islam /// 73*f9b51a41SMuminul Islam #[error("Failed to get Lapic state: {0}")] 74*f9b51a41SMuminul Islam GetlapicState(#[source] anyhow::Error), 75*f9b51a41SMuminul Islam /// 76*f9b51a41SMuminul Islam /// Setting MSR entries error 77*f9b51a41SMuminul Islam /// 78*f9b51a41SMuminul Islam #[error("Failed to set Msr entries: {0}")] 79*f9b51a41SMuminul Islam SetMsrEntries(#[source] anyhow::Error), 80*f9b51a41SMuminul Islam /// 81*f9b51a41SMuminul Islam /// Getting Msr entries error 82*f9b51a41SMuminul Islam /// 83*f9b51a41SMuminul Islam #[error("Failed to get Msr entries: {0}")] 84*f9b51a41SMuminul Islam GetMsrEntries(#[source] anyhow::Error), 85*f9b51a41SMuminul Islam /// 86*f9b51a41SMuminul Islam /// Setting MSR entries error 87*f9b51a41SMuminul Islam /// 88*f9b51a41SMuminul Islam #[error("Failed to set MP state: {0}")] 89*f9b51a41SMuminul Islam SetMpState(#[source] anyhow::Error), 90*f9b51a41SMuminul Islam /// 91*f9b51a41SMuminul Islam /// Getting Msr entries error 92*f9b51a41SMuminul Islam /// 93*f9b51a41SMuminul Islam #[error("Failed to get MP state: {0}")] 94*f9b51a41SMuminul Islam GetMpState(#[source] anyhow::Error), 95*f9b51a41SMuminul Islam /// 96*f9b51a41SMuminul Islam /// Setting Saved Processor Extended States error 97*f9b51a41SMuminul Islam /// 98*f9b51a41SMuminul Islam #[error("Failed to set Saved Processor Extended States: {0}")] 99*f9b51a41SMuminul Islam SetXsaveState(#[source] anyhow::Error), 100*f9b51a41SMuminul Islam /// 101*f9b51a41SMuminul Islam /// Getting Saved Processor Extended States error 102*f9b51a41SMuminul Islam /// 103*f9b51a41SMuminul Islam #[error("Failed to get Saved Processor Extended States: {0}")] 104*f9b51a41SMuminul Islam GetXsaveState(#[source] anyhow::Error), 105*f9b51a41SMuminul Islam /// 106*f9b51a41SMuminul Islam /// Setting Extended Control Registers error 107*f9b51a41SMuminul Islam /// 108*f9b51a41SMuminul Islam #[error("Failed to set Extended Control Registers: {0}")] 109*f9b51a41SMuminul Islam SetXcsr(#[source] anyhow::Error), 110*f9b51a41SMuminul Islam /// 111*f9b51a41SMuminul Islam /// Getting Extended Control Registers error 112*f9b51a41SMuminul Islam /// 113*f9b51a41SMuminul Islam #[error("Failed to get Extended Control Registers: {0}")] 114*f9b51a41SMuminul Islam GetXcsr(#[source] anyhow::Error), 115*f9b51a41SMuminul Islam /// 116*f9b51a41SMuminul Islam /// Running Vcpu error 117*f9b51a41SMuminul Islam /// 118*f9b51a41SMuminul Islam #[error("Failed to run vcpu: {0}")] 119*f9b51a41SMuminul Islam RunVcpu(#[source] anyhow::Error), 120*f9b51a41SMuminul Islam /// 121*f9b51a41SMuminul Islam /// Getting Vcpu events error 122*f9b51a41SMuminul Islam /// 123*f9b51a41SMuminul Islam #[error("Failed to get Vcpu events: {0}")] 124*f9b51a41SMuminul Islam GetVcpuEvents(#[source] anyhow::Error), 125*f9b51a41SMuminul Islam /// 126*f9b51a41SMuminul Islam /// Vcpu Init error 127*f9b51a41SMuminul Islam /// 128*f9b51a41SMuminul Islam #[error("Failed to init vcpu: {0}")] 129*f9b51a41SMuminul Islam VcpuInit(#[source] anyhow::Error), 130*f9b51a41SMuminul Islam /// 131*f9b51a41SMuminul Islam /// Setting one reg error 132*f9b51a41SMuminul Islam /// 133*f9b51a41SMuminul Islam #[error("Failed to init vcpu: {0}")] 134*f9b51a41SMuminul Islam SetOneReg(#[source] anyhow::Error), 135*f9b51a41SMuminul Islam /// 136*f9b51a41SMuminul Islam /// Getting one reg error 137*f9b51a41SMuminul Islam /// 138*f9b51a41SMuminul Islam #[error("Failed to init vcpu: {0}")] 139*f9b51a41SMuminul Islam GetOneReg(#[source] anyhow::Error), 140*f9b51a41SMuminul Islam } 141*f9b51a41SMuminul Islam 142*f9b51a41SMuminul Islam /// 143*f9b51a41SMuminul Islam /// Result type for returning from a function 144*f9b51a41SMuminul Islam /// 145*f9b51a41SMuminul Islam pub type Result<T> = anyhow::Result<T, HypervisorCpuError>; 146*f9b51a41SMuminul Islam /// 147*f9b51a41SMuminul Islam /// Trait to represent a generic Vcpu 148*f9b51a41SMuminul Islam /// 149*f9b51a41SMuminul Islam pub trait Vcpu: Send + Sync { 150*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 151*f9b51a41SMuminul Islam /// 152*f9b51a41SMuminul Islam /// Returns the vCPU general purpose registers. 153*f9b51a41SMuminul Islam /// 154*f9b51a41SMuminul Islam fn get_regs(&self) -> Result<StandardRegisters>; 155*f9b51a41SMuminul Islam 156*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 157*f9b51a41SMuminul Islam /// 158*f9b51a41SMuminul Islam /// Sets the vCPU general purpose registers. 159*f9b51a41SMuminul Islam /// 160*f9b51a41SMuminul Islam fn set_regs(&self, regs: &StandardRegisters) -> Result<()>; 161*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 162*f9b51a41SMuminul Islam /// 163*f9b51a41SMuminul Islam /// Returns the vCPU special registers. 164*f9b51a41SMuminul Islam /// 165*f9b51a41SMuminul Islam fn get_sregs(&self) -> Result<SpecialRegisters>; 166*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 167*f9b51a41SMuminul Islam /// 168*f9b51a41SMuminul Islam /// Sets the vCPU special registers 169*f9b51a41SMuminul Islam /// 170*f9b51a41SMuminul Islam fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>; 171*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 172*f9b51a41SMuminul Islam /// 173*f9b51a41SMuminul Islam /// Returns the floating point state (FPU) from the vCPU. 174*f9b51a41SMuminul Islam /// 175*f9b51a41SMuminul Islam fn get_fpu(&self) -> Result<FpuState>; 176*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 177*f9b51a41SMuminul Islam /// 178*f9b51a41SMuminul Islam /// Set the floating point state (FPU) of a vCPU 179*f9b51a41SMuminul Islam /// 180*f9b51a41SMuminul Islam fn set_fpu(&self, fpu: &FpuState) -> Result<()>; 181*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 182*f9b51a41SMuminul Islam /// 183*f9b51a41SMuminul Islam /// X86 specific call to setup the CPUID registers. 184*f9b51a41SMuminul Islam /// 185*f9b51a41SMuminul Islam fn set_cpuid2(&self, cpuid: &CpuId) -> Result<()>; 186*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 187*f9b51a41SMuminul Islam /// 188*f9b51a41SMuminul Islam /// X86 specific call to retrieve the CPUID registers. 189*f9b51a41SMuminul Islam /// 190*f9b51a41SMuminul Islam fn get_cpuid2(&self, num_entries: usize) -> Result<CpuId>; 191*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 192*f9b51a41SMuminul Islam /// 193*f9b51a41SMuminul Islam /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 194*f9b51a41SMuminul Islam /// 195*f9b51a41SMuminul Islam fn get_lapic(&self) -> Result<LapicState>; 196*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 197*f9b51a41SMuminul Islam /// 198*f9b51a41SMuminul Islam /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). 199*f9b51a41SMuminul Islam /// 200*f9b51a41SMuminul Islam fn set_lapic(&self, lapic: &LapicState) -> Result<()>; 201*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 202*f9b51a41SMuminul Islam /// 203*f9b51a41SMuminul Islam /// Returns the model-specific registers (MSR) for this vCPU. 204*f9b51a41SMuminul Islam /// 205*f9b51a41SMuminul Islam fn get_msrs(&self, msrs: &mut MsrEntries) -> Result<usize>; 206*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 207*f9b51a41SMuminul Islam /// 208*f9b51a41SMuminul Islam /// Setup the model-specific registers (MSR) for this vCPU. 209*f9b51a41SMuminul Islam /// 210*f9b51a41SMuminul Islam fn set_msrs(&self, msrs: &MsrEntries) -> Result<usize>; 211*f9b51a41SMuminul Islam /// 212*f9b51a41SMuminul Islam /// Returns the vcpu's current "multiprocessing state". 213*f9b51a41SMuminul Islam /// 214*f9b51a41SMuminul Islam fn get_mp_state(&self) -> Result<MpState>; 215*f9b51a41SMuminul Islam /// 216*f9b51a41SMuminul Islam /// Sets the vcpu's current "multiprocessing state". 217*f9b51a41SMuminul Islam /// 218*f9b51a41SMuminul Islam fn set_mp_state(&self, mp_state: MpState) -> Result<()>; 219*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 220*f9b51a41SMuminul Islam /// 221*f9b51a41SMuminul Islam /// X86 specific call that returns the vcpu's current "xsave struct". 222*f9b51a41SMuminul Islam /// 223*f9b51a41SMuminul Islam fn get_xsave(&self) -> Result<Xsave>; 224*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 225*f9b51a41SMuminul Islam /// 226*f9b51a41SMuminul Islam /// X86 specific call that sets the vcpu's current "xsave struct". 227*f9b51a41SMuminul Islam /// 228*f9b51a41SMuminul Islam fn set_xsave(&self, xsave: &Xsave) -> Result<()>; 229*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 230*f9b51a41SMuminul Islam /// 231*f9b51a41SMuminul Islam /// X86 specific call that returns the vcpu's current "xcrs". 232*f9b51a41SMuminul Islam /// 233*f9b51a41SMuminul Islam fn get_xcrs(&self) -> Result<ExtendedControlRegisters>; 234*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 235*f9b51a41SMuminul Islam /// 236*f9b51a41SMuminul Islam /// X86 specific call that sets the vcpu's current "xcrs". 237*f9b51a41SMuminul Islam /// 238*f9b51a41SMuminul Islam fn set_xcrs(&self, xcrs: &ExtendedControlRegisters) -> Result<()>; 239*f9b51a41SMuminul Islam /// 240*f9b51a41SMuminul Islam /// Triggers the running of the current virtual CPU returning an exit reason. 241*f9b51a41SMuminul Islam /// 242*f9b51a41SMuminul Islam fn run(&self) -> std::result::Result<VcpuExit, RunError>; 243*f9b51a41SMuminul Islam #[cfg(target_arch = "x86_64")] 244*f9b51a41SMuminul Islam /// 245*f9b51a41SMuminul Islam /// Returns currently pending exceptions, interrupts, and NMIs as well as related 246*f9b51a41SMuminul Islam /// states of the vcpu. 247*f9b51a41SMuminul Islam /// 248*f9b51a41SMuminul Islam fn get_vcpu_events(&self) -> Result<VcpuEvents>; 249*f9b51a41SMuminul Islam /// 250*f9b51a41SMuminul Islam /// Sets the type of CPU to be exposed to the guest and optional features. 251*f9b51a41SMuminul Islam /// 252*f9b51a41SMuminul Islam #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 253*f9b51a41SMuminul Islam fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>; 254*f9b51a41SMuminul Islam /// 255*f9b51a41SMuminul Islam /// Sets the value of one register for this vCPU. 256*f9b51a41SMuminul Islam /// 257*f9b51a41SMuminul Islam #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 258*f9b51a41SMuminul Islam fn set_one_reg(&self, reg_id: u64, data: u64) -> Result<()>; 259*f9b51a41SMuminul Islam /// 260*f9b51a41SMuminul Islam /// Sets the value of one register for this vCPU. 261*f9b51a41SMuminul Islam /// 262*f9b51a41SMuminul Islam #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] 263*f9b51a41SMuminul Islam fn get_one_reg(&self, reg_id: u64) -> Result<u64>; 264*f9b51a41SMuminul Islam /// 265*f9b51a41SMuminul Islam /// Retrieve the current cpu states. This function is necessary to snapshot the VM 266*f9b51a41SMuminul Islam /// 267*f9b51a41SMuminul Islam fn cpu_state(&self) -> Result<CpuState>; 268*f9b51a41SMuminul Islam /// 269*f9b51a41SMuminul Islam /// Setting the FPU state this. 270*f9b51a41SMuminul Islam /// This function is required when restoring the VM 271*f9b51a41SMuminul Islam /// 272*f9b51a41SMuminul Islam fn set_cpu_state(&self, state: &CpuState) -> Result<()>; 273*f9b51a41SMuminul Islam } 274