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
use crate::mem::PhysicalAddress;
use core::fmt::{Debug, Formatter, Error};
use super::super::super::hierarchical_table::{HierarchicalEntry, PageState};
use super::super::super::MappingAccessRights;
bitflags! {
pub struct I386EntryFlags: u32 {
const PRESENT = 1 << 0;
const WRITABLE = 1 << 1;
const USER_ACCESSIBLE = 1 << 2;
const WRITE_THROUGH = 1 << 3;
const NO_CACHE = 1 << 4;
const ACCESSED = 1 << 5;
const DIRTY = 1 << 6;
const HUGE_PAGE = 1 << 7;
const GLOBAL = 1 << 8;
const GUARD_PAGE = 1 << 9;
const USER_DEFINED_2 = 1 << 10;
const USER_DEFINED_3 = 1 << 11;
}
}
impl From<MappingAccessRights> for I386EntryFlags {
fn from(flags: MappingAccessRights) -> I386EntryFlags {
let mut newflags = I386EntryFlags::empty();
if flags.intersects(MappingAccessRights::READABLE | MappingAccessRights::WRITABLE | MappingAccessRights::EXECUTABLE) {
newflags |= I386EntryFlags::PRESENT
} else {
return I386EntryFlags::GUARD_PAGE;
}
if flags.contains(MappingAccessRights::WRITABLE) {
newflags |= I386EntryFlags::WRITABLE
};
if flags.contains(MappingAccessRights::USER_ACCESSIBLE) {
newflags |= I386EntryFlags::USER_ACCESSIBLE
};
newflags
}
}
const ENTRY_PHYS_ADDRESS_MASK: usize = 0xffff_f000;
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct I386Entry(u32);
impl Debug for I386Entry {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
f.debug_struct("Entry")
.field("flags", &self.flags())
.field("frame", &self.pointed_frame().as_option())
.finish()
}
}
impl HierarchicalEntry for I386Entry {
type EntryFlagsType = I386EntryFlags;
fn is_unused(&self) -> bool { self.0 == 0 }
fn set_unused(&mut self) -> PageState<PhysicalAddress> {
let ret = self.pointed_frame();
self.0 = 0;
ret
}
fn is_guard(&self) -> bool { self.flags().contains(I386EntryFlags::GUARD_PAGE) }
fn flags(&self) -> I386EntryFlags { I386EntryFlags::from_bits_truncate(self.0) }
fn pointed_frame(&self) -> PageState<PhysicalAddress> {
if self.flags().contains(I386EntryFlags::PRESENT) {
let frame_phys_addr = self.0 as usize & ENTRY_PHYS_ADDRESS_MASK;
PageState::Present(PhysicalAddress(frame_phys_addr))
} else if self.flags().contains(I386EntryFlags::GUARD_PAGE) {
PageState::Guarded
} else {
PageState::Available
}
}
fn set(&mut self, frame_phys_addr: PhysicalAddress, flags: I386EntryFlags) {
assert_eq!(flags.contains(I386EntryFlags::PRESENT)
&& flags.contains(I386EntryFlags::GUARD_PAGE), false,
"a GUARD_PAGE cannot also be PRESENT");
if flags.contains(I386EntryFlags::GUARD_PAGE) {
self.set_guard();
return;
}
assert_eq!(frame_phys_addr.addr() & !ENTRY_PHYS_ADDRESS_MASK, 0);
self.0 = (frame_phys_addr.addr() as u32) | flags.bits();
}
fn set_guard(&mut self) {
self.0 = 0x00000000 | I386EntryFlags::GUARD_PAGE.bits;
}
}