Split kernel/user trap handler && Fix user tests.
This commit is contained in:
parent
1008d92c35
commit
485db04a2b
13 changed files with 45 additions and 161 deletions
|
@ -3,6 +3,7 @@ use std::fs::{File, read_dir};
|
|||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=../user/src/");
|
||||
println!("cargo:rerun-if-changed={}", TARGET_PATH);
|
||||
insert_app_data().unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
pub const USER_STACK_SIZE: usize = 4096 * 2;
|
||||
pub const KERNEL_STACK_SIZE: usize = 4096 * 2;
|
||||
pub const MAX_APP_NUM: usize = 4;
|
||||
pub const APP_BASE_ADDRESS: usize = 0x80100000;
|
||||
pub const APP_SIZE_LIMIT: usize = 0x20000;
|
||||
pub const KERNEL_HEAP_SIZE: usize = 0x30_0000;
|
||||
pub const MEMORY_END: usize = 0x80800000;
|
||||
pub const PAGE_SIZE: usize = 0x1000;
|
||||
|
|
127
os/src/loader.rs
127
os/src/loader.rs
|
@ -1,54 +1,3 @@
|
|||
use crate::trap::TrapContext;
|
||||
use crate::task::TaskContext;
|
||||
use crate::config::*;
|
||||
use xmas_elf::ElfFile;
|
||||
|
||||
/*
|
||||
#[repr(align(4096))]
|
||||
struct KernelStack {
|
||||
data: [u8; KERNEL_STACK_SIZE],
|
||||
}
|
||||
|
||||
#[repr(align(4096))]
|
||||
struct UserStack {
|
||||
data: [u8; USER_STACK_SIZE],
|
||||
}
|
||||
|
||||
static KERNEL_STACK: [KernelStack; MAX_APP_NUM] = [
|
||||
KernelStack { data: [0; KERNEL_STACK_SIZE], };
|
||||
MAX_APP_NUM
|
||||
];
|
||||
|
||||
static USER_STACK: [UserStack; MAX_APP_NUM] = [
|
||||
UserStack { data: [0; USER_STACK_SIZE], };
|
||||
MAX_APP_NUM
|
||||
];
|
||||
|
||||
impl KernelStack {
|
||||
fn get_sp(&self) -> usize {
|
||||
self.data.as_ptr() as usize + KERNEL_STACK_SIZE
|
||||
}
|
||||
pub fn push_context(&self, trap_cx: TrapContext, task_cx: TaskContext) -> &'static mut TaskContext {
|
||||
unsafe {
|
||||
let trap_cx_ptr = (self.get_sp() - core::mem::size_of::<TrapContext>()) as *mut TrapContext;
|
||||
*trap_cx_ptr = trap_cx;
|
||||
let task_cx_ptr = (trap_cx_ptr as usize - core::mem::size_of::<TaskContext>()) as *mut TaskContext;
|
||||
*task_cx_ptr = task_cx;
|
||||
task_cx_ptr.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UserStack {
|
||||
fn get_sp(&self) -> usize {
|
||||
self.data.as_ptr() as usize + USER_STACK_SIZE
|
||||
}
|
||||
}
|
||||
*/
|
||||
fn get_base_i(app_id: usize) -> usize {
|
||||
APP_BASE_ADDRESS + app_id * APP_SIZE_LIMIT
|
||||
}
|
||||
|
||||
pub fn get_num_app() -> usize {
|
||||
extern "C" { fn _num_app(); }
|
||||
unsafe { (_num_app as usize as *const usize).read_volatile() }
|
||||
|
@ -69,79 +18,3 @@ pub fn get_app_data(app_id: usize) -> &'static [u8] {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fn debug_elf(start_addr: usize, end_addr: usize) {
|
||||
let data_array = unsafe {
|
||||
core::slice::from_raw_parts(start_addr as *const u8, end_addr - start_addr)
|
||||
};
|
||||
let elf = ElfFile::new(data_array).unwrap();
|
||||
let elf_header = elf.header;
|
||||
let magic = elf_header.pt1.magic;
|
||||
assert_eq!(magic, [0x7f, 0x45, 0x4c, 0x46], "invalid elf!");
|
||||
let ph_count = elf_header.pt2.ph_count();
|
||||
println!("ph_count = {}", ph_count);
|
||||
for i in 0..ph_count {
|
||||
let ph = elf.program_header(i).unwrap();
|
||||
if ph.get_type().unwrap() == xmas_elf::program::Type::Load {
|
||||
println!(
|
||||
"offset={:#x},va={:#x},pa={:#x},filesz={:#x},memsz={:#x},align={:#x},flag={:?}",
|
||||
ph.offset(),
|
||||
ph.virtual_addr(),
|
||||
ph.physical_addr(),
|
||||
ph.file_size(),
|
||||
ph.mem_size(),
|
||||
ph.align(),
|
||||
ph.flags(),
|
||||
);
|
||||
//println!("len={:?}", ph.get_data(&elf).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_apps() {
|
||||
extern "C" { fn _num_app(); }
|
||||
let num_app_ptr = _num_app as usize as *const usize;
|
||||
let num_app = get_num_app();
|
||||
let app_start = unsafe {
|
||||
core::slice::from_raw_parts(num_app_ptr.add(1), num_app + 1)
|
||||
};
|
||||
println!("num_app = {}", num_app);
|
||||
for i in 0..num_app {
|
||||
println!(
|
||||
"app_{} [{:#x},{:#x}) size={:#x}",
|
||||
i,
|
||||
app_start[i],
|
||||
app_start[i + 1],
|
||||
app_start[i + 1] - app_start[i]
|
||||
);
|
||||
debug_elf(app_start[i], app_start[i + 1]);
|
||||
}
|
||||
loop {}
|
||||
// clear i-cache first
|
||||
unsafe { llvm_asm!("fence.i" :::: "volatile"); }
|
||||
// load apps
|
||||
for i in 0..num_app {
|
||||
let base_i = get_base_i(i);
|
||||
// clear region
|
||||
(base_i..base_i + APP_SIZE_LIMIT).for_each(|addr| unsafe {
|
||||
(addr as *mut u8).write_volatile(0)
|
||||
});
|
||||
// load app from data section to memory
|
||||
let src = unsafe {
|
||||
core::slice::from_raw_parts(app_start[i] as *const u8, app_start[i + 1] - app_start[i])
|
||||
};
|
||||
let dst = unsafe {
|
||||
core::slice::from_raw_parts_mut(base_i as *mut u8, src.len())
|
||||
};
|
||||
dst.copy_from_slice(src);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_app_cx(app_id: usize) -> &'static TaskContext {
|
||||
KERNEL_STACK[app_id].push_context(
|
||||
TrapContext::app_init_context(get_base_i(app_id), USER_STACK[app_id].get_sp()),
|
||||
TaskContext::goto_restore(),
|
||||
)
|
||||
}
|
||||
*/
|
|
@ -44,10 +44,9 @@ pub fn rust_main() -> ! {
|
|||
println!("[kernel] back to world!");
|
||||
mm::remap_test();
|
||||
trap::init();
|
||||
//loader::load_apps();
|
||||
//trap::enable_interrupt();
|
||||
//trap::enable_timer_interrupt();
|
||||
//timer::set_next_trigger();
|
||||
trap::enable_timer_interrupt();
|
||||
timer::set_next_trigger();
|
||||
task::run_first_task();
|
||||
panic!("Unreachable in rust_main!");
|
||||
}
|
|
@ -2,7 +2,6 @@ use super::{PageTable, PageTableEntry, PTEFlags};
|
|||
use super::{VirtPageNum, VirtAddr, PhysPageNum, PhysAddr};
|
||||
use super::{FrameTracker, frame_alloc};
|
||||
use super::{VPNRange, StepByOne};
|
||||
use core::ops::Range;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec::Vec;
|
||||
use riscv::register::satp;
|
||||
|
@ -16,7 +15,6 @@ use crate::config::{
|
|||
TRAP_CONTEXT,
|
||||
USER_STACK_SIZE
|
||||
};
|
||||
use xmas_elf::ElfFile;
|
||||
|
||||
extern "C" {
|
||||
fn stext();
|
||||
|
@ -169,7 +167,7 @@ impl MemorySet {
|
|||
}
|
||||
// map user stack with U flags
|
||||
//println!("mapping user stack!");
|
||||
let mut max_end_va: VirtAddr = max_end_vpn.into();
|
||||
let max_end_va: VirtAddr = max_end_vpn.into();
|
||||
let mut user_stack_bottom: usize = max_end_va.into();
|
||||
// guard page
|
||||
user_stack_bottom += PAGE_SIZE;
|
||||
|
@ -227,8 +225,7 @@ impl MapArea {
|
|||
}
|
||||
}
|
||||
pub fn map_one(&mut self, page_table: &mut PageTable, vpn: VirtPageNum) {
|
||||
let mut pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap();
|
||||
let mut ppn = PhysPageNum(0);
|
||||
let ppn: PhysPageNum;
|
||||
match self.map_type {
|
||||
MapType::Identical => {
|
||||
ppn = PhysPageNum(vpn.0);
|
||||
|
@ -239,8 +236,10 @@ impl MapArea {
|
|||
self.data_frames.insert(vpn, frame);
|
||||
}
|
||||
}
|
||||
let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap();
|
||||
page_table.map(vpn, ppn, pte_flags);
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unmap_one(&mut self, page_table: &mut PageTable, vpn: VirtPageNum) {
|
||||
match self.map_type {
|
||||
MapType::Framed => {
|
||||
|
@ -255,6 +254,7 @@ impl MapArea {
|
|||
self.map_one(page_table, vpn);
|
||||
}
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unmap(&mut self, page_table: &mut PageTable) {
|
||||
for vpn in self.vpn_range {
|
||||
self.unmap_one(page_table, vpn);
|
||||
|
|
|
@ -113,12 +113,14 @@ impl PageTable {
|
|||
}
|
||||
result
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn map(&mut self, vpn: VirtPageNum, ppn: PhysPageNum, flags: PTEFlags) {
|
||||
//println!("mapping {:?} {:?}", vpn, ppn);
|
||||
let pte = self.find_pte_create(vpn).unwrap();
|
||||
assert!(!pte.is_valid(), "vpn {:?} is mapped before mapping", vpn);
|
||||
*pte = PageTableEntry::new(ppn, flags | PTEFlags::V);
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unmap(&mut self, vpn: VirtPageNum) {
|
||||
let pte = self.find_pte_create(vpn).unwrap();
|
||||
assert!(pte.is_valid(), "vpn {:?} is invalid before unmapping", vpn);
|
||||
|
|
|
@ -2,7 +2,6 @@ mod context;
|
|||
mod switch;
|
||||
mod task;
|
||||
|
||||
use crate::config::MAX_APP_NUM;
|
||||
use crate::loader::{get_num_app, get_app_data};
|
||||
use crate::trap::TrapContext;
|
||||
use core::cell::RefCell;
|
||||
|
|
|
@ -71,7 +71,6 @@ impl TaskControlBlock {
|
|||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum TaskStatus {
|
||||
UnInit,
|
||||
Ready,
|
||||
Running,
|
||||
Exited,
|
||||
|
|
|
@ -21,11 +21,7 @@ impl TrapContext {
|
|||
) -> 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);
|
||||
sstatus.set_spie(true);
|
||||
let mut cx = Self {
|
||||
x: [0; 32],
|
||||
sstatus,
|
||||
|
|
|
@ -26,11 +26,22 @@ use crate::config::{TRAP_CONTEXT, TRAMPOLINE};
|
|||
global_asm!(include_str!("trap.S"));
|
||||
|
||||
pub fn init() {
|
||||
set_kernel_trap_entry();
|
||||
}
|
||||
|
||||
fn set_kernel_trap_entry() {
|
||||
unsafe {
|
||||
stvec::write(TRAMPOLINE, TrapMode::Direct);
|
||||
stvec::write(trap_from_kernel as usize, TrapMode::Direct);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_user_trap_entry() {
|
||||
unsafe {
|
||||
stvec::write(TRAMPOLINE as usize, TrapMode::Direct);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn enable_interrupt() {
|
||||
unsafe { sstatus::set_sie(); }
|
||||
}
|
||||
|
@ -42,6 +53,7 @@ pub fn enable_timer_interrupt() {
|
|||
#[no_mangle]
|
||||
pub fn trap_handler() -> ! {
|
||||
//println!("into trap_handler!");
|
||||
set_kernel_trap_entry();
|
||||
let cx = current_trap_cx();
|
||||
let scause = scause::read();
|
||||
let stval = stval::read();
|
||||
|
@ -73,6 +85,7 @@ pub fn trap_handler() -> ! {
|
|||
|
||||
#[no_mangle]
|
||||
pub fn trap_return() -> ! {
|
||||
set_user_trap_entry();
|
||||
//println!("into trap_return");
|
||||
let trap_cx_ptr = TRAP_CONTEXT;
|
||||
let user_satp = current_user_token();
|
||||
|
@ -90,4 +103,9 @@ pub fn trap_return() -> ! {
|
|||
panic!("Unreachable in back_to_user!");
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn trap_from_kernel() -> ! {
|
||||
panic!("a trap from kernel!");
|
||||
}
|
||||
|
||||
pub use context::{TrapContext};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue