From 0b38f701edd1aadd53f8e4916d8b15deee5baacc Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 13 Mar 2018 20:06:25 +0100 Subject: [PATCH 1/4] 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 From 8cf793260c5668281d0bda4505baaa33507495ab Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 14 Mar 2018 18:59:17 +0100 Subject: [PATCH 2/4] it compiles now with the new x86 lib, triple faults when setting temp page to zero though --- kernel-rs/src/console.rs | 2 +- kernel-rs/src/memory/area_allocator.rs | 25 ++-- kernel-rs/src/memory/mod.rs | 29 +---- kernel-rs/src/memory/paging/mapper.rs | 23 +++- kernel-rs/src/memory/paging/mod.rs | 110 ++++++++++-------- kernel-rs/src/memory/paging/table.rs | 44 +++++-- kernel-rs/src/memory/paging/temporary_page.rs | 9 +- kernel-rs/x86 | 2 +- 8 files changed, 141 insertions(+), 103 deletions(-) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index fa9f34ca..6ababe05 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -178,7 +178,7 @@ pub fn acpi_info() -> Result <(), &'static str> { pub fn regs() -> Result <(), &'static str> { use x86::registers::control::*; println!("cr0={:#b}", Cr0::read()); - println!("cr3={:#x}", Cr3::read()); + println!("cr3={:?}", Cr3::read()); // TODO implement cr4 flags in `x86` module // println!("cr4={:#b}", Cr4::read()); Ok(()) diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/area_allocator.rs index 011f6cb4..6a24bb94 100644 --- a/kernel-rs/src/memory/area_allocator.rs +++ b/kernel-rs/src/memory/area_allocator.rs @@ -1,5 +1,6 @@ use memory::*; use multiboot2::{MemoryAreaIter, MemoryArea}; +use x86::*; pub struct AreaFrameAllocator { next_free_frame: PhysFrame, @@ -16,13 +17,17 @@ impl AreaFrameAllocator { multiboot_start: usize, multiboot_end: usize, memory_areas: MemoryAreaIter) -> AreaFrameAllocator { let mut allocator = AreaFrameAllocator { - next_free_frame: PhysFrame::containing_address(0), + next_free_frame: PhysFrame { number: 0 }, current_area: None, areas: memory_areas, - 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), + kernel_start: PhysFrame::containing_address( + PhysAddr::new(kernel_start as u32)), + kernel_end: PhysFrame::containing_address( + PhysAddr::new(kernel_end as u32)), + multiboot_start: PhysFrame::containing_address( + PhysAddr::new(multiboot_start as u32)), + multiboot_end: PhysFrame::containing_address( + PhysAddr::new(multiboot_end as u32)), }; allocator.choose_next_area(); allocator @@ -31,11 +36,12 @@ impl AreaFrameAllocator { fn choose_next_area(&mut self) { // get next area with free frames self.current_area = self.areas.clone().filter(|area| { - PhysFrame::containing_address(area.end_address()) >= self.next_free_frame + area.end_address() >= self.next_free_frame.start_address().as_u32() as usize }).min_by_key(|area| area.start_address()); if let Some(area) = self.current_area { - let start_frame = PhysFrame::containing_address(area.start_address()); + let start_frame = PhysFrame::containing_address( + PhysAddr::new(area.start_address() as u32)); if self.next_free_frame < start_frame { self.next_free_frame = start_frame; } @@ -45,9 +51,10 @@ impl AreaFrameAllocator { impl FrameAllocator for AreaFrameAllocator { fn allocate_frame(&mut self) -> Option { - if let Some(area) = self.current_arPhysea { + if let Some(area) = self.current_area { let frame = PhysFrame { number: self.next_free_frame.number }; - let current_area_last_frame = PhysFrame::containing_address(area.end_address()); + let current_area_last_frame = PhysFrame::containing_address( + PhysAddr::new(area.end_address() as u32)); if frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 89568f0b..c2a6c244 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -8,7 +8,7 @@ pub use self::area_allocator::*; pub use self::heap_allocator::*; pub use self::paging::remap_the_kernel; use multiboot2; - +use x86::*; use x86::structures::paging::*; pub trait FrameAllocator { @@ -16,25 +16,6 @@ pub trait FrameAllocator { fn deallocate_frame(&mut self, frame: PhysFrame); } -struct FrameIter { - start: PhysFrame, - end: PhysFrame, -} - -impl Iterator for FrameIter { - type Item = PhysFrame; - - fn next(&mut self) -> Option { - if self.start <= self.end { - let frame = self.start.clone(); - self.start.number += 1; - Some(frame) - } else { - None - } - } -} - /// memory initialisation should only be called once pub fn init(boot_info: &multiboot2::BootInformation) { let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); @@ -59,10 +40,12 @@ pub fn init(boot_info: &multiboot2::BootInformation) { boot_info); 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); + let heap_start_page = Page::containing_address( + VirtAddr::new(HEAP_START as u32)); + let heap_end_page = Page::containing_address( + VirtAddr::new(HEAP_START as u32 + HEAP_SIZE as u32 - 1)); - for page in Page::range_inclusive(heap_start_page, heap_end_page) { + for page in heap_start_page..heap_end_page { active_table.map(page, PageTableFlags::WRITABLE, &mut frame_allocator); } } diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index 27800c23..d8be6889 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -3,7 +3,8 @@ use core::ptr::Unique; use x86::structures::paging::*; use x86::instructions::tlb; use x86::*; -// +use super::paging::table::RecTable; + // virtual address of recursively mapped P2 // for protected mode non PAE // https://wiki.osdev.org/Page_Tables @@ -29,6 +30,7 @@ impl Mapper { unsafe { self.p2.as_mut() } } + /// virtual addr to physical addr translation pub fn translate(&self, virtual_address: VirtAddr) -> Option { let offset = virtual_address.as_u32() % PAGE_SIZE as u32; @@ -37,15 +39,26 @@ impl Mapper { } + /// virtual page to physical frame translation 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(PageTableFlags::HUGE_PAGE) { + // TODO 4MiB alignment check + return Some(start_frame + u32::from(page.p1_index())); + } + } + None + }; - p1.and_then() + p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) + .or_else(huge_page) } - + /// map a virtual page to a physical frame in the page tables pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags, allocator: &mut A) where A: FrameAllocator diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index c5363e1e..39785015 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -// mod table; +mod table; mod temporary_page; mod mapper; @@ -9,28 +9,9 @@ use self::mapper::Mapper; use self::temporary_page::TemporaryPage; use core::ops::{Deref, DerefMut}; use multiboot2::BootInformation; -use x86; +use x86::*; use x86::registers::control::Cr3; - -#[derive(Clone)] -pub struct PageIter { - start: Page, - end: Page, -} - -impl Iterator for PageIter { - type Item = Page; - - fn next(&mut self) -> Option { - if self.start <= self.end { - let page = self.start; - self.start.number += 1; - Some(page) - } else { - None - } - } -} +use x86::instructions::tlb; pub struct ActivePageTable { mapper: Mapper, @@ -63,14 +44,14 @@ impl ActivePageTable { f: F) where F: FnOnce(&mut Mapper) { - let (cr3_back, cr3flags_back) = Cr3::read(); + let (cr3_back, _cr3flags_back) = Cr3::read(); // map temp page to current p2 let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self); // overwrite recursive map self.p2_mut()[1023].set(table.p2_frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE); - x86::instructions::tlb::flush_all(); + tlb::flush_all(); // execute f in the new context f(self); @@ -80,17 +61,9 @@ impl ActivePageTable { } pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { - - let p2_frame = PhysFrame::containing_address(Cr3::read() as usize); - - let old_table = InactivePageTable { - p2_frame, - }; - - unsafe { - let frame = PhysFrame::containing_address(new_table.p2_frame.start_address()); - Cr3::write(frame.start_address()); - } + let (p2_frame, cr3_flags) = Cr3::read(); + let old_table = InactivePageTable { p2_frame }; + unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } old_table } @@ -103,19 +76,27 @@ pub struct InactivePageTable { impl InactivePageTable { pub fn new(frame: PhysFrame, active_table: &mut ActivePageTable, - temporary_page: &mut TemporaryPage, - ) -> InactivePageTable { + temporary_page: &mut TemporaryPage) + -> InactivePageTable { { - let table = temporary_page.map_table_frame(frame.clone(), - active_table); - table.zero(); + let table = temporary_page.map_table_frame(frame.clone(), active_table); + // table.zero(); + let iter = table.entries.iter_mut(); + for entry in iter { + println!("entry = {:?}", entry as *const _); + // println!("entry = {:?}", entry.flags()); + } + + println!("frame = {:?}", frame); + flush!(); + loop {} // set up recursive mapping for the table table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) } temporary_page.unmap(active_table); InactivePageTable { p2_frame: frame } - } + } } pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) @@ -133,7 +114,7 @@ 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 = PhysFrame::containing_address(0xb8000); + let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE, allocator); let elf_sections_tag = boot_info.elf_sections_tag() @@ -146,24 +127,53 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) assert!(section.start_address() % PAGE_SIZE as u64 == 0, "sections need to be page aligned"); - 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) { + let flags = elf_to_pagetable_flags(§ion.flags()); + let start_frame = PhysFrame::containing_address( + PhysAddr::new(section.start_address() as u32)); + let end_frame = PhysFrame::containing_address( + PhysAddr::new(section.end_address() as u32 - 1)); + for frame in start_frame..end_frame { mapper.identity_map(frame, flags, 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) { + let multiboot_start = PhysFrame::containing_address( + PhysAddr::new(boot_info.start_address() as u32)); + let multiboot_end = PhysFrame::containing_address( + PhysAddr::new(boot_info.end_address() as u32 - 1)); + for frame in multiboot_start..multiboot_end { mapper.identity_map(frame, PageTableFlags::PRESENT, allocator); } }); + let old_table = active_table.switch(new_table); - let old_p2_page = Page::containing_address(old_table.p2_frame.start_address()); + let old_p2_page = Page::containing_address( + VirtAddr::new(old_table.p2_frame.start_address().as_u32())); active_table.unmap(old_p2_page, allocator); active_table } + +fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) + -> PageTableFlags +{ + use multiboot2::ElfSectionFlags; + + let mut flags = PageTableFlags::empty(); + + if elf_flags.contains(ElfSectionFlags::ALLOCATED) { + // section is loaded to memory + flags = flags | PageTableFlags::PRESENT; + } + if elf_flags.contains(ElfSectionFlags::WRITABLE) { + flags = flags | PageTableFlags::WRITABLE; + } + + // LONG MODE STUFF + // if !elf_flags.contains(ELF_SECTION_EXECUTABLE) { + // flags = flags | PageTableFlags::NO_EXECUTE; + // } + + flags +} diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index d7aa7554..916813c9 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -1,23 +1,43 @@ use memory::*; use x86::structures::paging::*; +use x86::ux::*; - -pub trait TableNext - where A: FrameAllocator +pub trait RecTable { - 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 PageTable; + fn next_table_address(&self, index: u10) -> Option; + fn next_table(&self, index: u10) -> Option<&PageTable>; + fn next_table_mut(&mut self, index: u10) -> Option<&mut PageTable>; + fn next_table_create(&mut self, + index: u10, + allocator: &mut A) + -> &mut PageTable; } -impl TableNext<> for PageTable +impl RecTable for PageTable { + fn next_table_address(&self, index: u10) -> Option { + let entry_flags = self[index].flags(); + if entry_flags.contains(PageTableFlags::PRESENT) && !entry_flags.contains(PageTableFlags::HUGE_PAGE) { + let table_address = self as *const _ as u32; + Some(table_address << 10 | u32::from(index << 12)) + } else { + None + } + } + + fn next_table(&self, index: u10) -> Option<&PageTable> { + self.next_table_address(index) + .map(|address| unsafe { &*(address as *const _) }) + } + + fn next_table_mut(&mut self, index: u10) -> Option<&mut PageTable> { + self.next_table_address(index) + .map(|address| unsafe { &mut *(address as *mut _) }) + } + fn next_table_create(&mut self, - index: usize, - allocator: &mut A) -> &mut PageTable + index: u10, + allocator: &mut A) -> &mut PageTable where A: FrameAllocator { if self.next_table(index).is_none() { diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs index caab2d6a..709fcbfb 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -4,7 +4,7 @@ use x86::*; use x86::structures::paging::*; pub struct TemporaryPage { - page: Page, + pub page: Page, allocator: TinyAllocator, } @@ -26,6 +26,11 @@ impl TemporaryPage { assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped"); active_table.map_to(self.page, frame, PageTableFlags::WRITABLE, &mut self.allocator); + // this kind of check should be done in a test routine + assert!(active_table.translate_page(self.page).is_some(), + "temporary page was not mapped"); + println!("trans = {:?}", active_table.translate_page(self.page)); + println!("page = {:?}", self.page.start_address()); self.page.start_address() } @@ -40,7 +45,7 @@ impl TemporaryPage { frame: PhysFrame, active_table: &mut ActivePageTable) -> &mut PageTable { - unsafe { &mut *(self.map(frame, active_table) as *mut PageTable) } + unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) } } } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index dc9eb5ce..eae47083 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit dc9eb5ceb8981848d95e0ddd7040fb86ec9999e3 +Subproject commit eae470839b1ff232dbc4af5389e9a0b4fffe4b30 From 5c2b5f723b3f348a4cf9cf63b24a731c18747b96 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 15 Mar 2018 17:16:01 +0100 Subject: [PATCH 3/4] yuesterdays problem solved, now i triple fault on write to CR3, fun --- kernel-rs/src/memory/paging/mapper.rs | 10 ++--- kernel-rs/src/memory/paging/mod.rs | 38 ++++++++++++------- kernel-rs/src/memory/paging/table.rs | 20 +++++----- kernel-rs/src/memory/paging/temporary_page.rs | 2 - 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index d8be6889..408149ee 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -2,6 +2,7 @@ use memory::{PAGE_SIZE, FrameAllocator}; use core::ptr::Unique; use x86::structures::paging::*; use x86::instructions::tlb; +use x86::usize_conversions::usize_from; use x86::*; use super::paging::table::RecTable; @@ -41,7 +42,7 @@ impl Mapper { /// virtual page to physical frame translation pub fn translate_page(&self, page: Page) -> Option { - let p1 = self.p2().next_table(page.p2_index()); + let p1 = self.p2().next_table(usize_from(u32::from(page.p2_index()))); let huge_page = || { let p2_entry = &self.p2()[page.p2_index()]; @@ -55,7 +56,7 @@ impl Mapper { }; p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) - .or_else(huge_page) + .or_else(huge_page) } /// map a virtual page to a physical frame in the page tables @@ -64,8 +65,7 @@ impl Mapper { where A: FrameAllocator { let p2 = self.p2_mut(); - let p1 = p2.next_table_create(page.p2_index(), allocator); - + let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index())), allocator); assert!(p1[page.p1_index()].is_unused()); p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT); } @@ -91,7 +91,7 @@ impl Mapper { assert!(self.translate(page.start_address()).is_some()); let p1 = self.p2_mut() - .next_table_mut(page.p2_index()) + .next_table_mut(usize_from(u32::from(page.p2_index()))) .expect("mapping code does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 39785015..ce5a9bee 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -61,9 +61,23 @@ impl ActivePageTable { } pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { + let (p2_frame, cr3_flags) = Cr3::read(); let old_table = InactivePageTable { p2_frame }; - unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } + + // unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } + + ::console::regs(); + flush!(); + loop {} + + unsafe { asm!("mov $0, %cr3" :: "r" (4096) : "memory"); } + + // let addr = new_table.p2_frame.start_address(); + // let value = addr.as_u32() | cr3_flags.bits(); + // println!("value = {}", 0); + // flush!(); + // loop {} old_table } @@ -81,16 +95,7 @@ impl InactivePageTable { { let table = temporary_page.map_table_frame(frame.clone(), active_table); - // table.zero(); - let iter = table.entries.iter_mut(); - for entry in iter { - println!("entry = {:?}", entry as *const _); - // println!("entry = {:?}", entry.flags()); - } - - println!("frame = {:?}", frame); - flush!(); - loop {} + table.zero(); // set up recursive mapping for the table table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) } @@ -103,14 +108,14 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) -> ActivePageTable where A: FrameAllocator { - let mut temporary_page = TemporaryPage::new(Page { number: 0xcafe }, - allocator); + let mut temporary_page = TemporaryPage::new(Page{number: 0xcafe}, allocator); let mut active_table = unsafe { ActivePageTable::new() }; let mut new_table = { let frame = allocator.allocate_frame().expect("no more frames"); InactivePageTable::new(frame, &mut active_table, &mut temporary_page) }; + active_table.with(&mut new_table, &mut temporary_page, |mapper| { // identity map the VGA text buffer @@ -146,12 +151,17 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) } }); - let old_table = active_table.switch(new_table); + + println!("check!"); + flush!(); + loop {} + let old_p2_page = Page::containing_address( VirtAddr::new(old_table.p2_frame.start_address().as_u32())); active_table.unmap(old_p2_page, allocator); + active_table } diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index 916813c9..16060b05 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -4,39 +4,39 @@ use x86::ux::*; pub trait RecTable { - fn next_table_address(&self, index: u10) -> Option; - fn next_table(&self, index: u10) -> Option<&PageTable>; - fn next_table_mut(&mut self, index: u10) -> Option<&mut PageTable>; + 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: u10, + index: usize, allocator: &mut A) -> &mut PageTable; } impl RecTable for PageTable { - fn next_table_address(&self, index: u10) -> Option { + fn next_table_address(&self, index: usize) -> Option { let entry_flags = self[index].flags(); if entry_flags.contains(PageTableFlags::PRESENT) && !entry_flags.contains(PageTableFlags::HUGE_PAGE) { - let table_address = self as *const _ as u32; - Some(table_address << 10 | u32::from(index << 12)) + let table_address = self as *const _ as usize; + Some((table_address << 10 | index << 12) as u32) } else { None } } - fn next_table(&self, index: u10) -> Option<&PageTable> { + fn next_table(&self, index: usize) -> Option<&PageTable> { self.next_table_address(index) .map(|address| unsafe { &*(address as *const _) }) } - fn next_table_mut(&mut self, index: u10) -> Option<&mut PageTable> { + fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable> { self.next_table_address(index) .map(|address| unsafe { &mut *(address as *mut _) }) } fn next_table_create(&mut self, - index: u10, + index: usize, allocator: &mut A) -> &mut PageTable where A: FrameAllocator { diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs index 709fcbfb..33756ba0 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -29,8 +29,6 @@ impl TemporaryPage { // this kind of check should be done in a test routine assert!(active_table.translate_page(self.page).is_some(), "temporary page was not mapped"); - println!("trans = {:?}", active_table.translate_page(self.page)); - println!("page = {:?}", self.page.start_address()); self.page.start_address() } From ed03d247c715bb3111b45532eef9f91fb89c0bc2 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 19 Mar 2018 12:14:30 +0100 Subject: [PATCH 4/4] it works:))) --- kernel-rs/src/console.rs | 2 +- kernel-rs/src/lib.rs | 13 +--------- kernel-rs/src/memory/paging/mod.rs | 39 +++++++++--------------------- 3 files changed, 13 insertions(+), 41 deletions(-) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 6ababe05..4ffcdd54 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -179,8 +179,8 @@ pub fn regs() -> Result <(), &'static str> { use x86::registers::control::*; println!("cr0={:#b}", Cr0::read()); println!("cr3={:?}", Cr3::read()); + flush!(); // 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 1303e417..8cf31d6e 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -34,23 +34,12 @@ pub mod memory; pub extern fn kmain(multiboot_info_addr: usize) -> ! { // acpi::init().unwrap(); let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; + enable_write_protect_bit(); memory::init(&boot_info); vga::init(); - use alloc::boxed::Box; - let mut heap_test = Box::new(42); - *heap_test -= 15; - let heap_test2 = Box::new("Hello"); - println!("{:?} {:?}", heap_test, heap_test2); - - let mut vec_test = vec![1,2,3,4,5,6,7]; - vec_test[3] = 42; - for i in &vec_test { - print!("{} ", i); - } - loop { keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index ce5a9bee..5b3fbd67 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -65,19 +65,7 @@ impl ActivePageTable { let (p2_frame, cr3_flags) = Cr3::read(); let old_table = InactivePageTable { p2_frame }; - // unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } - - ::console::regs(); - flush!(); - loop {} - - unsafe { asm!("mov $0, %cr3" :: "r" (4096) : "memory"); } - - // let addr = new_table.p2_frame.start_address(); - // let value = addr.as_u32() | cr3_flags.bits(); - // println!("value = {}", 0); - // flush!(); - // loop {} + unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } old_table } @@ -92,15 +80,15 @@ impl InactivePageTable { active_table: &mut ActivePageTable, temporary_page: &mut TemporaryPage) -> InactivePageTable { - { - let table = temporary_page.map_table_frame(frame.clone(), active_table); + { + let table = temporary_page.map_table_frame(frame.clone(), active_table); - table.zero(); - // set up recursive mapping for the table - table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) - } - temporary_page.unmap(active_table); - InactivePageTable { p2_frame: frame } + table.zero(); + // set up recursive mapping for the table + table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) + } + temporary_page.unmap(active_table); + InactivePageTable { p2_frame: frame } } } @@ -137,7 +125,7 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) PhysAddr::new(section.start_address() as u32)); let end_frame = PhysFrame::containing_address( PhysAddr::new(section.end_address() as u32 - 1)); - for frame in start_frame..end_frame { + for frame in start_frame..end_frame + 1 { mapper.identity_map(frame, flags, allocator); } } @@ -146,17 +134,13 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) PhysAddr::new(boot_info.start_address() as u32)); let multiboot_end = PhysFrame::containing_address( PhysAddr::new(boot_info.end_address() as u32 - 1)); - for frame in multiboot_start..multiboot_end { + for frame in multiboot_start..multiboot_end + 1 { mapper.identity_map(frame, PageTableFlags::PRESENT, allocator); } }); let old_table = active_table.switch(new_table); - println!("check!"); - flush!(); - loop {} - let old_p2_page = Page::containing_address( VirtAddr::new(old_table.p2_frame.start_address().as_u32())); @@ -179,7 +163,6 @@ fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) if elf_flags.contains(ElfSectionFlags::WRITABLE) { flags = flags | PageTableFlags::WRITABLE; } - // LONG MODE STUFF // if !elf_flags.contains(ELF_SECTION_EXECUTABLE) { // flags = flags | PageTableFlags::NO_EXECUTE;