diff --git a/src/sys/mem/heap.rs b/src/sys/mem/heap.rs index ba380c17..cdbe5836 100644 --- a/src/sys/mem/heap.rs +++ b/src/sys/mem/heap.rs @@ -3,8 +3,7 @@ use crate::sys; use core::cmp; use linked_list_allocator::LockedHeap; use x86_64::structures::paging::{ - mapper::MapToError, page::PageRangeInclusive, - FrameAllocator, Mapper, OffsetPageTable, Page, PageTableFlags, Size4KiB, + mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB }; use x86_64::VirtAddr; @@ -52,65 +51,6 @@ pub fn init_heap() -> Result<(), MapToError> { Ok(()) } -pub fn alloc_pages( - mapper: &mut OffsetPageTable, addr: u64, size: usize -) -> Result<(), ()> { - let size = size.saturating_sub(1) as u64; - let mut frame_allocator = sys::mem::frame_allocator(); - - let pages = { - let start_page = Page::containing_address(VirtAddr::new(addr)); - let end_page = Page::containing_address(VirtAddr::new(addr + size)); - Page::range_inclusive(start_page, end_page) - }; - - let flags = PageTableFlags::PRESENT - | PageTableFlags::WRITABLE - | PageTableFlags::USER_ACCESSIBLE; - - for page in pages { - if let Some(frame) = frame_allocator.allocate_frame() { - let res = unsafe { - mapper.map_to(page, frame, flags, &mut frame_allocator) - }; - if let Ok(mapping) = res { - //debug!("Mapped {:?} to {:?}", page, frame); - mapping.flush(); - } else { - debug!("Could not map {:?} to {:?}", page, frame); - if let Ok(old_frame) = mapper.translate_page(page) { - debug!("Already mapped to {:?}", old_frame); - } - return Err(()); - } - } else { - debug!("Could not allocate frame for {:?}", page); - return Err(()); - } - } - - Ok(()) -} - -// TODO: Replace `free` by `dealloc` -pub fn free_pages(mapper: &mut OffsetPageTable, addr: u64, size: usize) { - let size = size.saturating_sub(1) as u64; - - let pages: PageRangeInclusive = { - let start_page = Page::containing_address(VirtAddr::new(addr)); - let end_page = Page::containing_address(VirtAddr::new(addr + size)); - Page::range_inclusive(start_page, end_page) - }; - - for page in pages { - if let Ok((_, mapping)) = mapper.unmap(page) { - mapping.flush(); - } else { - //debug!("Could not unmap {:?}", page); - } - } -} - pub fn heap_size() -> usize { ALLOCATOR.lock().size() } diff --git a/src/sys/mem/mod.rs b/src/sys/mem/mod.rs index 58b95cbf..ae8a0c0d 100644 --- a/src/sys/mem/mod.rs +++ b/src/sys/mem/mod.rs @@ -1,16 +1,16 @@ mod heap; +mod paging; mod phys; -pub use heap::{alloc_pages, free_pages}; +pub use paging::{alloc_pages, free_pages, active_page_table, create_page_table}; pub use phys::{phys_addr, PhysBuf}; use crate::sys; use bootloader::bootinfo::{BootInfo, MemoryMap, MemoryRegionType}; use core::sync::atomic::{AtomicUsize, Ordering}; //use x86_64::instructions::interrupts; -use x86_64::registers::control::Cr3; use x86_64::structures::paging::{ - FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB, Translate, + FrameAllocator, OffsetPageTable, PhysFrame, Size4KiB, Translate, }; use x86_64::{PhysAddr, VirtAddr}; @@ -60,7 +60,7 @@ pub fn init(boot_info: &'static BootInfo) { unsafe { MEMORY_MAP.replace(&boot_info.memory_map) }; unsafe { MAPPER.replace(OffsetPageTable::new( - active_page_table(), + paging::active_page_table(), VirtAddr::new(phys_mem_offset), )) }; @@ -71,7 +71,7 @@ pub fn init(boot_info: &'static BootInfo) { } pub fn mapper() -> &'static mut OffsetPageTable<'static> { - unsafe { sys::mem::MAPPER.as_mut().unwrap() } + unsafe { MAPPER.as_mut().unwrap() } } pub fn memory_size() -> usize { @@ -97,21 +97,6 @@ pub fn virt_to_phys(addr: VirtAddr) -> Option { mapper().translate_addr(addr) } -pub unsafe fn active_page_table() -> &'static mut PageTable { - let (frame, _) = Cr3::read(); - let phys_addr = frame.start_address(); - let virt_addr = phys_to_virt(phys_addr); - let page_table_ptr: *mut PageTable = virt_addr.as_mut_ptr(); - &mut *page_table_ptr // unsafe -} - -pub unsafe fn create_page_table(frame: PhysFrame) -> &'static mut PageTable { - let phys_addr = frame.start_address(); - let virt_addr = phys_to_virt(phys_addr); - let page_table_ptr: *mut PageTable = virt_addr.as_mut_ptr(); - &mut *page_table_ptr // unsafe -} - pub struct BootInfoFrameAllocator { memory_map: &'static MemoryMap, } diff --git a/src/sys/mem/paging.rs b/src/sys/mem/paging.rs new file mode 100644 index 00000000..85b4cfec --- /dev/null +++ b/src/sys/mem/paging.rs @@ -0,0 +1,81 @@ +use x86_64::registers::control::Cr3; +use x86_64::structures::paging::{ + page::PageRangeInclusive, + OffsetPageTable, PageTable, PhysFrame, Size4KiB, + Page, PageTableFlags, Mapper, FrameAllocator, +}; +use x86_64::VirtAddr; + +pub unsafe fn active_page_table() -> &'static mut PageTable { + let (frame, _) = Cr3::read(); + let phys_addr = frame.start_address(); + let virt_addr = super::phys_to_virt(phys_addr); + let page_table_ptr: *mut PageTable = virt_addr.as_mut_ptr(); + &mut *page_table_ptr // unsafe +} + +pub unsafe fn create_page_table(frame: PhysFrame) -> &'static mut PageTable { + let phys_addr = frame.start_address(); + let virt_addr = super::phys_to_virt(phys_addr); + let page_table_ptr: *mut PageTable = virt_addr.as_mut_ptr(); + &mut *page_table_ptr // unsafe +} + +pub fn alloc_pages( + mapper: &mut OffsetPageTable, addr: u64, size: usize +) -> Result<(), ()> { + let size = size.saturating_sub(1) as u64; + let mut frame_allocator = super::frame_allocator(); + + let pages = { + let start_page = Page::containing_address(VirtAddr::new(addr)); + let end_page = Page::containing_address(VirtAddr::new(addr + size)); + Page::range_inclusive(start_page, end_page) + }; + + let flags = PageTableFlags::PRESENT + | PageTableFlags::WRITABLE + | PageTableFlags::USER_ACCESSIBLE; + + for page in pages { + if let Some(frame) = frame_allocator.allocate_frame() { + let res = unsafe { + mapper.map_to(page, frame, flags, &mut frame_allocator) + }; + if let Ok(mapping) = res { + //debug!("Mapped {:?} to {:?}", page, frame); + mapping.flush(); + } else { + debug!("Could not map {:?} to {:?}", page, frame); + if let Ok(old_frame) = mapper.translate_page(page) { + debug!("Already mapped to {:?}", old_frame); + } + return Err(()); + } + } else { + debug!("Could not allocate frame for {:?}", page); + return Err(()); + } + } + + Ok(()) +} + +// TODO: Replace `free` by `dealloc` +pub fn free_pages(mapper: &mut OffsetPageTable, addr: u64, size: usize) { + let size = size.saturating_sub(1) as u64; + + let pages: PageRangeInclusive = { + let start_page = Page::containing_address(VirtAddr::new(addr)); + let end_page = Page::containing_address(VirtAddr::new(addr + size)); + Page::range_inclusive(start_page, end_page) + }; + + for page in pages { + if let Ok((_, mapping)) = mapper.unmap(page) { + mapping.flush(); + } else { + //debug!("Could not unmap {:?}", page); + } + } +}