mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-23 08:26:17 +04:00
Fork (not finished). Not depend on boot_info after remap_kernel.
This commit is contained in:
parent
678d1d2b54
commit
4d6925a562
@ -24,6 +24,7 @@ once = "0.3.3"
|
||||
linked_list_allocator = "0.5.0"
|
||||
redox_syscall = "0.1.37"
|
||||
xmas-elf = "0.6"
|
||||
arrayvec = { version = "0.4.7", default-features = false }
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
|
@ -26,7 +26,7 @@ pub const MAX_CPU_NUM: usize = 8;
|
||||
pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET - PML4_SIZE;
|
||||
pub const KERNEL_HEAP_PML4: usize = (KERNEL_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Size of kernel heap
|
||||
pub const KERNEL_HEAP_SIZE: usize = 1 * 1024 * 1024; // 1 MB
|
||||
pub const KERNEL_HEAP_SIZE: usize = 2 * 1024 * 1024; // 1 MB
|
||||
|
||||
/// Offset to kernel percpu variables
|
||||
//TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;
|
||||
|
@ -33,6 +33,7 @@ extern crate lazy_static;
|
||||
extern crate bit_field;
|
||||
extern crate syscall as redox_syscall;
|
||||
extern crate xmas_elf;
|
||||
extern crate arrayvec;
|
||||
|
||||
#[macro_use] // print!
|
||||
mod io;
|
||||
@ -76,7 +77,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) -> ! {
|
||||
|
||||
// FIXME: 开启SMP后,导致switch_to_user中设置rsp无效
|
||||
// arch::smp::start_other_cores(&acpi, &mut memory_controller);
|
||||
process::init(&mut memory_controller);
|
||||
process::init(memory_controller);
|
||||
|
||||
unsafe{ arch::interrupt::enable(); }
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
use memory::{Frame, FrameAllocator, PhysAddr};
|
||||
use multiboot2::{MemoryAreaIter, MemoryArea};
|
||||
use arrayvec::ArrayVec;
|
||||
|
||||
pub struct AreaFrameAllocator {
|
||||
next_free_frame: Frame,
|
||||
current_area: Option<&'static MemoryArea>,
|
||||
areas: MemoryAreaIter,
|
||||
current_area: Option<Area>,
|
||||
areas: ArrayVec<[Area; 4]>,
|
||||
kernel_start: Frame,
|
||||
kernel_end: Frame,
|
||||
multiboot_start: Frame,
|
||||
@ -62,10 +63,12 @@ impl AreaFrameAllocator {
|
||||
multiboot_start: PhysAddr, multiboot_end: PhysAddr,
|
||||
memory_areas: MemoryAreaIter) -> AreaFrameAllocator
|
||||
{
|
||||
let areas: ArrayVec<[Area; 4]> = memory_areas.map(|a| Area::from(a)).collect();
|
||||
|
||||
let mut allocator = AreaFrameAllocator {
|
||||
next_free_frame: Frame::of_addr(0),
|
||||
current_area: None,
|
||||
areas: memory_areas,
|
||||
areas,
|
||||
kernel_start: Frame::of_addr(kernel_start.0 as usize),
|
||||
kernel_end: Frame::of_addr(kernel_end.0 as usize),
|
||||
multiboot_start: Frame::of_addr(multiboot_start.0 as usize),
|
||||
@ -76,10 +79,11 @@ impl AreaFrameAllocator {
|
||||
}
|
||||
|
||||
fn choose_next_area(&mut self) {
|
||||
self.current_area = self.areas.clone().filter(|area| {
|
||||
self.current_area = self.areas.iter().filter(|area| {
|
||||
let address = area.end_address() - 1;
|
||||
Frame::of_addr(address as usize) >= self.next_free_frame
|
||||
}).min_by_key(|area| area.start_address());
|
||||
}).min_by_key(|area| area.start_address())
|
||||
.map(|area| area.clone());
|
||||
|
||||
if let Some(area) = self.current_area {
|
||||
let start_frame = Frame::of_addr(area.start_address());
|
||||
@ -89,3 +93,30 @@ impl AreaFrameAllocator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Area {
|
||||
start: usize,
|
||||
end: usize,
|
||||
}
|
||||
|
||||
impl Area {
|
||||
pub fn start_address(&self) -> usize {
|
||||
self.start
|
||||
}
|
||||
pub fn end_address(&self) -> usize {
|
||||
self.end
|
||||
}
|
||||
pub fn size(&self) -> usize {
|
||||
self.end - self.start
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a MemoryArea> for Area {
|
||||
fn from(a: &'a MemoryArea) -> Self {
|
||||
Area {
|
||||
start: a.start_address(),
|
||||
end: a.end_address(),
|
||||
}
|
||||
}
|
||||
}
|
@ -44,6 +44,14 @@ impl MemoryArea {
|
||||
name,
|
||||
}
|
||||
}
|
||||
pub unsafe fn as_slice(&self) -> &[u8] {
|
||||
use core::slice;
|
||||
slice::from_raw_parts(self.start_addr as *const u8, self.end_addr - self.start_addr)
|
||||
}
|
||||
pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
|
||||
use core::slice;
|
||||
slice::from_raw_parts_mut(self.start_addr as *mut u8, self.end_addr - self.start_addr)
|
||||
}
|
||||
pub fn contains(&self, addr: VirtAddr) -> bool {
|
||||
addr >= self.start_addr && addr < self.end_addr
|
||||
}
|
||||
@ -58,16 +66,17 @@ impl MemoryArea {
|
||||
|
||||
/// 内存空间集合,包含若干段连续空间
|
||||
/// 对应ucore中 `mm_struct`
|
||||
#[derive(Clone)]
|
||||
pub struct MemorySet {
|
||||
areas: Vec<MemoryArea>,
|
||||
page_table: Option<InactivePageTable>,
|
||||
// page_table: Option<InactivePageTable>,
|
||||
}
|
||||
|
||||
impl MemorySet {
|
||||
pub fn new() -> Self {
|
||||
MemorySet {
|
||||
areas: Vec::<MemoryArea>::new(),
|
||||
page_table: None,
|
||||
// page_table: None,
|
||||
}
|
||||
}
|
||||
/// Used for remap_kernel() where heap alloc is unavailable
|
||||
@ -76,7 +85,7 @@ impl MemorySet {
|
||||
let cap = slice.len() / size_of::<MemoryArea>();
|
||||
MemorySet {
|
||||
areas: Vec::<MemoryArea>::from_raw_parts(slice.as_ptr() as *mut MemoryArea, 0, cap),
|
||||
page_table: None,
|
||||
// page_table: None,
|
||||
}
|
||||
}
|
||||
pub fn find_area(&self, addr: VirtAddr) -> Option<&MemoryArea> {
|
||||
@ -88,8 +97,8 @@ impl MemorySet {
|
||||
.is_none(), "memory area overlap");
|
||||
self.areas.push(area);
|
||||
}
|
||||
pub fn map(&mut self, pt: &mut Mapper) {
|
||||
for area in self.areas.iter_mut() {
|
||||
pub fn map(&self, pt: &mut Mapper) {
|
||||
for area in self.areas.iter() {
|
||||
match area.phys_start_addr {
|
||||
Some(phys_start) => {
|
||||
for page in Page::range_of(area.start_addr, area.end_addr) {
|
||||
@ -105,13 +114,16 @@ impl MemorySet {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn unmap(&mut self, pt: &mut Mapper) {
|
||||
for area in self.areas.iter_mut() {
|
||||
pub fn unmap(&self, pt: &mut Mapper) {
|
||||
for area in self.areas.iter() {
|
||||
for page in Page::range_of(area.start_addr, area.end_addr) {
|
||||
pt.unmap(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn iter(&self) -> impl Iterator<Item=&MemoryArea> {
|
||||
self.areas.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for MemorySet {
|
||||
|
@ -18,8 +18,6 @@ mod stack_allocator;
|
||||
mod address;
|
||||
mod frame;
|
||||
|
||||
pub static ACITVE_PAGETABLE: Mutex<ActivePageTable> = Mutex::new(unsafe { ActivePageTable::new() });
|
||||
|
||||
pub static FRAME_ALLOCATOR: Mutex<Option<AreaFrameAllocator>> = Mutex::new(None);
|
||||
|
||||
pub fn alloc_frame() -> Frame {
|
||||
@ -31,6 +29,8 @@ pub fn alloc_frame() -> Frame {
|
||||
pub fn init(boot_info: BootInformation) -> MemoryController {
|
||||
assert_has_not_been_called!("memory::init must be called only once");
|
||||
|
||||
debug!("{:?}", boot_info);
|
||||
|
||||
let memory_map_tag = boot_info.memory_map_tag().expect(
|
||||
"Memory map tag required");
|
||||
let elf_sections_tag = boot_info.elf_sections_tag().expect(
|
||||
@ -70,14 +70,12 @@ pub fn init(boot_info: BootInformation) -> MemoryController {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remap_the_kernel(boot_info: BootInformation) -> Stack
|
||||
{
|
||||
let mut active_table = ACITVE_PAGETABLE.lock();
|
||||
pub fn remap_the_kernel(boot_info: BootInformation) -> Stack {
|
||||
let mut active_table = unsafe { ActivePageTable::new() };
|
||||
let mut memory_set = MemorySet::from(boot_info.elf_sections_tag().unwrap());
|
||||
|
||||
use consts::{KERNEL_HEAP_OFFSET, KERNEL_HEAP_SIZE};
|
||||
memory_set.push(MemoryArea::new_identity(0xb8000, 0xb9000, EntryFlags::WRITABLE, "VGA"));
|
||||
memory_set.push(MemoryArea::new_identity(boot_info.start_address(), boot_info.end_address(), EntryFlags::PRESENT, "multiboot"));
|
||||
memory_set.push(MemoryArea::new(KERNEL_HEAP_OFFSET, KERNEL_HEAP_OFFSET + KERNEL_HEAP_SIZE, EntryFlags::WRITABLE, "kernel_heap"));
|
||||
|
||||
let mut page_table = InactivePageTable::new(alloc_frame(), &mut active_table);
|
||||
@ -179,7 +177,7 @@ 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 {
|
||||
pub fn make_page_table(&mut self, set: &MemorySet) -> InactivePageTable {
|
||||
let mut page_table = InactivePageTable::new(alloc_frame(), &mut self.active_table);
|
||||
|
||||
use consts::{KERNEL_HEAP_PML4, KERNEL_PML4};
|
||||
|
@ -37,14 +37,14 @@ extern {
|
||||
}
|
||||
|
||||
|
||||
pub fn init(mc: &mut MemoryController) {
|
||||
pub fn init(mut mc: MemoryController) {
|
||||
PROCESSOR.call_once(|| {Mutex::new({
|
||||
let mut processor = Processor::new();
|
||||
let initproc = Process::new_init(mc);
|
||||
let idleproc = Process::new("idle", idle_thread, mc);
|
||||
let initproc = Process::new_init(&mut mc);
|
||||
let idleproc = Process::new("idle", idle_thread, &mut mc);
|
||||
#[cfg(feature = "link_user_program")]
|
||||
let forktest = Process::new_user(_binary_user_forktest_start as usize,
|
||||
_binary_user_forktest_end as usize, mc);
|
||||
_binary_user_forktest_end as usize, &mut mc);
|
||||
let mut processor = Processor::new(mc);
|
||||
processor.add(initproc);
|
||||
processor.add(idleproc);
|
||||
processor.add(forktest);
|
||||
@ -71,6 +71,7 @@ extern fn idle_thread() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fork the current process
|
||||
pub fn fork(tf: &TrapFrame) {
|
||||
unimplemented!()
|
||||
PROCESSOR.try().unwrap().lock().fork(tf);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use memory::{Stack, InactivePageTable};
|
||||
use memory::{self, Stack, InactivePageTable};
|
||||
use xmas_elf::{ElfFile, program::{Flags, ProgramHeader}, header::HeaderPt2};
|
||||
use core::slice;
|
||||
use alloc::rc::Rc;
|
||||
@ -71,7 +71,7 @@ impl Process {
|
||||
let mut memory_set = MemorySet::from(&elf);
|
||||
memory_set.push(MemoryArea::new(USER_STACK_OFFSET, USER_STACK_OFFSET + USER_STACK_SIZE,
|
||||
EntryFlags::WRITABLE | EntryFlags::NO_EXECUTE | EntryFlags::USER_ACCESSIBLE, "user_stack"));
|
||||
let page_table = mc.make_page_table(&mut memory_set);
|
||||
let page_table = mc.make_page_table(&memory_set);
|
||||
debug!("{:#x?}", memory_set);
|
||||
|
||||
// Temporary switch to it, in order to copy data
|
||||
@ -108,9 +108,42 @@ impl Process {
|
||||
}
|
||||
|
||||
/// Fork
|
||||
pub fn fork(&mut self) -> Self {
|
||||
pub fn fork(&self, tf: &TrapFrame, mc: &mut MemoryController) -> Self {
|
||||
assert!(self.is_user);
|
||||
unimplemented!()
|
||||
|
||||
// Clone memory set, make a new page table
|
||||
let memory_set = self.memory_set.as_ref().unwrap().clone();
|
||||
let page_table = mc.make_page_table(&memory_set);
|
||||
|
||||
// Copy data to temp space
|
||||
use alloc::Vec;
|
||||
let datas: Vec<Vec<u8>> = memory_set.iter().map(|area| {
|
||||
Vec::from(unsafe { area.as_slice() })
|
||||
}).collect();
|
||||
|
||||
// Temporary switch to it, in order to copy data
|
||||
let page_table = mc.with(page_table, || {
|
||||
for (area, data) in memory_set.iter().zip(datas.iter()) {
|
||||
unsafe { area.as_slice_mut() }.copy_from_slice(data.as_slice())
|
||||
}
|
||||
});
|
||||
|
||||
// Allocate kernel stack and push trap frame
|
||||
let kstack = mc.alloc_stack(7).unwrap();
|
||||
let mut tf = tf.clone();
|
||||
tf.scratch.rax = 1;
|
||||
let rsp = kstack.push_at_top(tf);
|
||||
|
||||
Process {
|
||||
pid: 0,
|
||||
name: "fork",
|
||||
kstack,
|
||||
memory_set: Some(memory_set),
|
||||
page_table: Some(page_table),
|
||||
status: Status::Ready,
|
||||
rsp,
|
||||
is_user: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,18 @@
|
||||
use alloc::BTreeMap;
|
||||
use memory::{ActivePageTable, InactivePageTable};
|
||||
use super::*;
|
||||
use core::cell::RefCell;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Processor {
|
||||
mc: RefCell<MemoryController>,
|
||||
procs: BTreeMap<Pid, Process>,
|
||||
current_pid: Pid,
|
||||
}
|
||||
|
||||
impl Processor {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(mc: MemoryController) -> Self {
|
||||
Processor {
|
||||
mc: RefCell::new(mc),
|
||||
procs: BTreeMap::<Pid, Process>::new(),
|
||||
current_pid: 0,
|
||||
}
|
||||
@ -73,4 +75,14 @@ impl Processor {
|
||||
self.current_pid = pid;
|
||||
debug!("Processor: switch from {} to {}\n rsp: {:#x} -> {:#x}", pid0, pid, rsp0, rsp);
|
||||
}
|
||||
|
||||
pub fn current(&self) -> &Process {
|
||||
self.procs.get(&self.current_pid).unwrap()
|
||||
}
|
||||
|
||||
/// Fork the current process
|
||||
pub fn fork(&mut self, tf: &TrapFrame) {
|
||||
let new = self.current().fork(tf, &mut self.mc.borrow_mut());
|
||||
self.add(new);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user