hypervisor/
x86_64.rs

1// Copyright 2020 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#[cfg(any(unix, feature = "haxm", feature = "whpx"))]
6use std::arch::x86_64::__cpuid;
7use std::arch::x86_64::_rdtsc;
8use std::arch::x86_64::CpuidResult;
9use std::collections::BTreeMap;
10use std::collections::HashSet;
11use std::sync::Arc;
12
13use anyhow::Context;
14use base::custom_serde::deserialize_seq_to_arr;
15use base::custom_serde::serialize_arr;
16use base::error;
17use base::warn;
18use base::Result;
19use bit_field::*;
20use libc::c_void;
21use serde::Deserialize;
22use serde::Serialize;
23use snapshot::AnySnapshot;
24use vm_memory::GuestAddress;
25
26use crate::Hypervisor;
27use crate::IrqRoute;
28use crate::IrqSource;
29use crate::IrqSourceChip;
30use crate::NestedMode;
31use crate::Vcpu;
32use crate::Vm;
33
34const MSR_F15H_PERF_CTL0: u32 = 0xc0010200;
35const MSR_F15H_PERF_CTL1: u32 = 0xc0010202;
36const MSR_F15H_PERF_CTL2: u32 = 0xc0010204;
37const MSR_F15H_PERF_CTL3: u32 = 0xc0010206;
38const MSR_F15H_PERF_CTL4: u32 = 0xc0010208;
39const MSR_F15H_PERF_CTL5: u32 = 0xc001020a;
40const MSR_F15H_PERF_CTR0: u32 = 0xc0010201;
41const MSR_F15H_PERF_CTR1: u32 = 0xc0010203;
42const MSR_F15H_PERF_CTR2: u32 = 0xc0010205;
43const MSR_F15H_PERF_CTR3: u32 = 0xc0010207;
44const MSR_F15H_PERF_CTR4: u32 = 0xc0010209;
45const MSR_F15H_PERF_CTR5: u32 = 0xc001020b;
46const MSR_IA32_PERF_CAPABILITIES: u32 = 0x00000345;
47
48/// A trait for managing cpuids for an x86_64 hypervisor and for checking its capabilities.
49pub trait HypervisorX86_64: Hypervisor {
50    /// Get the system supported CPUID values.
51    fn get_supported_cpuid(&self) -> Result<CpuId>;
52
53    /// Gets the list of supported MSRs.
54    fn get_msr_index_list(&self) -> Result<Vec<u32>>;
55}
56
57/// A wrapper for using a VM on x86_64 and getting/setting its state.
58pub trait VmX86_64: Vm {
59    /// Gets the `HypervisorX86_64` that created this VM.
60    fn get_hypervisor(&self) -> &dyn HypervisorX86_64;
61
62    /// Create a Vcpu with the specified Vcpu ID.
63    fn create_vcpu(&self, id: usize) -> Result<Arc<dyn VcpuX86_64>>;
64
65    /// Sets the address of the three-page region in the VM's address space.
66    fn set_tss_addr(&self, addr: GuestAddress) -> Result<()>;
67
68    /// Sets the address of a one-page region in the VM's address space.
69    fn set_identity_map_addr(&self, addr: GuestAddress) -> Result<()>;
70
71    /// Load pVM firmware for the VM, creating a memslot for it as needed.
72    ///
73    /// Only works on protected VMs (i.e. those with vm_type == KVM_X86_PKVM_PROTECTED_VM).
74    fn load_protected_vm_firmware(&self, fw_addr: GuestAddress, fw_max_size: u64) -> Result<()>;
75}
76
77/// A wrapper around creating and using a VCPU on x86_64.
78pub trait VcpuX86_64: Vcpu {
79    /// Sets or clears the flag that requests the VCPU to exit when it becomes possible to inject
80    /// interrupts into the guest.
81    fn set_interrupt_window_requested(&self, requested: bool);
82
83    /// Checks if we can inject an interrupt into the VCPU.
84    fn ready_for_interrupt(&self) -> bool;
85
86    /// Injects interrupt vector `irq` into the VCPU.
87    ///
88    /// This function should only be called when [`Self::ready_for_interrupt`] returns true.
89    /// Otherwise the interrupt injection may fail or the next VCPU run may fail. However, if
90    /// [`Self::interrupt`] returns [`Ok`], the implementation must guarantee that the interrupt
91    /// isn't injected in an uninterruptible window (e.g. right after the mov ss instruction).
92    ///
93    /// The caller should avoid calling this function more than 1 time for one VMEXIT, because the
94    /// hypervisor may behave differently: some hypervisors(e.g. WHPX, KVM) will only try to inject
95    /// the last `irq` requested, while some other hypervisors(e.g. HAXM) may try to inject all
96    /// `irq`s requested.
97    fn interrupt(&self, irq: u8) -> Result<()>;
98
99    /// Injects a non-maskable interrupt into the VCPU.
100    fn inject_nmi(&self) -> Result<()>;
101
102    /// Gets the VCPU general purpose registers.
103    fn get_regs(&self) -> Result<Regs>;
104
105    /// Sets the VCPU general purpose registers.
106    fn set_regs(&self, regs: &Regs) -> Result<()>;
107
108    /// Gets the VCPU special registers.
109    fn get_sregs(&self) -> Result<Sregs>;
110
111    /// Sets the VCPU special registers.
112    fn set_sregs(&self, sregs: &Sregs) -> Result<()>;
113
114    /// Gets the VCPU FPU registers.
115    fn get_fpu(&self) -> Result<Fpu>;
116
117    /// Sets the VCPU FPU registers.
118    fn set_fpu(&self, fpu: &Fpu) -> Result<()>;
119
120    /// Gets the VCPU debug registers.
121    fn get_debugregs(&self) -> Result<DebugRegs>;
122
123    /// Sets the VCPU debug registers.
124    fn set_debugregs(&self, debugregs: &DebugRegs) -> Result<()>;
125
126    /// Gets the VCPU extended control registers.
127    fn get_xcrs(&self) -> Result<BTreeMap<u32, u64>>;
128
129    /// Sets a VCPU extended control register.
130    fn set_xcr(&self, xcr: u32, value: u64) -> Result<()>;
131
132    /// Gets the VCPU x87 FPU, MMX, XMM, YMM and MXCSR registers.
133    fn get_xsave(&self) -> Result<Xsave>;
134
135    /// Sets the VCPU x87 FPU, MMX, XMM, YMM and MXCSR registers.
136    fn set_xsave(&self, xsave: &Xsave) -> Result<()>;
137
138    /// Gets hypervisor specific state for this VCPU that must be
139    /// saved/restored for snapshotting.
140    /// This state is fetched after VCPUs are frozen and interrupts are flushed.
141    fn get_hypervisor_specific_state(&self) -> Result<AnySnapshot>;
142
143    /// Sets hypervisor specific state for this VCPU. Only used for
144    /// snapshotting.
145    fn set_hypervisor_specific_state(&self, data: AnySnapshot) -> Result<()>;
146
147    /// Gets a single model-specific register's value.
148    fn get_msr(&self, msr_index: u32) -> Result<u64>;
149
150    /// Gets the model-specific registers. Returns all the MSRs for the VCPU.
151    fn get_all_msrs(&self) -> Result<BTreeMap<u32, u64>>;
152
153    /// Sets a single model-specific register's value.
154    fn set_msr(&self, msr_index: u32, value: u64) -> Result<()>;
155
156    /// Sets up the data returned by the CPUID instruction.
157    fn set_cpuid(&self, cpuid: &CpuId) -> Result<()>;
158
159    /// Sets up debug registers and configure vcpu for handling guest debug events.
160    fn set_guest_debug(&self, addrs: &[GuestAddress], enable_singlestep: bool) -> Result<()>;
161
162    /// This function should be called after `Vcpu::run` returns `VcpuExit::Cpuid`, and `entry`
163    /// should represent the result of emulating the CPUID instruction. The `handle_cpuid` function
164    /// will then set the appropriate registers on the vcpu.
165    fn handle_cpuid(&self, entry: &CpuIdEntry) -> Result<()>;
166
167    /// Gets the guest->host TSC offset.
168    ///
169    /// The default implementation uses [`VcpuX86_64::get_msr()`] to read the guest TSC.
170    fn get_tsc_offset(&self) -> Result<u64> {
171        // SAFETY:
172        // Safe because _rdtsc takes no arguments
173        let host_before_tsc = unsafe { _rdtsc() };
174
175        // get guest TSC value from our hypervisor
176        let guest_tsc = self.get_msr(crate::MSR_IA32_TSC)?;
177
178        // SAFETY:
179        // Safe because _rdtsc takes no arguments
180        let host_after_tsc = unsafe { _rdtsc() };
181
182        // Average the before and after host tsc to get the best value
183        let host_tsc = ((host_before_tsc as u128 + host_after_tsc as u128) / 2) as u64;
184
185        Ok(guest_tsc.wrapping_sub(host_tsc))
186    }
187
188    /// Sets the guest->host TSC offset.
189    ///
190    /// The default implementation uses [`VcpuX86_64::set_tsc_value()`] to set the TSC value.
191    ///
192    /// It sets TSC_OFFSET (VMCS / CB field) by setting the TSC MSR to the current
193    /// host TSC value plus the desired offset. We rely on the fact that hypervisors
194    /// determine the value of TSC_OFFSET by computing TSC_OFFSET = `new_tsc_value - _rdtsc()` =
195    /// `_rdtsc() + offset - _rdtsc()` ~= `offset`. Note that the ~= is important: this is an
196    /// approximate operation, because the two _rdtsc() calls
197    /// are separated by at least a few ticks.
198    ///
199    /// Note: TSC_OFFSET, host TSC, guest TSC, and TSC MSR are all different
200    /// concepts.
201    /// * When a guest executes rdtsc, the value (guest TSC) returned is host_tsc * TSC_MULTIPLIER +
202    ///   TSC_OFFSET + TSC_ADJUST.
203    /// * The TSC MSR is a special MSR that when written to by the host, will cause TSC_OFFSET to be
204    ///   set accordingly by the hypervisor.
205    /// * When the guest *writes* to TSC MSR, it actually changes the TSC_ADJUST MSR *for the
206    ///   guest*. Generally this is only happens if the guest is trying to re-zero or synchronize
207    ///   TSCs.
208    fn set_tsc_offset(&self, offset: u64) -> Result<()> {
209        // SAFETY: _rdtsc takes no arguments.
210        let host_tsc = unsafe { _rdtsc() };
211        self.set_tsc_value(host_tsc.wrapping_add(offset))
212    }
213
214    /// Sets the guest TSC exactly to the provided value.
215    ///
216    /// The default implementation sets the guest's TSC by writing the value to the MSR directly.
217    ///
218    /// See [`VcpuX86_64::set_tsc_offset()`] for an explanation of how this value is actually read
219    /// by the guest after being set.
220    fn set_tsc_value(&self, value: u64) -> Result<()> {
221        self.set_msr(crate::MSR_IA32_TSC, value)
222    }
223
224    /// Some hypervisors require special handling to restore timekeeping when
225    /// a snapshot is restored. They are provided with a host TSC reference
226    /// moment, guaranteed to be the same across all Vcpus, and the Vcpu's TSC
227    /// offset at the moment it was snapshotted.
228    fn restore_timekeeping(&self, host_tsc_reference_moment: u64, tsc_offset: u64) -> Result<()>;
229
230    /// Snapshot vCPU state
231    fn snapshot(&self) -> anyhow::Result<VcpuSnapshot> {
232        Ok(VcpuSnapshot {
233            vcpu_id: self.id(),
234            regs: self.get_regs()?,
235            sregs: self.get_sregs()?,
236            debug_regs: self.get_debugregs()?,
237            xcrs: self.get_xcrs()?,
238            msrs: self.get_all_msrs()?,
239            xsave: self.get_xsave()?,
240            hypervisor_data: self.get_hypervisor_specific_state()?,
241            tsc_offset: self.get_tsc_offset()?,
242        })
243    }
244
245    fn restore(
246        &self,
247        snapshot: &VcpuSnapshot,
248        host_tsc_reference_moment: u64,
249    ) -> anyhow::Result<()> {
250        // List of MSRs that may fail to restore due to lack of support in the host kernel.
251        // Some hosts are may be running older kernels which do not support all MSRs, but
252        // get_all_msrs will still fetch the MSRs supported by the CPU. Trying to set those MSRs
253        // will result in failures, so they will throw a warning instead.
254        let msr_allowlist = HashSet::from([
255            MSR_F15H_PERF_CTL0,
256            MSR_F15H_PERF_CTL1,
257            MSR_F15H_PERF_CTL2,
258            MSR_F15H_PERF_CTL3,
259            MSR_F15H_PERF_CTL4,
260            MSR_F15H_PERF_CTL5,
261            MSR_F15H_PERF_CTR0,
262            MSR_F15H_PERF_CTR1,
263            MSR_F15H_PERF_CTR2,
264            MSR_F15H_PERF_CTR3,
265            MSR_F15H_PERF_CTR4,
266            MSR_F15H_PERF_CTR5,
267            MSR_IA32_PERF_CAPABILITIES,
268        ]);
269        assert_eq!(snapshot.vcpu_id, self.id());
270        self.set_regs(&snapshot.regs)?;
271        self.set_sregs(&snapshot.sregs)?;
272        self.set_debugregs(&snapshot.debug_regs)?;
273        for (xcr_index, value) in &snapshot.xcrs {
274            self.set_xcr(*xcr_index, *value)?;
275        }
276
277        for (msr_index, value) in snapshot.msrs.iter() {
278            if self.get_msr(*msr_index) == Ok(*value) {
279                continue; // no need to set MSR since the values are the same.
280            }
281            if let Err(e) = self.set_msr(*msr_index, *value) {
282                if msr_allowlist.contains(msr_index) {
283                    warn!(
284                        "Failed to set MSR. MSR might not be supported in this kernel. Err: {}",
285                        e
286                    );
287                } else {
288                    return Err(e).context(
289                        "Failed to set MSR. MSR might not be supported by the CPU or by the kernel,
290                         and was not allow-listed.",
291                    );
292                }
293            };
294        }
295        self.set_xsave(&snapshot.xsave)?;
296        self.set_hypervisor_specific_state(snapshot.hypervisor_data.clone())?;
297        self.restore_timekeeping(host_tsc_reference_moment, snapshot.tsc_offset)?;
298        Ok(())
299    }
300}
301
302/// x86 specific vCPU snapshot.
303#[derive(Clone, Debug, Serialize, Deserialize)]
304pub struct VcpuSnapshot {
305    pub vcpu_id: usize,
306    regs: Regs,
307    sregs: Sregs,
308    debug_regs: DebugRegs,
309    xcrs: BTreeMap<u32, u64>,
310    msrs: BTreeMap<u32, u64>,
311    xsave: Xsave,
312    hypervisor_data: AnySnapshot,
313    tsc_offset: u64,
314}
315
316// TSC MSR
317pub const MSR_IA32_TSC: u32 = 0x00000010;
318
319/// Gets host cpu max physical address bits.
320#[cfg(any(unix, feature = "haxm", feature = "whpx"))]
321pub(crate) fn host_phys_addr_bits() -> u8 {
322    // SAFETY: trivially safe
323    let highest_ext_function = unsafe { __cpuid(0x80000000) };
324    if highest_ext_function.eax >= 0x80000008 {
325        // SAFETY: trivially safe
326        let addr_size = unsafe { __cpuid(0x80000008) };
327        // Low 8 bits of 0x80000008 leaf: host physical address size in bits.
328        addr_size.eax as u8
329    } else {
330        36
331    }
332}
333
334/// Initial state for x86_64 VCPUs.
335#[derive(Clone, Default)]
336pub struct VcpuInitX86_64 {
337    /// General-purpose registers.
338    pub regs: Regs,
339
340    /// Special registers.
341    pub sregs: Sregs,
342
343    /// Floating-point registers.
344    pub fpu: Fpu,
345
346    /// Machine-specific registers.
347    pub msrs: BTreeMap<u32, u64>,
348}
349
350/// Hold the CPU feature configurations that are needed to setup a vCPU.
351#[derive(Clone, Debug, PartialEq, Eq)]
352pub struct CpuConfigX86_64 {
353    /// whether to force using a calibrated TSC leaf (0x15).
354    pub force_calibrated_tsc_leaf: bool,
355
356    /// whether enabling host cpu topology.
357    pub host_cpu_topology: bool,
358
359    /// whether expose HWP feature to the guest.
360    pub enable_hwp: bool,
361
362    /// Wheter diabling SMT (Simultaneous Multithreading).
363    pub no_smt: bool,
364
365    /// whether enabling ITMT scheduler
366    pub itmt: bool,
367
368    /// whether setting hybrid CPU type
369    pub hybrid_type: Option<CpuHybridType>,
370
371    /// how to expose nested virtualization to the guest.
372    pub nested: NestedMode,
373}
374
375impl CpuConfigX86_64 {
376    pub fn new(
377        force_calibrated_tsc_leaf: bool,
378        host_cpu_topology: bool,
379        enable_hwp: bool,
380        no_smt: bool,
381        itmt: bool,
382        hybrid_type: Option<CpuHybridType>,
383        nested: NestedMode,
384    ) -> Self {
385        CpuConfigX86_64 {
386            force_calibrated_tsc_leaf,
387            host_cpu_topology,
388            enable_hwp,
389            no_smt,
390            itmt,
391            hybrid_type,
392            nested,
393        }
394    }
395}
396
397/// A CpuId Entry contains supported feature information for the given processor.
398/// This can be modified by the hypervisor to pass additional information to the guest kernel
399/// about the hypervisor or vm. Information is returned in the eax, ebx, ecx and edx registers
400/// by the cpu for a given function and index/subfunction (passed into the cpu via the eax and ecx
401/// register respectively).
402#[repr(C)]
403#[derive(Clone, Copy, Debug, PartialEq, Eq)]
404pub struct CpuIdEntry {
405    pub function: u32,
406    pub index: u32,
407    // flags is needed for KVM.  We store it on CpuIdEntry to preserve the flags across
408    // get_supported_cpuids() -> kvm_cpuid2 -> CpuId -> kvm_cpuid2 -> set_cpuid().
409    pub flags: u32,
410    pub cpuid: CpuidResult,
411}
412
413/// A container for the list of cpu id entries for the hypervisor and underlying cpu.
414pub struct CpuId {
415    pub cpu_id_entries: Vec<CpuIdEntry>,
416}
417
418impl CpuId {
419    /// Constructs a new CpuId, with space allocated for `initial_capacity` CpuIdEntries.
420    pub fn new(initial_capacity: usize) -> Self {
421        CpuId {
422            cpu_id_entries: Vec::with_capacity(initial_capacity),
423        }
424    }
425}
426
427#[bitfield]
428#[derive(Clone, Copy, Debug, PartialEq, Eq)]
429pub enum DestinationMode {
430    Physical = 0,
431    Logical = 1,
432}
433
434#[bitfield]
435#[derive(Clone, Copy, Debug, PartialEq, Eq)]
436pub enum TriggerMode {
437    Edge = 0,
438    Level = 1,
439}
440
441#[bitfield]
442#[derive(Debug, Clone, Copy, PartialEq, Eq)]
443pub enum DeliveryMode {
444    Fixed = 0b000,
445    Lowest = 0b001,
446    SMI = 0b010,        // System management interrupt
447    RemoteRead = 0b011, // This is no longer supported by intel.
448    NMI = 0b100,        // Non maskable interrupt
449    Init = 0b101,
450    Startup = 0b110,
451    External = 0b111,
452}
453
454// These MSI structures are for Intel's implementation of MSI.  The PCI spec defines most of MSI,
455// but the Intel spec defines the format of messages for raising interrupts.  The PCI spec defines
456// three u32s -- the address, address_high, and data -- but Intel only makes use of the address and
457// data.  The Intel portion of the specification is in Volume 3 section 10.11.
458#[bitfield]
459#[derive(Clone, Copy, PartialEq, Eq)]
460pub struct MsiAddressMessage {
461    pub reserved: BitField2,
462    #[bits = 1]
463    pub destination_mode: DestinationMode,
464    pub redirection_hint: BitField1,
465    pub reserved_2: BitField8,
466    pub destination_id: BitField8,
467    // According to Intel's implementation of MSI, these bits must always be 0xfee.
468    pub always_0xfee: BitField12,
469}
470
471#[bitfield]
472#[derive(Clone, Copy, PartialEq, Eq)]
473pub struct MsiDataMessage {
474    pub vector: BitField8,
475    #[bits = 3]
476    pub delivery_mode: DeliveryMode,
477    pub reserved: BitField3,
478    #[bits = 1]
479    pub level: Level,
480    #[bits = 1]
481    pub trigger: TriggerMode,
482    pub reserved2: BitField16,
483}
484
485#[bitfield]
486#[derive(Debug, Clone, Copy, PartialEq, Eq)]
487pub enum DeliveryStatus {
488    Idle = 0,
489    Pending = 1,
490}
491
492/// The level of a level-triggered interrupt: asserted or deasserted.
493#[bitfield]
494#[derive(Debug, Clone, Copy, PartialEq, Eq)]
495pub enum Level {
496    Deassert = 0,
497    Assert = 1,
498}
499
500/// Represents a IOAPIC redirection table entry.
501#[bitfield]
502#[derive(Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
503pub struct IoapicRedirectionTableEntry {
504    vector: BitField8,
505    #[bits = 3]
506    delivery_mode: DeliveryMode,
507    #[bits = 1]
508    dest_mode: DestinationMode,
509    #[bits = 1]
510    delivery_status: DeliveryStatus,
511    polarity: BitField1,
512    remote_irr: bool,
513    #[bits = 1]
514    trigger_mode: TriggerMode,
515    interrupt_mask: bool, // true iff interrupts are masked.
516    reserved: BitField39,
517    dest_id: BitField8,
518}
519
520/// Number of pins on the standard KVM/IOAPIC.
521pub const NUM_IOAPIC_PINS: usize = 24;
522
523/// Represents the state of the IOAPIC.
524#[repr(C)]
525#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
526pub struct IoapicState {
527    /// base_address is the memory base address for this IOAPIC. It cannot be changed.
528    pub base_address: u64,
529    /// ioregsel register. Used for selecting which entry of the redirect table to read/write.
530    pub ioregsel: u8,
531    /// ioapicid register. Bits 24 - 27 contain the APIC ID for this device.
532    pub ioapicid: u32,
533    /// current_interrupt_level_bitmap represents a bitmap of the state of all of the irq lines
534    pub current_interrupt_level_bitmap: u32,
535    /// redirect_table contains the irq settings for each irq line
536    #[serde(
537        serialize_with = "serialize_arr",
538        deserialize_with = "deserialize_seq_to_arr"
539    )]
540    pub redirect_table: [IoapicRedirectionTableEntry; NUM_IOAPIC_PINS],
541}
542
543impl Default for IoapicState {
544    fn default() -> IoapicState {
545        // SAFETY: trivially safe
546        unsafe { std::mem::zeroed() }
547    }
548}
549
550#[repr(C)]
551#[derive(Debug, Clone, Copy, PartialEq, Eq)]
552pub enum PicSelect {
553    Primary = 0,
554    Secondary = 1,
555}
556
557#[repr(C)]
558#[derive(enumn::N, Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
559pub enum PicInitState {
560    #[default]
561    Icw1 = 0,
562    Icw2 = 1,
563    Icw3 = 2,
564    Icw4 = 3,
565}
566
567/// Convenience implementation for converting from a u8
568impl From<u8> for PicInitState {
569    fn from(item: u8) -> Self {
570        PicInitState::n(item).unwrap_or_else(|| {
571            error!("Invalid PicInitState {}, setting to 0", item);
572            PicInitState::Icw1
573        })
574    }
575}
576
577/// Represents the state of the PIC.
578#[repr(C)]
579#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
580pub struct PicState {
581    /// Edge detection.
582    pub last_irr: u8,
583    /// Interrupt Request Register.
584    pub irr: u8,
585    /// Interrupt Mask Register.
586    pub imr: u8,
587    /// Interrupt Service Register.
588    pub isr: u8,
589    /// Highest priority, for priority rotation.
590    pub priority_add: u8,
591    pub irq_base: u8,
592    pub read_reg_select: bool,
593    pub poll: bool,
594    pub special_mask: bool,
595    pub init_state: PicInitState,
596    pub auto_eoi: bool,
597    pub rotate_on_auto_eoi: bool,
598    pub special_fully_nested_mode: bool,
599    /// PIC takes either 3 or 4 bytes of initialization command word during
600    /// initialization. use_4_byte_icw is true if 4 bytes of ICW are needed.
601    pub use_4_byte_icw: bool,
602    /// "Edge/Level Control Registers", for edge trigger selection.
603    /// When a particular bit is set, the corresponding IRQ is in level-triggered mode. Otherwise
604    /// it is in edge-triggered mode.
605    pub elcr: u8,
606    pub elcr_mask: u8,
607}
608
609/// The LapicState represents the state of an x86 CPU's Local APIC.
610/// The Local APIC consists of 64 128-bit registers, but only the first 32-bits of each register
611/// can be used, so this structure only stores the first 32-bits of each register.
612#[repr(C)]
613#[derive(Clone, Copy, Serialize, Deserialize)]
614pub struct LapicState {
615    #[serde(
616        serialize_with = "serialize_arr",
617        deserialize_with = "deserialize_seq_to_arr"
618    )]
619    pub regs: [LapicRegister; 64],
620}
621
622pub type LapicRegister = u32;
623
624// rust arrays longer than 32 need custom implementations of Debug
625impl std::fmt::Debug for LapicState {
626    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
627        self.regs[..].fmt(formatter)
628    }
629}
630
631// rust arrays longer than 32 need custom implementations of PartialEq
632impl PartialEq for LapicState {
633    fn eq(&self, other: &LapicState) -> bool {
634        self.regs[..] == other.regs[..]
635    }
636}
637
638// Lapic equality is reflexive, so we impl Eq
639impl Eq for LapicState {}
640
641// Local APIC ID register: index 2 (offset 0x20)
642pub const APIC_ID_REG: usize = 2;
643// Local APIC IRR registers: indices 32..=39 (offsets 0x200..0x270, vectors 0..=255)
644pub const APIC_IRR_START_REG: usize = 32;
645
646impl LapicState {
647    /// Returns the APIC ID from the LAPIC registers.
648    pub fn get_apic_id(&self) -> u32 {
649        (self.regs[APIC_ID_REG] >> 24) & 0xFF
650    }
651
652    /// Returns a list of all pending interrupt vectors set in the IRR (Interrupt Request Register).
653    pub fn get_pending_irr_vectors(&self) -> Vec<u8> {
654        let mut vectors = Vec::new();
655        for (i, &reg) in self.regs[APIC_IRR_START_REG..=APIC_IRR_START_REG + 7]
656            .iter()
657            .enumerate()
658        {
659            if reg != 0 {
660                for bit in 0..32 {
661                    if (reg & (1 << bit)) != 0 {
662                        vectors.push((i * 32 + bit) as u8);
663                    }
664                }
665            }
666        }
667        vectors
668    }
669}
670
671/// The PitState represents the state of the PIT (aka the Programmable Interval Timer).
672/// The state is simply the state of it's three channels.
673#[repr(C)]
674#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
675pub struct PitState {
676    pub channels: [PitChannelState; 3],
677    /// Hypervisor-specific flags for setting the pit state.
678    pub flags: u32,
679}
680
681/// The PitRWMode enum represents the access mode of a PIT channel.
682/// Reads and writes to the Pit happen over Port-mapped I/O, which happens one byte at a time,
683/// but the count values and latch values are two bytes. So the access mode controls which of the
684/// two bytes will be read when.
685#[repr(C)]
686#[derive(enumn::N, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
687pub enum PitRWMode {
688    /// None mode means that no access mode has been set.
689    None = 0,
690    /// Least mode means all reads/writes will read/write the least significant byte.
691    Least = 1,
692    /// Most mode means all reads/writes will read/write the most significant byte.
693    Most = 2,
694    /// Both mode means first the least significant byte will be read/written, then the
695    /// next read/write will read/write the most significant byte.
696    Both = 3,
697}
698
699/// Convenience implementation for converting from a u8
700impl From<u8> for PitRWMode {
701    fn from(item: u8) -> Self {
702        PitRWMode::n(item).unwrap_or_else(|| {
703            error!("Invalid PitRWMode value {}, setting to 0", item);
704            PitRWMode::None
705        })
706    }
707}
708
709/// The PitRWState enum represents the state of reading to or writing from a channel.
710/// This is related to the PitRWMode, it mainly gives more detail about the state of the channel
711/// with respect to PitRWMode::Both.
712#[repr(C)]
713#[derive(enumn::N, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
714pub enum PitRWState {
715    /// None mode means that no access mode has been set.
716    None = 0,
717    /// LSB means that the channel is in PitRWMode::Least access mode.
718    LSB = 1,
719    /// MSB means that the channel is in PitRWMode::Most access mode.
720    MSB = 2,
721    /// Word0 means that the channel is in PitRWMode::Both mode, and the least sginificant byte
722    /// has not been read/written yet.
723    Word0 = 3,
724    /// Word1 means that the channel is in PitRWMode::Both mode and the least significant byte
725    /// has already been read/written, and the next byte to be read/written will be the most
726    /// significant byte.
727    Word1 = 4,
728}
729
730/// Convenience implementation for converting from a u8
731impl From<u8> for PitRWState {
732    fn from(item: u8) -> Self {
733        PitRWState::n(item).unwrap_or_else(|| {
734            error!("Invalid PitRWState value {}, setting to 0", item);
735            PitRWState::None
736        })
737    }
738}
739
740/// The PitChannelState represents the state of one of the PIT's three counters.
741#[repr(C)]
742#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
743pub struct PitChannelState {
744    /// The starting value for the counter.
745    pub count: u32,
746    /// Stores the channel count from the last time the count was latched.
747    pub latched_count: u16,
748    /// Indicates the PitRWState state of reading the latch value.
749    pub count_latched: PitRWState,
750    /// Indicates whether ReadBack status has been latched.
751    pub status_latched: bool,
752    /// Stores the channel status from the last time the status was latched. The status contains
753    /// information about the access mode of this channel, but changing those bits in the status
754    /// will not change the behavior of the pit.
755    pub status: u8,
756    /// Indicates the PitRWState state of reading the counter.
757    pub read_state: PitRWState,
758    /// Indicates the PitRWState state of writing the counter.
759    pub write_state: PitRWState,
760    /// Stores the value with which the counter was initialized. Counters are 16-
761    /// bit values with an effective range of 1-65536 (65536 represented by 0).
762    pub reload_value: u16,
763    /// The command access mode of this channel.
764    pub rw_mode: PitRWMode,
765    /// The operation mode of this channel.
766    pub mode: u8,
767    /// Whether or not we are in bcd mode. Not supported by KVM or crosvm's PIT implementation.
768    pub bcd: bool,
769    /// Value of the gate input pin. This only applies to channel 2.
770    pub gate: bool,
771    /// Nanosecond timestamp of when the count value was loaded.
772    pub count_load_time: u64,
773}
774
775// Convenience constructors for IrqRoutes
776impl IrqRoute {
777    pub fn ioapic_irq_route(irq_num: u32) -> IrqRoute {
778        IrqRoute {
779            gsi: irq_num,
780            source: IrqSource::Irqchip {
781                chip: IrqSourceChip::Ioapic,
782                pin: irq_num,
783            },
784        }
785    }
786
787    pub fn pic_irq_route(id: IrqSourceChip, irq_num: u32) -> IrqRoute {
788        IrqRoute {
789            gsi: irq_num,
790            source: IrqSource::Irqchip {
791                chip: id,
792                pin: irq_num % 8,
793            },
794        }
795    }
796}
797
798/// State of a VCPU's general purpose registers.
799#[repr(C)]
800#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
801pub struct Regs {
802    pub rax: u64,
803    pub rbx: u64,
804    pub rcx: u64,
805    pub rdx: u64,
806    pub rsi: u64,
807    pub rdi: u64,
808    pub rsp: u64,
809    pub rbp: u64,
810    pub r8: u64,
811    pub r9: u64,
812    pub r10: u64,
813    pub r11: u64,
814    pub r12: u64,
815    pub r13: u64,
816    pub r14: u64,
817    pub r15: u64,
818    pub rip: u64,
819    pub rflags: u64,
820}
821
822impl Default for Regs {
823    fn default() -> Self {
824        Regs {
825            rax: 0,
826            rbx: 0,
827            rcx: 0,
828            rdx: 0,
829            rsi: 0,
830            rdi: 0,
831            rsp: 0,
832            rbp: 0,
833            r8: 0,
834            r9: 0,
835            r10: 0,
836            r11: 0,
837            r12: 0,
838            r13: 0,
839            r14: 0,
840            r15: 0,
841            rip: 0xfff0, // Reset vector.
842            rflags: 0x2, // Bit 1 (0x2) is always 1.
843        }
844    }
845}
846
847/// State of a memory segment.
848#[repr(C)]
849#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
850pub struct Segment {
851    pub base: u64,
852    /// Limit of the segment - always in bytes, regardless of granularity (`g`) field.
853    pub limit_bytes: u32,
854    pub selector: u16,
855    pub type_: u8,
856    pub present: u8,
857    pub dpl: u8,
858    pub db: u8,
859    pub s: u8,
860    pub l: u8,
861    pub g: u8,
862    pub avl: u8,
863}
864
865/// State of a global descriptor table or interrupt descriptor table.
866#[repr(C)]
867#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
868pub struct DescriptorTable {
869    pub base: u64,
870    pub limit: u16,
871}
872
873/// State of a VCPU's special registers.
874#[repr(C)]
875#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
876pub struct Sregs {
877    pub cs: Segment,
878    pub ds: Segment,
879    pub es: Segment,
880    pub fs: Segment,
881    pub gs: Segment,
882    pub ss: Segment,
883    pub tr: Segment,
884    pub ldt: Segment,
885    pub gdt: DescriptorTable,
886    pub idt: DescriptorTable,
887    pub cr0: u64,
888    pub cr2: u64,
889    pub cr3: u64,
890    pub cr4: u64,
891    pub cr8: u64,
892    pub efer: u64,
893}
894
895impl Default for Sregs {
896    fn default() -> Self {
897        // Intel SDM Vol. 3A, 3.4.5.1 ("Code- and Data-Segment Descriptor Types")
898        const SEG_TYPE_DATA: u8 = 0b0000;
899        const SEG_TYPE_DATA_WRITABLE: u8 = 0b0010;
900
901        const SEG_TYPE_CODE: u8 = 0b1000;
902        const SEG_TYPE_CODE_READABLE: u8 = 0b0010;
903
904        const SEG_TYPE_ACCESSED: u8 = 0b0001;
905
906        // Intel SDM Vol. 3A, 3.4.5 ("Segment Descriptors")
907        const SEG_S_SYSTEM: u8 = 0; // System segment.
908        const SEG_S_CODE_OR_DATA: u8 = 1; // Data/code segment.
909
910        // 16-bit real-mode code segment (reset vector).
911        let code_seg = Segment {
912            base: 0xffff0000,
913            limit_bytes: 0xffff,
914            selector: 0xf000,
915            type_: SEG_TYPE_CODE | SEG_TYPE_CODE_READABLE | SEG_TYPE_ACCESSED, // 11
916            present: 1,
917            s: SEG_S_CODE_OR_DATA,
918            ..Default::default()
919        };
920
921        // 16-bit real-mode data segment.
922        let data_seg = Segment {
923            base: 0,
924            limit_bytes: 0xffff,
925            selector: 0,
926            type_: SEG_TYPE_DATA | SEG_TYPE_DATA_WRITABLE | SEG_TYPE_ACCESSED, // 3
927            present: 1,
928            s: SEG_S_CODE_OR_DATA,
929            ..Default::default()
930        };
931
932        // 16-bit TSS segment.
933        let task_seg = Segment {
934            base: 0,
935            limit_bytes: 0xffff,
936            selector: 0,
937            type_: SEG_TYPE_CODE | SEG_TYPE_CODE_READABLE | SEG_TYPE_ACCESSED, // 11
938            present: 1,
939            s: SEG_S_SYSTEM,
940            ..Default::default()
941        };
942
943        // Local descriptor table.
944        let ldt = Segment {
945            base: 0,
946            limit_bytes: 0xffff,
947            selector: 0,
948            type_: SEG_TYPE_DATA | SEG_TYPE_DATA_WRITABLE, // 2
949            present: 1,
950            s: SEG_S_SYSTEM,
951            ..Default::default()
952        };
953
954        // Global descriptor table.
955        let gdt = DescriptorTable {
956            base: 0,
957            limit: 0xffff,
958        };
959
960        // Interrupt descriptor table.
961        let idt = DescriptorTable {
962            base: 0,
963            limit: 0xffff,
964        };
965
966        let cr0 = (1 << 4) // CR0.ET (reserved, always 1)
967                | (1 << 30); // CR0.CD (cache disable)
968
969        Sregs {
970            cs: code_seg,
971            ds: data_seg,
972            es: data_seg,
973            fs: data_seg,
974            gs: data_seg,
975            ss: data_seg,
976            tr: task_seg,
977            ldt,
978            gdt,
979            idt,
980            cr0,
981            cr2: 0,
982            cr3: 0,
983            cr4: 0,
984            cr8: 0,
985            efer: 0,
986        }
987    }
988}
989
990/// x87 80-bit floating point value.
991#[repr(C)]
992#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
993pub struct FpuReg {
994    /// 64-bit mantissa.
995    pub significand: u64,
996
997    /// 15-bit biased exponent and sign bit.
998    pub sign_exp: u16,
999}
1000
1001impl FpuReg {
1002    /// Convert an array of 8x16-byte arrays to an array of 8 `FpuReg`.
1003    ///
1004    /// Ignores any data in the upper 6 bytes of each element; the values represent 80-bit FPU
1005    /// registers, so the upper 48 bits are unused.
1006    pub fn from_16byte_arrays(byte_arrays: &[[u8; 16]; 8]) -> [FpuReg; 8] {
1007        let mut regs = [FpuReg::default(); 8];
1008        for (dst, src) in regs.iter_mut().zip(byte_arrays.iter()) {
1009            let tbyte: [u8; 10] = src[0..10].try_into().unwrap();
1010            *dst = FpuReg::from(tbyte);
1011        }
1012        regs
1013    }
1014
1015    /// Convert an array of 8 `FpuReg` into 8x16-byte arrays.
1016    pub fn to_16byte_arrays(regs: &[FpuReg; 8]) -> [[u8; 16]; 8] {
1017        let mut byte_arrays = [[0u8; 16]; 8];
1018        for (dst, src) in byte_arrays.iter_mut().zip(regs.iter()) {
1019            *dst = (*src).into();
1020        }
1021        byte_arrays
1022    }
1023}
1024
1025impl From<[u8; 10]> for FpuReg {
1026    /// Construct a `FpuReg` from an 80-bit representation.
1027    fn from(value: [u8; 10]) -> FpuReg {
1028        // These array sub-slices can't fail, but there's no (safe) way to express that in Rust
1029        // without an `unwrap()`.
1030        let significand_bytes = value[0..8].try_into().unwrap();
1031        let significand = u64::from_le_bytes(significand_bytes);
1032        let sign_exp_bytes = value[8..10].try_into().unwrap();
1033        let sign_exp = u16::from_le_bytes(sign_exp_bytes);
1034        FpuReg {
1035            significand,
1036            sign_exp,
1037        }
1038    }
1039}
1040
1041impl From<FpuReg> for [u8; 10] {
1042    /// Convert an `FpuReg` into its 80-bit "TBYTE" representation.
1043    fn from(value: FpuReg) -> [u8; 10] {
1044        let mut bytes = [0u8; 10];
1045        bytes[0..8].copy_from_slice(&value.significand.to_le_bytes());
1046        bytes[8..10].copy_from_slice(&value.sign_exp.to_le_bytes());
1047        bytes
1048    }
1049}
1050
1051impl From<FpuReg> for [u8; 16] {
1052    /// Convert an `FpuReg` into its 80-bit representation plus 6 unused upper bytes.
1053    /// This is a convenience function for converting to hypervisor types.
1054    fn from(value: FpuReg) -> [u8; 16] {
1055        let mut bytes = [0u8; 16];
1056        bytes[0..8].copy_from_slice(&value.significand.to_le_bytes());
1057        bytes[8..10].copy_from_slice(&value.sign_exp.to_le_bytes());
1058        bytes
1059    }
1060}
1061
1062/// State of a VCPU's floating point unit.
1063#[repr(C)]
1064#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
1065pub struct Fpu {
1066    pub fpr: [FpuReg; 8],
1067    pub fcw: u16,
1068    pub fsw: u16,
1069    pub ftwx: u8,
1070    pub last_opcode: u16,
1071    pub last_ip: u64,
1072    pub last_dp: u64,
1073    pub xmm: [[u8; 16usize]; 16usize],
1074    pub mxcsr: u32,
1075}
1076
1077impl Default for Fpu {
1078    fn default() -> Self {
1079        Fpu {
1080            fpr: Default::default(),
1081            fcw: 0x37f, // Intel SDM Vol. 1, 13.6
1082            fsw: 0,
1083            ftwx: 0,
1084            last_opcode: 0,
1085            last_ip: 0,
1086            last_dp: 0,
1087            xmm: Default::default(),
1088            mxcsr: 0x1f80, // Intel SDM Vol. 1, 11.6.4
1089        }
1090    }
1091}
1092
1093/// State of a VCPU's debug registers.
1094#[repr(C)]
1095#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
1096pub struct DebugRegs {
1097    pub db: [u64; 4usize],
1098    pub dr6: u64,
1099    pub dr7: u64,
1100}
1101
1102/// The hybrid type for intel hybrid CPU.
1103#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
1104pub enum CpuHybridType {
1105    /// Intel Atom.
1106    Atom,
1107    /// Intel Core.
1108    Core,
1109}
1110
1111/// State of the VCPU's x87 FPU, MMX, XMM, YMM registers.
1112/// May contain more state depending on enabled extensions.
1113#[derive(Clone, Debug, Serialize, Deserialize)]
1114pub struct Xsave {
1115    data: Vec<u32>,
1116
1117    // Actual length in bytes. May be smaller than data if a non-u32 multiple of bytes is
1118    // requested.
1119    len: usize,
1120}
1121
1122impl Xsave {
1123    /// Create a new buffer to store Xsave data.
1124    ///
1125    /// # Argments
1126    /// * `len` size in bytes.
1127    pub fn new(len: usize) -> Self {
1128        Xsave {
1129            data: vec![0; len.div_ceil(4)],
1130            len,
1131        }
1132    }
1133
1134    pub fn as_ptr(&self) -> *const c_void {
1135        self.data.as_ptr() as *const c_void
1136    }
1137
1138    pub fn as_mut_ptr(&mut self) -> *mut c_void {
1139        self.data.as_mut_ptr() as *mut c_void
1140    }
1141
1142    /// Length in bytes of the XSAVE data.
1143    pub fn len(&self) -> usize {
1144        self.len
1145    }
1146
1147    /// Returns true is length of XSAVE data is zero
1148    pub fn is_empty(&self) -> bool {
1149        self.len() == 0
1150    }
1151}
1152
1153#[cfg(test)]
1154mod tests {
1155    use super::*;
1156
1157    #[test]
1158    fn test_lapic_get_apic_id() {
1159        let mut lapic = LapicState { regs: [0; 64] };
1160        assert_eq!(lapic.get_apic_id(), 0);
1161
1162        // xAPIC mode: ID in bits 24..=31
1163        lapic.regs[APIC_ID_REG] = 0x05000000;
1164        assert_eq!(lapic.get_apic_id(), 5);
1165
1166        lapic.regs[APIC_ID_REG] = 0xFE000000;
1167        assert_eq!(lapic.get_apic_id(), 0xFE);
1168    }
1169
1170    #[test]
1171    fn test_lapic_get_pending_irr_vectors() {
1172        let mut lapic = LapicState { regs: [0; 64] };
1173        assert!(lapic.get_pending_irr_vectors().is_empty());
1174
1175        // Vector 0xEC (236): word 7 (regs[39]), bit 12 (236 - 224 = 12)
1176        lapic.regs[APIC_IRR_START_REG + 7] |= 1 << 12;
1177        // Vector 0x30 (48): word 1 (regs[33]), bit 16 (48 - 32 = 16)
1178        lapic.regs[APIC_IRR_START_REG + 1] |= 1 << 16;
1179
1180        let vectors = lapic.get_pending_irr_vectors();
1181        assert_eq!(vectors, vec![48, 236]);
1182    }
1183}