Skip to content

Commit

Permalink
Add paging file in mem module
Browse files Browse the repository at this point in the history
  • Loading branch information
vinc committed Oct 20, 2024
1 parent 56737cb commit cf407c7
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 81 deletions.
62 changes: 1 addition & 61 deletions src/sys/mem/heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -52,65 +51,6 @@ pub fn init_heap() -> Result<(), MapToError<Size4KiB>> {
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<Size4KiB> = {
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()
}
Expand Down
25 changes: 5 additions & 20 deletions src/sys/mem/mod.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down Expand Up @@ -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),
))
};
Expand All @@ -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 {
Expand All @@ -97,21 +97,6 @@ pub fn virt_to_phys(addr: VirtAddr) -> Option<PhysAddr> {
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,
}
Expand Down
81 changes: 81 additions & 0 deletions src/sys/mem/paging.rs
Original file line number Diff line number Diff line change
@@ -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<Size4KiB> = {
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);
}
}
}

0 comments on commit cf407c7

Please sign in to comment.