Ready for running user process. TODO: switch page table

master
WangRunji 7 years ago
parent 82739d3d3d
commit 369f3183a3

@ -7,9 +7,7 @@ pub mod pic;
pub mod keyboard; pub mod keyboard;
pub mod pit; pub mod pit;
pub fn init<F>(mut page_map: F) -> acpi::AcpiResult pub fn init(mut page_map: impl FnMut(usize)) -> acpi::AcpiResult {
where F: FnMut(usize) {
assert_has_not_been_called!(); assert_has_not_been_called!();
// TODO Handle this temp page map. // TODO Handle this temp page map.

@ -17,6 +17,16 @@ impl TrapFrame {
tf.iret.rflags = 0x282; tf.iret.rflags = 0x282;
tf tf
} }
pub fn new_user_thread(entry_addr: usize, rsp: usize) -> Self {
use arch::gdt;
let mut tf = TrapFrame::default();
tf.iret.cs = gdt::UCODE_SELECTOR.0 as usize;
tf.iret.rip = entry_addr;
tf.iret.ss = gdt::UDATA_SELECTOR.0 as usize;
tf.iret.rsp = rsp;
tf.iret.rflags = 0x3282;
tf
}
} }
#[inline(always)] #[inline(always)]

@ -27,7 +27,7 @@ impl MemoryArea {
/// 对应ucore中 `mm_struct` /// 对应ucore中 `mm_struct`
pub struct MemorySet { pub struct MemorySet {
areas: Vec<MemoryArea>, areas: Vec<MemoryArea>,
pub(in memory) page_table: Option<InactivePageTable>, page_table: Option<InactivePageTable>,
} }
impl MemorySet { impl MemorySet {
@ -51,16 +51,12 @@ impl MemorySet {
} }
pub fn push(&mut self, area: MemoryArea) { pub fn push(&mut self, area: MemoryArea) {
debug_assert!(area.start_addr <= area.end_addr, "invalid memory area"); debug_assert!(area.start_addr <= area.end_addr, "invalid memory area");
if self.areas.iter() assert!(self.areas.iter()
.find(|other| area.is_overlap_with(other)) .find(|other| area.is_overlap_with(other))
.is_some() { .is_none(), "memory area overlap");
panic!("memory area overlap");
}
self.areas.push(area); self.areas.push(area);
} }
pub fn map(&mut self, active_table: &mut ActivePageTable) { pub fn map(&mut self, pt: &mut Mapper) {
let mut page_table = InactivePageTable::new(alloc_frame(), active_table);
active_table.with(&mut page_table, |pt: &mut Mapper| {
for area in self.areas.iter_mut() { for area in self.areas.iter_mut() {
if area.mapped { if area.mapped {
continue continue
@ -80,8 +76,17 @@ impl MemorySet {
} }
area.mapped = true; area.mapped = true;
} }
}); }
self.page_table = Some(page_table); pub fn unmap(&mut self, pt: &mut Mapper) {
for area in self.areas.iter_mut() {
if !area.mapped {
continue
}
for page in Page::range_of(area.start_addr, area.end_addr) {
pt.unmap(page);
}
area.mapped = false;
}
} }
} }

@ -8,7 +8,6 @@ pub use self::memory_set::*;
use multiboot2::BootInformation; use multiboot2::BootInformation;
use consts::KERNEL_OFFSET; use consts::KERNEL_OFFSET;
use arch::paging; use arch::paging;
use arch::paging::EntryFlags;
use spin::Mutex; use spin::Mutex;
mod memory_set; mod memory_set;
@ -96,10 +95,12 @@ pub fn remap_the_kernel(boot_info: BootInformation) -> (ActivePageTable, Stack)
name: "kernel_heap", name: "kernel_heap",
mapped: false, mapped: false,
}); });
memory_set.map(&mut active_table);
let mut page_table = InactivePageTable::new(alloc_frame(), &mut active_table);
active_table.with(&mut page_table, |pt| memory_set.map(pt));
println!("{:#x?}", memory_set); println!("{:#x?}", memory_set);
let old_table = active_table.switch(memory_set.page_table.take().unwrap()); let old_table = active_table.switch(page_table);
println!("NEW TABLE!!!"); println!("NEW TABLE!!!");
// turn the stack bottom into a guard page // turn the stack bottom into a guard page
@ -208,4 +209,9 @@ impl MemoryController {
let flags = EntryFlags::WRITABLE; let flags = EntryFlags::WRITABLE;
self.active_table.map_to(page, frame, flags); self.active_table.map_to(page, frame, flags);
} }
pub fn make_page_table(&mut self, set: &mut MemorySet) -> InactivePageTable {
let mut page_table = InactivePageTable::new(alloc_frame(), &mut self.active_table);
self.active_table.with(&mut page_table, |pt| set.map(pt));
page_table
}
} }

@ -73,6 +73,13 @@ impl Stack {
pub fn bottom(&self) -> usize { pub fn bottom(&self) -> usize {
self.bottom self.bottom
} }
/// Push a value of type `T` at the top of the stack, return the rsp after.
pub fn push_at_top<T>(&self, value: T) -> usize {
let ptr = unsafe { (self.top as *mut T).offset(-1) };
unsafe { *ptr = value; }
ptr as usize
}
} }
impl Drop for Stack { impl Drop for Stack {

@ -46,6 +46,7 @@ pub fn init(mc: &mut MemoryController) {
_binary_user_forktest_end as usize, mc); _binary_user_forktest_end as usize, mc);
processor.add(initproc); processor.add(initproc);
processor.add(idleproc); processor.add(idleproc);
processor.add(forktest);
processor processor
})}); })});
} }

