run_next_app完成

ch2
zhangxinyu 2 years ago
parent 90ccb10e88
commit 41b6f80fdc

@ -1,6 +1,9 @@
use core::arch::asm;
use lazy_static::*; use lazy_static::*;
use riscv::register::mcause::Trap;
use crate::println; use crate::println;
use crate::sync::UPSafeCell; use crate::sync::UPSafeCell;
use crate::trap::TrapContext;
const USER_STACK_SIZE: usize = 4096 * 2; // 栈大小为8kb const USER_STACK_SIZE: usize = 4096 * 2; // 栈大小为8kb
const KERNEL_STACK_SIZE: usize = 4096 * 2; const KERNEL_STACK_SIZE: usize = 4096 * 2;
@ -10,7 +13,9 @@ const MAX_APP_NUM: usize = 16; // 系统最大支持的运行程序数量
const APP_BASE_ADDRESS: usize = 0x80400000; // 载入的app的起始的地址 const APP_BASE_ADDRESS: usize = 0x80400000; // 载入的app的起始的地址
const APP_SIZE_LIMIT: usize = 0x20000; // app的最大的二进制文件能够使用的大小 const APP_SIZE_LIMIT: usize = 0x20000; // app的最大的二进制文件能够使用的大小
// 在此之后应用使用UserStack, 而内核使用KernelStack, entry.asm设置的64k启动栈不再被使用 // 在此之后 应用使用UserStack, 而内核使用KernelStack, entry.asm设置的64k启动栈不再被使用(首次运行run_next_app时被接管了 mv sp, a0)
// KERNEL_STACK 保存的是 Trap Context
static KERNEL_STACK: [u8; KERNEL_STACK_SIZE] = [0; KERNEL_STACK_SIZE]; static KERNEL_STACK: [u8; KERNEL_STACK_SIZE] = [0; KERNEL_STACK_SIZE];
static USER_STACK: [u8; USER_STACK_SIZE] = [0; USER_STACK_SIZE]; static USER_STACK: [u8; USER_STACK_SIZE] = [0; USER_STACK_SIZE];
@ -52,13 +57,38 @@ impl AppManager{
println!("[kernel] num_app = {}", self.num_app); println!("[kernel] num_app = {}", self.num_app);
for i in 0..self.num_app { for i in 0..self.num_app {
println!( println!(
"[kernel] app_{} [{:#x}, {:#x})", "[kernel] app_{} ({:#x}, {:#x})",
i, i,
self.app_start_lis[i], self.app_start_lis[i],
self.app_start_lis[i + 1] self.app_start_lis[i + 1]
); );
} }
} }
// 把app_idx位置的app 加载到指定的内存APP_BASE_ADDRESS位置
unsafe fn load_app(&self, app_idx: usize){
if app_idx >= self.num_app{
panic!("All applications completed!")
}
// 清空app执行区域的内存
core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, APP_SIZE_LIMIT).fill(0);
// 得到指定app_idx位置的数据(下一个位置的开始 - 需要运行app的开始 = 需要运行app的内存大小
let app_src = core::slice::from_raw_parts(self.app_start_lis[app_idx] as *const u8,
self.app_start_lis[app_idx + 1] - self.app_start_lis[app_idx]);
// 把app的代码 copy到指定的运行的区域
let app_len = app_src.len();
if app_len > APP_SIZE_LIMIT {
panic!("app memory overrun!")
}
core::slice::from_raw_parts_mut(APP_BASE_ADDRESS as *mut u8, app_len)
.copy_from_slice(app_src);
// 刷新cache
asm!("fence.i");
}
} }
@ -66,6 +96,41 @@ pub fn init() {
APP_MANAGER.exclusive_access().show_app_info(); APP_MANAGER.exclusive_access().show_app_info();
} }
pub fn run_next_app() -> *mut TrapContext{
// 运行一个新的app
// 把需要执行的指定app, 加载到执行位置APP_BASE_ADDRESS
// app_manager 需要drop 或者在一个作用域中, 因为这个函数不会返回, 后面直接进入用户态了
{
let mut app_manager = APP_MANAGER.exclusive_access();
unsafe{
app_manager.load_app(app_manager.current_app);
}
app_manager.current_app += 1;
}
extern "C" {
fn __restore(trap_context_ptr: usize);
}
unsafe {
// 得到用户栈的栈顶
let user_stack_top = USER_STACK.as_ptr() as usize + USER_STACK_SIZE;
// 得到用户trap的上下文以及寄存器状态
let user_trap_context = TrapContext::app_init_context(APP_BASE_ADDRESS, user_stack_top);
// 把用户trap copy到内核栈, 并把内核栈栈顶返回
let kernel_stack_top = KERNEL_STACK.as_ptr() as usize + KERNEL_STACK_SIZE; // 现在栈顶和栈底都在一个内存位置
let kernel_trap_context_ptr = (kernel_stack_top - core::mem::size_of::<TrapContext>()) as * mut TrapContext; // 为trap context 分配栈空间
unsafe {
*kernel_trap_context_ptr = user_trap_context;
// 返回现在的内核栈顶
kernel_trap_context_ptr
}
}
}

