Fetching buffer arguments from user space.
This commit is contained in:
parent
d38b24a9cb
commit
9366099b28
20 changed files with 405 additions and 82 deletions
|
@ -5,17 +5,34 @@ pub struct TrapContext {
|
|||
pub x: [usize; 32],
|
||||
pub sstatus: Sstatus,
|
||||
pub sepc: usize,
|
||||
pub kernel_satp: usize,
|
||||
pub kernel_sp: usize,
|
||||
pub trap_handler: usize,
|
||||
}
|
||||
|
||||
impl TrapContext {
|
||||
pub fn set_sp(&mut self, sp: usize) { self.x[2] = sp; }
|
||||
pub fn app_init_context(entry: usize, sp: usize) -> Self {
|
||||
pub fn app_init_context(
|
||||
entry: usize,
|
||||
sp: usize,
|
||||
kernel_satp: usize,
|
||||
kernel_sp: usize,
|
||||
trap_handler: usize,
|
||||
) -> Self {
|
||||
let mut sstatus = sstatus::read();
|
||||
sstatus.set_spp(SPP::User);
|
||||
let mut temp_sstatus: usize;
|
||||
unsafe {
|
||||
llvm_asm!("csrr $0, sstatus" : "=r"(temp_sstatus) ::: "volatile");
|
||||
}
|
||||
println!("sstatus={:#x}", temp_sstatus);
|
||||
let mut cx = Self {
|
||||
x: [0; 32],
|
||||
sstatus,
|
||||
sepc: entry,
|
||||
kernel_satp,
|
||||
kernel_sp,
|
||||
trap_handler,
|
||||
};
|
||||
cx.set_sp(sp);
|
||||
cx
|
||||
|
|
|
@ -17,15 +17,17 @@ use crate::syscall::syscall;
|
|||
use crate::task::{
|
||||
exit_current_and_run_next,
|
||||
suspend_current_and_run_next,
|
||||
current_user_token,
|
||||
current_trap_cx,
|
||||
};
|
||||
use crate::timer::set_next_trigger;
|
||||
use crate::config::{TRAP_CONTEXT, TRAMPOLINE};
|
||||
|
||||
global_asm!(include_str!("trap.S"));
|
||||
|
||||
pub fn init() {
|
||||
extern "C" { fn __alltraps(); }
|
||||
unsafe {
|
||||
stvec::write(__alltraps as usize, TrapMode::Direct);
|
||||
stvec::write(TRAMPOLINE, TrapMode::Direct);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,11 +40,14 @@ pub fn enable_timer_interrupt() {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
|
||||
pub fn 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!");
|
||||
cx.sepc += 4;
|
||||
cx.x[10] = syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]]) as usize;
|
||||
}
|
||||
|
@ -63,7 +68,26 @@ pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
|
|||
panic!("Unsupported trap {:?}, stval = {:#x}!", scause.cause(), stval);
|
||||
}
|
||||
}
|
||||
cx
|
||||
trap_return();
|
||||
}
|
||||
|
||||
pub use context::TrapContext;
|
||||
#[no_mangle]
|
||||
pub fn 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);
|
||||
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);
|
||||
unsafe {
|
||||
llvm_asm!("jr $0" :: "r"(restore_va), "{a0}"(trap_cx_ptr), "{a1}"(user_satp) :: "volatile");
|
||||
}
|
||||
panic!("Unreachable in back_to_user!");
|
||||
}
|
||||
|
||||
pub use context::{TrapContext};
|
||||
|
|
|
@ -5,16 +5,14 @@
|
|||
.macro LOAD_GP n
|
||||
ld x\n, \n*8(sp)
|
||||
.endm
|
||||
.section .text
|
||||
.section .text.trampoline
|
||||
.globl __alltraps
|
||||
.globl __restore
|
||||
.align 2
|
||||
__alltraps:
|
||||
csrrw sp, sscratch, sp
|
||||
# now sp->kernel stack, sscratch->user stack
|
||||
# allocate a TrapContext on kernel stack
|
||||
addi sp, sp, -34*8
|
||||
# save general-purpose registers
|
||||
# now sp->*TrapContext in user space, sscratch->user stack
|
||||
# save other general purpose registers
|
||||
sd x1, 1*8(sp)
|
||||
# skip sp(x2), we will save it later
|
||||
sd x3, 3*8(sp)
|
||||
|
@ -25,28 +23,40 @@ __alltraps:
|
|||
SAVE_GP %n
|
||||
.set n, n+1
|
||||
.endr
|
||||
# we can use t0/t1/t2 freely, because they were saved on kernel stack
|
||||
# we can use t0/t1/t2 freely, because they have been saved in TrapContext
|
||||
csrr t0, sstatus
|
||||
csrr t1, sepc
|
||||
sd t0, 32*8(sp)
|
||||
sd t1, 33*8(sp)
|
||||
# read user stack from sscratch and save it on the kernel stack
|
||||
# read user stack from sscratch and save it in TrapContext
|
||||
csrr t2, sscratch
|
||||
sd t2, 2*8(sp)
|
||||
# set input argument of trap_handler(cx: &mut TrapContext)
|
||||
mv a0, sp
|
||||
call trap_handler
|
||||
# load kernel_satp into t0
|
||||
ld t0, 34*8(sp)
|
||||
# load trap_handler into t1
|
||||
ld t1, 36*8(sp)
|
||||
# move to kernel_sp
|
||||
ld sp, 35*8(sp)
|
||||
# switch to kernel space
|
||||
csrw satp, t0
|
||||
sfence.vma
|
||||
# jump to trap_handler
|
||||
jr t1
|
||||
|
||||
__restore:
|
||||
# now sp->kernel stack(after allocated), sscratch->user stack
|
||||
# a0: *TrapContext in user space(Constant); a1: user space token
|
||||
# switch to user space
|
||||
csrw satp, a1
|
||||
sfence.vma
|
||||
csrw sscratch, a0
|
||||
mv sp, a0
|
||||
# now sp points to TrapContext in user space, start restoring based on it
|
||||
# restore sstatus/sepc
|
||||
ld t0, 32*8(sp)
|
||||
ld t1, 33*8(sp)
|
||||
ld t2, 2*8(sp)
|
||||
csrw sstatus, t0
|
||||
csrw sepc, t1
|
||||
csrw sscratch, t2
|
||||
# restore general-purpuse registers except sp/tp
|
||||
# restore general purpose registers except x0/sp/tp
|
||||
ld x1, 1*8(sp)
|
||||
ld x3, 3*8(sp)
|
||||
.set n, 5
|
||||
|
@ -54,8 +64,6 @@ __restore:
|
|||
LOAD_GP %n
|
||||
.set n, n+1
|
||||
.endr
|
||||
# release TrapContext on kernel stack
|
||||
addi sp, sp, 34*8
|
||||
# now sp->kernel stack, sscratch->user stack
|
||||
csrrw sp, sscratch, sp
|
||||
# back to user stack
|
||||
ld sp, 2*8(sp)
|
||||
sret
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue