diff options
author | 2018-04-26 19:20:36 -0700 | |
---|---|---|
committer | 2018-04-26 19:20:36 -0700 | |
commit | 57a2bfac28ce1e62ce1051b9de731d81e1c25a8b (patch) | |
tree | 3d0f93200a5ad3c11cb685a4da9682b9c226c6a5 /src/bits32/segmentation.rs | |
parent | 848ec0fae090dbc1657d02b436b8b887df519e90 (diff) | |
download | rust-x86-57a2bfac28ce1e62ce1051b9de731d81e1c25a8b.tar.gz rust-x86-57a2bfac28ce1e62ce1051b9de731d81e1c25a8b.tar.zst rust-x86-57a2bfac28ce1e62ce1051b9de731d81e1c25a8b.zip |
More segmentation refactoring.
Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
Diffstat (limited to 'src/bits32/segmentation.rs')
-rw-r--r-- | src/bits32/segmentation.rs | 199 |
1 files changed, 1 insertions, 198 deletions
diff --git a/src/bits32/segmentation.rs b/src/bits32/segmentation.rs index dc6da52..5114394 100644 --- a/src/bits32/segmentation.rs +++ b/src/bits32/segmentation.rs @@ -1,202 +1,5 @@ #[allow(unused_imports)] use segmentation::{SegmentSelector}; -use segmentation::{DescriptorBuilder, DescriptorType, GateDescriptorBuilder, TaskGateDescriptorBuilder, SegmentDescriptorBuilder, LdtDescriptorBuilder, BuildDescriptor, SystemDescriptorTypes32, CodeSegmentType, DataSegmentType}; -use ::Ring; - -/// Entry for IDT, GDT or LDT. Provides size and location of a segment. -/// -/// See Intel 3a, Section 3.4.5 "Segment Descriptors", and Section 3.5.2 -#[derive(Copy, Clone, Debug, Default)] -#[repr(C, packed)] -pub struct Descriptor { - pub lower: u32, - pub upper: u32, -} - -impl Descriptor { - - pub(crate) fn apply_builder_settings(&mut self, builder: &DescriptorBuilder) { - builder.dpl.map(|ring| self.set_dpl(ring)); - builder.base_limit.map(|(base, limit)| self.set_base_limit(base as u32, limit as u32)); - builder.selector_offset.map(|(selector, offset)| self.set_selector_offset(selector, offset as u32)); - - if builder.present { - self.set_p(); - } - if builder.avl { - self.set_avl(); - } - if builder.db { - self.set_db(); - } - if builder.limit_granularity_4k { - self.set_g(); - } - } - - /// Create a new segment, TSS or LDT descriptor - /// by setting the three base and two limit fields. - pub fn set_base_limit(&mut self, base: u32, limit: u32) { - // Clear the base and limit fields in Descriptor - self.lower = 0; - self.upper = self.upper & 0x00F0FF00; - - // Set the new base - self.lower |= base << 16; - self.upper |= (base >> 16) & 0xff; - self.upper |= (base >> 24) << 24; - - // Set the new limit - self.lower |= limit & 0xffff; - let limit_last_four_bits = (limit >> 16) & 0x0f; - self.upper |= limit_last_four_bits << 16; - } - - /// Creates a new descriptor with selector and offset (for IDT Gate descriptors, - /// e.g. Trap, Interrupts and Task gates) - pub fn set_selector_offset(&mut self, selector: SegmentSelector, offset: u32) { - // Clear the selector and offset - self.lower = 0; - self.upper = self.upper & 0x0000ffff; - - // Set selector - self.lower |= (selector.bits() as u32) << 16; - - // Set offset - self.lower |= offset & 0x0000ffff; - self.upper |= offset & 0xffff0000; - } - - /// Set the type of the descriptor (bits 8-11). - /// Indicates the segment or gate type and specifies the kinds of access that can be made to the - /// segment and the direction of growth. The interpretation of this field depends on whether the descriptor - /// type flag specifies an application (code or data) descriptor or a system descriptor. - pub fn set_type(&mut self, typ: u8) { - self.upper &= !(0x0f << 8); // clear - self.upper |= (typ as u32 & 0x0f) << 8; - } - - /// Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S flag is set). - pub fn set_s(&mut self) { - self.upper |= bit!(12); - } - - /// Specifies the privilege level of the segment. The DPL is used to control access to the segment. - pub fn set_dpl(&mut self, ring: Ring) { - assert!(ring as u32 <= 0b11); - self.upper &= !(0b11 << 13); - self.upper |= (ring as u32) << 13; - } - - /// Set Present bit. - /// Indicates whether the segment is present in memory (set) or not present (clear). - /// If this flag is clear, the processor generates a segment-not-present exception (#NP) when a segment selector - /// that points to the segment descriptor is loaded into a segment register. - pub fn set_p(&mut self) { - self.upper |= bit!(15); - } - - /// Set AVL bit. System software can use this bit to store information. - pub fn set_avl(&mut self) { - self.upper |= bit!(20); - } - - /// Set L - /// In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a - /// code segment contains native 64-bit code. A value of 1 indicates instructions in this code - /// segment are executed in 64-bit mode. A value of 0 indicates the instructions in this code segment - /// are executed in compatibility mode. If L-bit is set, then D-bit must be cleared. - pub fn set_l(&mut self) { - self.upper |= bit!(21); - } - - /// Set D/B. - /// Performs different functions depending on whether the segment descriptor is an executable code segment, - /// an expand-down data segment, or a stack segment. - pub fn set_db(&mut self) { - self.upper |= bit!(22); - } - - /// Set G bit - /// Determines the scaling of the segment limit field. - /// When the granularity flag is clear, the segment limit is interpreted in byte units; - /// when flag is set, the segment limit is interpreted in 4-KByte units. - pub fn set_g(&mut self) { - self.upper |= bit!(23); - } -} - -impl GateDescriptorBuilder<u32> for DescriptorBuilder { - - fn tss_descriptor(selector: SegmentSelector, offset: u32, available: bool) -> DescriptorBuilder { - let typ = match available { - true => DescriptorType::System32(SystemDescriptorTypes32::TssAvailable32), - false => DescriptorType::System32(SystemDescriptorTypes32::TssBusy32), - }; - - DescriptorBuilder::with_selector_offset(selector, offset.into()).set_type(typ) - } - - fn call_gate_descriptor(selector: SegmentSelector, offset: u32) -> DescriptorBuilder { - DescriptorBuilder::with_selector_offset(selector, offset.into()).set_type(DescriptorType::System32(SystemDescriptorTypes32::CallGate32)) - } - - fn interrupt_descriptor(selector: SegmentSelector, offset: u32) -> DescriptorBuilder { - DescriptorBuilder::with_selector_offset(selector, offset.into()).set_type(DescriptorType::System32(SystemDescriptorTypes32::InterruptGate32)) - } - - fn trap_gate_descriptor(selector: SegmentSelector, offset: u32) -> DescriptorBuilder { - DescriptorBuilder::with_selector_offset(selector, offset.into()).set_type(DescriptorType::System32(SystemDescriptorTypes32::TrapGate32)) - } -} - -impl TaskGateDescriptorBuilder for DescriptorBuilder { - fn task_gate_descriptor(selector: SegmentSelector) -> DescriptorBuilder { - DescriptorBuilder::with_selector_offset(selector, 0).set_type(DescriptorType::System32(SystemDescriptorTypes32::TaskGate)) - } -} - -impl SegmentDescriptorBuilder<u32> for DescriptorBuilder { - fn code_descriptor(base: u32, limit: u32, cst: CodeSegmentType) -> DescriptorBuilder { - DescriptorBuilder::with_base_limit(base.into(), limit.into()).set_type(DescriptorType::Code(cst)).db() - } - - fn data_descriptor(base: u32, limit: u32, dst: DataSegmentType) -> DescriptorBuilder { - DescriptorBuilder::with_base_limit(base.into(), limit.into()).set_type(DescriptorType::Data(dst)).db() - } -} - -impl LdtDescriptorBuilder<u32> for DescriptorBuilder { - fn ldt_descriptor(base: u32, limit: u32) -> DescriptorBuilder { - DescriptorBuilder::with_base_limit(base.into(), limit.into()).set_type(DescriptorType::System32(SystemDescriptorTypes32::LDT)) - } -} - -impl BuildDescriptor<Descriptor> for DescriptorBuilder { - fn finish(&self) -> Descriptor { - let mut desc: Descriptor = Default::default(); - desc.apply_builder_settings(self); - - let typ = match self.typ { - Some(DescriptorType::System64(_)) => panic!("You shall not use 64-bit types on 32-bit descriptor."), - Some(DescriptorType::System32(typ)) => { - typ as u8 - }, - Some(DescriptorType::Data(typ)) => { - desc.set_s(); - typ as u8 - }, - Some(DescriptorType::Code(typ)) => { - desc.set_s(); - typ as u8 - }, - None => unreachable!("Type not set, this is a library bug in x86."), - }; - desc.set_type(typ); - - desc - } -} /// Reload code segment register. /// Note this is special since we can not directly move @@ -204,7 +7,7 @@ impl BuildDescriptor<Descriptor> for DescriptorBuilder { /// and return value on the stack and use lretl /// to reload cs and continue at 1:. #[cfg(target_arch="x86")] -pub unsafe fn set_cs(sel: SegmentSelector) { +pub unsafe fn load_cs(sel: SegmentSelector) { asm!("pushl $0; \ pushl $$1f; \ lretl; \ |