From 0b38f701edd1aadd53f8e4916d8b15deee5baacc Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 13 Mar 2018 20:06:25 +0100 Subject: [PATCH] WIP --- kernel-rs/.gitmodules | 3 + kernel-rs/Cargo.toml | 1 + kernel-rs/src/console.rs | 9 +- kernel-rs/src/lib.rs | 14 +-- kernel-rs/src/memory/area_allocator.rs | 38 ++++---- kernel-rs/src/memory/mod.rs | 42 ++------ kernel-rs/src/memory/paging/entry.rs | 66 ------------- kernel-rs/src/memory/paging/mapper.rs | 64 ++++++------ kernel-rs/src/memory/paging/mod.rs | 91 +++++------------ kernel-rs/src/memory/paging/table.rs | 97 ++++--------------- kernel-rs/src/memory/paging/temporary_page.rs | 27 +++--- kernel-rs/src/x86/mod.rs | 29 ------ kernel-rs/src/x86/structures/idt.rs | 4 + kernel-rs/src/x86/structures/mod.rs | 3 + kernel-rs/src/x86/tlb.rs | 10 -- kernel-rs/x86 | 1 + 16 files changed, 133 insertions(+), 366 deletions(-) delete mode 100644 kernel-rs/src/memory/paging/entry.rs delete mode 100644 kernel-rs/src/x86/mod.rs create mode 100644 kernel-rs/src/x86/structures/idt.rs create mode 100644 kernel-rs/src/x86/structures/mod.rs delete mode 100644 kernel-rs/src/x86/tlb.rs create mode 160000 kernel-rs/x86 diff --git a/kernel-rs/.gitmodules b/kernel-rs/.gitmodules index 7612dca4..820f6043 100644 --- a/kernel-rs/.gitmodules +++ b/kernel-rs/.gitmodules @@ -1,3 +1,6 @@ [submodule "multiboot2-elf64"] path = multiboot2-elf64 url = git@github.com:jzck/multiboot2-elf64.git +[submodule "x86"] + path = x86 + url = https://github.com/jzck/x86.git diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 68a70731..558231c0 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -10,3 +10,4 @@ crate-type = ["staticlib"] rlibc = "1.0" bitflags = "1.0.1" multiboot2 = { path = "multiboot2-elf64" } +x86 = { path = "x86" } diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 91f046dd..fa9f34ca 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -3,7 +3,6 @@ extern crate core; use acpi; use cpuio; -use x86; use core::char; use vga::*; @@ -177,9 +176,11 @@ pub fn acpi_info() -> Result <(), &'static str> { } pub fn regs() -> Result <(), &'static str> { - println!("cr0={:#b}", x86::cr0()); - println!("cr3={:#x}", x86::cr3()); - println!("cr4={:#b}", x86::cr4()); + use x86::registers::control::*; + println!("cr0={:#b}", Cr0::read()); + println!("cr3={:#x}", Cr3::read()); + // TODO implement cr4 flags in `x86` module + // println!("cr4={:#b}", Cr4::read()); Ok(()) } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 43d10e56..1303e417 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -11,8 +11,9 @@ extern crate rlibc; extern crate multiboot2; -#[macro_use] extern crate bitflags; +// #[macro_use] extern crate bitflags; #[macro_use] extern crate alloc; +extern crate x86; /// 80x25 screen and simplistic terminal driver #[macro_use] pub mod vga; @@ -20,14 +21,14 @@ extern crate multiboot2; pub mod keyboard; /// simplisitc kernel commands pub mod console; -/// wrappers around the x86-family I/O instructions. +/// rust wrappers around cpu I/O instructions. pub mod cpuio; /// ACPI self-content module pub mod acpi; -/// physical frame allocator + paging module +/// physical frame allocator + paging module + heap allocator pub mod memory; -/// a few x86 register and instruction wrappers -pub mod x86; +/// x86 interruptions +// pub mod interrupts; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { @@ -54,7 +55,8 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { } fn enable_write_protect_bit() { - unsafe { x86::cr0_write(x86::cr0() | (1 << 16)) }; + use x86::registers::control::{Cr0, Cr0Flags}; + unsafe { Cr0::write(Cr0::read() | Cr0Flags::WRITE_PROTECT) }; } #[lang = "eh_personality"] #[no_mangle] diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/area_allocator.rs index 09304cb6..011f6cb4 100644 --- a/kernel-rs/src/memory/area_allocator.rs +++ b/kernel-rs/src/memory/area_allocator.rs @@ -2,13 +2,13 @@ use memory::*; use multiboot2::{MemoryAreaIter, MemoryArea}; pub struct AreaFrameAllocator { - next_free_frame: Frame, + next_free_frame: PhysFrame, current_area: Option<&'static MemoryArea>, areas: MemoryAreaIter, - kernel_start: Frame, - kernel_end: Frame, - multiboot_start: Frame, - multiboot_end: Frame, + kernel_start: PhysFrame, + kernel_end: PhysFrame, + multiboot_start: PhysFrame, + multiboot_end: PhysFrame, } impl AreaFrameAllocator { @@ -16,13 +16,13 @@ impl AreaFrameAllocator { multiboot_start: usize, multiboot_end: usize, memory_areas: MemoryAreaIter) -> AreaFrameAllocator { let mut allocator = AreaFrameAllocator { - next_free_frame: Frame::containing_address(0), + next_free_frame: PhysFrame::containing_address(0), current_area: None, areas: memory_areas, - kernel_start: Frame::containing_address(kernel_start), - kernel_end: Frame::containing_address(kernel_end), - multiboot_start: Frame::containing_address(multiboot_start), - multiboot_end: Frame::containing_address(multiboot_end), + kernel_start: PhysFrame::containing_address(kernel_start), + kernel_end: PhysFrame::containing_address(kernel_end), + multiboot_start: PhysFrame::containing_address(multiboot_start), + multiboot_end: PhysFrame::containing_address(multiboot_end), }; allocator.choose_next_area(); allocator @@ -31,11 +31,11 @@ impl AreaFrameAllocator { fn choose_next_area(&mut self) { // get next area with free frames self.current_area = self.areas.clone().filter(|area| { - Frame::containing_address(area.end_address()) >= self.next_free_frame + PhysFrame::containing_address(area.end_address()) >= self.next_free_frame }).min_by_key(|area| area.start_address()); if let Some(area) = self.current_area { - let start_frame = Frame::containing_address(area.start_address()); + let start_frame = PhysFrame::containing_address(area.start_address()); if self.next_free_frame < start_frame { self.next_free_frame = start_frame; } @@ -44,21 +44,21 @@ impl AreaFrameAllocator { } impl FrameAllocator for AreaFrameAllocator { - fn allocate_frame(&mut self) -> Option { - if let Some(area) = self.current_area { - let frame = Frame { number: self.next_free_frame.number }; - let current_area_last_frame = Frame::containing_address(area.end_address()); + fn allocate_frame(&mut self) -> Option { + if let Some(area) = self.current_arPhysea { + let frame = PhysFrame { number: self.next_free_frame.number }; + let current_area_last_frame = PhysFrame::containing_address(area.end_address()); if frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); } else if frame >= self.kernel_start && frame <= self.kernel_end { // frame used by kernel - self.next_free_frame = Frame { + self.next_free_frame = PhysFrame { number: self.kernel_end.number + 1, } } else if frame >= self.multiboot_start && frame <= self.multiboot_end { // frame used by multiboot - self.next_free_frame = Frame { + self.next_free_frame = PhysFrame { number: self.multiboot_end.number + 1, } } else { @@ -72,7 +72,7 @@ impl FrameAllocator for AreaFrameAllocator { } } - fn deallocate_frame(&mut self, frame: Frame) { + fn deallocate_frame(&mut self, frame: PhysFrame) { unimplemented!(); } } diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 76189437..89568f0b 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -7,49 +7,24 @@ mod paging; pub use self::area_allocator::*; pub use self::heap_allocator::*; pub use self::paging::remap_the_kernel; -use self::paging::PhysicalAddress; use multiboot2; -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Frame { - number: usize, -} - -impl Frame { - fn containing_address(address: usize) -> Frame { - Frame{ number: address / PAGE_SIZE } - } - - fn start_address(&self) -> PhysicalAddress { - self.number * PAGE_SIZE - } - - fn clone(&self) ->Frame { - Frame { number: self.number } - } - - fn range_inclusive(start: Frame, end: Frame) -> FrameIter { - FrameIter { - start, - end, - } - } -} +use x86::structures::paging::*; pub trait FrameAllocator { - fn allocate_frame(&mut self) -> Option; - fn deallocate_frame(&mut self, frame: Frame); + fn allocate_frame(&mut self) -> Option; + fn deallocate_frame(&mut self, frame: PhysFrame); } struct FrameIter { - start: Frame, - end: Frame, + start: PhysFrame, + end: PhysFrame, } impl Iterator for FrameIter { - type Item = Frame; + type Item = PhysFrame; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.start <= self.end { let frame = self.start.clone(); self.start.number += 1; @@ -82,13 +57,12 @@ pub fn init(boot_info: &multiboot2::BootInformation) { let mut active_table = paging::remap_the_kernel(&mut frame_allocator, boot_info); - use self::paging::Page; use {HEAP_START, HEAP_SIZE}; let heap_start_page = Page::containing_address(HEAP_START); let heap_end_page = Page::containing_address(HEAP_START + HEAP_SIZE - 1); for page in Page::range_inclusive(heap_start_page, heap_end_page) { - active_table.map(page, paging::EntryFlags::WRITABLE, &mut frame_allocator); + active_table.map(page, PageTableFlags::WRITABLE, &mut frame_allocator); } } diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs deleted file mode 100644 index 26edb9c1..00000000 --- a/kernel-rs/src/memory/paging/entry.rs +++ /dev/null @@ -1,66 +0,0 @@ -use memory::Frame; - -pub struct Entry(u32); -use multiboot2::ElfSection; - -impl Entry { - pub fn is_unused(&self) -> bool { - self.0 == 0 - } - - pub fn set_unused(&mut self) { - self.0 = 0; - } - - pub fn flags(&self) -> EntryFlags { - EntryFlags::from_bits_truncate(self.0) - } - - pub fn pointed_frame(&self) -> Option { - if self.flags().contains(EntryFlags::PRESENT) { - Some(Frame::containing_address( - self.0 as usize & 0xffff_f000)) - } else { - None - } - } - - pub fn set(&mut self, frame: Frame, flags: EntryFlags) { - assert!(frame.start_address() & !0xffff_f000 == 0); - self.0 = (frame.start_address() as u32) | flags.bits(); - } -} - -bitflags! { - pub struct EntryFlags: u32 { - const PRESENT = 1 << 0; - const WRITABLE = 1 << 1; - const USER_ACCESSIBLE = 1 << 2; - const WRITE_THROUGH = 1 << 3; - const NO_CACHE = 1 << 4; - const ACCESSED = 1 << 5; - const DIRTY = 1 << 6; - const HUGE_PAGE = 1 << 7; - const GLOBAL = 1 << 8; - // LONG MODE - // const NO_EXECUTE = 1 << 63; - } -} - -impl EntryFlags { - pub fn from_elf_section_flags(section: &ElfSection) -> EntryFlags { - use multiboot2::ElfSectionFlags; - - let mut flags = EntryFlags::empty(); - if section.flags().contains(ElfSectionFlags::ALLOCATED) { - flags = flags | EntryFlags::PRESENT; - } - if section.flags().contains(ElfSectionFlags::WRITABLE) { - flags = flags | EntryFlags::WRITABLE; - } - // if !section.flags().contains(ElfSectionFlags::EXECUTABLE) { - // flags = flags | EntryFlags::NO_EXECUTE; - // } - flags - } -} diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index 93d5be86..27800c23 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -1,61 +1,52 @@ -use super::{VirtualAddress, PhysicalAddress, Page, ENTRY_COUNT}; -use super::entry::*; -use super::table::{self, Table, Level2}; -use memory::{PAGE_SIZE, Frame, FrameAllocator}; +use memory::{PAGE_SIZE, FrameAllocator}; use core::ptr::Unique; -use x86; +use x86::structures::paging::*; +use x86::instructions::tlb; +use x86::*; +// +// virtual address of recursively mapped P2 +// for protected mode non PAE +// https://wiki.osdev.org/Page_Tables +pub const P2: *mut PageTable = 0xffff_f000 as *mut _; pub struct Mapper { - p2: Unique>, + p2: Unique, } impl Mapper { pub unsafe fn new() -> Mapper { Mapper { - p2: Unique::new_unchecked(table::P2), + p2: Unique::new_unchecked(self::P2), } } // the remaining mapping methods, all public - pub fn p2(&self) -> &Table { + pub fn p2(&self) -> &PageTable { unsafe { self.p2.as_ref() } } - pub fn p2_mut(&mut self) -> &mut Table { + pub fn p2_mut(&mut self) -> &mut PageTable { unsafe { self.p2.as_mut() } } - pub fn translate(&self, virtual_address: VirtualAddress) -> Option + pub fn translate(&self, virtual_address: VirtAddr) -> Option { - let offset = virtual_address % PAGE_SIZE; + let offset = virtual_address.as_u32() % PAGE_SIZE as u32; self.translate_page(Page::containing_address(virtual_address)) - .map(|frame| frame.number * PAGE_SIZE + offset) + .map(|frame| frame.start_address() + offset) + } - pub fn translate_page(&self, page: Page) -> Option { + pub fn translate_page(&self, page: Page) -> Option { - let p1 = self.p2().next_table(page.p2_index()); + let p1 = self.p2()[page.p2_index()].points_to() + .and_then(|paddr| PageTable::from(paddr)); - let huge_page = || { - let p2_entry = &self.p2()[page.p2_index()]; - if let Some(start_frame) = p2_entry.pointed_frame() { - if p2_entry.flags().contains(EntryFlags::HUGE_PAGE) { - // 4KiB alignment check - assert!(start_frame.number % ENTRY_COUNT == 0); - return Some(Frame { - number: start_frame.number + page.p1_index() - }); - } - } - None - }; - - p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) - .or_else(huge_page) + p1.and_then() } - pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags, + pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags, allocator: &mut A) where A: FrameAllocator { @@ -63,20 +54,21 @@ impl Mapper { let p1 = p2.next_table_create(page.p2_index(), allocator); assert!(p1[page.p1_index()].is_unused()); - p1[page.p1_index()].set(frame, flags | EntryFlags::PRESENT); + p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT); } - pub fn map(&mut self, page: Page, flags: EntryFlags, allocator: &mut A) + pub fn map(&mut self, page: Page, flags: PageTableFlags, allocator: &mut A) where A: FrameAllocator { let frame = allocator.allocate_frame().expect("out of memory"); self.map_to(page, frame, flags, allocator) } - pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags, allocator: &mut A) + pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags, allocator: &mut A) where A: FrameAllocator { - let page = Page::containing_address(frame.start_address()); + let virt_addr = VirtAddr::new(frame.start_address().as_u32()); + let page = Page::containing_address(virt_addr); self.map_to(page, frame, flags, allocator); } @@ -90,7 +82,7 @@ impl Mapper { .expect("mapping code does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); - x86::tlb::flush(page.start_address()); + tlb::flush(page.start_address()); // TODO // allocator.deallocate_frame(frame); } diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 636f235d..c5363e1e 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -1,59 +1,16 @@ #![allow(dead_code)] -mod entry; -mod table; +// mod table; mod temporary_page; mod mapper; -use memory::PAGE_SIZE; use memory::*; use self::mapper::Mapper; use self::temporary_page::TemporaryPage; use core::ops::{Deref, DerefMut}; use multiboot2::BootInformation; use x86; - -pub use self::entry::*; -pub use self::table::*; - -// x86 non PAE has 1024 entries per table -const ENTRY_COUNT: usize = 1024; - -pub type PhysicalAddress = usize; -pub type VirtualAddress = usize; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct Page { - number: usize, -} - -impl Page { - pub fn containing_address(address: VirtualAddress) -> Page { - // assert!(address < 0x0000_8000_0000_0000 || - // address >= 0xffff_8000_0000_0000, - // "invalid addres: 0x{:x}", address); - Page { number: address / PAGE_SIZE } - } - - fn start_address(&self) -> usize { - self.number * PAGE_SIZE - } - - fn p2_index(&self) -> usize { - (self.number >> 10) & 0x3ff - } - - fn p1_index(&self) -> usize { - (self.number >> 0) & 0x3ff - } - - pub fn range_inclusive(start: Page, end: Page) -> PageIter { - PageIter { - start, - end, - } - } -} +use x86::registers::control::Cr3; #[derive(Clone)] pub struct PageIter { @@ -106,33 +63,33 @@ impl ActivePageTable { f: F) where F: FnOnce(&mut Mapper) { - let backup = Frame::containing_address(x86::cr3()); + let (cr3_back, cr3flags_back) = Cr3::read(); // map temp page to current p2 - let p2_table = temporary_page.map_table_frame(backup.clone(), self); + let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self); // overwrite recursive map - self.p2_mut()[1023].set(table.p2_frame.clone(), EntryFlags::PRESENT | EntryFlags::WRITABLE); - x86::tlb::flush_all(); + self.p2_mut()[1023].set(table.p2_frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE); + x86::instructions::tlb::flush_all(); // execute f in the new context f(self); // restore recursive mapping to original p2 table - p2_table[1023].set(backup, EntryFlags::PRESENT | EntryFlags::WRITABLE); + p2_table[1023].set(cr3_back, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); } pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { - let p2_frame = Frame::containing_address(x86::cr3() as usize); + let p2_frame = PhysFrame::containing_address(Cr3::read() as usize); let old_table = InactivePageTable { p2_frame, }; unsafe { - let frame = Frame::containing_address(new_table.p2_frame.start_address()); - x86::cr3_write(frame.start_address()); + let frame = PhysFrame::containing_address(new_table.p2_frame.start_address()); + Cr3::write(frame.start_address()); } old_table @@ -140,11 +97,11 @@ impl ActivePageTable { } pub struct InactivePageTable { - p2_frame: Frame, + p2_frame: PhysFrame, } impl InactivePageTable { - pub fn new(frame: Frame, + pub fn new(frame: PhysFrame, active_table: &mut ActivePageTable, temporary_page: &mut TemporaryPage, ) -> InactivePageTable { @@ -154,7 +111,7 @@ impl InactivePageTable { table.zero(); // set up recursive mapping for the table - table[1023].set(frame.clone(), EntryFlags::PRESENT | EntryFlags:: WRITABLE) + table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) } temporary_page.unmap(active_table); InactivePageTable { p2_frame: frame } @@ -176,33 +133,31 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) active_table.with(&mut new_table, &mut temporary_page, |mapper| { // identity map the VGA text buffer - let vga_buffer_frame = Frame::containing_address(0xb8000); - mapper.identity_map(vga_buffer_frame, EntryFlags::WRITABLE, allocator); + let vga_buffer_frame = PhysFrame::containing_address(0xb8000); + mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE, allocator); let elf_sections_tag = boot_info.elf_sections_tag() .expect("Memory map tag required"); for section in elf_sections_tag.sections() { - use self::entry::EntryFlags; - if !section.is_allocated() { continue; } assert!(section.start_address() % PAGE_SIZE as u64 == 0, "sections need to be page aligned"); - let flags = EntryFlags::from_elf_section_flags(§ion); - let start_frame = Frame::containing_address(section.start_address() as usize); - let end_frame = Frame::containing_address(section.end_address() as usize - 1); - for frame in Frame::range_inclusive(start_frame, end_frame) { + let flags = PageTableFlags::from_elf_section_flags(§ion); + let start_frame = PhysFrame::containing_address(section.start_address() as usize); + let end_frame = PhysFrame::containing_address(section.end_address() as usize - 1); + for frame in PhysFrame::range_inclusive(start_frame, end_frame) { mapper.identity_map(frame, flags, allocator); } } - let multiboot_start = Frame::containing_address(boot_info.start_address()); - let multiboot_end = Frame::containing_address(boot_info.end_address() - 1); - for frame in Frame::range_inclusive(multiboot_start, multiboot_end) { - mapper.identity_map(frame, EntryFlags::PRESENT, allocator); + let multiboot_start = PhysFrame::containing_address(boot_info.start_address()); + let multiboot_end = PhysFrame::containing_address(boot_info.end_address() - 1); + for frame in PhysFrame::range_inclusive(multiboot_start, multiboot_end) { + mapper.identity_map(frame, PageTableFlags::PRESENT, allocator); } }); diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index da35e011..d7aa7554 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -1,95 +1,32 @@ use memory::*; -use memory::paging::*; +use x86::structures::paging::*; -use core::ops::{Index, IndexMut}; -use core::marker::PhantomData; -// virtual address of P2 because its recursively mapped -// see protected mode Non-PAE -// https://wiki.osdev.org/Page_Tables -pub const P2: *mut Table = 0xffff_f000 as *mut _; - -pub struct Table { - entries: [Entry; ENTRY_COUNT], - level: PhantomData, -} - -impl Table where L: TableLevel +pub trait TableNext + where A: FrameAllocator { - pub fn zero(&mut self) { - for entry in self.entries.iter_mut() { - entry.set_unused(); - } - } -} - -impl Table where L: HierarchicalLevel -{ - fn next_table_address(&self, index: usize) -> Option { - let entry_flags = self[index].flags(); - if entry_flags.contains(EntryFlags::PRESENT) && !entry_flags.contains(EntryFlags::HUGE_PAGE) { - let table_address = self as *const _ as usize; - Some((table_address << 10) | (index << 12)) - } else { - None - } - } - - pub fn next_table(&self, index: usize) -> Option<&Table> { - self.next_table_address(index) - .map(|address| unsafe { &*(address as *const _) }) - } - - pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table> { - self.next_table_address(index) - .map(|address| unsafe { &mut *(address as *mut _) }) - } - - pub fn next_table_create(&mut self, + fn next_table_address(&self, index: usize) -> Option; + fn next_table(&self, index: usize) -> Option<&PageTable>; + fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>; + fn next_table_create(&mut self, index: usize, - allocator: &mut A) -> &mut Table + allocator: &mut A) -> &mut PageTable; +} + +impl TableNext<> for PageTable +{ + fn next_table_create(&mut self, + index: usize, + allocator: &mut A) -> &mut PageTable where A: FrameAllocator { if self.next_table(index).is_none() { - assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE), + assert!(!self[index].flags().contains(PageTableFlags::HUGE_PAGE), "mapping code does not support huge pages"); let frame = allocator.allocate_frame().expect("no frames available"); - self[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE); + self[index].set(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); self.next_table_mut(index).expect("next_table_mut gave None").zero() } self.next_table_mut(index).expect("no next table 2") } } - -impl Index for Table where L: TableLevel -{ - type Output = Entry; - - fn index(&self, index: usize) -> &Entry { - &self.entries[index] - } -} - -impl IndexMut for Table where L: TableLevel -{ - fn index_mut(&mut self, index: usize) -> &mut Entry { - &mut self.entries[index] - } -} - -pub trait TableLevel {} - -pub enum Level4 {} -pub enum Level3 {} -pub enum Level2 {} -pub enum Level1 {} - -impl TableLevel for Level4 {} -impl TableLevel for Level3 {} -impl TableLevel for Level2 {} -impl TableLevel for Level1 {} - -pub trait HierarchicalLevel: TableLevel { type NextLevel: TableLevel; } -impl HierarchicalLevel for Level4 { type NextLevel = Level3; } -impl HierarchicalLevel for Level3 { type NextLevel = Level2; } -impl HierarchicalLevel for Level2 { type NextLevel = Level1; } diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs index e098fef3..caab2d6a 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -1,6 +1,7 @@ -use super::{Page, ActivePageTable, VirtualAddress}; -use super::table::{Table, Level1}; -use memory::{Frame, FrameAllocator}; +use super::ActivePageTable; +use memory::{FrameAllocator}; +use x86::*; +use x86::structures::paging::*; pub struct TemporaryPage { page: Page, @@ -19,14 +20,12 @@ impl TemporaryPage { /// Maps the temporary page to the given frame in the active table. /// Returns the start address of the temporary page. - pub fn map(&mut self, frame: Frame, active_table: &mut ActivePageTable) - -> VirtualAddress + pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable) + -> VirtAddr { - use super::entry::EntryFlags; - assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped"); - active_table.map_to(self.page, frame, EntryFlags::WRITABLE, &mut self.allocator); + active_table.map_to(self.page, frame, PageTableFlags::WRITABLE, &mut self.allocator); self.page.start_address() } @@ -38,14 +37,14 @@ impl TemporaryPage { /// Maps the temporary page to the given page table frame in the active /// table. Returns a reference to the now mapped table. pub fn map_table_frame(&mut self, - frame: Frame, + frame: PhysFrame, active_table: &mut ActivePageTable) - -> &mut Table { - unsafe { &mut *(self.map(frame, active_table) as *mut Table) } + -> &mut PageTable { + unsafe { &mut *(self.map(frame, active_table) as *mut PageTable) } } } -struct TinyAllocator([Option; 1]); +struct TinyAllocator([Option; 1]); impl TinyAllocator { fn new(allocator: &mut A) -> TinyAllocator @@ -58,7 +57,7 @@ impl TinyAllocator { } impl FrameAllocator for TinyAllocator { - fn allocate_frame(&mut self) -> Option { + fn allocate_frame(&mut self) -> Option { for frame_option in &mut self.0 { if frame_option.is_some() { return frame_option.take(); @@ -67,7 +66,7 @@ impl FrameAllocator for TinyAllocator { None } - fn deallocate_frame(&mut self, frame: Frame) { + fn deallocate_frame(&mut self, frame: PhysFrame) { for frame_option in &mut self.0 { if frame_option.is_none() { *frame_option = Some(frame); diff --git a/kernel-rs/src/x86/mod.rs b/kernel-rs/src/x86/mod.rs deleted file mode 100644 index 7d9cf902..00000000 --- a/kernel-rs/src/x86/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! x86 (32 bit) only - -pub mod tlb; - -pub unsafe fn cr0_write(val: usize) { - asm!("mov $0, %cr0" :: "r"(val) : "memory"); -} - -pub fn cr0() -> usize { - let ret: usize; - unsafe { asm!("mov %cr0, $0" : "=r" (ret)) }; - ret -} - -pub fn cr3() -> usize { - let ret: usize; - unsafe { asm!("mov %cr3, $0" : "=r" (ret)) }; - ret -} - -pub fn cr4() -> usize { - let ret: usize; - unsafe { asm!("mov %cr4, $0" : "=r" (ret)) }; - ret -} - -pub unsafe fn cr3_write(val: usize) { - asm!("mov $0, %cr3" :: "r" (val) : "memory"); -} diff --git a/kernel-rs/src/x86/structures/idt.rs b/kernel-rs/src/x86/structures/idt.rs new file mode 100644 index 00000000..c8129caf --- /dev/null +++ b/kernel-rs/src/x86/structures/idt.rs @@ -0,0 +1,4 @@ +#[repr(C)] +pub struct Idt { + +} diff --git a/kernel-rs/src/x86/structures/mod.rs b/kernel-rs/src/x86/structures/mod.rs new file mode 100644 index 00000000..b00763f0 --- /dev/null +++ b/kernel-rs/src/x86/structures/mod.rs @@ -0,0 +1,3 @@ +pub mod idt; +// pub mod gdt; +// pub mod tss; diff --git a/kernel-rs/src/x86/tlb.rs b/kernel-rs/src/x86/tlb.rs deleted file mode 100644 index 1890ebaa..00000000 --- a/kernel-rs/src/x86/tlb.rs +++ /dev/null @@ -1,10 +0,0 @@ -use super::*; - -pub fn flush(addr: usize) { - unsafe { asm!("invlpg ($0)" :: "r"(addr) : "memory")} -} - -pub fn flush_all() { - let cr3 = cr3(); - unsafe { cr3_write(cr3); } -} diff --git a/kernel-rs/x86 b/kernel-rs/x86 new file mode 160000 index 00000000..dc9eb5ce --- /dev/null +++ b/kernel-rs/x86 @@ -0,0 +1 @@ +Subproject commit dc9eb5ceb8981848d95e0ddd7040fb86ec9999e3