xref: /cloud-hypervisor/hypervisor/src/cpu.rs (revision 9bcb9849629b2a6f67ecf3ba32d18a8d2582022c)
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::x86_64::{CpuId, LapicState};
17 #[cfg(target_arch = "x86_64")]
18 use crate::x86_64::{
19     ExtendedControlRegisters, FpuState, MsrEntries, SpecialRegisters, StandardRegisters, VcpuEvents,
20 };
21 use crate::CpuState;
22 #[cfg(target_arch = "aarch64")]
23 use crate::DeviceAttr;
24 #[cfg(feature = "kvm")]
25 use crate::MpState;
26 #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
27 use crate::SuspendRegisters;
28 #[cfg(target_arch = "x86_64")]
29 use crate::Xsave;
30 #[cfg(feature = "mshv")]
31 use mshv_bindings::*;
32 use thiserror::Error;
33 
34 #[derive(Error, Debug)]
35 ///
36 /// Enum for CPU error
37 pub enum HypervisorCpuError {
38     ///
39     /// Setting standard registers error
40     ///
41     #[error("Failed to set standard register: {0}")]
42     SetStandardRegs(#[source] anyhow::Error),
43     ///
44     /// Setting standard registers error
45     ///
46     #[error("Failed to get standard registers: {0}")]
47     GetStandardRegs(#[source] anyhow::Error),
48     ///
49     /// Getting suspend registers error
50     ///
51     #[error("Failed to get suspend registers: {0}")]
52     GetSuspendRegs(#[source] anyhow::Error),
53     ///
54     /// Setting special register error
55     ///
56     #[error("Failed to set special registers: {0}")]
57     SetSpecialRegs(#[source] anyhow::Error),
58     ///
59     /// Getting standard register error
60     ///
61     #[error("Failed to get special registers: {0}")]
62     GetSpecialRegs(#[source] anyhow::Error),
63     ///
64     /// Setting floating point registers error
65     ///
66     #[error("Failed to set special register: {0}")]
67     SetFloatingPointRegs(#[source] anyhow::Error),
68     ///
69     /// Getting floating point register error
70     ///
71     #[error("Failed to get special register: {0}")]
72     GetFloatingPointRegs(#[source] anyhow::Error),
73     ///
74     /// Setting Cpuid error
75     ///
76     #[error("Failed to set Cpuid: {0}")]
77     SetCpuid(#[source] anyhow::Error),
78     ///
79     /// Getting Cpuid error
80     ///
81     #[error("Failed to get Cpuid: {0}")]
82     GetCpuid(#[source] anyhow::Error),
83     ///
84     /// Setting lapic state error
85     ///
86     #[error("Failed to set Lapic state: {0}")]
87     SetLapicState(#[source] anyhow::Error),
88     ///
89     /// Getting Lapic state error
90     ///
91     #[error("Failed to get Lapic state: {0}")]
92     GetlapicState(#[source] anyhow::Error),
93     ///
94     /// Setting MSR entries error
95     ///
96     #[error("Failed to set Msr entries: {0}")]
97     SetMsrEntries(#[source] anyhow::Error),
98     ///
99     /// Getting Msr entries error
100     ///
101     #[error("Failed to get Msr entries: {0}")]
102     GetMsrEntries(#[source] anyhow::Error),
103     ///
104     /// Setting MSR entries error
105     ///
106     #[error("Failed to set MP state: {0}")]
107     SetMpState(#[source] anyhow::Error),
108     ///
109     /// Getting Msr entries error
110     ///
111     #[error("Failed to get MP state: {0}")]
112     GetMpState(#[source] anyhow::Error),
113     ///
114     /// Setting Saved Processor Extended States error
115     ///
116     #[error("Failed to set Saved Processor Extended States: {0}")]
117     SetXsaveState(#[source] anyhow::Error),
118     ///
119     /// Getting Saved Processor Extended States error
120     ///
121     #[error("Failed to get Saved Processor Extended States: {0}")]
122     GetXsaveState(#[source] anyhow::Error),
123     ///
124     /// Setting Extended Control Registers error
125     ///
126     #[error("Failed to set Extended Control Registers: {0}")]
127     SetXcsr(#[source] anyhow::Error),
128     ///
129     /// Getting Extended Control Registers error
130     ///
131     #[error("Failed to get Extended Control Registers: {0}")]
132     GetXcsr(#[source] anyhow::Error),
133     ///
134     /// Running Vcpu error
135     ///
136     #[error("Failed to run vcpu: {0}")]
137     RunVcpu(#[source] anyhow::Error),
138     ///
139     /// Getting Vcpu events error
140     ///
141     #[error("Failed to get Vcpu events: {0}")]
142     GetVcpuEvents(#[source] anyhow::Error),
143     ///
144     /// Setting Vcpu events error
145     ///
146     #[error("Failed to set Vcpu events: {0}")]
147     SetVcpuEvents(#[source] anyhow::Error),
148     ///
149     /// Vcpu Init error
150     ///
151     #[error("Failed to init vcpu: {0}")]
152     VcpuInit(#[source] anyhow::Error),
153     ///
154     /// Setting one reg error
155     ///
156     #[error("Failed to init vcpu: {0}")]
157     SetRegister(#[source] anyhow::Error),
158     ///
159     /// Getting one reg error
160     ///
161     #[error("Failed to init vcpu: {0}")]
162     GetRegister(#[source] anyhow::Error),
163     ///
164     /// Getting guest clock paused error
165     ///
166     #[error("Failed to notify guest its clock was paused: {0}")]
167     NotifyGuestClockPaused(#[source] anyhow::Error),
168     ///
169     /// Setting debug register error
170     ///
171     #[error("Failed to set debug registers: {0}")]
172     SetDebugRegs(#[source] anyhow::Error),
173     ///
174     /// Getting debug register error
175     ///
176     #[error("Failed to get debug registers: {0}")]
177     GetDebugRegs(#[source] anyhow::Error),
178     ///
179     /// Setting misc register error
180     ///
181     #[error("Failed to set misc registers: {0}")]
182     SetMiscRegs(#[source] anyhow::Error),
183     ///
184     /// Getting misc register error
185     ///
186     #[error("Failed to get misc registers: {0}")]
187     GetMiscRegs(#[source] anyhow::Error),
188     ///
189     /// Write to Guest Mem
190     ///
191     #[error("Failed to write to Guest Mem at: {0}")]
192     GuestMemWrite(#[source] anyhow::Error),
193     /// Enabling HyperV SynIC error
194     ///
195     #[error("Failed to enable HyperV SynIC")]
196     EnableHyperVSyncIc(#[source] anyhow::Error),
197     ///
198     /// Getting AArch64 core register error
199     ///
200     #[error("Failed to get core register: {0}")]
201     GetCoreRegister(#[source] anyhow::Error),
202     ///
203     /// Setting AArch64 core register error
204     ///
205     #[error("Failed to set core register: {0}")]
206     SetCoreRegister(#[source] anyhow::Error),
207     ///
208     /// Getting AArch64 registers list error
209     ///
210     #[error("Failed to retrieve list of registers: {0}")]
211     GetRegList(#[source] anyhow::Error),
212     ///
213     /// Getting AArch64 system register error
214     ///
215     #[error("Failed to get system register: {0}")]
216     GetSysRegister(#[source] anyhow::Error),
217     ///
218     /// Setting AArch64 system register error
219     ///
220     #[error("Failed to set system register: {0}")]
221     SetSysRegister(#[source] anyhow::Error),
222     ///
223     /// GVA translation error
224     ///
225     #[error("Failed to translate GVA: {0}")]
226     TranslateVirtualAddress(#[source] anyhow::Error),
227     ///
228     /// Set cpu attribute error
229     ///
230     #[error("Failed to set vcpu attribute: {0}")]
231     SetVcpuAttribute(#[source] anyhow::Error),
232     ///
233     /// Check if cpu has a certain attribute error
234     ///
235     #[error("Failed to check if vcpu has attribute: {0}")]
236     HasVcpuAttribute(#[source] anyhow::Error),
237     ///
238     /// Failed to initialize TDX on CPU
239     ///
240     #[cfg(feature = "tdx")]
241     #[error("Failed to initialize TDX: {0}")]
242     InitializeTdx(#[source] std::io::Error),
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 }
260 
261 ///
262 /// Result type for returning from a function
263 ///
264 pub type Result<T> = anyhow::Result<T, HypervisorCpuError>;
265 ///
266 /// Trait to represent a generic Vcpu
267 ///
268 pub trait Vcpu: Send + Sync {
269     #[cfg(target_arch = "x86_64")]
270     ///
271     /// Returns the vCPU general purpose registers.
272     ///
273     fn get_regs(&self) -> Result<StandardRegisters>;
274     #[cfg(target_arch = "aarch64")]
275     ///
276     /// Sets vcpu attribute
277     ///
278     fn set_vcpu_attr(&self, attr: &DeviceAttr) -> Result<()>;
279     #[cfg(target_arch = "aarch64")]
280     ///
281     /// Check if vcpu has attribute.
282     ///
283     fn has_vcpu_attr(&self, attr: &DeviceAttr) -> Result<()>;
284     #[cfg(target_arch = "x86_64")]
285     ///
286     /// Sets the vCPU general purpose registers.
287     ///
288     fn set_regs(&self, regs: &StandardRegisters) -> Result<()>;
289     #[cfg(target_arch = "x86_64")]
290     ///
291     /// Returns the vCPU special registers.
292     ///
293     fn get_sregs(&self) -> Result<SpecialRegisters>;
294     #[cfg(target_arch = "x86_64")]
295     ///
296     /// Sets the vCPU special registers
297     ///
298     fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>;
299     #[cfg(target_arch = "x86_64")]
300     ///
301     /// Returns the floating point state (FPU) from the vCPU.
302     ///
303     fn get_fpu(&self) -> Result<FpuState>;
304     #[cfg(target_arch = "x86_64")]
305     ///
306     /// Set the floating point state (FPU) of a vCPU
307     ///
308     fn set_fpu(&self, fpu: &FpuState) -> Result<()>;
309     #[cfg(target_arch = "x86_64")]
310     ///
311     /// X86 specific call to setup the CPUID registers.
312     ///
313     fn set_cpuid2(&self, cpuid: &CpuId) -> Result<()>;
314     #[cfg(target_arch = "x86_64")]
315     ///
316     /// X86 specific call to enable HyperV SynIC
317     ///
318     fn enable_hyperv_synic(&self) -> Result<()>;
319     #[cfg(target_arch = "x86_64")]
320     ///
321     /// X86 specific call to retrieve the CPUID registers.
322     ///
323     fn get_cpuid2(&self, num_entries: usize) -> Result<CpuId>;
324     #[cfg(target_arch = "x86_64")]
325     ///
326     /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
327     ///
328     fn get_lapic(&self) -> Result<LapicState>;
329     #[cfg(target_arch = "x86_64")]
330     ///
331     /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
332     ///
333     fn set_lapic(&self, lapic: &LapicState) -> Result<()>;
334     #[cfg(target_arch = "x86_64")]
335     ///
336     /// Returns the model-specific registers (MSR) for this vCPU.
337     ///
338     fn get_msrs(&self, msrs: &mut MsrEntries) -> Result<usize>;
339     #[cfg(target_arch = "x86_64")]
340     ///
341     /// Setup the model-specific registers (MSR) for this vCPU.
342     ///
343     fn set_msrs(&self, msrs: &MsrEntries) -> Result<usize>;
344     #[cfg(feature = "kvm")]
345     ///
346     /// Returns the vcpu's current "multiprocessing state".
347     ///
348     fn get_mp_state(&self) -> Result<MpState>;
349     #[cfg(feature = "kvm")]
350     ///
351     /// Sets the vcpu's current "multiprocessing state".
352     ///
353     fn set_mp_state(&self, mp_state: MpState) -> Result<()>;
354     #[cfg(target_arch = "x86_64")]
355     ///
356     /// X86 specific call that returns the vcpu's current "xsave struct".
357     ///
358     fn get_xsave(&self) -> Result<Xsave>;
359     #[cfg(target_arch = "x86_64")]
360     ///
361     /// X86 specific call that sets the vcpu's current "xsave struct".
362     ///
363     fn set_xsave(&self, xsave: &Xsave) -> Result<()>;
364     #[cfg(target_arch = "x86_64")]
365     ///
366     /// X86 specific call that returns the vcpu's current "xcrs".
367     ///
368     fn get_xcrs(&self) -> Result<ExtendedControlRegisters>;
369     #[cfg(target_arch = "x86_64")]
370     ///
371     /// X86 specific call that sets the vcpu's current "xcrs".
372     ///
373     fn set_xcrs(&self, xcrs: &ExtendedControlRegisters) -> Result<()>;
374     #[cfg(target_arch = "x86_64")]
375     ///
376     /// Returns currently pending exceptions, interrupts, and NMIs as well as related
377     /// states of the vcpu.
378     ///
379     fn get_vcpu_events(&self) -> Result<VcpuEvents>;
380     #[cfg(target_arch = "x86_64")]
381     ///
382     /// Sets pending exceptions, interrupts, and NMIs as well as related states
383     /// of the vcpu.
384     ///
385     fn set_vcpu_events(&self, events: &VcpuEvents) -> Result<()>;
386     #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
387     ///
388     /// Let the guest know that it has been paused, which prevents from
389     /// potential soft lockups when being resumed.
390     ///
391     fn notify_guest_clock_paused(&self) -> Result<()>;
392     ///
393     /// Sets the type of CPU to be exposed to the guest and optional features.
394     ///
395     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
396     fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>;
397     ///
398     /// Sets the value of one register for this vCPU.
399     ///
400     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
401     fn set_reg(&self, reg_id: u64, data: u64) -> Result<()>;
402     ///
403     /// Sets the value of one register for this vCPU.
404     ///
405     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
406     fn get_reg(&self, reg_id: u64) -> Result<u64>;
407     ///
408     /// Gets a list of the guest registers that are supported for the
409     /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
410     ///
411     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
412     fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>;
413     ///
414     /// Save the state of the core registers.
415     ///
416     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
417     fn core_registers(&self, state: &mut StandardRegisters) -> Result<()>;
418     ///
419     /// Restore the state of the core registers.
420     ///
421     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
422     fn set_core_registers(&self, state: &StandardRegisters) -> Result<()>;
423     ///
424     /// Save the state of the system registers.
425     ///
426     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
427     fn system_registers(&self, state: &mut Vec<Register>) -> Result<()>;
428     ///
429     /// Restore the state of the system registers.
430     ///
431     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
432     fn set_system_registers(&self, state: &[Register]) -> Result<()>;
433     ///
434     /// Read the MPIDR - Multiprocessor Affinity Register.
435     ///
436     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
437     fn read_mpidr(&self) -> Result<u64>;
438     ///
439     /// Retrieve the vCPU state.
440     /// This function is necessary to snapshot the VM
441     ///
442     fn state(&self) -> Result<CpuState>;
443     ///
444     /// Set the vCPU state.
445     /// This function is required when restoring the VM
446     ///
447     fn set_state(&self, state: &CpuState) -> Result<()>;
448     ///
449     /// Triggers the running of the current virtual CPU returning an exit reason.
450     ///
451     fn run(&self) -> std::result::Result<VmExit, HypervisorCpuError>;
452     #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
453     ///
454     /// Translate guest virtual address to guest physical address
455     ///
456     fn translate_gva(&self, gva: u64, flags: u64) -> Result<(u64, hv_translate_gva_result)>;
457     ///
458     /// Initialize TDX support on the vCPU
459     ///
460     #[cfg(feature = "tdx")]
461     fn tdx_init(&self, hob_address: u64) -> Result<()>;
462     #[cfg(all(feature = "mshv", target_arch = "x86_64"))]
463     ///
464     /// Return suspend registers(explicit and intercept suspend registers)
465     ///
466     fn get_suspend_regs(&self) -> Result<SuspendRegisters>;
467 }
468