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