diff options
-rw-r--r-- | src/lib.rs | 36 | ||||
-rw-r--r-- | src/paging.rs | 160 | ||||
-rw-r--r-- | tests/no_std_build.rs | 2 |
3 files changed, 137 insertions, 61 deletions
@@ -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); } diff --git a/tests/no_std_build.rs b/tests/no_std_build.rs index e95a828..bddedc8 100644 --- a/tests/no_std_build.rs +++ b/tests/no_std_build.rs @@ -1,4 +1,4 @@ -#![feature(lang_items, start, no_std, libc)] +#![feature(lang_items, start, libc)] #![no_std] extern crate libc; |