mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-25 19:03:35 +04:00
Fetch buffer in user space as a Vec.
This commit is contained in:
parent
064f1cb5cb
commit
f54573ae15
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,6 +125,7 @@ impl PageTable {
|
||||
*pte = PageTableEntry::empty();
|
||||
}
|
||||
pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> {
|
||||
//println!("into PageTable::translate");
|
||||
self.find_pte(vpn)
|
||||
.map(|pte| {pte.clone()})
|
||||
}
|
||||
@ -130,3 +133,29 @@ impl PageTable {
|
||||
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
|
||||
}
|
@ -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
|
||||
},
|
||||
_ => {
|
||||
|
@ -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),
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user