Skip to content

Commit 4afc124

Browse files
committed
Step 0-3: add heap and frame allocators
1 parent b8aa920 commit 4afc124

8 files changed

Lines changed: 162 additions & 0 deletions

File tree

hypervisor/Cargo.lock

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hypervisor/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ log = "0.4"
1111
spin = "0.9"
1212
cfg-if = "1.0"
1313
bitflags = "1.3"
14+
buddy_system_allocator = "0.8"
1415
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
16+
bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "88e871a" }
1517

1618
[target.'cfg(target_arch = "x86_64")'.dependencies]
1719
x86 = "0.52"

hypervisor/src/config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
pub const PHYS_VIRT_OFFSET: usize = 0xffff_ff80_0000_0000;
22

33
pub const BOOT_KERNEL_STACK_SIZE: usize = 4096 * 4; // 16K
4+
pub const KERNEL_HEAP_SIZE: usize = 0x40_0000; // 4M
5+
6+
pub const PHYS_MEMORY_BASE: usize = 0;
7+
pub const PHYS_MEMORY_SIZE: usize = 0x400_0000; // 64M
8+
pub const PHYS_MEMORY_END: usize = PHYS_MEMORY_BASE + PHYS_MEMORY_SIZE;
49

510
pub const TICKS_PER_SEC: u64 = 100;

hypervisor/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod logging;
1111

1212
mod arch;
1313
mod config;
14+
mod mm;
1415
mod timer;
1516

1617
#[cfg(not(test))]
@@ -64,10 +65,12 @@ fn main() -> ! {
6465
option_env!("LOG").unwrap_or(""),
6566
);
6667

68+
mm::init_heap_early();
6769
logging::init();
6870
info!("Logging is enabled.");
6971

7072
arch::init();
73+
mm::init();
7174
INIT_OK.store(true, Ordering::SeqCst);
7275
println!("Initialization completed.\n");
7376

hypervisor/src/mm/address.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use super::PAGE_SIZE;
2+
use crate::config::PHYS_VIRT_OFFSET;
3+
4+
pub(super) type PhysAddr = usize;
5+
pub(super) type VirtAddr = usize;
6+
7+
pub const fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
8+
paddr + PHYS_VIRT_OFFSET
9+
}
10+
11+
pub const fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
12+
vaddr - PHYS_VIRT_OFFSET
13+
}
14+
15+
pub const fn align_down(addr: usize) -> usize {
16+
addr & !(PAGE_SIZE - 1)
17+
}
18+
19+
pub const fn align_up(addr: usize) -> usize {
20+
(addr + PAGE_SIZE - 1) & !(PAGE_SIZE - 1)
21+
}

hypervisor/src/mm/frame.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use bitmap_allocator::BitAlloc;
2+
use spin::Mutex;
3+
4+
use super::address::{align_down, align_up, virt_to_phys, PhysAddr};
5+
use super::PAGE_SIZE;
6+
use crate::config::PHYS_MEMORY_END;
7+
8+
// Support max 1M * 4096 = 1GB memory.
9+
type FrameAlloc = bitmap_allocator::BitAlloc1M;
10+
11+
static FRAME_ALLOCATOR: Mutex<FrameAllocator> = Mutex::new(FrameAllocator::empty());
12+
13+
struct FrameAllocator {
14+
base: PhysAddr,
15+
inner: FrameAlloc,
16+
}
17+
18+
impl FrameAllocator {
19+
const fn empty() -> Self {
20+
Self {
21+
base: 0,
22+
inner: FrameAlloc::DEFAULT,
23+
}
24+
}
25+
26+
fn init(&mut self, base: PhysAddr, size: usize) {
27+
self.base = align_up(base);
28+
let page_count = align_up(size) / PAGE_SIZE;
29+
self.inner.insert(0..page_count);
30+
}
31+
32+
unsafe fn alloc(&mut self) -> Option<PhysAddr> {
33+
let ret = self.inner.alloc().map(|idx| idx * PAGE_SIZE + self.base);
34+
trace!("Allocate frame: {:x?}", ret);
35+
ret
36+
}
37+
38+
unsafe fn dealloc(&mut self, target: PhysAddr) {
39+
trace!("Deallocate frame: {:x}", target);
40+
self.inner.dealloc((target - self.base) / PAGE_SIZE)
41+
}
42+
}
43+
44+
pub unsafe fn alloc_page() -> Option<PhysAddr> {
45+
FRAME_ALLOCATOR.lock().alloc()
46+
}
47+
48+
pub unsafe fn dealloc_page(paddr: PhysAddr) {
49+
FRAME_ALLOCATOR.lock().dealloc(paddr)
50+
}
51+
52+
pub(super) fn init() {
53+
extern "C" {
54+
fn ekernel();
55+
}
56+
57+
let mem_pool_start = align_up(virt_to_phys(ekernel as usize));
58+
let mem_pool_end = align_down(PHYS_MEMORY_END);
59+
let mem_pool_size = mem_pool_end - mem_pool_start;
60+
println!(
61+
"Initializing frame allocator at: [{:#x?}, {:#x?})",
62+
mem_pool_start, mem_pool_end
63+
);
64+
FRAME_ALLOCATOR.lock().init(mem_pool_start, mem_pool_size);
65+
}

hypervisor/src/mm/heap.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use buddy_system_allocator::LockedHeap;
2+
use core::{alloc::Layout, mem::size_of};
3+
4+
use crate::config::KERNEL_HEAP_SIZE;
5+
6+
#[global_allocator]
7+
static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::empty();
8+
9+
#[alloc_error_handler]
10+
fn handle_alloc_error(layout: Layout) -> ! {
11+
panic!("Heap allocation error, layout = {:?}", layout);
12+
}
13+
14+
static mut HEAP_SPACE: [u64; KERNEL_HEAP_SIZE / size_of::<u64>()] =
15+
[0; KERNEL_HEAP_SIZE / size_of::<u64>()];
16+
17+
pub(super) fn init() {
18+
let heap_start = unsafe { HEAP_SPACE.as_ptr() as usize };
19+
println!(
20+
"Initializing heap at: [{:#x}, {:#x})",
21+
heap_start,
22+
heap_start + KERNEL_HEAP_SIZE
23+
);
24+
unsafe { HEAP_ALLOCATOR.lock().init(heap_start, KERNEL_HEAP_SIZE) }
25+
}

hypervisor/src/mm/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![allow(dead_code)]
2+
3+
mod heap;
4+
5+
pub mod address;
6+
pub mod frame;
7+
8+
pub const PAGE_SIZE: usize = 0x1000;
9+
10+
pub fn init_heap_early() {
11+
heap::init();
12+
}
13+
14+
pub fn init() {
15+
frame::init();
16+
}

0 commit comments

Comments
 (0)