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