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