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