xref: /cloud-hypervisor/hypervisor/src/cpu.rs (revision 88a9f799449c04180c6b9a21d3b9c0c4b57e2bd6)
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 use thiserror::Error;
12 use vm_memory::GuestAddress;
13 
14 #[cfg(target_arch = "aarch64")]
15 use crate::aarch64::{RegList, VcpuInit};
16 #[cfg(target_arch = "x86_64")]
17 use crate::arch::x86::{CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters};
18 #[cfg(feature = "tdx")]
19 use crate::kvm::{TdxExitDetails, TdxExitStatus};
20 use crate::CpuState;
21 use crate::MpState;
22 use crate::StandardRegisters;
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     /// Vcpu Finalize error
163     ///
164     #[error("Failed to finalize vcpu: {0}")]
165     VcpuFinalize(#[source] anyhow::Error),
166     ///
167     /// Setting one reg error
168     ///
169     #[error("Failed to set one reg: {0}")]
170     SetRegister(#[source] anyhow::Error),
171     ///
172     /// Getting one reg error
173     ///
174     #[error("Failed to get one reg: {0}")]
175     GetRegister(#[source] anyhow::Error),
176     ///
177     /// Getting guest clock paused error
178     ///
179     #[error("Failed to notify guest its clock was paused: {0}")]
180     NotifyGuestClockPaused(#[source] anyhow::Error),
181     ///
182     /// Setting debug register error
183     ///
184     #[error("Failed to set debug registers: {0}")]
185     SetDebugRegs(#[source] anyhow::Error),
186     ///
187     /// Getting debug register error
188     ///
189     #[error("Failed to get debug registers: {0}")]
190     GetDebugRegs(#[source] anyhow::Error),
191     ///
192     /// Setting misc register error
193     ///
194     #[error("Failed to set misc registers: {0}")]
195     SetMiscRegs(#[source] anyhow::Error),
196     ///
197     /// Getting misc register error
198     ///
199     #[error("Failed to get misc registers: {0}")]
200     GetMiscRegs(#[source] anyhow::Error),
201     ///
202     /// Write to Guest Mem
203     ///
204     #[error("Failed to write to Guest Mem at: {0}")]
205     GuestMemWrite(#[source] anyhow::Error),
206     /// Enabling HyperV SynIC error
207     ///
208     #[error("Failed to enable HyperV SynIC")]
209     EnableHyperVSyncIc(#[source] anyhow::Error),
210     ///
211     /// Getting AArch64 core register error
212     ///
213     #[error("Failed to get aarch64 core register: {0}")]
214     GetAarchCoreRegister(#[source] anyhow::Error),
215     ///
216     /// Setting AArch64 core register error
217     ///
218     #[error("Failed to set aarch64 core register: {0}")]
219     SetAarchCoreRegister(#[source] anyhow::Error),
220     ///
221     /// Getting registers list error
222     ///
223     #[error("Failed to retrieve list of registers: {0}")]
224     GetRegList(#[source] anyhow::Error),
225     ///
226     /// Getting AArch64 system register error
227     ///
228     #[error("Failed to get system register: {0}")]
229     GetSysRegister(#[source] anyhow::Error),
230     ///
231     /// Setting AArch64 system register error
232     ///
233     #[error("Failed to set system register: {0}")]
234     SetSysRegister(#[source] anyhow::Error),
235     ///
236     /// GVA translation error
237     ///
238     #[error("Failed to translate GVA: {0}")]
239     TranslateVirtualAddress(#[source] anyhow::Error),
240     ///
241     /// Set cpu attribute error
242     ///
243     #[error("Failed to set vcpu attribute: {0}")]
244     SetVcpuAttribute(#[source] anyhow::Error),
245     ///
246     /// Check if cpu has a certain attribute error
247     ///
248     #[error("Failed to check if vcpu has attribute: {0}")]
249     HasVcpuAttribute(#[source] anyhow::Error),
250     ///
251     /// Failed to initialize TDX on CPU
252     ///
253     #[cfg(feature = "tdx")]
254     #[error("Failed to initialize TDX: {0}")]
255     InitializeTdx(#[source] std::io::Error),
256     ///
257     /// Unknown TDX VM call
258     ///
259     #[cfg(feature = "tdx")]
260     #[error("Unknown TDX VM call")]
261     UnknownTdxVmCall,
262     #[cfg(target_arch = "aarch64")]
263     ///
264     /// Failed to initialize PMU
265     ///
266     #[error("Failed to initialize PMU")]
267     InitializePmu,
268     #[cfg(target_arch = "x86_64")]
269     ///
270     /// Error getting TSC frequency
271     ///
272     #[error("Failed to get TSC frequency: {0}")]
273     GetTscKhz(#[source] anyhow::Error),
274     ///
275     /// Error setting TSC frequency
276     ///
277     #[error("Failed to set TSC frequency: {0}")]
278     SetTscKhz(#[source] anyhow::Error),
279     ///
280     /// Error reading value at given GPA
281     ///
282     #[error("Failed to read from GPA: {0}")]
283     GpaRead(#[source] anyhow::Error),
284     ///
285     /// Error writing value at given GPA
286     ///
287     #[error("Failed to write to GPA: {0}")]
288     GpaWrite(#[source] anyhow::Error),
289     ///
290     /// Error getting CPUID leaf
291     ///
292     #[error("Failed to get CPUID entries: {0}")]
293     GetCpuidVales(#[source] anyhow::Error),
294     ///
295     /// Setting SEV control register error
296     ///
297     #[cfg(feature = "sev_snp")]
298     #[error("Failed to set sev control register: {0}")]
299     SetSevControlRegister(#[source] anyhow::Error),
300 
301     /// Error injecting NMI
302     ///
303     #[error("Failed to inject NMI")]
304     Nmi(#[source] anyhow::Error),
305 }
306 
307 #[derive(Debug)]
308 pub enum VmExit {
309     #[cfg(target_arch = "x86_64")]
310     IoapicEoi(u8 /* vector */),
311     Ignore,
312     Reset,
313     Shutdown,
314     Hyperv,
315     #[cfg(feature = "tdx")]
316     Tdx,
317     #[cfg(feature = "kvm")]
318     Debug,
319 }
320 
321 ///
322 /// Result type for returning from a function
323 ///
324 pub type Result<T> = anyhow::Result<T, HypervisorCpuError>;
325 ///
326 /// Trait to represent a generic Vcpu
327 ///
328 pub trait Vcpu: Send + Sync {
329     ///
330     /// Returns StandardRegisters with default value set
331     ///
332     fn create_standard_regs(&self) -> StandardRegisters {
333         unimplemented!();
334     }
335     ///
336     /// Returns the vCPU general purpose registers.
337     ///
338     fn get_regs(&self) -> Result<StandardRegisters>;
339     ///
340     /// Sets the vCPU general purpose registers.
341     ///
342     fn set_regs(&self, regs: &StandardRegisters) -> Result<()>;
343     #[cfg(target_arch = "x86_64")]
344     ///
345     /// Returns the vCPU special registers.
346     ///
347     fn get_sregs(&self) -> Result<SpecialRegisters>;
348     #[cfg(target_arch = "x86_64")]
349     ///
350     /// Sets the vCPU special registers
351     ///
352     fn set_sregs(&self, sregs: &SpecialRegisters) -> Result<()>;
353     #[cfg(target_arch = "x86_64")]
354     ///
355     /// Returns the floating point state (FPU) from the vCPU.
356     ///
357     fn get_fpu(&self) -> Result<FpuState>;
358     #[cfg(target_arch = "x86_64")]
359     ///
360     /// Set the floating point state (FPU) of a vCPU
361     ///
362     fn set_fpu(&self, fpu: &FpuState) -> Result<()>;
363     #[cfg(target_arch = "x86_64")]
364     ///
365     /// X86 specific call to setup the CPUID registers.
366     ///
367     fn set_cpuid2(&self, cpuid: &[CpuIdEntry]) -> Result<()>;
368     #[cfg(target_arch = "x86_64")]
369     ///
370     /// X86 specific call to enable HyperV SynIC
371     ///
372     fn enable_hyperv_synic(&self) -> Result<()>;
373     #[cfg(target_arch = "x86_64")]
374     ///
375     /// X86 specific call to retrieve the CPUID registers.
376     ///
377     fn get_cpuid2(&self, num_entries: usize) -> Result<Vec<CpuIdEntry>>;
378     #[cfg(target_arch = "x86_64")]
379     ///
380     /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
381     ///
382     fn get_lapic(&self) -> Result<LapicState>;
383     #[cfg(target_arch = "x86_64")]
384     ///
385     /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
386     ///
387     fn set_lapic(&self, lapic: &LapicState) -> Result<()>;
388     #[cfg(target_arch = "x86_64")]
389     ///
390     /// Returns the model-specific registers (MSR) for this vCPU.
391     ///
392     fn get_msrs(&self, msrs: &mut Vec<MsrEntry>) -> Result<usize>;
393     #[cfg(target_arch = "x86_64")]
394     ///
395     /// Setup the model-specific registers (MSR) for this vCPU.
396     ///
397     fn set_msrs(&self, msrs: &[MsrEntry]) -> Result<usize>;
398     ///
399     /// Returns the vcpu's current "multiprocessing state".
400     ///
401     fn get_mp_state(&self) -> Result<MpState>;
402     ///
403     /// Sets the vcpu's current "multiprocessing state".
404     ///
405     fn set_mp_state(&self, mp_state: MpState) -> Result<()>;
406     #[cfg(target_arch = "x86_64")]
407     ///
408     /// Let the guest know that it has been paused, which prevents from
409     /// potential soft lockups when being resumed.
410     ///
411     fn notify_guest_clock_paused(&self) -> Result<()> {
412         Ok(())
413     }
414     ///
415     /// Sets debug registers to set hardware breakpoints and/or enable single step.
416     ///
417     fn set_guest_debug(&self, _addrs: &[GuestAddress], _singlestep: bool) -> Result<()> {
418         Err(HypervisorCpuError::SetDebugRegs(anyhow!("unimplemented")))
419     }
420     ///
421     /// Sets the type of CPU to be exposed to the guest and optional features.
422     ///
423     #[cfg(target_arch = "aarch64")]
424     fn vcpu_init(&self, kvi: &VcpuInit) -> Result<()>;
425 
426     #[cfg(target_arch = "aarch64")]
427     fn vcpu_finalize(&self, feature: i32) -> Result<()>;
428 
429     ///
430     /// Gets a list of the guest registers that are supported for the
431     /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
432     ///
433     #[cfg(target_arch = "aarch64")]
434     fn get_reg_list(&self, reg_list: &mut RegList) -> Result<()>;
435     ///
436     /// Gets the value of a system register
437     ///
438     #[cfg(target_arch = "aarch64")]
439     fn get_sys_reg(&self, sys_reg: u32) -> Result<u64>;
440     ///
441     /// Configure core registers for a given CPU.
442     ///
443     #[cfg(target_arch = "aarch64")]
444     fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> Result<()>;
445     ///
446     /// Check if the CPU supports PMU
447     ///
448     #[cfg(target_arch = "aarch64")]
449     fn has_pmu_support(&self) -> bool;
450     ///
451     /// Initialize PMU
452     ///
453     #[cfg(target_arch = "aarch64")]
454     fn init_pmu(&self, irq: u32) -> Result<()>;
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         unimplemented!()
480     }
481     ///
482     /// Set the "immediate_exit" state
483     ///
484     fn set_immediate_exit(&self, _exit: bool) {}
485     #[cfg(feature = "tdx")]
486     ///
487     /// Returns the details about TDX exit reason
488     ///
489     fn get_tdx_exit_details(&mut self) -> Result<TdxExitDetails> {
490         unimplemented!()
491     }
492     #[cfg(feature = "tdx")]
493     ///
494     /// Set the status code for TDX exit
495     ///
496     fn set_tdx_status(&mut self, _status: TdxExitStatus) {
497         unimplemented!()
498     }
499     #[cfg(target_arch = "x86_64")]
500     ///
501     /// Return the list of initial MSR entries for a VCPU
502     ///
503     fn boot_msr_entries(&self) -> Vec<MsrEntry>;
504 
505     #[cfg(target_arch = "x86_64")]
506     ///
507     /// Get the frequency of the TSC if available
508     ///
509     fn tsc_khz(&self) -> Result<Option<u32>> {
510         Ok(None)
511     }
512     #[cfg(target_arch = "x86_64")]
513     ///
514     /// Set the frequency of the TSC if available
515     ///
516     fn set_tsc_khz(&self, _freq: u32) -> Result<()> {
517         Ok(())
518     }
519     #[cfg(target_arch = "x86_64")]
520     ///
521     /// X86 specific call to retrieve cpuid leaf
522     ///
523     fn get_cpuid_values(
524         &self,
525         _function: u32,
526         _index: u32,
527         _xfem: u64,
528         _xss: u64,
529     ) -> Result<[u32; 4]> {
530         unimplemented!()
531     }
532     #[cfg(feature = "mshv")]
533     fn set_sev_control_register(&self, _reg: u64) -> Result<()> {
534         unimplemented!()
535     }
536 
537     #[cfg(target_arch = "x86_64")]
538     ///
539     /// Trigger NMI interrupt
540     ///
541     fn nmi(&self) -> Result<()>;
542 }
543