aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Gerd Zellweger <mail@gerdzellweger.com> 2016-01-19 17:02:10 +0100
committerGravatar Gerd Zellweger <mail@gerdzellweger.com> 2016-01-19 17:02:10 +0100
commit46aed4c9d4f628ea118bc09b2e5308e9671d74f1 (patch)
tree79cf6057a9a91dadbd6e734da8f785e102a2be08 /src
parentf232011fe0ef21fbfe9fefc063501da53e4c1d74 (diff)
downloadrust-x86-46aed4c9d4f628ea118bc09b2e5308e9671d74f1.tar.gz
rust-x86-46aed4c9d4f628ea118bc09b2e5308e9671d74f1.tar.zst
rust-x86-46aed4c9d4f628ea118bc09b2e5308e9671d74f1.zip
Update paging.rs with helper function for flags.
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs36
-rw-r--r--src/paging.rs160
2 files changed, 136 insertions, 60 deletions
diff --git a/src/lib.rs b/src/lib.rs
index fb823aa..6e0901d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,12 +9,6 @@
#[macro_use]
mod bitflags;
-macro_rules! bit {
- ( $x:expr ) => {
- 1 << $x
- };
-}
-
#[macro_use]
extern crate raw_cpuid;
@@ -28,6 +22,36 @@ mod std {
pub use core::option;
}
+macro_rules! bit {
+ ( $x:expr ) => {
+ 1 << $x
+ };
+}
+
+macro_rules! check_flag {
+ ($doc:meta, $fun:ident, $flag:ident) => (
+ #[$doc]
+ pub fn $fun(&self) -> bool {
+ self.contains($flag)
+ }
+ )
+}
+
+macro_rules! is_bit_set {
+ ($field:expr, $bit:expr) => (
+ $field & (1 << $bit) > 0
+ )
+}
+
+macro_rules! check_bit_fn {
+ ($doc:meta, $fun:ident, $field:ident, $bit:expr) => (
+ #[$doc]
+ pub fn $fun(&self) -> bool {
+ is_bit_set!(self.$field, $bit)
+ }
+ )
+}
+
pub mod io;
pub mod controlregs;
pub mod msr;
diff --git a/src/paging.rs b/src/paging.rs
index aa218d9..22d9526 100644
--- a/src/paging.rs
+++ b/src/paging.rs
@@ -143,24 +143,24 @@ bitflags! {
#[derive(Debug)]
flags PML4Entry: u64 {
/// Present; must be 1 to reference a page-directory-pointer table
- const PML4_P = 0b00000001,
+ const PML4_P = bit!(0),
/// Read/write; if 0, writes may not be allowed to the 512-GByte region
/// controlled by this entry (see Section 4.6)
- const PML4_RW = 0b00000010,
+ const PML4_RW = bit!(1),
/// User/supervisor; if 0, user-mode accesses are not allowed
/// to the 512-GByte region controlled by this entry.
- const PML4_US = 0b00000100,
+ const PML4_US = bit!(2),
/// Page-level write-through; indirectly determines the memory type used to
/// access the page-directory-pointer table referenced by this entry.
- const PML4_PWT = 0b00001000,
+ const PML4_PWT = bit!(3),
/// Page-level cache disable; indirectly determines the memory type used to
/// access the page-directory-pointer table referenced by this entry.
- const PML4_PCD = 0b00010000,
+ const PML4_PCD = bit!(4),
/// Accessed; indicates whether this entry has been used for linear-address translation.
- const PML4_A = 0b00100000,
+ const PML4_A = bit!(5),
/// If IA32_EFER.NXE = 1, execute-disable
/// If 1, instruction fetches are not allowed from the 512-GByte region.
- const PML4_XD = 1 << 63,
+ const PML4_XD = bit!(63),
}
}
@@ -183,10 +183,19 @@ impl PML4Entry {
PAddr::from_u64(self.bits & ADDRESS_MASK)
}
- /// Convenience function to check if the present bit is set.
- pub fn is_present(self) -> bool {
- self.contains(PML4_P)
- }
+ check_flag!(doc = "Is page present?", is_present, PML4_P);
+ check_flag!(doc = "Read/write; if 0, writes may not be allowed to the 512-GByte region, controlled by this entry (see Section 4.6)",
+ is_writeable, PML4_RW);
+ check_flag!(doc = "User/supervisor; if 0, user-mode accesses are not allowed to the 512-GByte region controlled by this entry.",
+ is_user_mode_allowed, PML4_US);
+ check_flag!(doc = "Page-level write-through; indirectly determines the memory type used to access the page-directory-pointer table referenced by this entry.",
+ is_page_write_through, PML4_PWT);
+ check_flag!(doc = "Page-level cache disable; indirectly determines the memory type used to access the page-directory-pointer table referenced by this entry.",
+ is_page_level_cache_disabled, PML4_PCD);
+ check_flag!(doc = "Accessed; indicates whether this entry has been used for linear-address translation.",
+ is_accessed, PML4_A);
+ check_flag!(doc = "If IA32_EFER.NXE = 1, execute-disable. If 1, instruction fetches are not allowed from the 512-GByte region.",
+ is_instruction_fetching_disabled, PML4_XD);
}
/// PDPT Entry bits description.
@@ -194,32 +203,32 @@ bitflags! {
#[derive(Debug)]
flags PDPTEntry: u64 {
/// Present; must be 1 to map a 1-GByte page or reference a page directory.
- const PDPT_P = 0b00000001,
+ const PDPT_P = bit!(0),
/// Read/write; if 0, writes may not be allowed to the 1-GByte region controlled by this entry
- const PDPT_RW = 0b00000010,
+ const PDPT_RW = bit!(1),
/// User/supervisor; user-mode accesses are not allowed to the 1-GByte region controlled by this entry.
- const PDPT_US = 0b00000100,
+ const PDPT_US = bit!(2),
/// Page-level write-through.
- const PDPT_PWT = 0b00001000,
+ const PDPT_PWT = bit!(3),
/// Page-level cache disable.
- const PDPT_PCD = 0b00010000,
+ const PDPT_PCD = bit!(4),
/// Accessed; if PDPT_PS set indicates whether software has accessed the 1-GByte page
/// else indicates whether this entry has been used for linear-address translation
- const PDPT_A = 0b00100000,
+ const PDPT_A = bit!(5),
/// Dirty; if PDPT_PS indicates whether software has written to the 1-GByte page referenced by this entry.
/// else ignored.
- const PDPT_D = 0b01000000,
+ const PDPT_D = bit!(6),
/// Page size; if set this entry maps a 1-GByte page; otherwise, this entry references a page directory.
/// if not PDPT_PS this is ignored.
- const PDPT_PS = 0b10000000,
+ const PDPT_PS = bit!(7),
/// Global; if PDPT_PS && CR4.PGE = 1, determines whether the translation is global; ignored otherwise
/// if not PDPT_PS this is ignored.
- const PDPT_G = 1<<8,
+ const PDPT_G = bit!(8),
/// Indirectly determines the memory type used to access the 1-GByte page referenced by this entry.
- const PDPT_PAT = 1<<12,
+ const PDPT_PAT = bit!(12),
/// If IA32_EFER.NXE = 1, execute-disable
/// If 1, instruction fetches are not allowed from the 512-GByte region.
- const PDPT_XD = 1 << 63,
+ const PDPT_XD = bit!(63),
}
}
@@ -241,10 +250,21 @@ impl PDPTEntry {
PAddr::from_u64(self.bits & ADDRESS_MASK)
}
- /// Convenience function to check if the present bit is set.
- pub fn is_present(self) -> bool {
- self.contains(PDPT_P)
- }
+ check_flag!(doc = "Is page present?", is_present, PDPT_P);
+ check_flag!(doc = "Read/write; if 0, writes may not be allowed to the 1-GByte region controlled by this entry.",
+ is_writeable, PDPT_RW);
+ check_flag!(doc = "User/supervisor; user-mode accesses are not allowed to the 1-GByte region controlled by this entry.",
+ is_user_mode_allowed, PDPT_US);
+ check_flag!(doc = "Page-level write-through.",
+ is_page_write_through, PDPT_PWT);
+ check_flag!(doc = "Page-level cache disable.",
+ is_page_level_cache_disabled, PDPT_PCD);
+ check_flag!(doc = "Accessed; indicates whether this entry has been used for linear-address translation.",
+ is_accessed, PDPT_A);
+ check_flag!(doc = "Indirectly determines the memory type used to access the 1-GByte page referenced by this entry. if not PDPT_PS this is ignored.",
+ is_pat, PDPT_PAT);
+ check_flag!(doc = "If IA32_EFER.NXE = 1, execute-disable. If 1, instruction fetches are not allowed from the 512-GByte region.",
+ is_instruction_fetching_disabled, PDPT_XD);
}
/// PD Entry bits description.
@@ -252,32 +272,32 @@ bitflags! {
#[derive(Debug)]
flags PDEntry: u64 {
/// Present; must be 1 to map a 2-MByte page or reference a page table.
- const PD_P = 0b00000001,
+ const PD_P = bit!(0),
/// Read/write; if 0, writes may not be allowed to the 2-MByte region controlled by this entry
- const PD_RW = 0b00000010,
+ const PD_RW = bit!(1),
/// User/supervisor; user-mode accesses are not allowed to the 2-MByte region controlled by this entry.
- const PD_US = 0b00000100,
+ const PD_US = bit!(2),
/// Page-level write-through.
- const PD_PWT = 0b00001000,
+ const PD_PWT = bit!(3),
/// Page-level cache disable.
- const PD_PCD = 0b00010000,
+ const PD_PCD = bit!(4),
/// Accessed; if PD_PS set indicates whether software has accessed the 2-MByte page
/// else indicates whether this entry has been used for linear-address translation
- const PD_A = 0b00100000,
+ const PD_A = bit!(5),
/// Dirty; if PD_PS indicates whether software has written to the 2-MByte page referenced by this entry.
/// else ignored.
- const PD_D = 0b01000000,
+ const PD_D = bit!(6),
/// Page size; if set this entry maps a 2-MByte page; otherwise, this entry references a page directory.
- const PD_PS = 0b10000000,
+ const PD_PS = bit!(7),
/// Global; if PD_PS && CR4.PGE = 1, determines whether the translation is global; ignored otherwise
/// if not PD_PS this is ignored.
- const PD_G = 1<<8,
+ const PD_G = bit!(8),
/// Indirectly determines the memory type used to access the 2-MByte page referenced by this entry.
/// if not PD_PS this is ignored.
- const PD_PAT = 1<<12,
+ const PD_PAT = bit!(12),
/// If IA32_EFER.NXE = 1, execute-disable
/// If 1, instruction fetches are not allowed from the 512-GByte region.
- const PD_XD = 1 << 63,
+ const PD_XD = bit!(63),
}
}
@@ -299,10 +319,28 @@ impl PDEntry {
PAddr::from_u64(self.bits & ADDRESS_MASK)
}
- /// Convenience function to check if the present bit is set.
- pub fn is_present(self) -> bool {
- self.contains(PD_P)
- }
+ check_flag!(doc = "Present; must be 1 to map a 2-MByte page or reference a page table.",
+ is_present, PD_P);
+ check_flag!(doc = "Read/write; if 0, writes may not be allowed to the 2-MByte region controlled by this entry",
+ is_writeable, PD_RW);
+ check_flag!(doc = "User/supervisor; user-mode accesses are not allowed to the 2-MByte region controlled by this entry.",
+ is_user_mode_allowed, PD_US);
+ check_flag!(doc = "Page-level write-through.",
+ is_page_write_through, PD_PWT);
+ check_flag!(doc = "Page-level cache disable.",
+ is_page_level_cache_disabled, PD_PCD);
+ check_flag!(doc = "Accessed; if PD_PS set indicates whether software has accessed the 2-MByte page else indicates whether this entry has been used for linear-address translation.",
+ is_accessed, PD_A);
+ check_flag!(doc = "Dirty; if PD_PS set indicates whether software has written to the 2-MByte page referenced by this entry else ignored.",
+ is_dirty, PD_D);
+ check_flag!(doc = "Page size; if set this entry maps a 2-MByte page; otherwise, this entry references a page directory.",
+ is_page, PD_PS);
+ check_flag!(doc = "Global; if PD_PS && CR4.PGE = 1, determines whether the translation is global; ignored otherwise if not PD_PS this is ignored.",
+ is_global, PD_G);
+ check_flag!(doc = "Indirectly determines the memory type used to access the 2-MByte page referenced by this entry. if not PD_PS this is ignored.",
+ is_pat, PD_PAT);
+ check_flag!(doc = "If IA32_EFER.NXE = 1, execute-disable. If 1, instruction fetches are not allowed from the 2-Mbyte region.",
+ is_instruction_fetching_disabled, PD_XD);
}
/// PT Entry bits description.
@@ -310,24 +348,24 @@ bitflags! {
#[derive(Debug)]
flags PTEntry: u64 {
/// Present; must be 1 to map a 4-KByte page.
- const PT_P = 0b00000001,
+ const PT_P = bit!(0),
/// Read/write; if 0, writes may not be allowed to the 4-KByte region controlled by this entry
- const PT_RW = 0b00000010,
+ const PT_RW = bit!(1),
/// User/supervisor; user-mode accesses are not allowed to the 4-KByte region controlled by this entry.
- const PT_US = 0b00000100,
+ const PT_US = bit!(2),
/// Page-level write-through.
- const PT_PWT = 0b00001000,
+ const PT_PWT = bit!(3),
/// Page-level cache disable.
- const PT_PCD = 0b00010000,
+ const PT_PCD = bit!(4),
/// Accessed; indicates whether software has accessed the 4-KByte page
- const PT_A = 0b00100000,
+ const PT_A = bit!(5),
/// Dirty; indicates whether software has written to the 4-KByte page referenced by this entry.
- const PT_D = 0b01000000,
+ const PT_D = bit!(6),
/// Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwise
- const PT_G = 1<<8,
+ const PT_G = bit!(8),
/// If IA32_EFER.NXE = 1, execute-disable
/// If 1, instruction fetches are not allowed from the 512-GByte region.
- const PT_XD = 1 << 63,
+ const PT_XD = bit!(63),
}
}
@@ -350,8 +388,22 @@ impl PTEntry {
PAddr::from_u64(self.bits & ADDRESS_MASK)
}
- /// Convenience function to check if the present bit is set.
- pub fn is_present(self) -> bool {
- self.contains(PT_P)
- }
+ check_flag!(doc = "Present; must be 1 to map a 4-KByte page or reference a page table.",
+ is_present, PT_P);
+ check_flag!(doc = "Read/write; if 0, writes may not be allowed to the 4-KByte region controlled by this entry",
+ is_writeable, PT_RW);
+ check_flag!(doc = "User/supervisor; user-mode accesses are not allowed to the 4-KByte region controlled by this entry.",
+ is_user_mode_allowed, PT_US);
+ check_flag!(doc = "Page-level write-through.",
+ is_page_write_through, PT_PWT);
+ check_flag!(doc = "Page-level cache disable.",
+ is_page_level_cache_disabled, PT_PCD);
+ check_flag!(doc = "Accessed; if PT_PS set indicates whether software has accessed the 4-KByte page else indicates whether this entry has been used for linear-address translation.",
+ is_accessed, PT_A);
+ check_flag!(doc = "Dirty; if PD_PS set indicates whether software has written to the 4-KByte page referenced by this entry else ignored.",
+ is_dirty, PT_D);
+ check_flag!(doc = "Global; if PT_PS && CR4.PGE = 1, determines whether the translation is global; ignored otherwise if not PT_PS this is ignored.",
+ is_global, PT_G);
+ check_flag!(doc = "If IA32_EFER.NXE = 1, execute-disable. If 1, instruction fetches are not allowed from the 4-KByte region.",
+ is_instruction_fetching_disabled, PT_XD);
}