mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
wip
This commit is contained in:
115
src/interrupts/gdt.rs
Normal file
115
src/interrupts/gdt.rs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
use bit_field::BitField;
|
||||||
|
use collections::vec::Vec;
|
||||||
|
use core::ops::Range;
|
||||||
|
use x86::task::TaskStateSegment;
|
||||||
|
|
||||||
|
pub struct Gdt(Vec<BitField<u64>>);
|
||||||
|
|
||||||
|
impl Gdt {
|
||||||
|
pub fn new() -> Gdt {
|
||||||
|
let zero_entry = BitField::new(0);
|
||||||
|
Gdt(vec![zero_entry])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_entry(&mut self, entry: Entry) -> Selector {
|
||||||
|
use core::mem::size_of;
|
||||||
|
let index = self.0.len() * size_of::<BitField<u64>>();
|
||||||
|
|
||||||
|
match entry {
|
||||||
|
Entry::UserSegment(entry) => self.0.push(entry),
|
||||||
|
Entry::SystemSegment(entry_low, entry_high) => {
|
||||||
|
self.0.push(entry_low);
|
||||||
|
self.0.push(entry_high);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Selector(index as u16)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn load(&'static self) {
|
||||||
|
use x86::dtables::{DescriptorTablePointer, lgdt};
|
||||||
|
use core::mem::{self, size_of};
|
||||||
|
|
||||||
|
let ptr = DescriptorTablePointer {
|
||||||
|
base: self.0.as_ptr() as u64,
|
||||||
|
limit: (self.0.len() * size_of::<u64>() - 1) as u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
lgdt(&ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Entry {
|
||||||
|
UserSegment(BitField<u64>),
|
||||||
|
SystemSegment(BitField<u64>, BitField<u64>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entry {
|
||||||
|
pub fn code_segment() -> Entry {
|
||||||
|
let flags = DESCRIPTOR_TYPE | PRESENT | READ_WRITE | EXECUTABLE | LONG_MODE;
|
||||||
|
Entry::UserSegment(BitField::new(flags.bits()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data_segment() -> Entry {
|
||||||
|
let flags = DESCRIPTOR_TYPE | PRESENT | READ_WRITE;
|
||||||
|
Entry::UserSegment(BitField::new(flags.bits()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tss_segment(tss: &'static TaskStateSegment) -> Entry {
|
||||||
|
use core::mem::size_of;
|
||||||
|
|
||||||
|
let ptr = BitField::new(tss as *const _ as u64);
|
||||||
|
|
||||||
|
let mut low = BitField::new(PRESENT.bits());
|
||||||
|
low.set_range(0..16, (size_of::<TaskStateSegment>() - 1) as u64);
|
||||||
|
low.set_range(16..40, ptr.get_range(0..24));
|
||||||
|
low.set_range(40..44, 0b1001); // type: available 64-bit tss
|
||||||
|
|
||||||
|
let mut high = BitField::new(0);
|
||||||
|
high.set_range(0..32, ptr.get_range(32..64));
|
||||||
|
|
||||||
|
Entry::SystemSegment(low, high)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
flags EntryFlags: u64 {
|
||||||
|
const READ_WRITE = 1 << 41,
|
||||||
|
const CONFORMING = 1 << 42,
|
||||||
|
const EXECUTABLE = 1 << 43,
|
||||||
|
const DESCRIPTOR_TYPE = 1 << 44,
|
||||||
|
const PRESENT = 1 << 47,
|
||||||
|
const LONG_MODE = 1 << 53,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Selector(u16);
|
||||||
|
|
||||||
|
pub fn reload_segment_registers(code_selector: Selector, data_selector: Selector) {
|
||||||
|
|
||||||
|
let current_code_selector: u16;
|
||||||
|
let current_data_selector: u16;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
asm!("mov $0, cs" : "=r" (current_code_selector) ::: "intel");
|
||||||
|
asm!("mov $0, ds" : "=r" (current_data_selector) ::: "intel");
|
||||||
|
}
|
||||||
|
assert_eq!(code_selector.0, current_code_selector);
|
||||||
|
assert_eq!(data_selector.0, current_data_selector);
|
||||||
|
|
||||||
|
// jmp ax:.new_code_segment // TODO
|
||||||
|
// .new_code_segment:
|
||||||
|
// unsafe { asm!("
|
||||||
|
// mov ax, $1
|
||||||
|
// mov ss, ax
|
||||||
|
// mov ds, ax
|
||||||
|
// mov es, ax
|
||||||
|
// ":: "r" (code_selector.0), "r" (data_selector.0) :: "intel")};
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load the task state register.
|
||||||
|
pub unsafe fn load_ltr(selector: Selector) {
|
||||||
|
asm!("ltr $0" :: "r" (selector));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user