@ -1,6 +1,6 @@
use super::*; use super::*;
use memory::Stack; use memory::Stack;
use xmas_elf::ElfFile; use xmas_elf::{ElfFile, program::{Flags, ProgramHeader}};
use core::slice; use core::slice;
use alloc::rc::Rc; use alloc::rc::Rc;
@ -12,6 +12,7 @@ pub struct Process {
// memory_set: Rc<MemorySet>, // memory_set: Rc<MemorySet>,
pub(in process) status: Status, pub(in process) status: Status,
pub(in process) rsp: usize, pub(in process) rsp: usize,
pub(in process) is_user: bool,
} }
pub type Pid = usize; pub type Pid = usize;
@ -25,10 +26,8 @@ impl Process {
/// Make a new kernel thread /// Make a new kernel thread
pub fn new(name: &'static str, entry: extern fn(), mc: &mut MemoryController) -> Self { pub fn new(name: &'static str, entry: extern fn(), mc: &mut MemoryController) -> Self {
let kstack = mc.alloc_stack(7).unwrap(); let kstack = mc.alloc_stack(7).unwrap();
let rsp = unsafe{ (kstack.top() as *mut TrapFrame).offset(-1) } as usize; let tf = TrapFrame::new_kernel_thread(entry, kstack.top());
let rsp = kstack.push_at_top(tf);
let tf = unsafe{ &mut *(rsp as *mut TrapFrame) };
*tf = TrapFrame::new_kernel_thread(entry, kstack.top());
Process { Process {
pid: 0, pid: 0,
@ -36,6 +35,7 @@ impl Process {
kstack, kstack,
status: Status::Ready, status: Status::Ready,
rsp, rsp,
is_user: false,
} }
} }
/// Make the first kernel thread `initproc` /// Make the first kernel thread `initproc`
@ -48,40 +48,72 @@ impl Process {
kstack: mc.kernel_stack.take().unwrap(), kstack: mc.kernel_stack.take().unwrap(),
status: Status::Running, status: Status::Running,
rsp: 0, // will be set at first schedule rsp: 0, // will be set at first schedule
is_user: false,
} }
} }
pub fn new_user(begin: usize, end: usize, mc: &mut MemoryController) -> Self { pub fn new_user(begin: usize, end: usize, mc: &mut MemoryController) -> Self {
let slice = unsafe{ slice::from_raw_parts(begin as *const u8, end - begin) }; let slice = unsafe{ slice::from_raw_parts(begin as *const u8, end - begin) };
let elf = ElfFile::new(slice).expect("failed to read elf"); let elf = ElfFile::new(slice).expect("failed to read elf");
let mut set = MemorySet::from(&elf); let phys_start = PhysAddr::from_kernel_virtual(begin);
// set.map(mc); let mut set = MemorySet::from((&elf, phys_start));
unimplemented!(); let page_table = mc.make_page_table(&mut set);
debug!("{:#x?}", set);
use xmas_elf::header::HeaderPt2;
let entry_addr = match elf.header.pt2 {
HeaderPt2::Header64(header) => header.entry_point,
_ => unimplemented!(),
} as usize;
let kstack = mc.alloc_stack(7).unwrap();
let tf = TrapFrame::new_user_thread(entry_addr, kstack.top());
let rsp = kstack.push_at_top(tf);
Process {
pid: 0,
name: "user",
kstack,
status: Status::Ready,
rsp,
is_user: true,
}
} }
} }
use memory::{MemorySet, MemoryArea}; use memory::{MemorySet, MemoryArea, PhysAddr, FromToVirtualAddress, EntryFlags};
impl<'a> From<&'a ElfFile<'a>> for MemorySet {
fn from(elf: &'a ElfFile<'a>) -> Self {
use xmas_elf::program::ProgramHeader;
impl<'a> From<(&'a ElfFile<'a>, PhysAddr)> for MemorySet {
fn from(input: (&'a ElfFile<'a>, PhysAddr)) -> Self {
let (elf, phys_start) = input;
let mut set = MemorySet::new(); let mut set = MemorySet::new();
for ph in elf.program_iter() { for ph in elf.program_iter() {
match ph { let ph = match ph {
ProgramHeader::Ph32(ph) => unimplemented!(), ProgramHeader::Ph64(ph) => ph,
ProgramHeader::Ph64(ph) => { _ => unimplemented!(),
};
set.push(MemoryArea { set.push(MemoryArea {
start_addr: ph.virtual_addr as usize, start_addr: ph.virtual_addr as usize,
end_addr: (ph.virtual_addr + ph.mem_size) as usize, end_addr: (ph.virtual_addr + ph.mem_size) as usize,
phys_start_addr: None, phys_start_addr: Some(PhysAddr(phys_start.get() as u64 + ph.offset)),
flags: ph.flags.0, // TODO: handle it flags: EntryFlags::from(ph.flags).bits() as u32,
name: "", name: "",
mapped: false, mapped: false,
}); });
},
}
} }
set set
} }
} }
impl From<Flags> for EntryFlags {
fn from(elf_flags: Flags) -> Self {
let mut flags = EntryFlags::PRESENT;
if elf_flags.is_write() {
flags = flags | EntryFlags::WRITABLE;
}
if !elf_flags.is_execute() {
flags = flags | EntryFlags::NO_EXECUTE;
}
flags
}
}
Loading…
Cancel
Save