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