master
WangRunji 6 years ago
parent 52fe93188d
commit 18640b7537

@ -12,5 +12,6 @@ pub mod cow;
pub mod swap;
pub mod memory_set;
mod addr;
pub mod no_mmu;
pub use crate::addr::*;

@ -0,0 +1,66 @@
use alloc::vec::Vec;
use alloc::alloc::{Layout, GlobalAlloc};
use core::marker::PhantomData;
pub trait NoMMUSupport {
type Alloc: GlobalAlloc;
fn allocator() -> &'static Self::Alloc;
}
#[derive(Clone, Debug)]
pub struct MemorySet<S: NoMMUSupport> {
areas: Vec<MemoryArea<S>>,
support: PhantomData<S>,
}
impl<S: NoMMUSupport> MemorySet<S> {
pub fn new() -> Self {
Self {
areas: Vec::new(),
support: PhantomData,
}
}
/// Allocate `size` bytes space. Return the slice.
pub fn push(&mut self, size: usize) -> &'static mut [u8] {
let area = MemoryArea::new(size);
let slice = unsafe { area.as_buf() };
self.areas.push(area);
slice
}
// empty impls
pub fn with<T>(&self, f: impl FnOnce() -> T) -> T { f() }
pub fn token(&self) -> usize { 0 }
pub unsafe fn activate(&self) {}
}
#[derive(Debug)]
struct MemoryArea<S: NoMMUSupport> {
ptr: usize,
layout: Layout,
support: PhantomData<S>,
}
impl<S: NoMMUSupport> MemoryArea<S> {
fn new(size: usize) -> Self {
let layout = Layout::from_size_align(size, 1).unwrap();
let ptr = unsafe { S::allocator().alloc(layout) } as usize;
MemoryArea { ptr, layout, support: PhantomData }
}
unsafe fn as_buf(&self) -> &'static mut [u8] {
core::slice::from_raw_parts_mut(self.ptr as *mut u8, self.layout.size())
}
}
impl<S: NoMMUSupport> Clone for MemoryArea<S> {
fn clone(&self) -> Self {
let new_area = MemoryArea::new(self.layout.size());
unsafe { new_area.as_buf().copy_from_slice(self.as_buf()) }
new_area
}
}
impl<S: NoMMUSupport> Drop for MemoryArea<S> {
fn drop(&mut self) {
unsafe { S::allocator().dealloc(self.ptr as *mut u8, self.layout) }
}
}

16
kernel/Cargo.lock generated

