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
pub use super::model_specific::{Efer, EferFlags};
use PhysAddr;
use structures::paging::PhysFrame;
pub struct Cr0;
impl Cr0 {
pub fn read() -> Cr0Flags {
Cr0Flags::from_bits_truncate(Self::read_raw())
}
pub fn read_raw() -> u64 {
let value: u64;
unsafe {
asm!("mov %cr0, $0" : "=r" (value));
}
value
}
pub unsafe fn write(flags: Cr0Flags) {
let mut value = Self::read_raw();
value |= flags.bits();
asm!("mov $0, %cr0" :: "r" (value) : "memory")
}
pub unsafe fn update<F>(f: F)
where
F: FnOnce(&mut Cr0Flags),
{
let mut flags = Self::read();
f(&mut flags);
Self::write(flags);
}
}
bitflags! {
pub struct Cr0Flags: u64 {
const PROTECTED_MODE_ENABLE = 1 << 0;
const MONITOR_COPROCESSOR = 1 << 1;
const EMULATION = 1 << 2;
const TASK_SWITCHED = 1 << 3;
const EXTENSION_TYPE = 1 << 4;
const NUMERIC_ERROR = 1 << 5;
const WRITE_PROTECT = 1 << 16;
const ALIGNMENT_MASK = 1 << 18;
const NON_WRITE_THROUGH = 1 << 29;
const CACHE_DISABLE = 1 << 30;
const PAGING = 1 << 31;
}
}
pub struct Cr3;
impl Cr3 {
pub fn read() -> (PhysFrame, Cr3Flags) {
let value: u64;
unsafe {
asm!("mov %cr3, $0" : "=r" (value));
}
let flags = Cr3Flags::from_bits_truncate(value);
let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000);
let frame = PhysFrame::containing_address(addr);
(frame, flags)
}
pub unsafe fn write(frame: PhysFrame, flags: Cr3Flags) {
let addr = frame.start_address();
let value = addr.as_u64() | flags.bits();
asm!("mov $0, %cr3" :: "r" (value) : "memory")
}
}
bitflags! {
pub struct Cr3Flags: u64 {
const PAGE_LEVEL_WRITETHROUGH = 1 << 3;
const PAGE_LEVEL_CACHE_DISABLE = 1 << 4;
}
}