Skip to content

Commit

Permalink
Mem: Continue work on vm manager for processes
Browse files Browse the repository at this point in the history
  • Loading branch information
corigan01 committed Jan 21, 2025
1 parent 5391e07 commit 4b6b440
Show file tree
Hide file tree
Showing 9 changed files with 324 additions and 267 deletions.
9 changes: 9 additions & 0 deletions crates/elf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA

#![no_std]

use core::fmt::Display;

#[cfg(feature = "alloc")]
pub mod elf_owned;
pub mod tables;
Expand All @@ -37,6 +39,13 @@ pub enum ElfErrorKind {
Invalid,
}

impl core::error::Error for ElfErrorKind {}
impl Display for ElfErrorKind {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "Elf failed : {:?}", self)
}
}

pub type Result<T> = core::result::Result<T, ElfErrorKind>;

// TODO: Add 'loader' trait for calling code when a section needs to be loaded
Expand Down
15 changes: 15 additions & 0 deletions crates/mem/src/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ impl<S: PagingStructureSize> PhysPage<S> {
pub const fn page(&self) -> usize {
self.id
}

/// Check if this address is contained within this page
pub fn is_addr_contained_in_page(&self, addr: PhysAddr) -> bool {
self.addr() <= addr && self.addr().offset(S::N_BYTES) >= addr
}
}

/// A structure representing a well aligned Virtual page
Expand Down Expand Up @@ -233,6 +238,11 @@ impl<S: PagingStructureSize> VirtPage<S> {
(lhs.id - self.id) * S::N_BYTES
}

/// Offset this page by an offset of pages
pub const fn offset_by(self, offset: usize) -> Self {
Self::new(self.id + offset)
}

/// Get the distance (in pages) from `self` to `lhs`.
///
/// # Note
Expand All @@ -246,6 +256,11 @@ impl<S: PagingStructureSize> VirtPage<S> {
pub const fn page(&self) -> usize {
self.id
}

/// Check if this address is contained within this page
pub fn is_addr_contained_in_page(&self, addr: VirtAddr) -> bool {
self.addr() <= addr && self.addr().offset(S::N_BYTES) >= addr
}
}

