|
|
@ -1,7 +1,7 @@
|
|
|
|
//! memory set, area
|
|
|
|
//! memory set, area
|
|
|
|
//! and the inactive page table
|
|
|
|
//! and the inactive page table
|
|
|
|
|
|
|
|
|
|
|
|
use alloc::{boxed::Box, vec::Vec, string::String};
|
|
|
|
use alloc::{boxed::Box, string::String, vec::Vec};
|
|
|
|
use core::fmt::{Debug, Error, Formatter};
|
|
|
|
use core::fmt::{Debug, Error, Formatter};
|
|
|
|
|
|
|
|
|
|
|
|
use crate::paging::*;
|
|
|
|
use crate::paging::*;
|
|
|
@ -23,35 +23,40 @@ pub struct MemoryArea {
|
|
|
|
name: &'static str,
|
|
|
|
name: &'static str,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsafe impl Send for MemoryArea { }
|
|
|
|
unsafe impl Send for MemoryArea {}
|
|
|
|
|
|
|
|
|
|
|
|
impl MemoryArea {
|
|
|
|
impl MemoryArea {
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief get slice of the content in the memory area
|
|
|
|
** @brief get slice of the content in the memory area
|
|
|
|
** @retval &[u8] the slice of the content in the memory area
|
|
|
|
** @retval &[u8] the slice of the content in the memory area
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub unsafe fn as_slice(&self) -> &[u8] {
|
|
|
|
pub unsafe fn as_slice(&self) -> &[u8] {
|
|
|
|
::core::slice::from_raw_parts(self.start_addr as *const u8, self.end_addr - self.start_addr)
|
|
|
|
::core::slice::from_raw_parts(
|
|
|
|
|
|
|
|
self.start_addr as *const u8,
|
|
|
|
|
|
|
|
self.end_addr - self.start_addr,
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief get mutable slice of the content in the memory area
|
|
|
|
** @brief get mutable slice of the content in the memory area
|
|
|
|
** @retval &mut[u8] the mutable slice of the content in the memory area
|
|
|
|
** @retval &mut[u8] the mutable slice of the content in the memory area
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
|
|
|
|
pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
|
|
|
|
::core::slice::from_raw_parts_mut(self.start_addr as *mut u8, self.end_addr - self.start_addr)
|
|
|
|
::core::slice::from_raw_parts_mut(
|
|
|
|
|
|
|
|
self.start_addr as *mut u8,
|
|
|
|
|
|
|
|
self.end_addr - self.start_addr,
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief test whether a virtual address is in the memory area
|
|
|
|
** @brief test whether a virtual address is in the memory area
|
|
|
|
** @param addr: VirtAddr the virtual address to test
|
|
|
|
** @param addr: VirtAddr the virtual address to test
|
|
|
|
** @retval bool whether the virtual address is in the memory area
|
|
|
|
** @retval bool whether the virtual address is in the memory area
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn contains(&self, addr: VirtAddr) -> bool {
|
|
|
|
pub fn contains(&self, addr: VirtAddr) -> bool {
|
|
|
|
addr >= self.start_addr && addr < self.end_addr
|
|
|
|
addr >= self.start_addr && addr < self.end_addr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Check the array is within the readable memory
|
|
|
|
/// Check the array is within the readable memory
|
|
|
|
fn check_read_array<S>(&self, ptr: *const S, count: usize) -> bool {
|
|
|
|
fn check_read_array<S>(&self, ptr: *const S, count: usize) -> bool {
|
|
|
|
ptr as usize >= self.start_addr &&
|
|
|
|
ptr as usize >= self.start_addr && unsafe { ptr.add(count) as usize } <= self.end_addr
|
|
|
|
unsafe { ptr.add(count) as usize } <= self.end_addr
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Check the array is within the writable memory
|
|
|
|
/// Check the array is within the writable memory
|
|
|
|
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> bool {
|
|
|
|
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> bool {
|
|
|
@ -80,30 +85,30 @@ impl MemoryArea {
|
|
|
|
!(p1 <= p2 || p0 >= p3)
|
|
|
|
!(p1 <= p2 || p0 >= p3)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief map the memory area to the physice address in a page table
|
|
|
|
** @brief map the memory area to the physice address in a page table
|
|
|
|
** @param pt: &mut T::Active the page table to use
|
|
|
|
** @param pt: &mut T::Active the page table to use
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
fn map(&self, pt: &mut PageTable) {
|
|
|
|
fn map(&self, pt: &mut PageTable) {
|
|
|
|
for page in Page::range_of(self.start_addr, self.end_addr) {
|
|
|
|
for page in Page::range_of(self.start_addr, self.end_addr) {
|
|
|
|
self.handler.map(pt, page.start_address(), &self.attr);
|
|
|
|
self.handler.map(pt, page.start_address(), &self.attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief map the memory area to the physice address in a page table eagerly
|
|
|
|
** @brief map the memory area to the physice address in a page table eagerly
|
|
|
|
** @param pt: &mut T::Active the page table to use
|
|
|
|
** @param pt: &mut T::Active the page table to use
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
fn map_eager(&self, pt: &mut PageTable) {
|
|
|
|
fn map_eager(&self, pt: &mut PageTable) {
|
|
|
|
for page in Page::range_of(self.start_addr, self.end_addr) {
|
|
|
|
for page in Page::range_of(self.start_addr, self.end_addr) {
|
|
|
|
self.handler.map_eager(pt, page.start_address(), &self.attr);
|
|
|
|
self.handler.map_eager(pt, page.start_address(), &self.attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief unmap the memory area from the physice address in a page table
|
|
|
|
** @brief unmap the memory area from the physice address in a page table
|
|
|
|
** @param pt: &mut T::Active the page table to use
|
|
|
|
** @param pt: &mut T::Active the page table to use
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
fn unmap(&self, pt: &mut PageTable) {
|
|
|
|
fn unmap(&self, pt: &mut PageTable) {
|
|
|
|
for page in Page::range_of(self.start_addr, self.end_addr) {
|
|
|
|
for page in Page::range_of(self.start_addr, self.end_addr) {
|
|
|
|
self.handler.unmap(pt, page.start_address());
|
|
|
|
self.handler.unmap(pt, page.start_address());
|
|
|
@ -122,41 +127,41 @@ pub struct MemoryAttr {
|
|
|
|
|
|
|
|
|
|
|
|
impl MemoryAttr {
|
|
|
|
impl MemoryAttr {
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief set the memory attribute's user bit
|
|
|
|
** @brief set the memory attribute's user bit
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn user(mut self) -> Self {
|
|
|
|
pub fn user(mut self) -> Self {
|
|
|
|
self.user = true;
|
|
|
|
self.user = true;
|
|
|
|
self
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief set the memory attribute's readonly bit
|
|
|
|
** @brief set the memory attribute's readonly bit
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn readonly(mut self) -> Self {
|
|
|
|
pub fn readonly(mut self) -> Self {
|
|
|
|
self.readonly = true;
|
|
|
|
self.readonly = true;
|
|
|
|
self
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief unset the memory attribute's readonly bit
|
|
|
|
** @brief unset the memory attribute's readonly bit
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn writable(mut self) -> Self {
|
|
|
|
pub fn writable(mut self) -> Self {
|
|
|
|
self.readonly = false;
|
|
|
|
self.readonly = false;
|
|
|
|
self
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief set the memory attribute's execute bit
|
|
|
|
** @brief set the memory attribute's execute bit
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn execute(mut self) -> Self {
|
|
|
|
pub fn execute(mut self) -> Self {
|
|
|
|
self.execute = true;
|
|
|
|
self.execute = true;
|
|
|
|
self
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief set the MMIO type
|
|
|
|
** @brief set the MMIO type
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
** @retval MemoryAttr the memory attribute itself
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn mmio(mut self, value: u8) -> Self {
|
|
|
|
pub fn mmio(mut self, value: u8) -> Self {
|
|
|
|
self.mmio = value;
|
|
|
|
self.mmio = value;
|
|
|
|
self
|
|
|
|
self
|
|
|
@ -181,9 +186,9 @@ pub struct MemorySet<T: InactivePageTable> {
|
|
|
|
|
|
|
|
|
|
|
|
impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief create a memory set
|
|
|
|
** @brief create a memory set
|
|
|
|
** @retval MemorySet<T> the memory set created
|
|
|
|
** @retval MemorySet<T> the memory set created
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn new() -> Self {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
MemorySet {
|
|
|
|
MemorySet {
|
|
|
|
areas: Vec::new(),
|
|
|
|
areas: Vec::new(),
|
|
|
@ -206,24 +211,30 @@ impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Check the array is within the readable memory
|
|
|
|
/// Check the array is within the readable memory
|
|
|
|
pub fn check_read_array<S>(&self, ptr: *const S, count: usize) -> VMResult<()> {
|
|
|
|
pub fn check_read_array<S>(&self, ptr: *const S, count: usize) -> VMResult<()> {
|
|
|
|
self.areas.iter()
|
|
|
|
self.areas
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
.find(|area| area.check_read_array(ptr, count))
|
|
|
|
.find(|area| area.check_read_array(ptr, count))
|
|
|
|
.map(|_|()).ok_or(VMError::InvalidPtr)
|
|
|
|
.map(|_| ())
|
|
|
|
|
|
|
|
.ok_or(VMError::InvalidPtr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Check the array is within the writable memory
|
|
|
|
/// Check the array is within the writable memory
|
|
|
|
pub fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> VMResult<()> {
|
|
|
|
pub fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> VMResult<()> {
|
|
|
|
self.areas.iter()
|
|
|
|
self.areas
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
.find(|area| area.check_write_array(ptr, count))
|
|
|
|
.find(|area| area.check_write_array(ptr, count))
|
|
|
|
.map(|_|()).ok_or(VMError::InvalidPtr)
|
|
|
|
.map(|_| ())
|
|
|
|
|
|
|
|
.ok_or(VMError::InvalidPtr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Check the null-end C string is within the readable memory, and is valid.
|
|
|
|
/// Check the null-end C string is within the readable memory, and is valid.
|
|
|
|
/// If so, clone it to a String.
|
|
|
|
/// If so, clone it to a String.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// Unsafe: the page table must be active.
|
|
|
|
/// Unsafe: the page table must be active.
|
|
|
|
pub unsafe fn check_and_clone_cstr(&self, ptr: *const u8) -> VMResult<String> {
|
|
|
|
pub unsafe fn check_and_clone_cstr(&self, ptr: *const u8) -> VMResult<String> {
|
|
|
|
self.areas.iter()
|
|
|
|
self.areas
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
.filter_map(|area| area.check_and_clone_cstr(ptr))
|
|
|
|
.filter_map(|area| area.check_and_clone_cstr(ptr))
|
|
|
|
.next().ok_or(VMError::InvalidPtr)
|
|
|
|
.next()
|
|
|
|
|
|
|
|
.ok_or(VMError::InvalidPtr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Find a free area with hint address `addr_hint` and length `len`.
|
|
|
|
/// Find a free area with hint address `addr_hint` and length `len`.
|
|
|
|
/// Return the start address of found free area.
|
|
|
|
/// Return the start address of found free area.
|
|
|
@ -239,28 +250,45 @@ impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Test if [`start_addr`, `end_addr`) is a free area
|
|
|
|
/// Test if [`start_addr`, `end_addr`) is a free area
|
|
|
|
fn test_free_area(&self, start_addr: usize, end_addr: usize) -> bool {
|
|
|
|
fn test_free_area(&self, start_addr: usize, end_addr: usize) -> bool {
|
|
|
|
self.areas.iter()
|
|
|
|
self.areas
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
.find(|area| area.is_overlap_with(start_addr, end_addr))
|
|
|
|
.find(|area| area.is_overlap_with(start_addr, end_addr))
|
|
|
|
.is_none()
|
|
|
|
.is_none()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief add the memory area to the memory set
|
|
|
|
** @brief add the memory area to the memory set
|
|
|
|
** @param area: MemoryArea the memory area to add
|
|
|
|
** @param area: MemoryArea the memory area to add
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn push(&mut self, start_addr: VirtAddr, end_addr: VirtAddr, attr: MemoryAttr, handler: impl MemoryHandler, name: &'static str) {
|
|
|
|
pub fn push(
|
|
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
|
|
start_addr: VirtAddr,
|
|
|
|
|
|
|
|
end_addr: VirtAddr,
|
|
|
|
|
|
|
|
attr: MemoryAttr,
|
|
|
|
|
|
|
|
handler: impl MemoryHandler,
|
|
|
|
|
|
|
|
name: &'static str,
|
|
|
|
|
|
|
|
) {
|
|
|
|
assert!(start_addr <= end_addr, "invalid memory area");
|
|
|
|
assert!(start_addr <= end_addr, "invalid memory area");
|
|
|
|
assert!(self.test_free_area(start_addr, end_addr), "memory area overlap");
|
|
|
|
assert!(
|
|
|
|
let area = MemoryArea { start_addr, end_addr, attr, handler: Box::new(handler), name };
|
|
|
|
self.test_free_area(start_addr, end_addr),
|
|
|
|
|
|
|
|
"memory area overlap"
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
let area = MemoryArea {
|
|
|
|
|
|
|
|
start_addr,
|
|
|
|
|
|
|
|
end_addr,
|
|
|
|
|
|
|
|
attr,
|
|
|
|
|
|
|
|
handler: Box::new(handler),
|
|
|
|
|
|
|
|
name,
|
|
|
|
|
|
|
|
};
|
|
|
|
self.page_table.edit(|pt| area.map(pt));
|
|
|
|
self.page_table.edit(|pt| area.map(pt));
|
|
|
|
self.areas.push(area);
|
|
|
|
self.areas.push(area);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief remove the memory area from the memory set
|
|
|
|
** @brief remove the memory area from the memory set
|
|
|
|
** @param area: MemoryArea the memory area to remove
|
|
|
|
** @param area: MemoryArea the memory area to remove
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn pop(&mut self, start_addr: VirtAddr, end_addr: VirtAddr) {
|
|
|
|
pub fn pop(&mut self, start_addr: VirtAddr, end_addr: VirtAddr) {
|
|
|
|
assert!(start_addr <= end_addr, "invalid memory area");
|
|
|
|
assert!(start_addr <= end_addr, "invalid memory area");
|
|
|
|
for i in 0..self.areas.len() {
|
|
|
|
for i in 0..self.areas.len() {
|
|
|
@ -274,10 +302,10 @@ impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief remove the memory area from the memory set and split existed ones when necessary
|
|
|
|
** @brief remove the memory area from the memory set and split existed ones when necessary
|
|
|
|
** @param area: MemoryArea the memory area to remove
|
|
|
|
** @param area: MemoryArea the memory area to remove
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn pop_with_split(&mut self, start_addr: VirtAddr, end_addr: VirtAddr) {
|
|
|
|
pub fn pop_with_split(&mut self, start_addr: VirtAddr, end_addr: VirtAddr) {
|
|
|
|
assert!(start_addr <= end_addr, "invalid memory area");
|
|
|
|
assert!(start_addr <= end_addr, "invalid memory area");
|
|
|
|
let mut i = 0;
|
|
|
|
let mut i = 0;
|
|
|
@ -288,28 +316,73 @@ impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
let area = self.areas.remove(i);
|
|
|
|
let area = self.areas.remove(i);
|
|
|
|
self.page_table.edit(|pt| area.unmap(pt));
|
|
|
|
self.page_table.edit(|pt| area.unmap(pt));
|
|
|
|
i -= 1;
|
|
|
|
i -= 1;
|
|
|
|
} else if self.areas[i].start_addr >= start_addr && self.areas[i].start_addr < end_addr {
|
|
|
|
} else if self.areas[i].start_addr >= start_addr
|
|
|
|
|
|
|
|
&& self.areas[i].start_addr < end_addr
|
|
|
|
|
|
|
|
{
|
|
|
|
// prefix
|
|
|
|
// prefix
|
|
|
|
let area = self.areas.remove(i);
|
|
|
|
let area = self.areas.remove(i);
|
|
|
|
let dead_area = MemoryArea { start_addr: area.start_addr, end_addr, attr: area.attr, handler: area.handler.box_clone(), name: area.name };
|
|
|
|
let dead_area = MemoryArea {
|
|
|
|
|
|
|
|
start_addr: area.start_addr,
|
|
|
|
|
|
|
|
end_addr,
|
|
|
|
|
|
|
|
attr: area.attr,
|
|
|
|
|
|
|
|
handler: area.handler.box_clone(),
|
|
|
|
|
|
|
|
name: area.name,
|
|
|
|
|
|
|
|
};
|
|
|
|
self.page_table.edit(|pt| dead_area.unmap(pt));
|
|
|
|
self.page_table.edit(|pt| dead_area.unmap(pt));
|
|
|
|
let new_area = MemoryArea { start_addr: end_addr, end_addr: area.end_addr, attr: area.attr, handler: area.handler, name: area.name };
|
|
|
|
let new_area = MemoryArea {
|
|
|
|
|
|
|
|
start_addr: end_addr,
|
|
|
|
|
|
|
|
end_addr: area.end_addr,
|
|
|
|
|
|
|
|
attr: area.attr,
|
|
|
|
|
|
|
|
handler: area.handler,
|
|
|
|
|
|
|
|
name: area.name,
|
|
|
|
|
|
|
|
};
|
|
|
|
self.areas.insert(i, new_area);
|
|
|
|
self.areas.insert(i, new_area);
|
|
|
|
} else if self.areas[i].end_addr <= end_addr && self.areas[i].end_addr > start_addr {
|
|
|
|
} else if self.areas[i].end_addr <= end_addr && self.areas[i].end_addr > start_addr
|
|
|
|
|
|
|
|
{
|
|
|
|
// postfix
|
|
|
|
// postfix
|
|
|
|
let area = self.areas.remove(i);
|
|
|
|
let area = self.areas.remove(i);
|
|
|
|
let dead_area = MemoryArea { start_addr: start_addr, end_addr: area.end_addr, attr: area.attr, handler: area.handler.box_clone(), name: area.name };
|
|
|
|
let dead_area = MemoryArea {
|
|
|
|
|
|
|
|
start_addr: start_addr,
|
|
|
|
|
|
|
|
end_addr: area.end_addr,
|
|
|
|
|
|
|
|
attr: area.attr,
|
|
|
|
|
|
|
|
handler: area.handler.box_clone(),
|
|
|
|
|
|
|
|
name: area.name,
|
|
|
|
|
|
|
|
};
|
|
|
|
self.page_table.edit(|pt| dead_area.unmap(pt));
|
|
|
|
self.page_table.edit(|pt| dead_area.unmap(pt));
|
|
|
|
let new_area = MemoryArea { start_addr: area.start_addr, end_addr: start_addr, attr: area.attr, handler: area.handler, name: area.name };
|
|
|
|
let new_area = MemoryArea {
|
|
|
|
|
|
|
|
start_addr: area.start_addr,
|
|
|
|
|
|
|
|
end_addr: start_addr,
|
|
|
|
|
|
|
|
attr: area.attr,
|
|
|
|
|
|
|
|
handler: area.handler,
|
|
|
|
|
|
|
|
name: area.name,
|
|
|
|
|
|
|
|
};
|
|
|
|
self.areas.insert(i, new_area);
|
|
|
|
self.areas.insert(i, new_area);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// superset
|
|
|
|
// superset
|
|
|
|
let area = self.areas.remove(i);
|
|
|
|
let area = self.areas.remove(i);
|
|
|
|
let dead_area = MemoryArea { start_addr: start_addr, end_addr: end_addr, attr: area.attr, handler: area.handler.box_clone(), name: area.name };
|
|
|
|
let dead_area = MemoryArea {
|
|
|
|
|
|
|
|
start_addr: start_addr,
|
|
|
|
|
|
|
|
end_addr: end_addr,
|
|
|
|
|
|
|
|
attr: area.attr,
|
|
|
|
|
|
|
|
handler: area.handler.box_clone(),
|
|
|
|
|
|
|
|
name: area.name,
|
|
|
|
|
|
|
|
};
|
|
|
|
self.page_table.edit(|pt| dead_area.unmap(pt));
|
|
|
|
self.page_table.edit(|pt| dead_area.unmap(pt));
|
|
|
|
let new_area_left = MemoryArea { start_addr: area.start_addr, end_addr: start_addr, attr: area.attr, handler: area.handler.box_clone(), name: area.name };
|
|
|
|
let new_area_left = MemoryArea {
|
|
|
|
|
|
|
|
start_addr: area.start_addr,
|
|
|
|
|
|
|
|
end_addr: start_addr,
|
|
|
|
|
|
|
|
attr: area.attr,
|
|
|
|
|
|
|
|
handler: area.handler.box_clone(),
|
|
|
|
|
|
|
|
name: area.name,
|
|
|
|
|
|
|
|
};
|
|
|
|
self.areas.insert(i, new_area_left);
|
|
|
|
self.areas.insert(i, new_area_left);
|
|
|
|
let new_area_right = MemoryArea { start_addr: end_addr, end_addr: area.end_addr, attr: area.attr, handler: area.handler, name: area.name };
|
|
|
|
let new_area_right = MemoryArea {
|
|
|
|
|
|
|
|
start_addr: end_addr,
|
|
|
|
|
|
|
|
end_addr: area.end_addr,
|
|
|
|
|
|
|
|
attr: area.attr,
|
|
|
|
|
|
|
|
handler: area.handler,
|
|
|
|
|
|
|
|
name: area.name,
|
|
|
|
|
|
|
|
};
|
|
|
|
self.areas.insert(i + 1, new_area_right);
|
|
|
|
self.areas.insert(i + 1, new_area_right);
|
|
|
|
i += 1;
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -319,44 +392,48 @@ impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief get iterator of the memory area
|
|
|
|
** @brief get iterator of the memory area
|
|
|
|
** @retval impl Iterator<Item=&MemoryArea>
|
|
|
|
** @retval impl Iterator<Item=&MemoryArea>
|
|
|
|
** the memory area iterator
|
|
|
|
** the memory area iterator
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn iter(&self) -> impl Iterator<Item=&MemoryArea> {
|
|
|
|
pub fn iter(&self) -> impl Iterator<Item = &MemoryArea> {
|
|
|
|
self.areas.iter()
|
|
|
|
self.areas.iter()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn edit(&mut self, f: impl FnOnce(&mut T::Active)) {
|
|
|
|
pub fn edit(&mut self, f: impl FnOnce(&mut T::Active)) {
|
|
|
|
self.page_table.edit(f);
|
|
|
|
self.page_table.edit(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief execute function with the associated page table
|
|
|
|
** @brief execute function with the associated page table
|
|
|
|
** @param f: impl FnOnce() the function to be executed
|
|
|
|
** @param f: impl FnOnce() the function to be executed
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub unsafe fn with(&self, f: impl FnOnce()) {
|
|
|
|
pub unsafe fn with(&self, f: impl FnOnce()) {
|
|
|
|
self.page_table.with(f);
|
|
|
|
self.page_table.with(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief activate the associated page table
|
|
|
|
** @brief activate the associated page table
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub unsafe fn activate(&self) {
|
|
|
|
pub unsafe fn activate(&self) {
|
|
|
|
self.page_table.activate();
|
|
|
|
self.page_table.activate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief get the token of the associated page table
|
|
|
|
** @brief get the token of the associated page table
|
|
|
|
** @retval usize the token of the inactive page table
|
|
|
|
** @retval usize the token of the inactive page table
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn token(&self) -> usize {
|
|
|
|
pub fn token(&self) -> usize {
|
|
|
|
self.page_table.token()
|
|
|
|
self.page_table.token()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief clear the memory set
|
|
|
|
** @brief clear the memory set
|
|
|
|
** @retval none
|
|
|
|
** @retval none
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn clear(&mut self) {
|
|
|
|
pub fn clear(&mut self) {
|
|
|
|
let Self { ref mut page_table, ref mut areas, .. } = self;
|
|
|
|
let Self {
|
|
|
|
|
|
|
|
ref mut page_table,
|
|
|
|
|
|
|
|
ref mut areas,
|
|
|
|
|
|
|
|
..
|
|
|
|
|
|
|
|
} = self;
|
|
|
|
page_table.edit(|pt| {
|
|
|
|
page_table.edit(|pt| {
|
|
|
|
for area in areas.iter() {
|
|
|
|
for area in areas.iter() {
|
|
|
|
area.unmap(pt);
|
|
|
|
area.unmap(pt);
|
|
|
@ -379,17 +456,19 @@ impl<T: InactivePageTable> MemorySet<T> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
** @brief get the mutable reference for the inactive page table
|
|
|
|
** @brief get the mutable reference for the inactive page table
|
|
|
|
** @retval: &mut T the mutable reference of the inactive page table
|
|
|
|
** @retval: &mut T the mutable reference of the inactive page table
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
pub fn get_page_table_mut(&mut self) -> &mut T{
|
|
|
|
pub fn get_page_table_mut(&mut self) -> &mut T {
|
|
|
|
&mut self.page_table
|
|
|
|
&mut self.page_table
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn handle_page_fault(&mut self, addr: VirtAddr) -> bool {
|
|
|
|
pub fn handle_page_fault(&mut self, addr: VirtAddr) -> bool {
|
|
|
|
let area = self.areas.iter().find(|area| area.contains(addr));
|
|
|
|
let area = self.areas.iter().find(|area| area.contains(addr));
|
|
|
|
match area {
|
|
|
|
match area {
|
|
|
|
Some(area) => self.page_table.edit(|pt| area.handler.handle_page_fault(pt, addr)),
|
|
|
|
Some(area) => self
|
|
|
|
|
|
|
|
.page_table
|
|
|
|
|
|
|
|
.edit(|pt| area.handler.handle_page_fault(pt, addr)),
|
|
|
|
None => false,
|
|
|
|
None => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -419,8 +498,6 @@ impl<T: InactivePageTable> Drop for MemorySet<T> {
|
|
|
|
|
|
|
|
|
|
|
|
impl<T: InactivePageTable> Debug for MemorySet<T> {
|
|
|
|
impl<T: InactivePageTable> Debug for MemorySet<T> {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
|
|
|
f.debug_list()
|
|
|
|
f.debug_list().entries(self.areas.iter()).finish()
|
|
|
|
.entries(self.areas.iter())
|
|
|
|
|
|
|
|
.finish()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|