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