-
Notifications
You must be signed in to change notification settings - Fork 5
feat(RV64): implement dynamic memory/cpu decider, timer and interrupt controller #659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
dc941ae to
ae727a2
Compare
ae727a2 to
d665eac
Compare
PeterWrighten
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[WIP] Some Debugging code Modification required
d665eac to
ef55de7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements dynamic memory/CPU detection, timer, and interrupt controller support for the RV64 architecture to close issues #463, #489, and #487. The implementation uses Flattened Device Tree (FDT) parsing to dynamically detect system resources instead of relying on hardcoded values.
Key Changes:
- Added FDT-based dynamic memory and CPU count detection with fallback mechanisms
- Implemented RISC-V PLIC (Platform-Level Interrupt Controller) and timer support
- Restructured boot sequence to initialize heap before memory management (required for page tables)
Reviewed Changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
kernel/src/arch/rv64/timer.rs |
New RISC-V timer implementation using ACLINT MTIME/MTIMECMP registers |
kernel/src/arch/rv64/interrupt_controller.rs |
New PLIC interrupt controller implementation with IPI support |
kernel/src/arch/rv64/kernel_main.rs |
Restructured initialization sequence with dynamic heap allocation and DTB registration |
kernel/src/arch/rv64/boot.S |
Added M-mode trap handlers for timer and software interrupts, DTB pointer preservation |
kernel/src/arch/rv64/config.rs |
Removed hardcoded HEAP_START constant |
awkernel_lib/src/arch/rv64/fdt.rs |
New FDT parser for memory and CPU detection with fallback mechanisms |
awkernel_lib/src/arch/rv64/vm.rs |
Dynamic heap size calculation based on detected memory |
awkernel_lib/src/arch/rv64.rs |
Added memory/CPU detection functions and DTB pointer management |
awkernel_lib/src/arch/rv64/delay.rs |
Fixed uptime calculation to use relative time from boot |
awkernel_lib/src/interrupt.rs |
Added RISC-V specific IRQ handler |
kernel/ld/rv64-link.lds |
Changed entry point from 0x80200000 to 0x80000000 for -bios none |
awkernel_lib/Cargo.toml |
Added fdt crate dependency for rv64 feature |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Created FDT parser for dynamic memory/cpu detection from device tree, with fallback mechanisms - Register and implement RISC-V timer - Register and implement interrupt controller and IPI
ef55de7 to
67fb94e
Compare
…plicit implementation
0667506 to
b52a912
Compare
# Conflicts: # awkernel_lib/src/arch/rv64/vm.rs
158f627 to
1b3a54d
Compare
|
|
||
| // Calculate available memory after kernel | ||
| let kernel_end = PhyAddr::from_usize(ekernel as *const () as usize); | ||
| let memory_end = PhyAddr::from_usize(memory_end_addr as usize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ekernel to MEMORY_END will be used by MMU for the page table as follows.
awkernel/awkernel_lib/src/arch/rv64/frame_allocator.rs
Lines 45 to 49 in e9ef59c
| if let Some(allocator_ref) = allocator.as_mut() { | |
| allocator_ref.init( | |
| PhyAddr::from_usize(ekernel as *const () as usize).ceil(), | |
| PhyAddr::from_usize(MEMORY_END as usize).floor(), | |
| ); |
ekernel to memory_end_addr will be used by heap.
I think some memory frames are used as heap memory and page tables.
As a result of this, the page table will be corrupted.
|
Following pseudo code explain how to construct heap memory region dynamically. fn map_heap_region() {
let mut frame_allocator = FrameAllocator.new(detected_phy_start, detected_phy_end);
let heap_virt_addr_start = SomeValue;
let i = 0;
while let Some(frame) in frame_allocator.alloc() {
page_table.map_to(heap_virt_addr_start + i * PAGE_SIZE, frame.phy_addr, &mut frame_allocator);
i += 1;
}
let detect_heap_end = heap_virt_addr_start + i * PAGE_SIZE;
}
impl PageTable {
fn map_to(virt_addr: VirtAddr, phy_addr: PhysAddr, frame_allocator: &mut FrameAllocator) {
// map `virt_addr` to `phy_addr`
// if necessary, use `frame_allocator.alloc()` to allocate a page for the page table.
}
} |
I consider the following logics would make frame allocator exhausted, but seems a balanced solution. while let Some(frame) in frame_allocator.alloc() {
page_table.map_to(heap_virt_addr_start + i * PAGE_SIZE, frame.phy_addr, &mut frame_allocator);
i += 1;
} |
Yes. |
Description
In order to close #463 , #489, #487 .
Register and implement Interrupt Controller and Timer.
FDT Based Dynamic Decider is implemented as the following design.
Created FDT(Flattened Device Tree) parser for dynamic memory detection from device tree, with
fallback mechanisms. (Using fdt crate)
Dynamic Heap Size and Start Decider implementation in vm.rs
Dynamic CPU Counts implementation.
How was this PR tested?
I tested this heap decider with QEMU memory size 512M, 1G, and 2G. Test results are shown as the following.
Both heap and VM are initialized successfully by using Dynamic Heap Decider.
After Implementation of Interrupt Controller and timer, the RV64 version kernel worked well as the following.