From 1ad3ed738e4b0fecf7ab9372f9fa1032c79fefcb Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sat, 14 Jul 2018 11:56:55 +0800 Subject: [PATCH] Can run user program in RV32 --- crate/riscv | 2 +- kernel/src/arch/riscv32/context.rs | 11 +++++++++-- kernel/src/arch/riscv32/memory.rs | 3 ++- kernel/src/process/process.rs | 26 ++++++++++++-------------- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/crate/riscv b/crate/riscv index a8bbb3e..aa26e4d 160000 --- a/crate/riscv +++ b/crate/riscv @@ -1 +1 @@ -Subproject commit a8bbb3eb031fc377098e1493b14f22ba8448b2ad +Subproject commit aa26e4dd950089e115ae0573bab7fb7aeac7764e diff --git a/kernel/src/arch/riscv32/context.rs b/kernel/src/arch/riscv32/context.rs index d889238..5089784 100644 --- a/kernel/src/arch/riscv32/context.rs +++ b/kernel/src/arch/riscv32/context.rs @@ -24,8 +24,15 @@ impl TrapFrame { tf.sstatus.set_spp(sstatus::SPP::Supervisor); tf } - fn new_user_thread(entry_addr: usize, rsp: usize) -> Self { - unimplemented!() + fn new_user_thread(entry_addr: usize, sp: usize) -> Self { + use core::mem::zeroed; + let mut tf: Self = unsafe { zeroed() }; + tf.x[2] = sp; + tf.sepc = entry_addr; + tf.sstatus = sstatus::read(); + tf.sstatus.set_spie(false); // Enable interrupt + tf.sstatus.set_spp(sstatus::SPP::User); + tf } pub fn is_user(&self) -> bool { unimplemented!() diff --git a/kernel/src/arch/riscv32/memory.rs b/kernel/src/arch/riscv32/memory.rs index d8e7a7d..bd5e409 100644 --- a/kernel/src/arch/riscv32/memory.rs +++ b/kernel/src/arch/riscv32/memory.rs @@ -1,6 +1,6 @@ use core::slice; use memory::{active_table, FRAME_ALLOCATOR, init_heap, MemoryArea, MemoryAttr, MemorySet, Stack}; -use super::riscv::addr::*; +use super::riscv::{addr::*, register::sstatus}; use ucore_memory::PAGE_SIZE; pub fn init() { @@ -8,6 +8,7 @@ pub fn init() { struct PageData([u8; PAGE_SIZE]); static PAGE_TABLE_ROOT: PageData = PageData([0; PAGE_SIZE]); + unsafe { sstatus::set_sum(); } // Allow user memory access let frame = Frame::of_addr(PhysAddr::new(&PAGE_TABLE_ROOT as *const _ as u32)); super::paging::setup_page_table(frame); init_frame_allocator(); diff --git a/kernel/src/process/process.rs b/kernel/src/process/process.rs index 5d096c1..935d251 100644 --- a/kernel/src/process/process.rs +++ b/kernel/src/process/process.rs @@ -1,7 +1,7 @@ use alloc::String; use arch::interrupt::*; use memory::{MemoryArea, MemoryAttr, MemorySet}; -use xmas_elf::{ElfFile, header::HeaderPt2, program::{Flags, ProgramHeader}}; +use xmas_elf::{ElfFile, header, program::{Flags, ProgramHeader, Type}}; #[derive(Debug)] pub struct Process { @@ -55,16 +55,15 @@ impl Process { } } - /// Make a new user thread - /// The program elf data is placed at [begin, end) - /// uCore x86 32bit program is planned to be supported. + /// Make a new user thread from ELF data pub fn new_user(data: &[u8]) -> Self { // Parse elf let elf = ElfFile::new(data).expect("failed to read elf"); let is32 = match elf.header.pt2 { - HeaderPt2::Header32(_) => true, - HeaderPt2::Header64(_) => false, + header::HeaderPt2::Header32(_) => true, + header::HeaderPt2::Header64(_) => false, }; + assert_eq!(elf.header.pt2.type_().as_type(), header::Type::Executable, "ELF is not executable"); // User stack use consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER32_STACK_OFFSET}; @@ -78,19 +77,15 @@ impl Process { memory_set.push(MemoryArea::new(user_stack_buttom, user_stack_top, MemoryAttr::default().user(), "user_stack")); trace!("{:#x?}", memory_set); - let entry_addr = match elf.header.pt2 { - HeaderPt2::Header32(header) => header.entry_point as usize, - HeaderPt2::Header64(header) => header.entry_point as usize, - }; + let entry_addr = elf.header.pt2.entry_point() as usize; // Temporary switch to it, in order to copy data unsafe { memory_set.with(|| { for ph in elf.program_iter() { - let (virt_addr, offset, file_size) = match ph { - ProgramHeader::Ph32(ph) => (ph.virtual_addr as usize, ph.offset as usize, ph.file_size as usize), - ProgramHeader::Ph64(ph) => (ph.virtual_addr as usize, ph.offset as usize, ph.file_size as usize), - }; + let virt_addr = ph.virtual_addr() as usize; + let offset = ph.offset() as usize; + let file_size = ph.file_size() as usize; use core::slice; let target = unsafe { slice::from_raw_parts_mut(virt_addr as *mut u8, file_size) }; target.copy_from_slice(&data[offset..offset + file_size]); @@ -166,6 +161,9 @@ impl Process { fn memory_set_from<'a>(elf: &'a ElfFile<'a>) -> MemorySet { let mut set = MemorySet::new(); for ph in elf.program_iter() { + if ph.get_type() != Ok(Type::Load) { + continue; + } let (virt_addr, mem_size, flags) = match ph { ProgramHeader::Ph32(ph) => (ph.virtual_addr as usize, ph.mem_size as usize, ph.flags), ProgramHeader::Ph64(ph) => (ph.virtual_addr as usize, ph.mem_size as usize, ph.flags),