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 pit;
pub fn init<F>(mut page_map: F) -> acpi::AcpiResult
where F: FnMut(usize) {
pub fn init(mut page_map: impl FnMut(usize)) -> acpi::AcpiResult {
assert_has_not_been_called!();
// TODO Handle this temp page map.

@ -17,6 +17,16 @@ impl TrapFrame {
tf.iret.rflags = 0x282;
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)]

@ -27,7 +27,7 @@ impl MemoryArea {
/// 对应ucore中 `mm_struct`
pub struct MemorySet {
areas: Vec<MemoryArea>,
pub(in memory) page_table: Option<InactivePageTable>,
page_table: Option<InactivePageTable>,
}
impl MemorySet {
@ -51,37 +51,42 @@ impl MemorySet {
}
pub fn push(&mut self, area: MemoryArea) {
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))
.is_some() {
panic!("memory area overlap");
}
.is_none(), "memory area overlap");
self.areas.push(area);
}
pub fn map(&mut self, active_table: &mut ActivePageTable) {
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() {
if area.mapped {
continue
}
match area.phys_start_addr {
Some(phys_start) => {
for page in Page::range_of(area.start_addr, area.end_addr) {
let frame = Frame::of_addr(phys_start.get() + page.start_address() - area.start_addr);
pt.map_to(page, frame.clone(), EntryFlags::from_bits(area.flags.into()).unwrap());
}
},
None => {
for page in Page::range_of(area.start_addr, area.end_addr) {
pt.map(page, EntryFlags::from_bits(area.flags.into()).unwrap());
}
},
}
area.mapped = true;
pub fn map(&mut self, pt: &mut Mapper) {
for area in self.areas.iter_mut() {
if area.mapped {
continue
}
});
self.page_table = Some(page_table);
match area.phys_start_addr {
Some(phys_start) => {
for page in Page::range_of(area.start_addr, area.end_addr) {
let frame = Frame::of_addr(phys_start.get() + page.start_address() - area.start_addr);
pt.map_to(page, frame.clone(), EntryFlags::from_bits(area.flags.into()).unwrap());
}
},
None => {
for page in Page::range_of(area.start_addr, area.end_addr) {
pt.map(page, EntryFlags::from_bits(area.flags.into()).unwrap());
}
},
}
area.mapped = true;
}
}
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 consts::KERNEL_OFFSET;
use arch::paging;
use arch::paging::EntryFlags;
use spin::Mutex;
mod memory_set;
@ -96,10 +95,12 @@ pub fn remap_the_kernel(boot_info: BootInformation) -> (ActivePageTable, Stack)
name: "kernel_heap",
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);
let old_table = active_table.switch(memory_set.page_table.take().unwrap());
let old_table = active_table.switch(page_table);
println!("NEW TABLE!!!");
// turn the stack bottom into a guard page
@ -208,4 +209,9 @@ impl MemoryController {
let flags = EntryFlags::WRITABLE;
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 {
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 {

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

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