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