1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
//! `x86_64` flags and bitfields.
pub use x86_64::*;
#[rustfmt::skip]
mod x86_64 {
/* Rflags Register */
/// Carry flag.
pub const RFLAGS_CF: u64 = 1 << 0;
/// Parity flag.
pub const RFLAGS_PF: u64 = 1 << 2;
/// Adjust flag.
pub const RFLAGS_AF: u64 = 1 << 4;
/// Zero flag.
pub const RFLAGS_ZF: u64 = 1 << 6;
/// Sign flag.
pub const RFLAGS_SF: u64 = 1 << 7;
/// Sign flag.
pub const RFLAGS_IF: u64 = 1 << 9;
/// Direction flag.
pub const RFLAGS_DF: u64 = 1 << 10;
/// Overflow flag.
pub const RFLAGS_OF: u64 = 1 << 11;
/// I/O privilege level.
pub const RFLAGS_IOPL: u64 = 0b11 << 12;
/// Alignment check.
pub const RFLAGS_AC: u64 = 1 << 18;
pub const fn rflags_cf(r: u64) -> u64 { (r & RFLAGS_CF) >> 0 }
pub const fn rflags_pf(r: u64) -> u64 { (r & RFLAGS_PF) >> 2 }
pub const fn rflags_af(r: u64) -> u64 { (r & RFLAGS_AF) >> 4 }
pub const fn rflags_zf(r: u64) -> u64 { (r & RFLAGS_ZF) >> 6 }
pub const fn rflags_sf(r: u64) -> u64 { (r & RFLAGS_SF) >> 7 }
pub const fn rflags_if(r: u64) -> u64 { (r & RFLAGS_IF) >> 9 }
pub const fn rflags_df(r: u64) -> u64 { (r & RFLAGS_DF) >> 10 }
pub const fn rflags_of(r: u64) -> u64 { (r & RFLAGS_OF) >> 11 }
pub const fn rflags_iopl(r: u64) -> u64 { (r & RFLAGS_IOPL) >> 12 }
pub const fn rflags_ac(r: u64) -> u64 { (r & RFLAGS_AC) >> 18 }
/* Segment Selector */
/// Requested privilege level.
///
/// Privilege level of the segment selector, where `0` is the most privileged mode and `3` the
/// least.
pub const SEG_SELECTOR_RPL: u16 = 0b11 << 0;
/// Table indicator.
///
/// | TI | Table |
/// |----|-------|
/// | 0 | GDT |
/// | 1 | LDT |
pub const SEG_SELECTOR_TI: u16 = 1 << 2;
/// Table index.
///
/// Index into the `GDT` or `LDT` table to select the segment descriptor. `GDT.base + 8 * index`
/// gives the address of the segment descriptor (times `8` because every segment descriptor is `8
/// byte`).
pub const SEG_SELECTOR_INDEX: u16 = 0x1fff << 3;
pub const fn seg_selector_rpl(s: u16) -> u16 { (s & SEG_SELECTOR_RPL) >> 0 }
pub const fn seg_selector_ti(s: u16) -> u16 { (s & SEG_SELECTOR_TI) >> 2 }
pub const fn seg_selector_index(s: u16) -> u16 { (s & SEG_SELECTOR_INDEX) >> 3 }
/* Control Register CR0 (operation mode & state of the processor) */
/// Protection Enable.
///
/// Enables `protected mode` when set and `real-address mode` when cleared. This enables
/// `segment-level protection` not paging.
pub const CR0_PE: u64 = 1 << 0;
/// Monitor Coprocessor.
pub const CR0_MP: u64 = 1 << 1;
/// Emulation.
///
/// When set indicates the process does not have a FPU. FPU instructions will generate an exception
/// that software can emulate the instruction.
pub const CR0_EM: u64 = 1 << 2;
/// Task Switched.
pub const CR0_TS: u64 = 1 << 3;
/// Extension Type.
pub const CR0_ET: u64 = 1 << 4;
/// Numeric Error.
pub const CR0_NE: u64 = 1 << 5;
/// Write Protect.
///
/// When set supervisor-level procedures can't write to read-only pages.
pub const CR0_WP: u64 = 1 << 16;
/// Alignment Mask.
///
/// Enables alignment check for `CPL=3`, check is only done if the [AC
/// bit](crate::x86_64::RFLAGS_AC) of the `rflags` register ist set.
pub const CR0_AM: u64 = 1 << 18;
/// Not Write-Torugh.
pub const CR0_NW: u64 = 1 << 29;
/// Cachine disable.
pub const CR0_CD: u64 = 1 << 30;
/// Paging.
///
/// Enables paging when set, requires [CR0_PE](crate::x86_64::CR0_PE) to be set as well.
pub const CR0_PG: u64 = 1 << 31;
/* Control Register CR3 (paging information)
*
* Holds the physical base address of the first paging structure. The 12 lower bytes of the base
* address are assumed to be 0 and hence the first paging structure must be aligned to a 4K
* boundary.
*/
/// Mask for physical base address of paging structure.
pub const CR3_PAGE_BASE_MASK: u64 = 0xffff_ffff_ffff_0000;
/// Page-level Write-Through.
pub const CR3_PWT: u64 = 1 << 3;
/// Page-level Cache Disable.
pub const CR3_PCD: u64 = 1 << 4;
/* Control Register CR4 (flags for arch extenstions processor capabilities) */
/// Physical Address Extenstion.
///
/// When set enables paging to produce physicall addresses with more than 32 bits. Required before
/// entering `long mode`.
pub const CR4_PAE: u64 = 1 << 5;
/// 57-bit Linear Addresses.
///
/// When set in `long mode` enables `5-level` paging to translate `57-bit` linear addresses. When
/// cleared use `4-level` paging to translate `48-bit` linear addresses.
pub const CR4_LA57: u64 = 1 << 5;
/* Extended Feature Enable Register (EFER) */
/// Extended Feature Enable Register MSR number.
///
/// MSR number used with the [`rdmsr`][msr] and [`wrmsr`][msr] instructions to read/write the
/// `EFER` model specific register.
///
/// [msr]: https://johannst.github.io/notes/arch/x86_64.html#model-specific-register-msr
pub const MSR_EFER: u64 = 0xc000_0080;
/// Long Mode Enable.
///
/// When set enables long mode operations.
pub const EFER_LME: u64 = 1 << 8;
/// Long Mode Active (readonly).
///
/// When set indicates long mode is active.
pub const EFER_LMA: u64 = 1 << 10;
/* Paging */
/// Page entry present.
pub const PAGE_ENTRY_PRESENT: u64 = 1 << 0;
/// Page region read/write.
///
/// If set, region reference by paging entry is writeable.
pub const PAGE_RENTRY_RW: u64 = 1 << 1;
}