mirror of
https://github.com/rcore-os/rCore-Tutorial-v3.git
synced 2024-11-22 01:16:26 +04:00
Frame Allocator OK.
This commit is contained in:
parent
2fd70b0ff4
commit
1256085d36
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,5 +2,7 @@
|
||||
os/target/*
|
||||
os/.idea/*
|
||||
os/src/link_app.S
|
||||
os/Cargo.lock
|
||||
user/target/*
|
||||
user/.idea/*
|
||||
user/.idea/*
|
||||
user/Cargo.lock
|
||||
|
148
os/Cargo.lock
generated
148
os/Cargo.lock
generated
@ -1,148 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "buddy_system_allocator"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4e85e760e105b46ae0bd1236578793c6c147ae7463fe95c8350296b8bfcb830"
|
||||
dependencies = [
|
||||
"spin 0.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
dependencies = [
|
||||
"spin 0.5.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "os"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"buddy_system_allocator",
|
||||
"lazy_static",
|
||||
"riscv",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
|
||||
|
||||
[[package]]
|
||||
name = "riscv"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/rcore-os/riscv#21e32ee1dc786cc0d5006ceee0040ce4f8398575"
|
||||
dependencies = [
|
||||
"bare-metal",
|
||||
"bit_field",
|
||||
"bitflags",
|
||||
"riscv-target",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-target"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "652ac3743312871a5fb703f0337e68ffa3cdc28c863efad0b8dc858fa10c991b"
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
@ -10,6 +10,7 @@ edition = "2018"
|
||||
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
|
||||
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
||||
buddy_system_allocator = "0.6"
|
||||
spin = "0.7.0"
|
||||
|
||||
[features]
|
||||
board_qemu = []
|
||||
|
@ -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;
|
||||
|
@ -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
70
os/src/mm/address.rs
Normal 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) }
|
||||
}
|
118
os/src/mm/frame_allocator.rs
Normal file
118
os/src/mm/frame_allocator.rs
Normal 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!");
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
5
user/Cargo.lock
generated
5
user/Cargo.lock
generated
@ -1,5 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "user_lib"
|
||||
version = "0.1.0"
|
Loading…
Reference in New Issue
Block a user