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