|
|
|
@ -1,10 +1,13 @@
|
|
|
|
|
//! memory set, area
|
|
|
|
|
//! and the inactive page table
|
|
|
|
|
|
|
|
|
|
use alloc::{vec::Vec, boxed::Box};
|
|
|
|
|
use alloc::{boxed::Box, vec::Vec, string::String};
|
|
|
|
|
use core::fmt::{Debug, Error, Formatter};
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
use crate::paging::*;
|
|
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
use self::handler::MemoryHandler;
|
|
|
|
|
|
|
|
|
|
pub mod handler;
|
|
|
|
@ -42,6 +45,40 @@ impl MemoryArea {
|
|
|
|
|
pub fn contains(&self, addr: VirtAddr) -> bool {
|
|
|
|
|
addr >= self.start_addr && addr < self.end_addr
|
|
|
|
|
}
|
|
|
|
|
/// Check the pointer is within the readable memory
|
|
|
|
|
pub fn check_ptr<T>(&self, ptr: *const T) -> bool {
|
|
|
|
|
self.check_array(ptr, 1)
|
|
|
|
|
}
|
|
|
|
|
/// Check the pointer is within the writable memory
|
|
|
|
|
pub fn check_mut_ptr<T>(&self, ptr: *mut T) -> bool {
|
|
|
|
|
self.check_mut_array(ptr, 1)
|
|
|
|
|
}
|
|
|
|
|
/// Check the array is within the readable memory
|
|
|
|
|
pub fn check_array<S>(&self, ptr: *const S, count: usize) -> bool {
|
|
|
|
|
// FIXME: check readable
|
|
|
|
|
ptr as usize >= self.start_addr &&
|
|
|
|
|
unsafe { ptr.offset(count as isize) as usize } <= self.end_addr
|
|
|
|
|
}
|
|
|
|
|
/// Check the array is within the writable memory
|
|
|
|
|
pub fn check_mut_array<S>(&self, ptr: *mut S, count: usize) -> bool {
|
|
|
|
|
// FIXME: check writable
|
|
|
|
|
ptr as usize >= self.start_addr &&
|
|
|
|
|
unsafe { ptr.offset(count as isize) as usize } <= self.end_addr
|
|
|
|
|
}
|
|
|
|
|
/// Check the null-end C string is within the readable memory, and is valid.
|
|
|
|
|
/// If so, clone it to a String.
|
|
|
|
|
///
|
|
|
|
|
/// Unsafe: the page table must be active.
|
|
|
|
|
pub unsafe fn check_and_clone_cstr(&self, ptr: *const u8) -> Option<String> {
|
|
|
|
|
if ptr as usize >= self.end_addr {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
let max_len = self.end_addr - ptr as usize;
|
|
|
|
|
(0..max_len)
|
|
|
|
|
.find(|&i| ptr.offset(i as isize).read() == 0)
|
|
|
|
|
.and_then(|len| core::str::from_utf8(core::slice::from_raw_parts(ptr, len)).ok())
|
|
|
|
|
.map(|s| String::from(s))
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
** @brief test whether the memory area is overlap with another memory area
|
|
|
|
|
** @param other: &MemoryArea another memory area to test
|
|
|
|
@ -158,13 +195,30 @@ impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
|
page_table: T::new_bare(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
** @brief find the memory area from virtual address
|
|
|
|
|
** @param addr: VirtAddr the virtual address to find
|
|
|
|
|
** @retval Option<&MemoryArea> the memory area with the virtual address, if presented
|
|
|
|
|
*/
|
|
|
|
|
pub fn find_area(&self, addr: VirtAddr) -> Option<&MemoryArea> {
|
|
|
|
|
self.areas.iter().find(|area| area.contains(addr))
|
|
|
|
|
/// Check the pointer is within the readable memory
|
|
|
|
|
pub fn check_ptr<S>(&self, ptr: *const S) -> bool {
|
|
|
|
|
self.areas.iter().find(|area| area.check_ptr(ptr)).is_some()
|
|
|
|
|
}
|
|
|
|
|
/// Check the pointer is within the writable memory
|
|
|
|
|
pub fn check_mut_ptr<S>(&self, ptr: *mut S) -> bool {
|
|
|
|
|
self.areas.iter().find(|area| area.check_mut_ptr(ptr)).is_some()
|
|
|
|
|
}
|
|
|
|
|
/// Check the array is within the readable memory
|
|
|
|
|
pub fn check_array<S>(&self, ptr: *const S, count: usize) -> bool {
|
|
|
|
|
self.areas.iter().find(|area| area.check_array(ptr, count)).is_some()
|
|
|
|
|
}
|
|
|
|
|
/// Check the array is within the writable memory
|
|
|
|
|
pub fn check_mut_array<S>(&self, ptr: *mut S, count: usize) -> bool {
|
|
|
|
|
self.areas.iter().find(|area| area.check_mut_array(ptr, count)).is_some()
|
|
|
|
|
}
|
|
|
|
|
/// Check the null-end C string is within the readable memory, and is valid.
|
|
|
|
|
/// If so, clone it to a String.
|
|
|
|
|
///
|
|
|
|
|
/// Unsafe: the page table must be active.
|
|
|
|
|
pub unsafe fn check_and_clone_cstr(&self, ptr: *const u8) -> Option<String> {
|
|
|
|
|
self.areas.iter()
|
|
|
|
|
.filter_map(|area| area.check_and_clone_cstr(ptr))
|
|
|
|
|
.next()
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
** @brief add the memory area to the memory set
|
|
|
|
|