@ -10,6 +10,7 @@ pub mod lang_items;
pub mod sbi; pub mod sbi;
pub mod batch; pub mod batch;
pub mod sync; pub mod sync;
pub mod trap;
// 汇编脚本引入, 调整内核的内存布局之后, 会跳入到 rust_main中执行 // 汇编脚本引入, 调整内核的内存布局之后, 会跳入到 rust_main中执行
global_asm!(include_str!("entry.asm")); global_asm!(include_str!("entry.asm"));
@ -35,6 +36,7 @@ pub fn rust_main(){
println!("boot_stack_top_bound: {:#x}, boot_stack_lower_bound: {:#x}", boot_stack_top_bound as usize, boot_stack_lower_bound as usize); println!("boot_stack_top_bound: {:#x}, boot_stack_lower_bound: {:#x}", boot_stack_top_bound as usize, boot_stack_lower_bound as usize);
batch::init(); batch::init();
batch::run_next_app();
} }
/// ## 初始化bss段 /// ## 初始化bss段

@ -1 +1,2 @@
mod context; mod context;
pub use context::TrapContext;

@ -0,0 +1,71 @@
.altmacro
.macro SAVE_GP n
sd x\n, \n*8(sp) // x_n
.endm
.macro LOAD_GP n
ld x\n, \n*8(sp) // x_n
.endm
.section .text // .text
.globl __alltraps // __alltraps
.globl __restore // __restore
.align 2 // 2^2 = 4
__alltraps: // __alltraps
csrrw sp, sscratch, sp // sp sscratch
# sp sscratch
# TrapContext
addi sp, sp, -34*8 // 34*8
#
sd x1, 1*8(sp) // x1 (x0, 便)
# sp(x2)
sd x3, 3*8(sp) // x3 (x4, 便)
# tp(x4)使
# x5~x31
.set n, 5 // n 5
.rept 27 // 27
SAVE_GP %n // x_n
.set n, n+1 // n 1
.endr //
# 使 t0/t1/t2
csrr t0, sstatus // sstatus
csrr t1, sepc // sepc
sd t0, 32*8(sp) // sstatus
sd t1, 33*8(sp) // sepc
# sscratch
csrr t2, sscratch // sscratch
sd t2, 2*8(sp) // trap context
# trap_handler(cx: &mut TrapContext)
mv a0, sp // TrapContext a0
call trap_handler // trap_handler #
__restore: // __restore
# case1:
# case2: U
mv sp, a0 // a0 sp sp KERNEL_STACK_SIZE,
# sstatus/sepc
ld t0, 32*8(sp) // sstatus
ld t1, 33*8(sp) // sepc
ld t2, 2*8(sp) //
csrw sstatus, t0 // sstatus
csrw sepc, t1 // sepc
csrw sscratch, t2 // sscratch
# sp sscratch
# sp/tp
# x0
ld x1, 1*8(sp) // x1
# x2
ld x3, 3*8(sp) // x3
#
.set n, 5 // n 5
.rept 27 // 27
LOAD_GP %n // x_n
.set n, n+1 // n 1
.endr //
# sp sscratch , TrapContext, ,
addi sp, sp, 34*8 // sizeof<TrapContext>
csrrw sp, sscratch, sp // sp sscratch , sscratch, sp USER_STACK()
sret // , sstatus(/) sepc(/ pc)
Loading…
Cancel
Save