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 160 161 162
//! Abstractions for cpu flags and control registers
use core::arch::asm;
use bitfield_struct::bitfield;
use super::paging::Physical;
/// The RFLAGS register.
#[bitfield(u32)]
pub struct Flags {
/// Set by hardware if last arithmetic operation generated a carry out of the
/// most-significant bit of the result.
pub carry: bool,
__: bool,
/// Set by hardware if last result has an even number of 1 bits (only for some operations).
pub parity: bool,
__: bool,
/// Set by hardware if last arithmetic operation generated a carry ouf of bit 3 of the
/// result.
pub auxiliary_carry: bool,
__: bool,
/// Set by hardware if last arithmetic operation resulted in a zero value.
pub zero: bool,
/// Set by hardware if last arithmetic operation resulted in a negative value.
pub sign: bool,
/// Enable single-step mode for debugging.
pub trap: bool,
/// Enable interrupts.
pub interrupt: bool,
/// Determines the order in which strings are processed.
pub direction: bool,
/// Set by hardware to indicate that the sign bit of the result of the last signed integer
/// operation differs from the source operands.
pub overflow: bool,
/// Specifies the privilege level required for executing I/O address-space instructions.
pub iopl_low: bool,
/// Specifies the privilege level required for executing I/O address-space instructions.
pub iopl_high: bool,
/// Used by `iret` in hardware task switch mode to determine if current task is nested.
pub nested_task: bool,
__: bool,
/// Temporarily disables debug exceptions so that an instruction can be restarted after a debug exception
/// without immediately causing another debug exception.
pub resume: bool,
/// Enable the virtual-8086 mode.
pub virtual_8086_mode: bool,
/// Enable automatic alignment checking if [Cr0::alignment_mask] is set. Only works if CPL is 3.
pub alignment_check: bool,
/// Virtual interrupt flag.
pub virtual_interrupt: bool,
/// Virtual interrupt pending.
pub virtual_interrupt_pending: bool,
/// Able to use CPUID instruction.
pub id: bool,
#[bits(10)]
__: (),
}
impl Flags {
pub fn read() -> Self {
let value: u32;
unsafe { asm!("pushfd\npop {}", out(reg) value, options(nomem)) };
Self(value)
}
}
/// Contains system control flags that control operating mode and states of the processor.
#[bitfield(u32)]
pub struct Cr0 {
/// Enables protected mode.
pub protected_mode_enable: bool,
/// Enables monitoring of the coprocessor, typical for x87 instructions.
pub monitor_coprocessor: bool,
/// Indicates that the processor does not have an internal or external x87 FPU when set.
pub emulate_coprocessor: bool,
/// Automatically set to 1 on _hardware_ task switch.
///
/// This flags allows lazily saving x87/MMX/SSE instructions on hardware context switches.
pub task_switched: bool,
__: bool,
/// Enables the native error reporting mechanism for x87 FPU errors.
pub numeric_error: bool,
#[bits(10)]
__: (),
/// Controls whether supervisor-level writes to read-only pages are inhibited.
pub write_protect: bool,
__: bool,
/// Enables automatic alignment checking.
pub alignment_mask: bool,
#[bits(10)]
__: (),
/// Ignored. Used to control write-back/write-through cache strategy on older CPUs.
pub not_write_through: bool,
/// Disables internal caches (only for some cases).
pub cache_disable: bool,
/// Enables page translation.
pub paging: bool,
}
impl Cr0 {
pub fn read() -> Self {
let value: u32;
unsafe { asm!("mov {}, cr0", out(reg) value, options(nomem)) };
Self(value)
}
pub fn update(f: impl FnOnce(Self) -> Self) {
unsafe { f(Self::read()).write() }
}
unsafe fn write(self) {
asm!("mov cr0, {}", in(reg) self.0, options(nostack));
}
}
/// Contains the page-fault linear address.
#[repr(transparent)]
pub struct Cr2(pub u32);
impl Cr2 {
pub fn read() -> Self {
let value: u32;
unsafe { asm!("mov {}, cr2", out(reg) value, options(nomem)) };
Self(value)
}
}
/// Contains the physical address of the base of the paging-structure hierarchy
/// and two flags (PCD and PWT).
///
/// The PCD and PWT flags control caching of that paging structure in the
/// processor’s internal data caches (they do not control TLB caching of
/// page-directory information).
#[bitfield(u32)]
pub struct Cr3 {
#[bits(3)]
__: (),
/// Page-level write-through.
pub write_through: bool,
/// Page-level cache disable.
pub cache_disable: bool,
#[bits(7)]
__: (),
/// Physical address of the page directory.
/// The lower 12 bits of the address are assumed to be 0.
/// The page directory must thus be aligned to a page (4K) boundary.
#[bits(20)]
pub address: Physical,
}
impl Cr3 {
pub fn read() -> Self {
let value: u32;
unsafe { asm!("mov {}, cr3", out(reg) value, options(nomem)) };
Self(value)
}
pub unsafe fn write(self) {
asm!("mov cr3, {}", in(reg) self.0, options(nostack));
}
}