Fetch buffer in user space as a Vec.

This commit is contained in:
Yifan Wu 2020-12-07 18:07:19 +08:00
parent 064f1cb5cb
commit f54573ae15
6 changed files with 49 additions and 15 deletions

View File

@ -260,7 +260,7 @@ impl MapArea {
self.unmap_one(page_table, vpn); self.unmap_one(page_table, vpn);
} }
} }
/// data: start-aligned but maybe with shorted length /// data: start-aligned but maybe with shorter length
/// assume that all frames were cleared before /// assume that all frames were cleared before
pub fn copy_data(&mut self, page_table: &mut PageTable, data: &[u8]) { pub fn copy_data(&mut self, page_table: &mut PageTable, data: &[u8]) {
assert_eq!(self.map_type, MapType::Framed); assert_eq!(self.map_type, MapType::Framed);

View File

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

View File

@ -1,4 +1,4 @@
use super::{frame_alloc, PhysPageNum, FrameTracker, VirtPageNum}; use super::{frame_alloc, PhysPageNum, FrameTracker, VirtPageNum, VirtAddr, StepByOne};
use alloc::vec::Vec; use alloc::vec::Vec;
use alloc::vec; use alloc::vec;
use bitflags::*; use bitflags::*;
@ -69,9 +69,9 @@ impl PageTable {
} }
} }
/// Temporarily used to get arguments from user space. /// Temporarily used to get arguments from user space.
pub fn from_root_ppn(root_ppn: PhysPageNum) -> Self { pub fn from_token(satp: usize) -> Self {
Self { Self {
root_ppn, root_ppn: PhysPageNum::from(satp & ((1usize << 44) - 1)),
frames: Vec::new(), frames: Vec::new(),
} }
} }
@ -95,6 +95,8 @@ impl PageTable {
result result
} }
fn find_pte(&self, vpn: VirtPageNum) -> Option<&PageTableEntry> { fn find_pte(&self, vpn: VirtPageNum) -> Option<&PageTableEntry> {
//println!("into find_pte");
//println!("root_ppn = {:?}", self.root_ppn);
let idxs = vpn.indexes(); let idxs = vpn.indexes();
let mut ppn = self.root_ppn; let mut ppn = self.root_ppn;
let mut result: Option<&PageTableEntry> = None; let mut result: Option<&PageTableEntry> = None;
@ -123,6 +125,7 @@ impl PageTable {
*pte = PageTableEntry::empty(); *pte = PageTableEntry::empty();
} }
pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> { pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> {
//println!("into PageTable::translate");
self.find_pte(vpn) self.find_pte(vpn)
.map(|pte| {pte.clone()}) .map(|pte| {pte.clone()})
} }
@ -130,3 +133,29 @@ impl PageTable {
8usize << 60 | self.root_ppn.0 8usize << 60 | self.root_ppn.0
} }
} }
pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&'static [u8]> {
//println!("into translated_byte_buffer!");
let page_table = PageTable::from_token(token);
let mut start = ptr as usize;
let end = start + len;
//println!("start={:#x},end={:#x}", start, end);
let mut v = Vec::new();
while start < end {
//println!("start={:#x}", start);
let start_va = VirtAddr::from(start);
let mut vpn = start_va.floor();
//println!("vpn={:?}", vpn);
let ppn = page_table
.translate(vpn)
.unwrap()
.ppn();
//println!("ppn={:?}", ppn);
vpn.step();
let mut end_va: VirtAddr = vpn.into();
end_va = end_va.min(VirtAddr::from(end));
v.push(&ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]);
start = end_va.into();
}
v
}

View File

@ -1,11 +1,16 @@
use crate::mm::translated_byte_buffer;
use crate::task::current_user_token;
const FD_STDOUT: usize = 1; const FD_STDOUT: usize = 1;
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
//println!("into sys_write!");
match fd { match fd {
FD_STDOUT => { FD_STDOUT => {
let slice = unsafe { core::slice::from_raw_parts(buf, len) }; let buffers = translated_byte_buffer(current_user_token(), buf, len);
let str = core::str::from_utf8(slice).unwrap(); for buffer in buffers {
print!("{}", str); print!("{}", core::str::from_utf8(buffer).unwrap());
}
len as isize len as isize
}, },
_ => { _ => {

View File

@ -10,7 +10,7 @@ use fs::*;
use process::*; use process::*;
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
println!("into syscall!"); //println!("into syscall!");
match syscall_id { match syscall_id {
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
SYSCALL_EXIT => sys_exit(args[0] as i32), SYSCALL_EXIT => sys_exit(args[0] as i32),

View File

@ -41,13 +41,13 @@ pub fn enable_timer_interrupt() {
#[no_mangle] #[no_mangle]
pub fn trap_handler() -> ! { pub fn trap_handler() -> ! {
println!("into trap_handler!"); //println!("into trap_handler!");
let cx = current_trap_cx(); let cx = current_trap_cx();
let scause = scause::read(); let scause = scause::read();
let stval = stval::read(); let stval = stval::read();
match scause.cause() { match scause.cause() {
Trap::Exception(Exception::UserEnvCall) => { Trap::Exception(Exception::UserEnvCall) => {
println!("found UserEnvCall!"); //println!("found UserEnvCall!");
cx.sepc += 4; cx.sepc += 4;
cx.x[10] = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize; cx.x[10] = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize;
} }
@ -73,17 +73,17 @@ pub fn trap_handler() -> ! {
#[no_mangle] #[no_mangle]
pub fn trap_return() -> ! { pub fn trap_return() -> ! {
println!("into trap_return"); //println!("into trap_return");
let trap_cx_ptr = TRAP_CONTEXT; let trap_cx_ptr = TRAP_CONTEXT;
let user_satp = current_user_token(); let user_satp = current_user_token();
println!("trap_cx_ptr={:#x}, user_satp={:#x}", trap_cx_ptr, user_satp); //println!("trap_cx_ptr={:#x}, user_satp={:#x}", trap_cx_ptr, user_satp);
extern "C" { extern "C" {
fn __alltraps(); fn __alltraps();
fn __restore(); fn __restore();
} }
let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE; let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE;
println!("__alltraps={:#x},__restore={:#x}", __alltraps as usize, __restore as usize); //println!("__alltraps={:#x},__restore={:#x}", __alltraps as usize, __restore as usize);
println!("restore_va={:#x}", restore_va); //println!("restore_va={:#x}", restore_va);
unsafe { unsafe {
llvm_asm!("jr $0" :: "r"(restore_va), "{a0}"(trap_cx_ptr), "{a1}"(user_satp) :: "volatile"); llvm_asm!("jr $0" :: "r"(restore_va), "{a0}"(trap_cx_ptr), "{a1}"(user_satp) :: "volatile");
} }