Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions os/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion os/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ edition = "2024"

[dependencies]
sbi-rt = { version = "0.0.2", features = ["legacy"] }
riscv = "0.15.0"
riscv = "0.15.0"
talc = { version = "4" }
lock_api = "0.4"
8 changes: 7 additions & 1 deletion os/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// constants for the operating system
//! constants for the operating system (platform-independent)
#![allow(unused)]

// about memory management
pub const PAGE_SIZE: usize = 4096;
pub const KERNEL_HEAP_SIZE: usize = 16 * 1024 * 1024; // 16MB
pub const USER_STACK_SIZE: usize = 4 * 1024 * 1024; // 4MB

// memory layout constants
// temporarily set for QEMU RISC-V virt machine
// FIXME: refactor it to arch/riscv because it's platform-dependent
// TODO: fetch it form device tree in the future(after/while implemented devices feature)
pub const MEMORY_END: usize = 0x88000000; // 128MB for QEMU RISC-V virt

pub use crate::arch::platform::qemu::*;
3 changes: 3 additions & 0 deletions os/src/linker.ld
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ SECTIONS

. = ALIGN(4K);
ebss = .;
sheap = .;
. = . + 16M;
eheap = .;
ekernel = .;

/DISCARD/ : {
Expand Down
28 changes: 7 additions & 21 deletions os/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,6 @@

extern crate alloc;

use core::alloc::{GlobalAlloc, Layout};

/// TODO: replace with proper heap allocator
/// Dummy allocator that always fails - placeholder until heap allocator is implemented
struct DummyAllocator;

unsafe impl GlobalAlloc for DummyAllocator {
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
core::ptr::null_mut()
}

unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
panic!("dealloc called on DummyAllocator");
}
}

#[global_allocator]
static ALLOCATOR: DummyAllocator = DummyAllocator;

#[macro_use]
mod console;
mod sbi;
Expand Down Expand Up @@ -52,17 +33,22 @@ global_asm!(include_str!("entry.asm"));

#[unsafe(no_mangle)]
pub extern "C" fn rust_main() -> ! {
unsafe extern "C" {
fn ekernel();
}
clear_bss();
mm::init_frame_allocator(ekernel as usize, config::MEMORY_END);
mm::init_heap();
println!("Hello, world!");

// 初始化工作
trap::init();
timer::init();
trap::enable_interrupts();

#[cfg(test)]
test_main();

shutdown(false)
}

Expand Down
91 changes: 91 additions & 0 deletions os/src/mm/global_allocator/global_allocator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//! Global allocator module
//!
//! This module provides dynamic heap memory allocation functionality using the talc allocator.
//!
//! # Components
//!
//! - Global heap allocator based on talc::Talck
//! - Heap memory region defined by linker symbols
//! - Initialization function to set up the heap

use core::cell::UnsafeCell;
use lock_api::{GuardSend, RawMutex};
use talc::{Span, Talc, Talck};

/// Empty mutex implementation for single-core, single-task environment
///
/// This is a zero-overhead placeholder that provides no actual locking,
/// as it's only used before multitasking is enabled.
///
/// TODO: Replace with proper synchronization primitive when multitasking is implemented
pub struct EmptyRawMutex;

unsafe impl RawMutex for EmptyRawMutex {
#[allow(clippy::declare_interior_mutable_const)]
const INIT: Self = EmptyRawMutex;

type GuardMarker = GuardSend;

fn lock(&self) {
// No-op: single-task environment doesn't need locking
}

fn try_lock(&self) -> bool {
// Always succeeds: no contention possible
true
}

unsafe fn unlock(&self) {
// No-op: nothing to unlock
}
}

/// Global heap allocator instance
///
/// Uses talc's lock-based allocator (Talck) with a placeholder empty mutex.
/// In single-core, single-task environment, locking is not needed.
///
/// Initialized with an empty span; actual memory will be claimed in init_heap().
#[global_allocator]
static ALLOCATOR: Talck<EmptyRawMutex, talc::ClaimOnOom> = Talc::new(unsafe {
talc::ClaimOnOom::new(Span::empty())
})
.lock();

/// Initialize the heap allocator with the heap memory region defined in linker script
///
/// This function must be called early in the boot process, after BSS clearing
/// but before any heap allocations are attempted.
///
/// # Safety
///
/// - Must be called exactly once during boot
/// - Must be called before any heap allocations
/// - Heap region defined by linker symbols (sheap, eheap) must be valid
pub fn init_heap() {
unsafe extern "C" {
fn sheap();
fn eheap();
}

let heap_start = sheap as usize;
let heap_end = eheap as usize;
let heap_size = heap_end - heap_start;

println!(
"Initializing heap: start={:#x}, end={:#x}, size={:#x} ({} MB)",
heap_start,
heap_end,
heap_size,
heap_size / 1024 / 1024
);

unsafe {
ALLOCATOR
.lock()
.claim(Span::new(heap_start as *mut u8, heap_end as *mut u8))
.expect("Failed to initialize heap allocator");
}

println!("Heap allocator initialized successfully");
}
11 changes: 11 additions & 0 deletions os/src/mm/global_allocator/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! Global allocator module
//!
//! This module provides dynamic heap memory allocation functionality using the talc allocator.
//!
//! # Components
//!
//! - [`init_heap`]: Initialize the global heap allocator

mod global_allocator;

pub use global_allocator::init_heap;
7 changes: 6 additions & 1 deletion os/src/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
//!
//! - [`address`]: Address and page number abstractions
//! - [`frame_allocator`]: Physical frame allocation
//! - [`global_allocator`]: Global heap allocator

mod address;
mod frame_allocator;
mod frame_allocator;
mod global_allocator;

pub use frame_allocator::init_frame_allocator;
pub use global_allocator::init_heap;