xref: /cloud-hypervisor/hypervisor/src/cpu.rs (revision f9b51a41b5ae37e69ddc8646da310a17dd0986a6)
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