aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar John Ericson <Ericson2314@Yahoo.com> 2016-06-29 16:19:18 -0700
committerGravatar John Ericson <Ericson2314@Yahoo.com> 2016-07-01 14:50:24 -0700
commitc37a7b580d528f0a4d0721702ddd645a357a405d (patch)
tree4cc74350de6782a702f002d3545378ba4d96c182
parent7234146529386a0d59817055c847b5e906ab605c (diff)
downloadrust-x86-c37a7b580d528f0a4d0721702ddd645a357a405d.tar.gz
rust-x86-c37a7b580d528f0a4d0721702ddd645a357a405d.tar.zst
rust-x86-c37a7b580d528f0a4d0721702ddd645a357a405d.zip
Combine Interface: SegmentSelector; libcpu: permissions parameter
-rw-r--r--src/bits64/segmentation.rs116
-rw-r--r--src/bits64/task.rs5
-rw-r--r--src/shared/mod.rs55
-rw-r--r--src/shared/segmentation.rs135
4 files changed, 142 insertions, 169 deletions
diff --git a/src/bits64/segmentation.rs b/src/bits64/segmentation.rs
index e46b333..4f12358 100644
--- a/src/bits64/segmentation.rs
+++ b/src/bits64/segmentation.rs
@@ -1,76 +1,5 @@
//! Program x86 segmentation hardware.
-use core::fmt;
-
-/// Specifies which element to load into a segment from
-/// descriptor tables (i.e., is a index to LDT or GDT table
-/// with some additional flags).
-bitflags! {
- pub flags SegmentSelector: u16 {
- /// Requestor Privilege Level
- const RPL_0 = 0b00,
- const RPL_1 = 0b01,
- const RPL_2 = 0b10,
- const RPL_3 = 0b11,
-
- /// Table Indicator (TI) 0 means GDT is used.
- const TI_GDT = 0 << 3,
- /// Table Indicator (TI) 1 means LDT is used.
- const TI_LDT = 1 << 3,
- }
-}
-
-impl SegmentSelector {
- /// Create a new SegmentSelector
- ///
- /// # Arguments
- /// * `index` index in GDT or LDT array.
- ///
- pub fn new(index: u16) -> SegmentSelector {
- SegmentSelector { bits: index << 3 }
- }
-
- pub fn from_raw(bits: u16) -> SegmentSelector {
- SegmentSelector { bits: bits }
- }
-}
-
-impl fmt::Display for SegmentSelector {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let r0 = match self.contains(RPL_0) {
- false => "",
- true => "Ring 0 segment selector.",
- };
- let r1 = match self.contains(RPL_1) {
- false => "",
- true => "Ring 1 segment selector.",
- };
- let r2 = match self.contains(RPL_2) {
- false => "",
- true => "Ring 2 segment selector.",
- };
- let r3 = match self.contains(RPL_3) {
- false => "",
- true => "Ring 3 segment selector.",
- };
- let tbl = match self.contains(TI_LDT) {
- false => "GDT Table",
- true => "LDT Table",
- };
-
- write!(f,
- "Index {} in {}, {}{}{}{}",
- self.bits >> 3,
- tbl,
- r0,
- r1,
- r2,
- r3)
- // write!(f, "Index")
- }
-}
-
-
/// Entry for GDT or LDT. Provides size and location of a segment.
bitflags! {
pub flags SegmentDescriptor: u64 {
@@ -161,48 +90,3 @@ impl SegmentDescriptor {
}
}
}
-
-/// Reload stack segment register.
-pub unsafe fn load_ss(sel: SegmentSelector) {
- asm!("movw $0, %ss " :: "r" (sel) : "memory");
-}
-
-/// Reload data segment register.
-pub unsafe fn load_ds(sel: SegmentSelector) {
- asm!("movw $0, %ds " :: "r" (sel) : "memory");
-}
-
-/// Reload es segment register.
-pub unsafe fn load_es(sel: SegmentSelector) {
- asm!("movw $0, %es " :: "r" (sel) : "memory");
-}
-
-/// Reload fs segment register.
-pub unsafe fn load_fs(sel: SegmentSelector) {
- asm!("movw $0, %fs " :: "r" (sel) : "memory");
-}
-
-/// Reload gs segment register.
-pub unsafe fn load_gs(sel: SegmentSelector) {
- asm!("movw $0, %gs " :: "r" (sel) : "memory");
-}
-
-/// Reload code segment register.
-/// Note this is special since we can not directly move
-/// to %cs. Instead we push the new segment selector
-/// and return value on the stack and use lretq
-/// to reload cs and continue at 1:.
-pub unsafe fn load_cs(sel: SegmentSelector) {
- asm!("pushq $0
- lea 1f(%rip), %rax
- pushq %rax
- lretq
- 1:" :: "r" (sel.bits() as u64) : "{rax}" "memory");
-}
-
-/// Returns the current value of the code segment register.
-pub fn cs() -> SegmentSelector {
- let segment: u16;
- unsafe { asm!("mov %cs, $0" : "=r" (segment) ) };
- SegmentSelector::from_raw(segment)
-}
diff --git a/src/bits64/task.rs b/src/bits64/task.rs
index 97d3341..fff00fe 100644
--- a/src/bits64/task.rs
+++ b/src/bits64/task.rs
@@ -1,6 +1,9 @@
//! Helpers to program the task state segment.
-use super::segmentation;
+mod segmentation {
+ pub use shared::segmentation::*;
+ pub use super::super::segmentation::*;
+}
pub type TaskStateDescriptorLow = segmentation::SegmentDescriptor;
pub type TaskStateDescriptorHigh = u64;
diff --git a/src/shared/mod.rs b/src/shared/mod.rs
index 977dcf4..f110934 100644
--- a/src/shared/mod.rs
+++ b/src/shared/mod.rs
@@ -6,6 +6,9 @@ pub mod dtables;
pub mod io;
pub mod irq;
pub mod paging;
+pub mod segmentation;
+
+use self::segmentation::SegmentSelector;
bitflags! {
pub flags Flags: usize {
@@ -133,64 +136,12 @@ pub enum PrivilegeLevel {
Ring3 = 3,
}
-#[derive(Copy, Clone, PartialEq, Eq)]
-#[repr(C, packed)]
-pub struct SegmentSelector {
- data: u16
-}
-
-impl SegmentSelector {
- #[inline(always)]
- pub fn new(index: u16, rpl: PrivilegeLevel) -> SegmentSelector {
- SegmentSelector {
- data: index << 3 | rpl as u16
- }
- }
-
- pub fn bits(&self) -> u16 {
- self.data
- }
-}
-
#[inline(always)]
pub unsafe fn set_tr(selector: SegmentSelector) {
asm!("ltr $0" :: "r"(selector.bits()) :: "volatile", "intel");
}
#[inline(always)]
-pub unsafe fn set_ss(selector: SegmentSelector) {
- asm!("mov ss, $0" :: "r"(selector.bits()) :: "volatile", "intel");
-}
-
-#[inline(always)]
-pub unsafe fn set_ds(selector: SegmentSelector) {
- asm!("mov ds, $0" :: "r"(selector.bits()) :: "volatile", "intel");
-}
-
-#[inline(always)]
-pub unsafe fn set_es(selector: SegmentSelector) {
- asm!("mov es, $0" :: "r"(selector.bits()) :: "volatile", "intel");
-}
-
-#[inline(always)]
-pub unsafe fn set_gs(selector: SegmentSelector) {
- asm!("mov gs, $0" :: "r"(selector.bits()) :: "volatile", "intel");
-}
-
-#[inline(always)]
-pub unsafe fn set_fs(selector: SegmentSelector) {
- asm!("mov fs, $0" :: "r"(selector.bits()) :: "volatile", "intel");
-}
-
-#[inline(always)]
-pub unsafe fn set_cs(selector: SegmentSelector) {
- asm!("push $0;
- push $$1f
- lret;
- 1:" :: "ri"(selector.bits() as usize) :: "volatile");
-}
-
-#[inline(always)]
pub unsafe fn halt() {
asm!("hlt" :::: "volatile", "intel");
}
diff --git a/src/shared/segmentation.rs b/src/shared/segmentation.rs
new file mode 100644
index 0000000..f4dc194
--- /dev/null
+++ b/src/shared/segmentation.rs
@@ -0,0 +1,135 @@
+use core::fmt;
+
+use shared::PrivilegeLevel;
+
+/// Specifies which element to load into a segment from
+/// descriptor tables (i.e., is a index to LDT or GDT table
+/// with some additional flags).
+bitflags! {
+ #[repr(C, packed)]
+ pub flags SegmentSelector: u16 {
+ /// Requestor Privilege Level
+ const RPL_0 = 0b00,
+ const RPL_1 = 0b01,
+ const RPL_2 = 0b10,
+ const RPL_3 = 0b11,
+
+ /// Table Indicator (TI) 0 means GDT is used.
+ const TI_GDT = 0 << 3,
+ /// Table Indicator (TI) 1 means LDT is used.
+ const TI_LDT = 1 << 3,
+ }
+}
+
+/// Reload code segment register.
+/// Note this is special since we can not directly move
+/// to %cs. Instead we push the new segment selector
+/// and return value on the stack and use lretq
+/// to reload cs and continue at 1:.
+pub unsafe fn set_cs(sel: SegmentSelector) {
+
+ #[cfg(target_arch="x86")]
+ #[inline(always)]
+ unsafe fn inner(sel: SegmentSelector) {
+ asm!("pushl $0; \
+ pushl $$1f; \
+ lretl; \
+ 1:" :: "ri" (sel.bits() as usize) : "{rax}" "memory");
+ }
+
+ #[cfg(target_arch="x86_64")]
+ #[inline(always)]
+ unsafe fn inner(sel: SegmentSelector) {
+ asm!("pushq $0; \
+ leaq 1f(%rip), %rax; \
+ pushq %rax; \
+ lretq; \
+ 1:" :: "ri" (sel.bits() as usize) : "{rax}" "memory");
+ }
+
+ inner(sel)
+}
+
+
+impl SegmentSelector {
+ /// Create a new SegmentSelector
+ ///
+ /// # Arguments
+ /// * `index` index in GDT or LDT array.
+ ///
+ pub const fn new(index: u16, rpl: PrivilegeLevel) -> SegmentSelector {
+ SegmentSelector { bits: index << 3 | (rpl as u16) }
+ }
+
+ pub const fn from_raw(bits: u16) -> SegmentSelector {
+ SegmentSelector { bits: bits }
+ }
+}
+
+impl fmt::Display for SegmentSelector {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let r0 = match self.contains(RPL_0) {
+ false => "",
+ true => "Ring 0 segment selector.",
+ };
+ let r1 = match self.contains(RPL_1) {
+ false => "",
+ true => "Ring 1 segment selector.",
+ };
+ let r2 = match self.contains(RPL_2) {
+ false => "",
+ true => "Ring 2 segment selector.",
+ };
+ let r3 = match self.contains(RPL_3) {
+ false => "",
+ true => "Ring 3 segment selector.",
+ };
+ let tbl = match self.contains(TI_LDT) {
+ false => "GDT Table",
+ true => "LDT Table",
+ };
+
+ write!(f,
+ "Index {} in {}, {}{}{}{}",
+ self.bits >> 3,
+ tbl,
+ r0,
+ r1,
+ r2,
+ r3)
+ // write!(f, "Index")
+ }
+}
+
+
+/// Reload stack segment register.
+pub unsafe fn load_ss(sel: SegmentSelector) {
+ asm!("movw $0, %ss " :: "r" (sel) : "memory");
+}
+
+/// Reload data segment register.
+pub unsafe fn load_ds(sel: SegmentSelector) {
+ asm!("movw $0, %ds " :: "r" (sel) : "memory");
+}
+
+/// Reload es segment register.
+pub unsafe fn load_es(sel: SegmentSelector) {
+ asm!("movw $0, %es " :: "r" (sel) : "memory");
+}
+
+/// Reload fs segment register.
+pub unsafe fn load_fs(sel: SegmentSelector) {
+ asm!("movw $0, %fs " :: "r" (sel) : "memory");
+}
+
+/// Reload gs segment register.
+pub unsafe fn load_gs(sel: SegmentSelector) {
+ asm!("movw $0, %gs " :: "r" (sel) : "memory");
+}
+
+/// Returns the current value of the code segment register.
+pub fn cs() -> SegmentSelector {
+ let segment: u16;
+ unsafe { asm!("mov %cs, $0" : "=r" (segment) ) };
+ SegmentSelector::from_raw(segment)
+}