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(®s)
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