Frame Allocator OK.

This commit is contained in:
Yifan Wu 2020-12-03 10:40:30 +08:00
parent 528d99258a
commit e37e5708e4
9 changed files with 205 additions and 158 deletions

View file

@ -4,6 +4,9 @@ pub const MAX_APP_NUM: usize = 4;
pub const APP_BASE_ADDRESS: usize = 0x80100000;
pub const APP_SIZE_LIMIT: usize = 0x20000;
pub const KERNEL_HEAP_SIZE: usize = 0x30_0000;
pub const MEMORY_END: usize = 0x80800000;
pub const PAGE_SIZE: usize = 0x1000;
pub const PAGE_SIZE_BITS: usize = 0xc;
#[cfg(feature = "board_k210")]
pub const CPU_FREQ: usize = 10000000;

View file

@ -37,8 +37,7 @@ fn clear_bss() {
pub fn rust_main() -> ! {
clear_bss();
println!("[kernel] Hello, world!");
mm::init_heap();
mm::heap_test();
mm::init();
loop {}
trap::init();
loader::load_apps();

70
os/src/mm/address.rs Normal file
View file

@ -0,0 +1,70 @@
/// T: {PhysAddr, VirtAddr, PhysPageNum, VirtPageNum}
/// T -> usize: T.0
/// usize -> T: usize.into()
use crate::config::{PAGE_SIZE, PAGE_SIZE_BITS};
/// Definitions
#[derive(Copy, Clone, Debug)]
pub struct PhysAddr(pub usize);
#[derive(Copy, Clone, Debug)]
pub struct VirtAddr(pub usize);
#[derive(Copy, Clone, Debug)]
pub struct PhysPageNum(pub usize);
#[derive(Copy, Clone, Debug)]
pub struct VirtPageNum(pub usize);
impl From<usize> for PhysAddr {
fn from(v: usize) -> Self { Self(v) }
}
impl From<usize> for PhysPageNum {
fn from(v: usize) -> Self { Self(v) }
}
impl From<PhysAddr> for usize {
fn from(v: PhysAddr) -> Self { v.0 }
}
impl From<PhysPageNum> for usize {
fn from(v: PhysPageNum) -> Self { v.0 }
}
impl From<usize> for VirtAddr {
fn from(v: usize) -> Self { Self(v) }
}
impl From<usize> for VirtPageNum {
fn from(v: usize) -> Self { Self(v) }
}
impl From<VirtAddr> for usize {
fn from(v: VirtAddr) -> Self { v.0 }
}
impl From<VirtPageNum> for usize {
fn from(v: VirtPageNum) -> Self { v.0 }
}
impl VirtAddr {
pub fn floor(&self) -> VirtPageNum { VirtPageNum(self.0 / PAGE_SIZE) }
pub fn ceil(&self) -> VirtPageNum { VirtPageNum((self.0 + PAGE_SIZE - 1) / PAGE_SIZE) }
pub fn page_offset(&self) -> usize { self.0 & (PAGE_SIZE - 1) }
}
impl From<VirtAddr> for VirtPageNum {
fn from(v: VirtAddr) -> Self {
assert_eq!(v.page_offset(), 0);
v.floor()
}
}
impl From<VirtPageNum> for VirtAddr {
fn from(v: VirtPageNum) -> Self { Self(v.0 << PAGE_SIZE_BITS) }
}
impl PhysAddr {
pub fn floor(&self) -> PhysPageNum { PhysPageNum(self.0 / PAGE_SIZE) }
pub fn ceil(&self) -> PhysPageNum { PhysPageNum((self.0 + PAGE_SIZE - 1) / PAGE_SIZE) }
pub fn page_offset(&self) -> usize { self.0 & (PAGE_SIZE - 1) }
}
impl From<PhysAddr> for PhysPageNum {
fn from(v: PhysAddr) -> Self {
assert_eq!(v.page_offset(), 0);
v.floor()
}
}
impl From<PhysPageNum> for PhysAddr {
fn from(v: PhysPageNum) -> Self { Self(v.0 << PAGE_SIZE_BITS) }
}

View file

@ -0,0 +1,118 @@
use super::{PhysAddr, PhysPageNum};
use alloc::vec::Vec;
use spin::Mutex;
use crate::config::MEMORY_END;
use lazy_static::*;
use core::fmt::{self, Debug, Formatter};
pub struct FrameTracker(PhysPageNum);
impl Debug for FrameTracker {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!("FrameTracker:PPN={:#x}", self.0.0))
}
}
impl Drop for FrameTracker {
fn drop(&mut self) {
frame_dealloc(self.0);
}
}
trait FrameAllocator {
fn new() -> Self;
fn alloc(&mut self) -> Option<PhysPageNum>;
fn dealloc(&mut self, ppn: PhysPageNum);
}
pub struct StackFrameAllocator {
current: usize,
end: usize,
recycled: Vec<usize>,
}
impl StackFrameAllocator {
pub fn init(&mut self, l: PhysPageNum, r: PhysPageNum) {
self.current = l.0;
self.end = r.0;
}
}
impl FrameAllocator for StackFrameAllocator {
fn new() -> Self {
Self {
current: 0,
end: 0,
recycled: Vec::new(),
}
}
fn alloc(&mut self) -> Option<PhysPageNum> {
if let Some(ppn) = self.recycled.pop() {
Some(ppn.into())
} else {
if self.current == self.end {
None
} else {
self.current += 1;
Some((self.current - 1).into())
}
}
}
fn dealloc(&mut self, ppn: PhysPageNum) {
let ppn = ppn.0;
// validity check
if ppn >= self.current || self.recycled
.iter()
.find(|&v| {*v == ppn})
.is_some() {
panic!("Frame ppn={:#x} has not been allocated!", ppn);
}
// recycle
self.recycled.push(ppn);
}
}
type FrameAllocatorImpl = StackFrameAllocator;
lazy_static! {
pub static ref FRAME_ALLOCATOR: Mutex<FrameAllocatorImpl> =
Mutex::new(FrameAllocatorImpl::new());
}
pub fn init_frame_allocator() {
extern "C" {
fn ekernel();
}
FRAME_ALLOCATOR
.lock()
.init(PhysAddr::from(ekernel as usize).ceil(), PhysAddr::from(MEMORY_END).floor());
}
pub fn frame_alloc() -> Option<FrameTracker> {
FRAME_ALLOCATOR
.lock()
.alloc()
.map(|ppn| FrameTracker(ppn))
}
fn frame_dealloc(ppn: PhysPageNum) {
FRAME_ALLOCATOR
.lock()
.dealloc(ppn);
}
#[allow(unused)]
pub fn frame_allocator_test() {
let mut v: Vec<FrameTracker> = Vec::new();
for i in 0..5 {
let frame = frame_alloc().unwrap();
println!("{:?}", frame);
v.push(frame);
}
v.clear();
for i in 0..5 {
let frame = frame_alloc().unwrap();
println!("{:?}", frame);
v.push(frame);
}
drop(v);
println!("frame_allocator_test passed!");
}

View file

@ -1,4 +1,11 @@
mod heap_allocator;
mod address;
mod frame_allocator;
pub use heap_allocator::init_heap;
pub use heap_allocator::heap_test;
pub use address::{PhysAddr, VirtAddr, PhysPageNum, VirtPageNum};
pub use frame_allocator::{FrameTracker, frame_alloc};
pub fn init() {
heap_allocator::init_heap();
frame_allocator::init_frame_allocator();
}