• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use std::arch::x86_64::CpuidResult;
6 #[cfg(any(unix, feature = "haxm", feature = "whpx"))]
7 use std::arch::x86_64::__cpuid;
8 #[cfg(any(unix, feature = "haxm", feature = "whpx"))]
9 use std::arch::x86_64::_rdtsc;
10 
11 use base::error;
12 use base::Result;
13 use bit_field::*;
14 use downcast_rs::impl_downcast;
15 use serde::Deserialize;
16 use serde::Serialize;
17 use vm_memory::GuestAddress;
18 
19 use crate::Hypervisor;
20 use crate::IrqRoute;
21 use crate::IrqSource;
22 use crate::IrqSourceChip;
23 use crate::Vcpu;
24 use crate::Vm;
25 
26 /// A trait for managing cpuids for an x86_64 hypervisor and for checking its capabilities.
27 pub trait HypervisorX86_64: Hypervisor {
28     /// Get the system supported CPUID values.
get_supported_cpuid(&self) -> Result<CpuId>29     fn get_supported_cpuid(&self) -> Result<CpuId>;
30 
31     /// Get the system emulated CPUID values.
get_emulated_cpuid(&self) -> Result<CpuId>32     fn get_emulated_cpuid(&self) -> Result<CpuId>;
33 
34     /// Gets the list of supported MSRs.
get_msr_index_list(&self) -> Result<Vec<u32>>35     fn get_msr_index_list(&self) -> Result<Vec<u32>>;
36 }
37 
38 /// A wrapper for using a VM on x86_64 and getting/setting its state.
39 pub trait VmX86_64: Vm {
40     /// Gets the `HypervisorX86_64` that created this VM.
get_hypervisor(&self) -> &dyn HypervisorX86_6441     fn get_hypervisor(&self) -> &dyn HypervisorX86_64;
42 
43     /// Create a Vcpu with the specified Vcpu ID.
create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuX86_64>>44     fn create_vcpu(&self, id: usize) -> Result<Box<dyn VcpuX86_64>>;
45 
46     /// Sets the address of the three-page region in the VM's address space.
set_tss_addr(&self, addr: GuestAddress) -> Result<()>47     fn set_tss_addr(&self, addr: GuestAddress) -> Result<()>;
48 
49     /// Sets the address of a one-page region in the VM's address space.
set_identity_map_addr(&self, addr: GuestAddress) -> Result<()>50     fn set_identity_map_addr(&self, addr: GuestAddress) -> Result<()>;
51 }
52 
53 /// A wrapper around creating and using a VCPU on x86_64.
54 pub trait VcpuX86_64: Vcpu {
55     /// Sets or clears the flag that requests the VCPU to exit when it becomes possible to inject
56     /// interrupts into the guest.
set_interrupt_window_requested(&self, requested: bool)57     fn set_interrupt_window_requested(&self, requested: bool);
58 
59     /// Checks if we can inject an interrupt into the VCPU.
ready_for_interrupt(&self) -> bool60     fn ready_for_interrupt(&self) -> bool;
61 
62     /// Injects interrupt vector `irq` into the VCPU.
interrupt(&self, irq: u32) -> Result<()>63     fn interrupt(&self, irq: u32) -> Result<()>;
64 
65     /// Injects a non-maskable interrupt into the VCPU.
inject_nmi(&self) -> Result<()>66     fn inject_nmi(&self) -> Result<()>;
67 
68     /// Gets the VCPU general purpose registers.
get_regs(&self) -> Result<Regs>69     fn get_regs(&self) -> Result<Regs>;
70 
71     /// Sets the VCPU general purpose registers.
set_regs(&self, regs: &Regs) -> Result<()>72     fn set_regs(&self, regs: &Regs) -> Result<()>;
73 
74     /// Gets the VCPU special registers.
get_sregs(&self) -> Result<Sregs>75     fn get_sregs(&self) -> Result<Sregs>;
76 
77     /// Sets the VCPU special registers.
set_sregs(&self, sregs: &Sregs) -> Result<()>78     fn set_sregs(&self, sregs: &Sregs) -> Result<()>;
79 
80     /// Gets the VCPU FPU registers.
get_fpu(&self) -> Result<Fpu>81     fn get_fpu(&self) -> Result<Fpu>;
82 
83     /// Sets the VCPU FPU registers.
set_fpu(&self, fpu: &Fpu) -> Result<()>84     fn set_fpu(&self, fpu: &Fpu) -> Result<()>;
85 
86     /// Gets the VCPU debug registers.
get_debugregs(&self) -> Result<DebugRegs>87     fn get_debugregs(&self) -> Result<DebugRegs>;
88 
89     /// Sets the VCPU debug registers.
set_debugregs(&self, debugregs: &DebugRegs) -> Result<()>90     fn set_debugregs(&self, debugregs: &DebugRegs) -> Result<()>;
91 
92     /// Gets the VCPU extended control registers.
get_xcrs(&self) -> Result<Vec<Register>>93     fn get_xcrs(&self) -> Result<Vec<Register>>;
94 
95     /// Sets the VCPU extended control registers.
set_xcrs(&self, xcrs: &[Register]) -> Result<()>96     fn set_xcrs(&self, xcrs: &[Register]) -> Result<()>;
97 
98     /// Gets the VCPU x87 FPU, MMX, XMM, YMM and MXCSR registers.
get_xsave(&self) -> Result<Xsave>99     fn get_xsave(&self) -> Result<Xsave>;
100 
101     /// Sets the VCPU x87 FPU, MMX, XMM, YMM and MXCSR registers.
set_xsave(&self, xsave: &Xsave) -> Result<()>102     fn set_xsave(&self, xsave: &Xsave) -> Result<()>;
103 
104     /// Gets the VCPU Events states.
get_vcpu_events(&self) -> Result<VcpuEvents>105     fn get_vcpu_events(&self) -> Result<VcpuEvents>;
106 
107     /// Sets the VCPU Events states.
set_vcpu_events(&self, vcpu_evts: &VcpuEvents) -> Result<()>108     fn set_vcpu_events(&self, vcpu_evts: &VcpuEvents) -> Result<()>;
109 
110     /// Gets the model-specific registers.  `msrs` specifies the MSR indexes to be queried, and
111     /// on success contains their indexes and values.
get_msrs(&self, msrs: &mut Vec<Register>) -> Result<()>112     fn get_msrs(&self, msrs: &mut Vec<Register>) -> Result<()>;
113 
114     /// Gets the model-specific registers. Returns all the MSRs for the VCPU.
get_all_msrs(&self) -> Result<Vec<Register>>115     fn get_all_msrs(&self) -> Result<Vec<Register>>;
116 
117     /// Sets the model-specific registers.
set_msrs(&self, msrs: &[Register]) -> Result<()>118     fn set_msrs(&self, msrs: &[Register]) -> Result<()>;
119 
120     /// Sets up the data returned by the CPUID instruction.
set_cpuid(&self, cpuid: &CpuId) -> Result<()>121     fn set_cpuid(&self, cpuid: &CpuId) -> Result<()>;
122 
123     /// Gets the system emulated hyper-v CPUID values.
get_hyperv_cpuid(&self) -> Result<CpuId>124     fn get_hyperv_cpuid(&self) -> Result<CpuId>;
125 
126     /// Sets up debug registers and configure vcpu for handling guest debug events.
set_guest_debug(&self, addrs: &[GuestAddress], enable_singlestep: bool) -> Result<()>127     fn set_guest_debug(&self, addrs: &[GuestAddress], enable_singlestep: bool) -> Result<()>;
128 
129     /// This function should be called after `Vcpu::run` returns `VcpuExit::Cpuid`, and `entry`
130     /// should represent the result of emulating the CPUID instruction. The `handle_cpuid` function
131     /// will then set the appropriate registers on the vcpu.
handle_cpuid(&mut self, entry: &CpuIdEntry) -> Result<()>132     fn handle_cpuid(&mut self, entry: &CpuIdEntry) -> Result<()>;
133 
134     /// Get the guest->host TSC offset
get_tsc_offset(&self) -> Result<u64>135     fn get_tsc_offset(&self) -> Result<u64>;
136 
137     /// Set the guest->host TSC offset
set_tsc_offset(&self, offset: u64) -> Result<()>138     fn set_tsc_offset(&self, offset: u64) -> Result<()>;
139 
140     /// Snapshot vCPU state
snapshot(&self) -> anyhow::Result<VcpuSnapshot>141     fn snapshot(&self) -> anyhow::Result<VcpuSnapshot> {
142         Ok(VcpuSnapshot {
143             vcpu_id: self.id(),
144             regs: self.get_regs()?,
145             sregs: self.get_sregs()?,
146             debug_regs: self.get_debugregs()?,
147             xcrs: self.get_xcrs()?,
148             msrs: self.get_all_msrs()?,
149             xsave: self.get_xsave()?,
150             vcpu_events: self.get_vcpu_events()?,
151             tsc_offset: self.get_tsc_offset()?,
152         })
153     }
154 
restore(&mut self, snapshot: &VcpuSnapshot) -> anyhow::Result<()>155     fn restore(&mut self, snapshot: &VcpuSnapshot) -> anyhow::Result<()> {
156         assert_eq!(snapshot.vcpu_id, self.id());
157         self.set_regs(&snapshot.regs)?;
158         self.set_sregs(&snapshot.sregs)?;
159         self.set_debugregs(&snapshot.debug_regs)?;
160         self.set_xcrs(&snapshot.xcrs)?;
161         self.set_msrs(&snapshot.msrs)?;
162         self.set_xsave(&snapshot.xsave)?;
163         self.set_vcpu_events(&snapshot.vcpu_events)?;
164         self.set_tsc_offset(snapshot.tsc_offset)?;
165         Ok(())
166     }
167 }
168 
169 /// x86 specific vCPU snapshot.
170 #[derive(Clone, Debug, Serialize, Deserialize)]
171 pub struct VcpuSnapshot {
172     pub vcpu_id: usize,
173     regs: Regs,
174     sregs: Sregs,
175     debug_regs: DebugRegs,
176     xcrs: Vec<Register>,
177     msrs: Vec<Register>,
178     xsave: Xsave,
179     vcpu_events: VcpuEvents,
180     tsc_offset: u64,
181 }
182 
183 impl_downcast!(VcpuX86_64);
184 
185 // TSC MSR
186 pub const MSR_IA32_TSC: u32 = 0x00000010;
187 
188 /// Implementation of get_tsc_offset that uses VcpuX86_64::get_msrs.
189 #[cfg(any(unix, feature = "haxm", feature = "whpx"))]
get_tsc_offset_from_msr(vcpu: &impl VcpuX86_64) -> Result<u64>190 pub(crate) fn get_tsc_offset_from_msr(vcpu: &impl VcpuX86_64) -> Result<u64> {
191     let mut regs = vec![Register {
192         id: crate::MSR_IA32_TSC,
193         value: 0,
194     }];
195 
196     // Safe because _rdtsc takes no arguments
197     let host_before_tsc = unsafe { _rdtsc() };
198 
199     // get guest TSC value from our hypervisor
200     vcpu.get_msrs(&mut regs)?;
201 
202     // Safe because _rdtsc takes no arguments
203     let host_after_tsc = unsafe { _rdtsc() };
204 
205     // Average the before and after host tsc to get the best value
206     let host_tsc = ((host_before_tsc as u128 + host_after_tsc as u128) / 2) as u64;
207 
208     Ok(regs[0].value.wrapping_sub(host_tsc))
209 }
210 
211 /// Implementation of get_tsc_offset that uses VcpuX86_64::get_msrs.
212 #[cfg(any(unix, feature = "haxm", feature = "whpx"))]
set_tsc_offset_via_msr(vcpu: &impl VcpuX86_64, offset: u64) -> Result<()>213 pub(crate) fn set_tsc_offset_via_msr(vcpu: &impl VcpuX86_64, offset: u64) -> Result<()> {
214     // Safe because _rdtsc takes no arguments
215     let host_tsc = unsafe { _rdtsc() };
216 
217     let regs = vec![Register {
218         id: crate::MSR_IA32_TSC,
219         value: host_tsc.wrapping_add(offset),
220     }];
221 
222     // set guest TSC value from our hypervisor
223     vcpu.set_msrs(&regs)
224 }
225 
226 /// Gets host cpu max physical address bits.
227 #[cfg(any(unix, feature = "haxm", feature = "whpx"))]
host_phys_addr_bits() -> u8228 pub(crate) fn host_phys_addr_bits() -> u8 {
229     let highest_ext_function = unsafe { __cpuid(0x80000000) };
230     if highest_ext_function.eax >= 0x80000008 {
231         let addr_size = unsafe { __cpuid(0x80000008) };
232         // Low 8 bits of 0x80000008 leaf: host physical address size in bits.
233         addr_size.eax as u8
234     } else {
235         36
236     }
237 }
238 
239 /// Initial state for x86_64 VCPUs.
240 #[derive(Clone, Default)]
241 pub struct VcpuInitX86_64 {
242     /// General-purpose registers.
243     pub regs: Regs,
244 
245     /// Special registers.
246     pub sregs: Sregs,
247 
248     /// Floating-point registers.
249     pub fpu: Fpu,
250 
251     /// Machine-specific registers.
252     pub msrs: Vec<Register>,
253 }
254 
255 /// Hold the CPU feature configurations that are needed to setup a vCPU.
256 #[derive(Clone, Debug, PartialEq, Eq)]
257 pub struct CpuConfigX86_64 {
258     /// whether to force using a calibrated TSC leaf (0x15).
259     pub force_calibrated_tsc_leaf: bool,
260 
261     /// whether enabling host cpu topology.
262     pub host_cpu_topology: bool,
263 
264     /// whether expose HWP feature to the guest.
265     pub enable_hwp: bool,
266 
267     /// whether enabling host cpu topology.
268     pub enable_pnp_data: bool,
269 
270     /// Wheter diabling SMT (Simultaneous Multithreading).
271     pub no_smt: bool,
272 
273     /// whether enabling ITMT scheduler
274     pub itmt: bool,
275 
276     /// whether setting hybrid CPU type
277     pub hybrid_type: Option<CpuHybridType>,
278 }
279 
280 impl CpuConfigX86_64 {
new( force_calibrated_tsc_leaf: bool, host_cpu_topology: bool, enable_hwp: bool, enable_pnp_data: bool, no_smt: bool, itmt: bool, hybrid_type: Option<CpuHybridType>, ) -> Self281     pub fn new(
282         force_calibrated_tsc_leaf: bool,
283         host_cpu_topology: bool,
284         enable_hwp: bool,
285         enable_pnp_data: bool,
286         no_smt: bool,
287         itmt: bool,
288         hybrid_type: Option<CpuHybridType>,
289     ) -> Self {
290         CpuConfigX86_64 {
291             force_calibrated_tsc_leaf,
292             host_cpu_topology,
293             enable_hwp,
294             enable_pnp_data,
295             no_smt,
296             itmt,
297             hybrid_type,
298         }
299     }
300 }
301 
302 /// A CpuId Entry contains supported feature information for the given processor.
303 /// This can be modified by the hypervisor to pass additional information to the guest kernel
304 /// about the hypervisor or vm. Information is returned in the eax, ebx, ecx and edx registers
305 /// by the cpu for a given function and index/subfunction (passed into the cpu via the eax and ecx
306 /// register respectively).
307 #[repr(C)]
308 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
309 pub struct CpuIdEntry {
310     pub function: u32,
311     pub index: u32,
312     // flags is needed for KVM.  We store it on CpuIdEntry to preserve the flags across
313     // get_supported_cpuids() -> kvm_cpuid2 -> CpuId -> kvm_cpuid2 -> set_cpuid().
314     pub flags: u32,
315     pub cpuid: CpuidResult,
316 }
317 
318 /// A container for the list of cpu id entries for the hypervisor and underlying cpu.
319 pub struct CpuId {
320     pub cpu_id_entries: Vec<CpuIdEntry>,
321 }
322 
323 impl CpuId {
324     /// Constructs a new CpuId, with space allocated for `initial_capacity` CpuIdEntries.
new(initial_capacity: usize) -> Self325     pub fn new(initial_capacity: usize) -> Self {
326         CpuId {
327             cpu_id_entries: Vec::with_capacity(initial_capacity),
328         }
329     }
330 }
331 
332 #[bitfield]
333 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
334 pub enum DestinationMode {
335     Physical = 0,
336     Logical = 1,
337 }
338 
339 #[bitfield]
340 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
341 pub enum TriggerMode {
342     Edge = 0,
343     Level = 1,
344 }
345 
346 #[bitfield]
347 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
348 pub enum DeliveryMode {
349     Fixed = 0b000,
350     Lowest = 0b001,
351     SMI = 0b010,        // System management interrupt
352     RemoteRead = 0b011, // This is no longer supported by intel.
353     NMI = 0b100,        // Non maskable interrupt
354     Init = 0b101,
355     Startup = 0b110,
356     External = 0b111,
357 }
358 
359 // These MSI structures are for Intel's implementation of MSI.  The PCI spec defines most of MSI,
360 // but the Intel spec defines the format of messages for raising interrupts.  The PCI spec defines
361 // three u32s -- the address, address_high, and data -- but Intel only makes use of the address and
362 // data.  The Intel portion of the specification is in Volume 3 section 10.11.
363 #[bitfield]
364 #[derive(Clone, Copy, PartialEq, Eq)]
365 pub struct MsiAddressMessage {
366     pub reserved: BitField2,
367     #[bits = 1]
368     pub destination_mode: DestinationMode,
369     pub redirection_hint: BitField1,
370     pub reserved_2: BitField8,
371     pub destination_id: BitField8,
372     // According to Intel's implementation of MSI, these bits must always be 0xfee.
373     pub always_0xfee: BitField12,
374 }
375 
376 #[bitfield]
377 #[derive(Clone, Copy, PartialEq, Eq)]
378 pub struct MsiDataMessage {
379     pub vector: BitField8,
380     #[bits = 3]
381     pub delivery_mode: DeliveryMode,
382     pub reserved: BitField3,
383     #[bits = 1]
384     pub level: Level,
385     #[bits = 1]
386     pub trigger: TriggerMode,
387     pub reserved2: BitField16,
388 }
389 
390 #[bitfield]
391 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
392 pub enum DeliveryStatus {
393     Idle = 0,
394     Pending = 1,
395 }
396 
397 /// The level of a level-triggered interrupt: asserted or deasserted.
398 #[bitfield]
399 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
400 pub enum Level {
401     Deassert = 0,
402     Assert = 1,
403 }
404 
405 /// Represents a IOAPIC redirection table entry.
406 #[bitfield]
407 #[derive(Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
408 pub struct IoapicRedirectionTableEntry {
409     vector: BitField8,
410     #[bits = 3]
411     delivery_mode: DeliveryMode,
412     #[bits = 1]
413     dest_mode: DestinationMode,
414     #[bits = 1]
415     delivery_status: DeliveryStatus,
416     polarity: BitField1,
417     remote_irr: bool,
418     #[bits = 1]
419     trigger_mode: TriggerMode,
420     interrupt_mask: bool, // true iff interrupts are masked.
421     reserved: BitField39,
422     dest_id: BitField8,
423 }
424 
425 /// Number of pins on the standard KVM/IOAPIC.
426 pub const NUM_IOAPIC_PINS: usize = 24;
427 
428 /// Maximum number of pins on the IOAPIC.
429 pub const MAX_IOAPIC_PINS: usize = 120;
430 
431 /// Represents the state of the IOAPIC.
432 #[repr(C)]
433 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
434 pub struct IoapicState {
435     /// base_address is the memory base address for this IOAPIC. It cannot be changed.
436     pub base_address: u64,
437     /// ioregsel register. Used for selecting which entry of the redirect table to read/write.
438     pub ioregsel: u8,
439     /// ioapicid register. Bits 24 - 27 contain the APIC ID for this device.
440     pub ioapicid: u32,
441     /// current_interrupt_level_bitmap represents a bitmap of the state of all of the irq lines
442     pub current_interrupt_level_bitmap: u32,
443     /// redirect_table contains the irq settings for each irq line
444     pub redirect_table: [IoapicRedirectionTableEntry; 120],
445 }
446 
447 impl Default for IoapicState {
default() -> IoapicState448     fn default() -> IoapicState {
449         unsafe { std::mem::zeroed() }
450     }
451 }
452 
453 #[repr(C)]
454 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
455 pub enum PicSelect {
456     Primary = 0,
457     Secondary = 1,
458 }
459 
460 #[repr(C)]
461 #[derive(enumn::N, Debug, Clone, Copy, Default, PartialEq, Eq)]
462 pub enum PicInitState {
463     #[default]
464     Icw1 = 0,
465     Icw2 = 1,
466     Icw3 = 2,
467     Icw4 = 3,
468 }
469 
470 /// Convenience implementation for converting from a u8
471 impl From<u8> for PicInitState {
from(item: u8) -> Self472     fn from(item: u8) -> Self {
473         PicInitState::n(item).unwrap_or_else(|| {
474             error!("Invalid PicInitState {}, setting to 0", item);
475             PicInitState::Icw1
476         })
477     }
478 }
479 
480 /// Represents the state of the PIC.
481 #[repr(C)]
482 #[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
483 pub struct PicState {
484     /// Edge detection.
485     pub last_irr: u8,
486     /// Interrupt Request Register.
487     pub irr: u8,
488     /// Interrupt Mask Register.
489     pub imr: u8,
490     /// Interrupt Service Register.
491     pub isr: u8,
492     /// Highest priority, for priority rotation.
493     pub priority_add: u8,
494     pub irq_base: u8,
495     pub read_reg_select: bool,
496     pub poll: bool,
497     pub special_mask: bool,
498     pub init_state: PicInitState,
499     pub auto_eoi: bool,
500     pub rotate_on_auto_eoi: bool,
501     pub special_fully_nested_mode: bool,
502     /// PIC takes either 3 or 4 bytes of initialization command word during
503     /// initialization. use_4_byte_icw is true if 4 bytes of ICW are needed.
504     pub use_4_byte_icw: bool,
505     /// "Edge/Level Control Registers", for edge trigger selection.
506     /// When a particular bit is set, the corresponding IRQ is in level-triggered mode. Otherwise it
507     /// is in edge-triggered mode.
508     pub elcr: u8,
509     pub elcr_mask: u8,
510 }
511 
512 /// The LapicState represents the state of an x86 CPU's Local APIC.
513 /// The Local APIC consists of 64 128-bit registers, but only the first 32-bits of each register
514 /// can be used, so this structure only stores the first 32-bits of each register.
515 #[repr(C)]
516 #[derive(Clone, Copy)]
517 pub struct LapicState {
518     pub regs: [LapicRegister; 64],
519 }
520 
521 pub type LapicRegister = u32;
522 
523 // rust arrays longer than 32 need custom implementations of Debug
524 impl std::fmt::Debug for LapicState {
fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result525     fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
526         self.regs[..].fmt(formatter)
527     }
528 }
529 
530 // rust arrays longer than 32 need custom implementations of PartialEq
531 impl PartialEq for LapicState {
eq(&self, other: &LapicState) -> bool532     fn eq(&self, other: &LapicState) -> bool {
533         self.regs[..] == other.regs[..]
534     }
535 }
536 
537 // Lapic equality is reflexive, so we impl Eq
538 impl Eq for LapicState {}
539 
540 /// The PitState represents the state of the PIT (aka the Programmable Interval Timer).
541 /// The state is simply the state of it's three channels.
542 #[repr(C)]
543 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
544 pub struct PitState {
545     pub channels: [PitChannelState; 3],
546     /// Hypervisor-specific flags for setting the pit state.
547     pub flags: u32,
548 }
549 
550 /// The PitRWMode enum represents the access mode of a PIT channel.
551 /// Reads and writes to the Pit happen over Port-mapped I/O, which happens one byte at a time,
552 /// but the count values and latch values are two bytes. So the access mode controls which of the
553 /// two bytes will be read when.
554 #[repr(C)]
555 #[derive(enumn::N, Clone, Copy, Debug, PartialEq, Eq)]
556 pub enum PitRWMode {
557     /// None mode means that no access mode has been set.
558     None = 0,
559     /// Least mode means all reads/writes will read/write the least significant byte.
560     Least = 1,
561     /// Most mode means all reads/writes will read/write the most significant byte.
562     Most = 2,
563     /// Both mode means first the least significant byte will be read/written, then the
564     /// next read/write will read/write the most significant byte.
565     Both = 3,
566 }
567 
568 /// Convenience implementation for converting from a u8
569 impl From<u8> for PitRWMode {
from(item: u8) -> Self570     fn from(item: u8) -> Self {
571         PitRWMode::n(item).unwrap_or_else(|| {
572             error!("Invalid PitRWMode value {}, setting to 0", item);
573             PitRWMode::None
574         })
575     }
576 }
577 
578 /// The PitRWState enum represents the state of reading to or writing from a channel.
579 /// This is related to the PitRWMode, it mainly gives more detail about the state of the channel
580 /// with respect to PitRWMode::Both.
581 #[repr(C)]
582 #[derive(enumn::N, Clone, Copy, Debug, PartialEq, Eq)]
583 pub enum PitRWState {
584     /// None mode means that no access mode has been set.
585     None = 0,
586     /// LSB means that the channel is in PitRWMode::Least access mode.
587     LSB = 1,
588     /// MSB means that the channel is in PitRWMode::Most access mode.
589     MSB = 2,
590     /// Word0 means that the channel is in PitRWMode::Both mode, and the least sginificant byte
591     /// has not been read/written yet.
592     Word0 = 3,
593     /// Word1 means that the channel is in PitRWMode::Both mode and the least significant byte
594     /// has already been read/written, and the next byte to be read/written will be the most
595     /// significant byte.
596     Word1 = 4,
597 }
598 
599 /// Convenience implementation for converting from a u8
600 impl From<u8> for PitRWState {
from(item: u8) -> Self601     fn from(item: u8) -> Self {
602         PitRWState::n(item).unwrap_or_else(|| {
603             error!("Invalid PitRWState value {}, setting to 0", item);
604             PitRWState::None
605         })
606     }
607 }
608 
609 /// The PitChannelState represents the state of one of the PIT's three counters.
610 #[repr(C)]
611 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
612 pub struct PitChannelState {
613     /// The starting value for the counter.
614     pub count: u32,
615     /// Stores the channel count from the last time the count was latched.
616     pub latched_count: u16,
617     /// Indicates the PitRWState state of reading the latch value.
618     pub count_latched: PitRWState,
619     /// Indicates whether ReadBack status has been latched.
620     pub status_latched: bool,
621     /// Stores the channel status from the last time the status was latched. The status contains
622     /// information about the access mode of this channel, but changing those bits in the status
623     /// will not change the behavior of the pit.
624     pub status: u8,
625     /// Indicates the PitRWState state of reading the counter.
626     pub read_state: PitRWState,
627     /// Indicates the PitRWState state of writing the counter.
628     pub write_state: PitRWState,
629     /// Stores the value with which the counter was initialized. Counters are 16-
630     /// bit values with an effective range of 1-65536 (65536 represented by 0).
631     pub reload_value: u16,
632     /// The command access mode of this channel.
633     pub rw_mode: PitRWMode,
634     /// The operation mode of this channel.
635     pub mode: u8,
636     /// Whether or not we are in bcd mode. Not supported by KVM or crosvm's PIT implementation.
637     pub bcd: bool,
638     /// Value of the gate input pin. This only applies to channel 2.
639     pub gate: bool,
640     /// Nanosecond timestamp of when the count value was loaded.
641     pub count_load_time: u64,
642 }
643 
644 // Convenience constructors for IrqRoutes
645 impl IrqRoute {
ioapic_irq_route(irq_num: u32) -> IrqRoute646     pub fn ioapic_irq_route(irq_num: u32) -> IrqRoute {
647         IrqRoute {
648             gsi: irq_num,
649             source: IrqSource::Irqchip {
650                 chip: IrqSourceChip::Ioapic,
651                 pin: irq_num,
652             },
653         }
654     }
655 
pic_irq_route(id: IrqSourceChip, irq_num: u32) -> IrqRoute656     pub fn pic_irq_route(id: IrqSourceChip, irq_num: u32) -> IrqRoute {
657         IrqRoute {
658             gsi: irq_num,
659             source: IrqSource::Irqchip {
660                 chip: id,
661                 pin: irq_num % 8,
662             },
663         }
664     }
665 }
666 
667 /// State of a VCPU's general purpose registers.
668 #[repr(C)]
669 #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
670 pub struct Regs {
671     pub rax: u64,
672     pub rbx: u64,
673     pub rcx: u64,
674     pub rdx: u64,
675     pub rsi: u64,
676     pub rdi: u64,
677     pub rsp: u64,
678     pub rbp: u64,
679     pub r8: u64,
680     pub r9: u64,
681     pub r10: u64,
682     pub r11: u64,
683     pub r12: u64,
684     pub r13: u64,
685     pub r14: u64,
686     pub r15: u64,
687     pub rip: u64,
688     pub rflags: u64,
689 }
690 
691 impl Default for Regs {
default() -> Self692     fn default() -> Self {
693         Regs {
694             rax: 0,
695             rbx: 0,
696             rcx: 0,
697             rdx: 0,
698             rsi: 0,
699             rdi: 0,
700             rsp: 0,
701             rbp: 0,
702             r8: 0,
703             r9: 0,
704             r10: 0,
705             r11: 0,
706             r12: 0,
707             r13: 0,
708             r14: 0,
709             r15: 0,
710             rip: 0xfff0, // Reset vector.
711             rflags: 0x2, // Bit 1 (0x2) is always 1.
712         }
713     }
714 }
715 
716 /// State of a memory segment.
717 #[repr(C)]
718 #[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
719 pub struct Segment {
720     pub base: u64,
721     pub limit: u32,
722     pub selector: u16,
723     pub type_: u8,
724     pub present: u8,
725     pub dpl: u8,
726     pub db: u8,
727     pub s: u8,
728     pub l: u8,
729     pub g: u8,
730     pub avl: u8,
731 }
732 
733 /// State of a global descriptor table or interrupt descriptor table.
734 #[repr(C)]
735 #[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
736 pub struct DescriptorTable {
737     pub base: u64,
738     pub limit: u16,
739 }
740 
741 /// State of a VCPU's special registers.
742 #[repr(C)]
743 #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
744 pub struct Sregs {
745     pub cs: Segment,
746     pub ds: Segment,
747     pub es: Segment,
748     pub fs: Segment,
749     pub gs: Segment,
750     pub ss: Segment,
751     pub tr: Segment,
752     pub ldt: Segment,
753     pub gdt: DescriptorTable,
754     pub idt: DescriptorTable,
755     pub cr0: u64,
756     pub cr2: u64,
757     pub cr3: u64,
758     pub cr4: u64,
759     pub cr8: u64,
760     pub efer: u64,
761 }
762 
763 impl Default for Sregs {
default() -> Self764     fn default() -> Self {
765         // Intel SDM Vol. 3A, 3.4.5.1 ("Code- and Data-Segment Descriptor Types")
766         const SEG_TYPE_DATA: u8 = 0b0000;
767         const SEG_TYPE_DATA_WRITABLE: u8 = 0b0010;
768 
769         const SEG_TYPE_CODE: u8 = 0b1000;
770         const SEG_TYPE_CODE_READABLE: u8 = 0b0010;
771 
772         const SEG_TYPE_ACCESSED: u8 = 0b0001;
773 
774         // Intel SDM Vol. 3A, 3.4.5 ("Segment Descriptors")
775         const SEG_S_SYSTEM: u8 = 0; // System segment.
776         const SEG_S_CODE_OR_DATA: u8 = 1; // Data/code segment.
777 
778         // 16-bit real-mode code segment (reset vector).
779         let code_seg = Segment {
780             base: 0xffff0000,
781             limit: 0xffff,
782             selector: 0xf000,
783             type_: SEG_TYPE_CODE | SEG_TYPE_CODE_READABLE | SEG_TYPE_ACCESSED, // 11
784             present: 1,
785             s: SEG_S_CODE_OR_DATA,
786             ..Default::default()
787         };
788 
789         // 16-bit real-mode data segment.
790         let data_seg = Segment {
791             base: 0,
792             limit: 0xffff,
793             selector: 0,
794             type_: SEG_TYPE_DATA | SEG_TYPE_DATA_WRITABLE | SEG_TYPE_ACCESSED, // 3
795             present: 1,
796             s: SEG_S_CODE_OR_DATA,
797             ..Default::default()
798         };
799 
800         // 16-bit TSS segment.
801         let task_seg = Segment {
802             base: 0,
803             limit: 0xffff,
804             selector: 0,
805             type_: SEG_TYPE_CODE | SEG_TYPE_CODE_READABLE | SEG_TYPE_ACCESSED, // 11
806             present: 1,
807             s: SEG_S_SYSTEM,
808             ..Default::default()
809         };
810 
811         // Local descriptor table.
812         let ldt = Segment {
813             base: 0,
814             limit: 0xffff,
815             selector: 0,
816             type_: SEG_TYPE_DATA | SEG_TYPE_DATA_WRITABLE, // 2
817             present: 1,
818             s: SEG_S_SYSTEM,
819             ..Default::default()
820         };
821 
822         // Global descriptor table.
823         let gdt = DescriptorTable {
824             base: 0,
825             limit: 0xffff,
826         };
827 
828         // Interrupt descriptor table.
829         let idt = DescriptorTable {
830             base: 0,
831             limit: 0xffff,
832         };
833 
834         let cr0 = (1 << 4) // CR0.ET (reserved, always 1)
835                 | (1 << 30); // CR0.CD (cache disable)
836 
837         Sregs {
838             cs: code_seg,
839             ds: data_seg,
840             es: data_seg,
841             fs: data_seg,
842             gs: data_seg,
843             ss: data_seg,
844             tr: task_seg,
845             ldt,
846             gdt,
847             idt,
848             cr0,
849             cr2: 0,
850             cr3: 0,
851             cr4: 0,
852             cr8: 0,
853             efer: 0,
854         }
855     }
856 }
857 
858 /// State of a VCPU's floating point unit.
859 #[repr(C)]
860 #[derive(Debug, Copy, Clone, Serialize, Deserialize)]
861 pub struct Fpu {
862     pub fpr: [[u8; 16usize]; 8usize],
863     pub fcw: u16,
864     pub fsw: u16,
865     pub ftwx: u8,
866     pub last_opcode: u16,
867     pub last_ip: u64,
868     pub last_dp: u64,
869     pub xmm: [[u8; 16usize]; 16usize],
870     pub mxcsr: u32,
871 }
872 
873 impl Default for Fpu {
default() -> Self874     fn default() -> Self {
875         Fpu {
876             fpr: Default::default(),
877             fcw: 0x37f, // Intel SDM Vol. 1, 13.6
878             fsw: 0,
879             ftwx: 0,
880             last_opcode: 0,
881             last_ip: 0,
882             last_dp: 0,
883             xmm: Default::default(),
884             mxcsr: 0x1f80, // Intel SDM Vol. 1, 11.6.4
885         }
886     }
887 }
888 
889 #[derive(Debug, Clone, Serialize, Deserialize)]
890 pub struct VcpuEvents {
891     pub exception: VcpuExceptionState,
892     pub interrupt: VcpuInterruptState,
893     pub nmi: VcpuNmiState,
894     pub sipi_vector: Option<u32>,
895     pub smi: VcpuSmiState,
896     pub triple_fault: VcpuTripleFaultState,
897     pub exception_payload: Option<u64>,
898 }
899 
900 #[derive(Debug, Clone, Serialize, Deserialize)]
901 pub struct VcpuExceptionState {
902     pub injected: bool,
903     pub nr: u8,
904     pub has_error_code: bool,
905     pub pending: Option<bool>,
906     pub error_code: u32,
907 }
908 
909 #[derive(Debug, Clone, Serialize, Deserialize)]
910 pub struct VcpuInterruptState {
911     pub injected: bool,
912     pub nr: u8,
913     pub soft: bool,
914     pub shadow: Option<u8>,
915 }
916 
917 #[derive(Debug, Clone, Serialize, Deserialize)]
918 pub struct VcpuNmiState {
919     pub injected: bool,
920     pub pending: Option<bool>,
921     pub masked: bool,
922 }
923 
924 #[derive(Debug, Clone, Serialize, Deserialize)]
925 pub struct VcpuSmiState {
926     pub smm: Option<bool>,
927     pub pending: bool,
928     pub smm_inside_nmi: bool,
929     pub latched_init: u8,
930 }
931 
932 #[derive(Debug, Clone, Serialize, Deserialize)]
933 pub struct VcpuTripleFaultState {
934     pub pending: Option<bool>,
935 }
936 
937 /// State of a VCPU's debug registers.
938 #[repr(C)]
939 #[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
940 pub struct DebugRegs {
941     pub db: [u64; 4usize],
942     pub dr6: u64,
943     pub dr7: u64,
944 }
945 
946 /// State of one VCPU register.  Currently used for MSRs and XCRs.
947 #[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)]
948 pub struct Register {
949     pub id: u32,
950     pub value: u64,
951 }
952 
953 /// The hybrid type for intel hybrid CPU.
954 #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
955 pub enum CpuHybridType {
956     /// Intel Atom.
957     Atom,
958     /// Intel Core.
959     Core,
960 }
961 
962 /// State of the VCPU's x87 FPU, MMX, XMM, YMM registers.
963 /// May contain more state depending on enabled extensions.
964 #[derive(Clone, Debug, Serialize, Deserialize)]
965 pub struct Xsave(pub Vec<u32>);
966