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