@ -37,7 +37,7 @@ name = "bcm2837"
version = "0.1.0"
dependencies = [
"cortex-a 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bootloader"
version = "0.3.4"
source = "git+https://github.com/wangrunji0408/bootloader#dd5723c3d7d50856073a5003e0a355ea0fc3d46c"
source = "git+https://github.com/wangrunji0408/bootloader#24bdcafc302e7d2659ac126049a45571462907d9"
dependencies = [
"apic 0.1.0 (git+https://github.com/wangrunji0408/APIC-Rust)",
"fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -132,7 +132,7 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.43"
version = "0.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -185,7 +185,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -324,7 +324,7 @@ dependencies = [
"uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ucore-memory 0.1.0",
"ucore-process 0.1.0",
"volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"x86_64 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -361,7 +361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "volatile"
version = "0.2.4"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -446,7 +446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
"checksum linked_list_allocator 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "655d57c71827fe0891ce72231b6aa5e14033dae3f604609e6a6f807267c1678d"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
@ -472,7 +472,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5"
"checksum ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53d8df5dd8d07fedccd202de1887d94481fadaea3db70479f459e8163a1fab41"
"checksum volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "54d4343a2df2d65144a874f95950754ee7b7e8594f6027aae8c7d0f4858a3fe8"
"checksum volatile 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ca391c55768e479d5c2f8beb40c136df09257292a809ea514e82cfdfc15d00"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

@ -5,8 +5,8 @@ authors = ["Runji Wang <wangrunji0408@163.com>"]
edition = "2018"
[features]
link_user_program = []
no_bbl = []
no_mmu = []
board_raspi3 = []
[profile.dev]

@ -52,7 +52,8 @@ qemu_opts := \
-machine $(board) \
-serial null -serial mon:stdio \
-nographic \
-kernel $(bin)
-kernel $(bin) \
-smp cores=$(smp)
endif
ifdef d
@ -66,10 +67,8 @@ features := $(features) no_bbl
endif
endif
# Link user binaries at ../user
ifdef link_user
features := $(features) link_user_program
assembly_object_files := $(assembly_object_files) $(user_obj)
ifdef nommu
features := $(features) no_mmu
endif
features := $(features) board_$(board)

@ -2,12 +2,24 @@ use core::{slice, mem};
use riscv::{addr::*, register::sstatus};
use ucore_memory::PAGE_SIZE;
use log::*;
use crate::memory::{active_table, FRAME_ALLOCATOR, init_heap, MemoryArea, MemoryAttr, MemorySet};
use crate::memory::{active_table, FRAME_ALLOCATOR, init_heap, MemoryArea, MemoryAttr, MemorySet, MEMORY_ALLOCATOR};
use crate::consts::{MEMORY_OFFSET, MEMORY_END};
#[cfg(feature = "no_mmu")]
pub fn init() {
init_heap();
let heap_bottom = end as usize;
let heap_size = MEMORY_END - heap_bottom;
unsafe { MEMORY_ALLOCATOR.lock().init(heap_bottom, heap_size); }
info!("available memory: [{:#x}, {:#x})", heap_bottom, MEMORY_END);
}
/*
* @brief:
* Init the mermory management module, allow memory access and set up page table and init heap and frame allocator
*/
#[cfg(not(feature = "no_mmu"))]
pub fn init() {
#[repr(align(4096))] // align the PageData struct to 4096 bytes
struct PageData([u8; PAGE_SIZE]);
@ -37,7 +49,6 @@ pub fn init_other() {
fn init_frame_allocator() {
use bit_allocator::BitAlloc;
use core::ops::Range;
use crate::consts::{MEMORY_OFFSET, MEMORY_END};
let mut ba = FRAME_ALLOCATOR.lock();
ba.insert(to_range(end as usize + PAGE_SIZE, MEMORY_END));
@ -63,6 +74,7 @@ fn init_frame_allocator() {
* @brief:
* remmap the kernel memory address with 4K page recorded in p1 page table
*/
#[cfg(not(feature = "no_mmu"))]
fn remap_the_kernel() {
let mut ms = MemorySet::new_bare();
#[cfg(feature = "no_bbl")]

@ -4,16 +4,20 @@ use crate::consts::MEMORY_OFFSET;
use super::HEAP_ALLOCATOR;
use ucore_memory::{*, paging::PageTable};
use ucore_memory::cow::CowExt;
pub use ucore_memory::memory_set::{MemoryArea, MemoryAttr, MemorySet as MemorySet_, InactivePageTable};
pub use ucore_memory::memory_set::{MemoryArea, MemoryAttr, InactivePageTable};
use ucore_memory::swap::*;
use crate::process::{process};
use crate::sync::{SpinNoIrqLock, SpinNoIrq, MutexGuard};
use alloc::collections::VecDeque;
use lazy_static::*;
use log::*;
use linked_list_allocator::LockedHeap;
#[cfg(not(feature = "no_mmu"))]
pub type MemorySet = ucore_memory::memory_set::MemorySet<InactivePageTable0>;
pub type MemorySet = MemorySet_<InactivePageTable0>;
#[cfg(feature = "no_mmu")]
pub type MemorySet = ucore_memory::no_mmu::MemorySet<NoMMUSupportImpl>;
// x86_64 support up to 256M memory
#[cfg(target_arch = "x86_64")]
@ -101,6 +105,7 @@ impl Drop for KernelStack {
* @retval:
* Return true to continue, false to halt
*/
#[cfg(not(feature = "no_mmu"))]
pub fn page_fault_handler(addr: usize) -> bool {
info!("start handling swap in/out page fault");
//unsafe { ACTIVE_TABLE_SWAP.force_unlock(); }
@ -140,6 +145,25 @@ pub fn init_heap() {
info!("heap init end");
}
/// Allocator for the rest memory space on NO-MMU case.
pub static MEMORY_ALLOCATOR: LockedHeap = LockedHeap::empty();
#[derive(Debug, Clone, Copy)]
pub struct NoMMUSupportImpl;
impl ucore_memory::no_mmu::NoMMUSupport for NoMMUSupportImpl {
type Alloc = LockedHeap;
fn allocator() -> &'static Self::Alloc {
&MEMORY_ALLOCATOR
}
}
#[cfg(feature = "no_mmu")]
pub fn page_fault_handler(_addr: usize) -> bool {
unreachable!()
}
//pub mod test {
// pub fn cow() {
// use super::*;

@ -1,6 +1,6 @@
use crate::arch::interrupt::{TrapFrame, Context as ArchContext};
use crate::memory::{MemoryArea, MemoryAttr, MemorySet, KernelStack, active_table_swap, alloc_frame, InactivePageTable0};
use xmas_elf::{ElfFile, header, program::{Flags, ProgramHeader, Type}};
use xmas_elf::{ElfFile, header, program::{Flags, ProgramHeader, Type, SegmentData}};
use core::fmt::{Debug, Error, Formatter};
use alloc::{boxed::Box, collections::BTreeMap, vec::Vec, sync::Arc, string::String};
use ucore_memory::{Page};
@ -75,45 +75,44 @@ impl ContextImpl {
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 crate::consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER32_STACK_OFFSET};
let (ustack_buttom, mut ustack_top) = match is32 {
true => (USER32_STACK_OFFSET, USER32_STACK_OFFSET + USER_STACK_SIZE),
false => (USER_STACK_OFFSET, USER_STACK_OFFSET + USER_STACK_SIZE),
};
match elf.header.pt2.type_().as_type() {
header::Type::Executable => {
// #[cfg(feature = "no_mmu")]
// panic!("ELF is not shared object");
},
header::Type::SharedObject => {},
_ => panic!("ELF is not executable or shared object"),
}
// Make page table
let mut memory_set = memory_set_from(&elf);
memory_set.push(MemoryArea::new(ustack_buttom, ustack_top, MemoryAttr::default().user(), "user_stack"));
trace!("{:#x?}", memory_set);
let entry_addr = elf.header.pt2.entry_point() as usize;
// User stack
use crate::consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER32_STACK_OFFSET};
#[cfg(not(feature = "no_mmu"))]
let mut ustack_top = {
let (ustack_buttom, ustack_top) = match is32 {
true => (USER32_STACK_OFFSET, USER32_STACK_OFFSET + USER_STACK_SIZE),
false => (USER_STACK_OFFSET, USER_STACK_OFFSET + USER_STACK_SIZE),
};
memory_set.push(MemoryArea::new(ustack_buttom, ustack_top, MemoryAttr::default().user(), "user_stack"));
ustack_top
};
#[cfg(feature = "no_mmu")]
let mut ustack_top = memory_set.push(USER_STACK_SIZE).as_ptr() as usize + USER_STACK_SIZE;
// Temporary switch to it, in order to copy data
unsafe {
memory_set.with(|| {
for ph in elf.program_iter() {
let virt_addr = ph.virtual_addr() as usize;
let offset = ph.offset() as usize;
let file_size = ph.file_size() as usize;
let mem_size = ph.mem_size() as usize;
let target = unsafe { ::core::slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size) };
if file_size != 0 {
target[..file_size].copy_from_slice(&data[offset..offset + file_size]);
}
target[file_size..].iter_mut().for_each(|x| *x = 0);
}
ustack_top = push_args_at_stack(args, ustack_top);
});
memory_set.with(|| { ustack_top = push_args_at_stack(args, ustack_top) });
}
trace!("{:#x?}", memory_set);
let entry_addr = elf.header.pt2.entry_point() as usize;
let kstack = KernelStack::new();
//set the user Memory pages in the memory set swappable
#[cfg(not(feature = "no_mmu"))]
memory_set_map_swappable(&mut memory_set);
Box::new(ContextImpl {
@ -135,27 +134,20 @@ impl ContextImpl {
let mut memory_set = self.memory_set.clone();
info!("finish mmset clone in fork!");
info!("before copy data to temp space");
// Copy data to temp space
use alloc::vec::Vec;
let datas: Vec<Vec<u8>> = memory_set.iter().map(|area| {
Vec::from(unsafe { area.as_slice() })
}).collect();
info!("Finish copy data to temp space.");
// Temporarily switch to it, in order to copy data
unsafe {
memory_set.with(|| {
for (area, data) in memory_set.iter().zip(datas.iter()) {
area.as_slice_mut().copy_from_slice(data.as_slice())
}
});
// MMU: copy data to the new space
// NoMMU: coping data has been done in `memory_set.clone()`
#[cfg(not(feature = "no_mmu"))]
for area in memory_set.iter() {
let data = Vec::<u8>::from(unsafe { area.as_slice() });
unsafe { memory_set.with(|| {
area.as_slice_mut().copy_from_slice(data.as_slice())
}) }
}
info!("temporary copy data!");
let kstack = KernelStack::new();
#[cfg(not(feature = "no_mmu"))]
memory_set_map_swappable(&mut memory_set);
info!("FORK() finsihed!");
@ -169,7 +161,8 @@ impl ContextImpl {
}
}
impl Drop for ContextImpl{
#[cfg(not(feature = "no_mmu"))]
impl Drop for ContextImpl {
fn drop(&mut self){
info!("come in to drop for ContextImpl");
//set the user Memory pages in the memory set unswappable
@ -232,19 +225,34 @@ unsafe fn push_args_at_stack<'a, Iter>(args: Iter, stack_top: usize) -> usize
*/
fn memory_set_from<'a>(elf: &'a ElfFile<'a>) -> MemorySet {
debug!("come in to memory_set_from");
let mut set = MemorySet::new();
let mut ms = 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),
let virt_addr = ph.virtual_addr() as usize;
let offset = ph.offset() as usize;
let file_size = ph.file_size() as usize;
let mem_size = ph.mem_size() as usize;
// Get target slice
#[cfg(feature = "no_mmu")]
let target = ms.push(mem_size);
#[cfg(not(feature = "no_mmu"))]
let target = {
ms.push(MemoryArea::new(virt_addr, virt_addr + mem_size, memory_attr_from(ph.flags()), ""));
unsafe { ::core::slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size) }
};
set.push(MemoryArea::new(virt_addr, virt_addr + mem_size, memory_attr_from(flags), ""));
// Copy data
unsafe {
ms.with(|| {
if file_size != 0 {
target[..file_size].copy_from_slice(&elf.input[offset..offset + file_size]);
}
target[file_size..].iter_mut().for_each(|x| *x = 0);
});
}
}
set
ms
}
fn memory_attr_from(elf_flags: Flags) -> MemoryAttr {
@ -260,6 +268,7 @@ fn memory_attr_from(elf_flags: Flags) -> MemoryAttr {
* @brief:
* map the memory area in the memory_set swappalbe, specially for the user process
*/
#[cfg(not(feature = "no_mmu"))]
pub fn memory_set_map_swappable(memory_set: &mut MemorySet){
info!("COME INTO memory set map swappable!");
let pt = unsafe {

Loading…
Cancel
Save