Skip to main content

x86defs/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Definitions relating to the x86 architecture, including the core CPU and
5//! its interrupt controller (APIC).
6
7#![expect(missing_docs)]
8#![no_std]
9#![forbid(unsafe_code)]
10
11pub mod apic;
12pub mod cpuid;
13pub mod msi;
14pub mod snp;
15pub mod tdx;
16pub mod vmx;
17pub mod xsave;
18
19use bitfield_struct::bitfield;
20use open_enum::open_enum;
21use zerocopy::FromBytes;
22use zerocopy::FromZeros;
23use zerocopy::Immutable;
24use zerocopy::IntoBytes;
25use zerocopy::KnownLayout;
26
27pub const X64_CR0_PE: u64 = 0x0000000000000001; // protection enable
28pub const X64_CR0_MP: u64 = 0x0000000000000002; // math present
29pub const X64_CR0_EM: u64 = 0x0000000000000004; // emulate math coprocessor
30pub const X64_CR0_TS: u64 = 0x0000000000000008; // task switched
31pub const X64_CR0_ET: u64 = 0x0000000000000010; // extension type (80387)
32pub const X64_CR0_NE: u64 = 0x0000000000000020; // numeric error
33pub const X64_CR0_WP: u64 = 0x0000000000010000; // write protect
34pub const X64_CR0_AM: u64 = 0x0000000000040000; // alignment mask
35pub const X64_CR0_NW: u64 = 0x0000000020000000; // not write-through
36pub const X64_CR0_CD: u64 = 0x0000000040000000; // cache disable
37pub const X64_CR0_PG: u64 = 0x0000000080000000; // paging
38
39/// Reserved bits in the low 32 of CR0 (bits 6-15, 17, 19-28).
40pub const X64_CR0_RSVDZ_MASK: u64 = 0x1FFA_FFC0;
41
42pub const X64_CR4_VME: u64 = 0x0000000000000001; // Virtual 8086 mode extensions
43pub const X64_CR4_PVI: u64 = 0x0000000000000002; // Protected mode virtual interrupts
44pub const X64_CR4_TSD: u64 = 0x0000000000000004; // Time stamp disable
45pub const X64_CR4_DE: u64 = 0x0000000000000008; // Debugging extensions
46pub const X64_CR4_PSE: u64 = 0x0000000000000010; // Page size extensions
47pub const X64_CR4_PAE: u64 = 0x0000000000000020; // Physical address extensions
48pub const X64_CR4_MCE: u64 = 0x0000000000000040; // Machine check enable
49pub const X64_CR4_PGE: u64 = 0x0000000000000080; // Page global enable
50pub const X64_CR4_PCE: u64 = 0x0000000000000100; // Performance Counter Enable
51pub const X64_CR4_FXSR: u64 = 0x0000000000000200; // FXSR used by OS
52pub const X64_CR4_XMMEXCPT: u64 = 0x0000000000000400; // XMMI used by OS
53pub const X64_CR4_UMIP: u64 = 0x0000000000000800; // UMIP used by OS
54pub const X64_CR4_LA57: u64 = 0x0000000000001000; // 5-level paging enabled
55pub const X64_CR4_VMXE: u64 = 0x0000000000002000; // VMX enabled
56pub const X64_CR4_RWFSGS: u64 = 0x0000000000010000; // RDWRFSGS enabled by OS
57pub const X64_CR4_PCIDE: u64 = 0x0000000000020000; // PCID enabled by OS
58pub const X64_CR4_OSXSAVE: u64 = 0x0000000000040000; // XSAVE enabled by OS
59pub const X64_CR4_SMEP: u64 = 0x0000000000100000; // Supervisor Mode Execution Protection
60pub const X64_CR4_SMAP: u64 = 0x0000000000200000; // Supervisor Mode Access Protection
61pub const X64_CR4_CET: u64 = 0x0000000000800000; // CET enabled by OS
62
63pub const X64_EFER_SCE: u64 = 0x0000000000000001; // Syscall Enable
64pub const X64_EFER_LME: u64 = 0x0000000000000100; // Long Mode Enabled
65pub const X64_EFER_LMA: u64 = 0x0000000000000400; // Long Mode Active
66pub const X64_EFER_NXE: u64 = 0x0000000000000800; // No-execute Enable
67pub const X64_EFER_SVME: u64 = 0x0000000000001000; // SVM enable
68pub const X64_EFER_FFXSR: u64 = 0x0000000000004000; // Fast save/restore enabled
69pub const X64_EFER_TCE: u64 = 0x0000000000008000; // Translation Cache Extension enable
70
71pub const X86X_MSR_DEFAULT_PAT: u64 = 0x0007040600070406;
72pub const X64_EMPTY_DR7: u64 = 0x0000000000000400;
73
74pub const USER_MODE_DPL: u8 = 3;
75
76/// Returns true if `v` is a canonical linear address for a paging mode with
77/// `bits` effective virtual address bits (48 or 57): the top `64 - bits` bits
78/// must be a sign-extension of the highest used bit.
79pub fn is_canonical_address(v: u64, bits: u32) -> bool {
80    let high = (v as i64) >> (bits - 1);
81    high == 0 || high == -1
82}
83
84pub const X64_DEFAULT_CODE_SEGMENT_ATTRIBUTES: SegmentAttributes = SegmentAttributes::new()
85    .with_granularity(true)
86    .with_long(true)
87    .with_present(true)
88    .with_non_system_segment(true)
89    .with_segment_type(0xb);
90pub const X64_DEFAULT_DATA_SEGMENT_ATTRIBUTES: SegmentAttributes = SegmentAttributes::new()
91    .with_granularity(true)
92    .with_default(true)
93    .with_present(true)
94    .with_non_system_segment(true)
95    .with_segment_type(0x3);
96pub const X64_BUSY_TSS_SEGMENT_ATTRIBUTES: SegmentAttributes = SegmentAttributes::new()
97    .with_present(true)
98    .with_segment_type(0xb);
99
100#[bitfield(u16)]
101#[derive(PartialEq)]
102pub struct SegmentAttributes {
103    #[bits(4)]
104    pub segment_type: u8,
105    pub non_system_segment: bool,
106    #[bits(2)]
107    pub descriptor_privilege_level: u8,
108    pub present: bool,
109    #[bits(4)]
110    _reserved: u8,
111    pub available: bool,
112    pub long: bool,
113    pub default: bool,
114    pub granularity: bool,
115}
116
117impl SegmentAttributes {
118    pub const fn as_bits(&self) -> u16 {
119        self.0
120    }
121}
122
123#[cfg(feature = "arbitrary")]
124impl<'a> arbitrary::Arbitrary<'a> for SegmentAttributes {
125    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
126        let x: u16 = u.arbitrary()?;
127        Ok(x.into())
128    }
129}
130
131/// Segment selector (what goes into a segment register)
132#[bitfield(u16)]
133#[derive(PartialEq, Eq)]
134pub struct SegmentSelector {
135    #[bits(2)]
136    /// Request Privilege Level (ring 0-3, where 0 is the highest)
137    pub rpl: u8,
138    /// Table indicator: 0 - GDT, 1 - LDT
139    pub ti: bool,
140    #[bits(13)]
141    /// Index in the descriptor table
142    pub index: u16,
143}
144
145impl SegmentSelector {
146    pub const fn as_bits(&self) -> u16 {
147        self.0
148    }
149
150    pub fn from_gdt_index(index: u16, rpl: u8) -> Self {
151        Self::new().with_index(index).with_rpl(rpl).with_ti(false)
152    }
153}
154
155#[derive(Debug, Copy, Clone, PartialEq)]
156pub struct SegmentRegister {
157    pub base: u64,
158    pub limit: u32,
159    pub selector: u16,
160    pub attributes: SegmentAttributes,
161}
162
163#[cfg(feature = "arbitrary")]
164impl<'a> arbitrary::Arbitrary<'a> for SegmentRegister {
165    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
166        Ok(SegmentRegister {
167            base: u.arbitrary()?,
168            limit: u.arbitrary()?,
169            selector: u.arbitrary()?,
170            attributes: u.arbitrary()?,
171        })
172    }
173}
174
175/// Values for `X86X_IA32_MSR_MISC_ENABLE` MSR.
176///
177/// Many of these fields are undocumented or underdocumented and do not always
178/// have the same meaning across different CPU models. However, this MSR must
179/// have appropriate values for Linux to successfully boot.
180#[bitfield(u64)]
181pub struct MiscEnable {
182    pub fast_string: bool,
183    pub tcc: bool,
184    pub x87_compat: bool,
185    pub tm1: bool,
186    pub split_lock_disable: bool,
187    _reserved5: bool,
188    pub l3cache_disable: bool,
189    pub emon: bool,
190    pub suppress_lock: bool,
191    pub prefetch_disable: bool,
192    pub ferr: bool,
193    pub bts_unavailable: bool,
194    pub pebs_unavailable: bool,
195    pub tm2: bool,
196    _reserved14: bool,
197    _reserved15: bool,
198    pub enhanced_speedstep: bool,
199    _reserved17: bool,
200    pub mwait: bool,
201    pub adj_prefetch_disable: bool,
202    pub enable_speedstep_lock: bool,
203    _reserved21: bool,
204    pub limit_cpuid: bool,
205    pub xtpr_disable: bool,
206    pub l1d_context: bool,
207    #[bits(39)]
208    _reserved: u64,
209}
210
211pub const X86X_MSR_TSC: u32 = 0x10;
212pub const X86X_IA32_MSR_PLATFORM_ID: u32 = 0x17;
213pub const X86X_MSR_APIC_BASE: u32 = 0x1b;
214pub const X86X_MSR_EBL_CR_POWERON: u32 = 0x2a;
215pub const X86X_IA32_MSR_SMI_COUNT: u32 = 0x34;
216pub const X86X_IA32_MSR_FEATURE_CONTROL: u32 = 0x3a;
217pub const X86X_MSR_PPIN_CTL: u32 = 0x4e;
218pub const X86X_MSR_BIOS_UPDT_TRIG: u32 = 0x79;
219pub const X86X_MSR_MC_UPDATE_PATCH_LEVEL: u32 = 0x8b;
220pub const X86X_MSR_PLATFORM_INFO: u32 = 0xce;
221pub const X86X_MSR_UMWAIT_CONTROL: u32 = 0xe1;
222pub const X86X_MSR_MTRR_CAP: u32 = 0xfe;
223pub const X86X_MSR_MISC_FEATURE_ENABLES: u32 = 0x140;
224pub const X86X_MSR_SYSENTER_CS: u32 = 0x174;
225pub const X86X_MSR_SYSENTER_ESP: u32 = 0x175;
226pub const X86X_MSR_SYSENTER_EIP: u32 = 0x176;
227pub const X86X_MSR_MCG_CAP: u32 = 0x179;
228pub const X86X_MSR_MCG_STATUS: u32 = 0x17a;
229
230/// [`X86X_MSR_MCG_CAP`] (MSR 0x179): global machine-check capability register.
231///
232/// Layout per the Intel SDM Volume 3B, Section 18.3.1.1 / Figure 18-2
233/// (doc 325384-092).
234#[bitfield(u64)]
235#[derive(PartialEq, Eq)]
236pub struct McgCap {
237    /// Number of hardware unit error-reporting banks.
238    pub count: u8,
239    /// `MCG_CTL_P`: `IA32_MCG_CTL` MSR is present.
240    pub ctl_p: bool,
241    /// `MCG_EXT_P`: extended machine-check state MSRs (at 0x180) are present.
242    pub ext_p: bool,
243    /// `MCG_CMCI_P`: corrected MC error counting/signaling extension present.
244    pub cmci_p: bool,
245    /// `MCG_TES_P`: threshold-based error status present.
246    pub tes_p: bool,
247    /// `MCG_SEAM_NR_P`: `IA32_MCG_STATUS.SEAM_NR` (bit 12) is supported.
248    pub seam_nr_p: bool,
249    #[bits(3)]
250    _reserved: u8,
251    /// `MCG_EXT_CNT`: number of extended machine-check state registers
252    /// (meaningful only when `ext_p` is set).
253    pub ext_cnt: u8,
254    /// `MCG_SER_P`: software error recovery is supported.
255    pub ser_p: bool,
256    /// `MCG_EMC_P`: enhanced machine-check capability (firmware-first
257    /// signaling) is supported.
258    pub emc_p: bool,
259    /// `MCG_ELOG_P`: extended error logging is supported.
260    pub elog_p: bool,
261    /// `MCG_LMCE_P`: local machine-check exception is supported.
262    pub lmce_p: bool,
263    #[bits(36)]
264    _reserved2: u64,
265}
266
267pub const X86X_IA32_MSR_MISC_ENABLE: u32 = 0x1a0;
268pub const X86X_MSR_MTRR_PHYSBASE0: u32 = 0x200;
269pub const X86X_MSR_MTRR_FIX64K_00000: u32 = 0x0250;
270pub const X86X_MSR_MTRR_FIX16K_80000: u32 = 0x0258;
271pub const X86X_MSR_MTRR_FIX16K_A0000: u32 = 0x0259;
272pub const X86X_MSR_MTRR_FIX4K_C0000: u32 = 0x0268;
273pub const X86X_MSR_MTRR_FIX4K_C8000: u32 = 0x0269;
274pub const X86X_MSR_MTRR_FIX4K_D0000: u32 = 0x026A;
275pub const X86X_MSR_MTRR_FIX4K_D8000: u32 = 0x026B;
276pub const X86X_MSR_MTRR_FIX4K_E0000: u32 = 0x026C;
277pub const X86X_MSR_MTRR_FIX4K_E8000: u32 = 0x026D;
278pub const X86X_MSR_MTRR_FIX4K_F0000: u32 = 0x026E;
279pub const X86X_MSR_MTRR_FIX4K_F8000: u32 = 0x026F;
280pub const X86X_MSR_CR_PAT: u32 = 0x277;
281pub const X86X_MSR_MTRR_DEF_TYPE: u32 = 0x2ff;
282
283pub const X86X_MSR_XSS: u32 = 0xda0;
284
285pub const X86X_IA32_MSR_RAPL_POWER_UNIT: u32 = 0x606;
286pub const X86X_IA32_MSR_PKG_ENERGY_STATUS: u32 = 0x611;
287pub const X86X_IA32_MSR_DRAM_ENERGY_STATUS: u32 = 0x619;
288pub const X86X_IA32_MSR_PP0_ENERGY_STATUS: u32 = 0x639;
289
290pub const X86X_MSR_U_CET: u32 = 0x6a0;
291pub const X86X_MSR_S_CET: u32 = 0x6a2;
292pub const X86X_MSR_PL0_SSP: u32 = 0x6a4;
293pub const X86X_MSR_PL1_SSP: u32 = 0x6a5;
294pub const X86X_MSR_PL2_SSP: u32 = 0x6a6;
295pub const X86X_MSR_PL3_SSP: u32 = 0x6a7;
296pub const X86X_MSR_INTERRUPT_SSP_TABLE_ADDR: u32 = 0x6a8;
297
298pub const X86X_MSR_STAR: u32 = 0xC0000081;
299pub const X86X_MSR_LSTAR: u32 = 0xC0000082;
300pub const X86X_MSR_CSTAR: u32 = 0xC0000083;
301pub const X86X_MSR_SFMASK: u32 = 0xC0000084;
302
303pub const X86X_MSR_EFER: u32 = 0xC0000080;
304pub const X64_MSR_FS_BASE: u32 = 0xC0000100;
305pub const X64_MSR_GS_BASE: u32 = 0xC0000101;
306pub const X64_MSR_KERNEL_GS_BASE: u32 = 0xC0000102;
307
308pub const X86X_MSR_TSC_AUX: u32 = 0xC0000103;
309
310pub const X86X_MSR_SPEC_CTRL: u32 = 0x48;
311pub const X86X_IA32_MSR_XFD: u32 = 0x1C4;
312pub const X86X_IA32_MSR_XFD_ERR: u32 = 0x1C5;
313
314pub const X86X_AMD_MSR_PERF_EVT_SEL0: u32 = 0xC0010000;
315pub const X86X_AMD_MSR_PERF_EVT_SEL1: u32 = 0xC0010001;
316pub const X86X_AMD_MSR_PERF_EVT_SEL2: u32 = 0xC0010002;
317pub const X86X_AMD_MSR_PERF_EVT_SEL3: u32 = 0xC0010003;
318pub const X86X_AMD_MSR_PERF_CTR0: u32 = 0xC0010004;
319pub const X86X_AMD_MSR_PERF_CTR1: u32 = 0xC0010005;
320pub const X86X_AMD_MSR_PERF_CTR2: u32 = 0xC0010006;
321pub const X86X_AMD_MSR_PERF_CTR3: u32 = 0xC0010007;
322pub const X86X_AMD_MSR_SYSCFG: u32 = 0xC0010010;
323pub const X86X_AMD_MSR_HW_CFG: u32 = 0xC0010015;
324pub const X86X_AMD_MSR_NB_CFG: u32 = 0xC001001F;
325pub const X86X_AMD_MSR_VM_CR: u32 = 0xC0010114;
326pub const X86X_AMD_MSR_IGNNE: u32 = 0xC0010115;
327pub const X86X_AMD_MSR_GHCB: u32 = 0xC0010130;
328pub const X86X_AMD_MSR_SEV: u32 = 0xC0010131;
329pub const X86X_AMD_MSR_SECURE_AVIC_CONTROL: u32 = 0xc0010138;
330pub const X86X_AMD_MSR_OSVW_ID_LENGTH: u32 = 0xc0010140;
331pub const X86X_AMD_MSR_OSVW_ID_STATUS: u32 = 0xc0010141;
332pub const X86X_AMD_MSR_DE_CFG: u32 = 0xc0011029;
333
334pub const DR6_BREAKPOINT_MASK: u64 = 0xf;
335pub const DR6_SINGLE_STEP: u64 = 0x4000;
336
337#[bitfield(u64, default = false)]
338#[derive(PartialEq)]
339pub struct RFlags {
340    // FLAGS
341    pub carry: bool,
342    pub reserved_must_be_1: bool,
343    pub parity: bool,
344    _reserved1: bool,
345    pub adjust: bool,
346    _reserved2: bool,
347    pub zero: bool,
348    pub sign: bool,
349    pub trap: bool,
350    pub interrupt_enable: bool,
351    pub direction: bool,
352    pub overflow: bool,
353    #[bits(2)]
354    pub io_privilege_level: u8,
355    pub nested_task: bool,
356    pub mode: bool,
357
358    // EFLAGS
359    pub resume: bool,
360    pub virtual_8086_mode: bool,
361    pub alignment_check: bool,
362    pub virtual_interrupt: bool,
363    pub virtual_interrupt_pending: bool,
364    pub cpuid_allowed: bool,
365    _reserved3: u8,
366    pub aes_key_schedule_loaded: bool,
367    _reserved4: bool,
368
369    // RFLAGS
370    _reserved5: u32,
371}
372
373impl RFlags {
374    /// Returns the reset value of the RFLAGS register.
375    pub fn at_reset() -> Self {
376        Self::new().with_reserved_must_be_1(true)
377    }
378}
379
380impl core::ops::BitAnd<RFlags> for RFlags {
381    type Output = RFlags;
382
383    fn bitand(self, rhs: RFlags) -> Self::Output {
384        RFlags(self.0 & rhs.0)
385    }
386}
387
388#[cfg(feature = "arbitrary")]
389impl<'a> arbitrary::Arbitrary<'a> for RFlags {
390    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
391        let x: u64 = u.arbitrary()?;
392        Ok(x.into())
393    }
394}
395
396#[repr(C)]
397#[derive(Debug, Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
398pub struct IdtEntry64 {
399    pub offset_low: u16,
400    pub selector: u16,
401    pub attributes: IdtAttributes,
402    pub offset_middle: u16,
403    pub offset_high: u32,
404    pub reserved: u32,
405}
406
407#[bitfield(u16)]
408#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
409pub struct IdtAttributes {
410    #[bits(3)]
411    pub ist: u8,
412    #[bits(5)]
413    _reserved: u8,
414    #[bits(4)]
415    pub gate_type: u8,
416    _reserved2: bool,
417    #[bits(2)]
418    pub dpl: u8,
419    pub present: bool,
420}
421
422#[repr(C)]
423#[derive(Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
424pub struct GdtEntry {
425    pub limit_low: u16,
426    pub base_low: u16,
427    pub base_middle: u8,
428    pub attr_low: u8,
429    pub attr_high: u8,
430    pub base_high: u8,
431}
432
433#[repr(C)]
434#[derive(Clone, Copy, IntoBytes, Immutable, KnownLayout, FromBytes)]
435pub struct LargeGdtEntry {
436    pub limit_low: u16,
437    pub base_low: u16,
438    pub base_middle: u8,
439    pub attr_low: u8,
440    pub attr_high: u8,
441    pub base_high: u8,
442    pub base_upper: u32,
443    pub mbz: u32,
444}
445
446impl LargeGdtEntry {
447    /// Get the large GDT entry as two smaller GDT entries, for building a GDT.
448    pub fn get_gdt_entries(&self) -> [GdtEntry; 2] {
449        let mut entries = [GdtEntry::new_zeroed(); 2];
450        entries.as_mut_bytes().copy_from_slice(self.as_bytes());
451        entries
452    }
453}
454
455#[repr(C, packed)]
456#[derive(Clone, Copy, Immutable, KnownLayout, IntoBytes, FromBytes)]
457pub struct Tss64 {
458    pub _mbz0: u32,
459    pub rsp: [u64; 3],
460    pub ist: [u64; 8],
461    pub _mbz1: u64,
462    pub _mbz2: u16,
463    pub io_map_base: u16,
464}
465
466open_enum! {
467    pub enum Exception: u8 {
468        DIVIDE_ERROR = 0x0,
469        DEBUG = 0x1,
470        BREAKPOINT = 0x3,
471        OVERFLOW = 0x4,
472        BOUND_RANGE_EXCEEDED = 0x5,
473        INVALID_OPCODE = 0x6,
474        DEVICE_NOT_AVAILABLE = 0x7,
475        DOUBLE_FAULT = 0x8,
476        INVALID_TSS = 0x0A,
477        SEGMENT_NOT_PRESENT = 0x0B,
478        STACK_SEGMENT_FAULT = 0x0C,
479        GENERAL_PROTECTION_FAULT = 0x0D,
480        PAGE_FAULT = 0x0E,
481        FLOATING_POINT_EXCEPTION = 0x10,
482        ALIGNMENT_CHECK = 0x11,
483        MACHINE_CHECK = 0x12,
484        SIMD_FLOATING_POINT_EXCEPTION = 0x13,
485        CONTROL_PROTECTION_EXCEPTION = 0x15,
486        SEV_VMM_COMMUNICATION = 0x1D,
487    }
488}
489
490#[bitfield(u32)]
491pub struct PageFaultErrorCode {
492    pub present: bool,
493    pub write: bool,
494    pub user: bool,
495    pub reserved: bool,
496    pub fetch: bool,
497    #[bits(27)]
498    _unused: u32,
499}
500
501pub const X64_PAGE_SIZE: u64 = 0x1000;
502pub const X64_LARGE_PAGE_SIZE: u64 = 0x200000;
503
504#[bitfield(u64)]
505#[derive(PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
506pub struct Pte {
507    pub present: bool,
508    pub read_write: bool,
509    pub user: bool,
510    pub write_through: bool,
511    pub cache_disable: bool,
512    pub accessed: bool,
513    pub dirty: bool,
514    pub pat: bool,
515    pub global: bool,
516    #[bits(3)]
517    pub available0: u64,
518    #[bits(40)]
519    pub pfn: u64,
520    #[bits(11)]
521    pub available1: u64,
522    pub no_execute: bool,
523}
524
525impl Pte {
526    pub fn address(&self) -> u64 {
527        self.pfn() << 12
528    }
529
530    pub fn with_address(self, address: u64) -> Self {
531        assert!(address & 0xfff == 0);
532        self.with_pfn(address >> 12)
533    }
534
535    pub fn set_address(&mut self, address: u64) -> &mut Self {
536        *self = self.with_address(address);
537        self
538    }
539}
540
541#[bitfield(u64)]
542#[derive(PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
543pub struct LargePde {
544    pub present: bool,
545    pub read_write: bool,
546    pub user: bool,
547    pub write_through: bool,
548    pub cache_disable: bool,
549    pub accessed: bool,
550    pub dirty: bool,
551    pub large_page: bool,
552    pub global: bool,
553    #[bits(3)]
554    pub available0: u64,
555    pub pat: bool,
556    #[bits(8)]
557    _reserved0: u64,
558    #[bits(31)]
559    pub large_page_base: u64,
560    #[bits(11)]
561    pub available1: u64,
562    pub no_execute: bool,
563}
564
565#[bitfield(u64)]
566#[derive(PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
567pub struct X86xMcgStatusRegister {
568    pub ripv: bool, // Restart IP is valid
569    pub eipv: bool, // Error IP is valid
570    pub mcip: bool, // Machine check is in progress
571    #[bits(61)]
572    pub reserved0: u64,
573}
574
575#[repr(C)]
576#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
577pub struct ApicRegisterValue {
578    pub value: u32,
579    _reserved: [u32; 3],
580}