diff --git a/os/src/mm/memory_set.rs b/os/src/mm/memory_set.rs index dc9c57d7..580451b2 100644 --- a/os/src/mm/memory_set.rs +++ b/os/src/mm/memory_set.rs @@ -260,7 +260,7 @@ impl MapArea { 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 pub fn copy_data(&mut self, page_table: &mut PageTable, data: &[u8]) { assert_eq!(self.map_type, MapType::Framed); diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 8c07c4d8..0118b194 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -8,7 +8,7 @@ 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}; +pub use page_table::{PageTableEntry, translated_byte_buffer}; pub use memory_set::{MemorySet, KERNEL_SPACE, MapPermission}; pub use memory_set::remap_test; diff --git a/os/src/mm/page_table.rs b/os/src/mm/page_table.rs index fa6b5cc5..86ba8d8d 100644 --- a/os/src/mm/page_table.rs +++ b/os/src/mm/page_table.rs @@ -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; use bitflags::*; @@ -69,9 +69,9 @@ impl PageTable { } } /// 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 { - root_ppn, + root_ppn: PhysPageNum::from(satp & ((1usize << 44) - 1)), frames: Vec::new(), } } @@ -95,6 +95,8 @@ impl PageTable { result } fn find_pte(&self, vpn: VirtPageNum) -> Option<&PageTableEntry> { + //println!("into find_pte"); + //println!("root_ppn = {:?}", self.root_ppn); let idxs = vpn.indexes(); let mut ppn = self.root_ppn; let mut result: Option<&PageTableEntry> = None; @@ -123,10 +125,37 @@ impl PageTable { *pte = PageTableEntry::empty(); } pub fn translate(&self, vpn: VirtPageNum) -> Option { + //println!("into PageTable::translate"); self.find_pte(vpn) .map(|pte| {pte.clone()}) } pub fn token(&self) -> usize { 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 } \ No newline at end of file diff --git a/os/src/syscall/fs.rs b/os/src/syscall/fs.rs index b8c46591..c431dfc9 100644 --- a/os/src/syscall/fs.rs +++ b/os/src/syscall/fs.rs @@ -1,11 +1,16 @@ +use crate::mm::translated_byte_buffer; +use crate::task::current_user_token; + const FD_STDOUT: usize = 1; pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize { + //println!("into sys_write!"); match fd { FD_STDOUT => { - let slice = unsafe { core::slice::from_raw_parts(buf, len) }; - let str = core::str::from_utf8(slice).unwrap(); - print!("{}", str); + let buffers = translated_byte_buffer(current_user_token(), buf, len); + for buffer in buffers { + print!("{}", core::str::from_utf8(buffer).unwrap()); + } len as isize }, _ => { diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index ee0d0fc9..fc5254d0 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -10,7 +10,7 @@ use fs::*; use process::*; pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { - println!("into syscall!"); + //println!("into syscall!"); match syscall_id { SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]), SYSCALL_EXIT => sys_exit(args[0] as i32), diff --git a/os/src/trap/mod.rs b/os/src/trap/mod.rs index 026e1b36..f11106d9 100644 --- a/os/src/trap/mod.rs +++ b/os/src/trap/mod.rs @@ -41,13 +41,13 @@ pub fn enable_timer_interrupt() { #[no_mangle] pub fn trap_handler() -> ! { - println!("into trap_handler!"); + //println!("into trap_handler!"); let cx = current_trap_cx(); let scause = scause::read(); let stval = stval::read(); match scause.cause() { Trap::Exception(Exception::UserEnvCall) => { - println!("found UserEnvCall!"); + //println!("found UserEnvCall!"); cx.sepc += 4; 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] pub fn trap_return() -> ! { - println!("into trap_return"); + //println!("into trap_return"); let trap_cx_ptr = TRAP_CONTEXT; 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" { fn __alltraps(); fn __restore(); } let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE; - println!("__alltraps={:#x},__restore={:#x}", __alltraps as usize, __restore as usize); - println!("restore_va={:#x}", restore_va); + //println!("__alltraps={:#x},__restore={:#x}", __alltraps as usize, __restore as usize); + //println!("restore_va={:#x}", restore_va); unsafe { llvm_asm!("jr $0" :: "r"(restore_va), "{a0}"(trap_cx_ptr), "{a1}"(user_satp) :: "volatile"); }