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