macro_rules! impl_traits_for {
Expand Down
37 changes: 33 additions & 4 deletions crates/mem/src/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
*/

extern crate alloc;
use core::ops::{BitOr, BitOrAssign};
use core::ops::{Add, AddAssign, BitOr, BitOrAssign};

use crate::{
addr::{PhysAddr, VirtAddr},
Expand Down Expand Up @@ -869,6 +869,20 @@ impl VmOptions {
}
}

impl Add for VmPermissions {
type Output = VmPermissions;

fn add(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}

impl AddAssign for VmPermissions {
fn add_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}

impl core::fmt::Debug for VmPermissions {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("VmPermissions")
Expand Down Expand Up @@ -1032,8 +1046,13 @@ impl SafePageMapLvl4 {
index < 512,
"Table index ({index}) was out of range for a PageTable (max=512)!"
);
let is_zero = self.lower[index].is_none();
let table_mut = self.lower[index].get_or_insert_with(|| Box::new(SafePageMapLvl3::empty()));
let mut entry_mut = self.table.get(index);
let mut entry_mut = if is_zero {
PageEntryLvl4::zero()
} else {
self.table.get(index)
};

let reponse = f(&mut entry_mut, table_mut);

Expand Down Expand Up @@ -1081,8 +1100,13 @@ impl SafePageMapLvl3 {
index < 512,
"Table index ({index}) was out of range for a PageTable (max=512)!"
);
let is_zero = self.lower[index].is_none();
let table_mut = self.lower[index].get_or_insert_with(|| Box::new(SafePageMapLvl2::empty()));
let mut entry_mut = self.table.get(index);
let mut entry_mut = if is_zero {
PageEntryLvl3::zero()
} else {
self.table.get(index)
};

let reponse = f(&mut entry_mut, table_mut);

Expand Down Expand Up @@ -1130,8 +1154,13 @@ impl SafePageMapLvl2 {
index < 512,
"Table index ({index}) was out of range for a PageTable (max=512)!"
);
let is_zero = self.lower[index].is_none();
let table_mut = self.lower[index].get_or_insert_with(|| Box::new(SafePageMapLvl1::empty()));
let mut entry_mut = self.table.get(index);
let mut entry_mut = if is_zero {
PageEntryLvl2::zero()
} else {
self.table.get(index)
};

let reponse = f(&mut entry_mut, table_mut);

Expand Down
107 changes: 64 additions & 43 deletions crates/mem/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use core::{error::Error, fmt::Display};
use crate::{
MemoryError,
addr::{AlignedTo, VirtAddr},
page::{Page4K, PhysPage, VirtPage},
page::{PhysPage, VirtPage},
paging::{PageCorrelationError, Virt2PhysMapping, VmOptions, VmPermissions},
pmm::SharedPhysPage,
};
Expand All @@ -41,8 +41,8 @@ use util::consts::PAGE_4K;
/// A region of virtual memory 'virtual in pages'
#[derive(Debug, Clone, Copy)]
pub struct VmRegion {
start: VirtPage,
end: VirtPage,
pub start: VirtPage,
pub end: VirtPage,
}

impl VmRegion {
Expand Down Expand Up @@ -101,6 +101,8 @@ pub enum PopulationReponse {
Okay,
/// There was a problem mapping this page
MappingError(PageCorrelationError),
/// There was a problem mapping this page in the Inject action
InjectError(Box<dyn Error>),
}

pub trait VmInjectFillAction: core::fmt::Debug {
Expand Down Expand Up @@ -149,7 +151,7 @@ pub trait VmInjectFillAction: core::fmt::Debug {
}

/// What to do with this VmObject's memory. How should it be filled?
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum VmFillAction {
/// Don't do anything after allocating a physical page
Nothing,
Expand All @@ -159,6 +161,13 @@ pub enum VmFillAction {
InjectWith(Arc<RwLock<dyn VmInjectFillAction>>),
}

impl VmFillAction {
/// Convert a VmInjectFillAction into a VmFillAction
pub fn convert(thing: impl VmInjectFillAction + 'static) -> Self {
Self::InjectWith(Arc::new(RwLock::new(thing)))
}
}

/// Scrub the vpage's memory with the given pattern.
///
/// The vpage must be kernel accessable before calling this function.
Expand Down Expand Up @@ -267,6 +276,8 @@ pub enum NewVmObjectError {
/// The type of error given when trying to map a page with a VmObject
#[derive(Debug)]
pub enum VmObjectMappingError {
/// We cannot populate a page if this table is not loaded
PageTableNotLoaded,
/// Cannot map this page
MappingError(PageCorrelationError),
/// Failed to get a physical page
Expand All @@ -276,6 +287,8 @@ pub enum VmObjectMappingError {
region: VmRegion,
requested_vpage: VirtPage,
},
/// There was a problem populating this entry
InjectError(Box<dyn Error>),
}

impl Error for VmObjectMappingError {}
Expand Down Expand Up @@ -347,6 +360,11 @@ impl VmObject {
});
}

// We cannot populate page table while the table isnt loaded
if !vm_process.page_tables.is_loaded() {
return Err(VmObjectMappingError::PageTableNotLoaded);
}

// Get a new backing page for this vpage
let backing_page = SharedPhysPage::allocate_anywhere()
.map_err(|err| VmObjectMappingError::CannotGetPhysicalPage(err))?;
Expand All @@ -372,6 +390,9 @@ impl VmObject {
PopulationReponse::MappingError(page_correlation_error) => {
return Err(VmObjectMappingError::MappingError(page_correlation_error));
}
PopulationReponse::InjectError(inject) => {
return Err(VmObjectMappingError::InjectError(inject));
}
}

// Finally map the page back to the user when done
Expand Down Expand Up @@ -639,42 +660,42 @@ pub fn remove_page_fault_handler() {
*MAIN_PAGE_FAULT_HANDLER.write() = None;
}

// TODO: REMOVE THIS FUNCTION, its just for testing :)
pub fn test() {
let proc = VmProcess::new();

proc.inplace_new_vmobject(
VmRegion::new(VirtPage::new(10), VirtPage::new(20)),
VmPermissions::none()
.set_read_flag(true)
.set_write_flag(true)
.set_user_flag(true),
VmFillAction::Nothing,
)
.unwrap();

logln!(
"{:#?}",
proc.page_fault_handler(PageFaultInfo {
is_present: false,
write_read_access: false,
execute_fault: false,
user_fault: false,
vaddr: VirtPage::<Page4K>::new(15).addr(),
})
);
logln!(
"{:#?}",
proc.page_fault_handler(PageFaultInfo {
is_present: false,
write_read_access: false,
execute_fault: false,
user_fault: false,
vaddr: VirtPage::<Page4K>::new(16).addr(),
})
);

logln!("{}", proc.page_tables);

todo!("Test Done!");
}
// // TODO: REMOVE THIS FUNCTION, its just for testing :)
// pub fn test() {
// let proc = VmProcess::new();

// proc.inplace_new_vmobject(
// VmRegion::new(VirtPage::new(10), VirtPage::new(20)),
// VmPermissions::none()
// .set_read_flag(true)
// .set_write_flag(true)
// .set_user_flag(true),
// VmFillAction::Nothing,
// )
// .unwrap();

// logln!(
// "{:#?}",
// proc.page_fault_handler(PageFaultInfo {
// is_present: false,
// write_read_access: false,
// execute_fault: false,
// user_fault: false,
// vaddr: VirtPage::<Page4K>::new(15).addr(),
// })
// );
// logln!(
// "{:#?}",
// proc.page_fault_handler(PageFaultInfo {
// is_present: false,
// write_read_access: false,
// execute_fault: false,
// user_fault: false,
// vaddr: VirtPage::<Page4K>::new(16).addr(),
// })
// );

// logln!("{}", proc.page_tables);

// todo!("Test Done!");
// }
5 changes: 4 additions & 1 deletion kernel/src/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ fn exception_handler(args: InterruptInfo) {
}
// panic
mem::vm::PageFaultReponse::NotAttachedHandler => {
panic!("PageFault without attached handler!");
panic!(
"PageFault without attached handler!\n{:#016x?}\n{:#016x?}",
info, args
);
}
}
}
Expand Down
Loading

0 comments on commit 4b6b440

Please sign in to comment.