Implement many process syscalls.

This commit is contained in:
Yifan Wu 2020-12-10 11:57:26 +08:00
parent e56ea17566
commit 8fbadfc951
20 changed files with 383 additions and 88 deletions

View file

@ -110,6 +110,13 @@ impl VirtPageNum {
}
}
impl PhysAddr {
pub fn get_mut<T>(&self) -> &'static mut T {
unsafe {
(self.0 as *mut T).as_mut().unwrap()
}
}
}
impl PhysPageNum {
pub fn get_pte_array(&self) -> &'static mut [PageTableEntry] {
let pa: PhysAddr = self.clone().into();
@ -125,9 +132,7 @@ impl PhysPageNum {
}
pub fn get_mut<T>(&self) -> &'static mut T {
let pa: PhysAddr = self.clone().into();
unsafe {
(pa.0 as *mut T).as_mut().unwrap()
}
pa.get_mut()
}
}

View file

@ -47,6 +47,7 @@ impl MemorySet {
areas: Vec::new(),
}
}
#[allow(unused)]
pub fn dealloc_all_frames(&mut self) {
*self = Self::new_bare();
}
@ -68,7 +69,6 @@ impl MemorySet {
area.unmap(&mut self.page_table);
self.areas.remove(idx);
}
panic!("Area not found!");
}
fn push(&mut self, mut map_area: MapArea, data: Option<&[u8]>) {
map_area.map(&mut self.page_table);
@ -189,6 +189,23 @@ impl MemorySet {
), None);
(memory_set, user_stack_top, elf.header.pt2.entry_point() as usize)
}
pub fn from_existed_user(user_space: &MemorySet) -> MemorySet {
let mut memory_set = Self::new_bare();
// map trampoline
memory_set.map_trampoline();
// copy data sections/trap_context/user_stack
for area in user_space.areas.iter() {
let new_area = MapArea::from_another(area);
memory_set.push(new_area, None);
// copy data from another space
for vpn in area.vpn_range {
let src_ppn = user_space.translate(vpn).unwrap().ppn();
let dst_ppn = memory_set.translate(vpn).unwrap().ppn();
dst_ppn.get_bytes_array().copy_from_slice(src_ppn.get_bytes_array());
}
}
memory_set
}
pub fn activate(&self) {
let satp = self.page_table.token();
unsafe {
@ -199,6 +216,9 @@ impl MemorySet {
pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> {
self.page_table.translate(vpn)
}
pub fn clear(&mut self) {
*self = Self::new_bare();
}
}
pub struct MapArea {
@ -224,6 +244,14 @@ impl MapArea {
map_perm,
}
}
pub fn from_another(another: &MapArea) -> Self {
Self {
vpn_range: VPNRange::new(another.vpn_range.get_start(), another.vpn_range.get_end()),
data_frames: BTreeMap::new(),
map_type: another.map_type,
map_perm: another.map_perm,
}
}
pub fn map_one(&mut self, page_table: &mut PageTable, vpn: VirtPageNum) {
let ppn: PhysPageNum;
match self.map_type {

View file

@ -8,7 +8,12 @@ use page_table::{PageTable, PTEFlags};
use address::{VPNRange, StepByOne};
pub use address::{PhysAddr, VirtAddr, PhysPageNum, VirtPageNum};
pub use frame_allocator::{FrameTracker, frame_alloc};
pub use page_table::{PageTableEntry, translated_byte_buffer};
pub use page_table::{
PageTableEntry,
translated_byte_buffer,
translated_str,
translated_refmut,
};
pub use memory_set::{MemorySet, KERNEL_SPACE, MapPermission};
pub use memory_set::remap_test;

View file

@ -1,6 +1,15 @@
use super::{frame_alloc, PhysPageNum, FrameTracker, VirtPageNum, VirtAddr, StepByOne};
use super::{
frame_alloc,
PhysPageNum,
FrameTracker,
VirtPageNum,
VirtAddr,
PhysAddr,
StepByOne
};
use alloc::vec::Vec;
use alloc::vec;
use alloc::string::String;
use bitflags::*;
bitflags! {
@ -126,6 +135,17 @@ impl PageTable {
self.find_pte(vpn)
.map(|pte| {pte.clone()})
}
pub fn translate_va(&self, va: VirtAddr) -> Option<PhysAddr> {
self.find_pte(va.clone().floor())
.map(|pte| {
//println!("translate_va:va = {:?}", va);
let aligned_pa: PhysAddr = pte.ppn().into();
//println!("translate_va:pa_align = {:?}", aligned_pa);
let offset = va.page_offset();
let aligned_pa_usize: usize = aligned_pa.into();
(aligned_pa_usize + offset).into()
})
}
pub fn token(&self) -> usize {
8usize << 60 | self.root_ppn.0
}
@ -150,4 +170,28 @@ pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&
start = end_va.into();
}
v
}
pub fn translated_str(token: usize, ptr: *const u8) -> String {
let page_table = PageTable::from_token(token);
let mut string = String::new();
let mut va = ptr as usize;
loop {
let ch: u8 = *(page_table.translate_va(VirtAddr::from(va)).unwrap().get_mut());
if ch == 0 {
break;
} else {
string.push(ch as char);
va += 1;
}
}
string
}
pub fn translated_refmut<T>(token: usize, ptr: *mut T) -> &'static mut T {
//println!("into translated_refmut!");
let page_table = PageTable::from_token(token);
let va = ptr as usize;
//println!("translated_refmut: before translate_va");
page_table.translate_va(VirtAddr::from(va)).unwrap().get_mut()
}