You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
3.0 KiB

use core::{slice, mem};
use riscv::{addr::*, register::sstatus};
use ucore_memory::PAGE_SIZE;
use log::*;
use crate::memory::{active_table, FRAME_ALLOCATOR, init_heap, MemoryArea, MemoryAttr, MemorySet};
/*
* @brief:
* Init the mermory management module, allow memory access and set up page table and init heap and frame allocator
*/
pub fn init() {
#[repr(align(4096))] // align the PageData struct to 4096 bytes
struct PageData([u8; PAGE_SIZE]);
static PAGE_TABLE_ROOT: PageData = PageData([0; PAGE_SIZE]);
unsafe { sstatus::set_sum(); } // Allow user memory access
let frame = Frame::of_addr(PhysAddr::new(&PAGE_TABLE_ROOT as *const _ as u32));
super::paging::setup_page_table(frame); // set up page table
// initialize heap and Frame allocator
init_frame_allocator();
init_heap();
// remap the kernel use 4K page
remap_the_kernel();
}
pub fn init_other() {
unsafe {
sstatus::set_sum(); // Allow user memory access
asm!("csrw 0x180, $0; sfence.vma" :: "r"(SATP) :: "volatile");
}
}
/*
* @brief:
* Init frame allocator, here use a BitAlloc implemented by segment tree.
*/
fn init_frame_allocator() {
use bit_allocator::BitAlloc;
use core::ops::Range;
use crate::consts::{MEMORY_OFFSET, MEMORY_END};
let mut ba = FRAME_ALLOCATOR.lock();
ba.insert(to_range(end as usize + PAGE_SIZE, MEMORY_END));
info!("FrameAllocator init end");
/*
* @param:
* start: start address
* end: end address
* @brief:
* transform the memory address to the page number
* @retval:
* the page number range from start address to end address
*/
fn to_range(start: usize, end: usize) -> Range<usize> {
let page_start = (start - MEMORY_OFFSET) / PAGE_SIZE;
let page_end = (end - MEMORY_OFFSET - 1) / PAGE_SIZE + 1;
page_start..page_end
}
}
/*
* @brief:
* remmap the kernel memory address with 4K page recorded in p1 page table
*/
fn remap_the_kernel() {
let mut ms = MemorySet::new_bare();
#[cfg(feature = "no_bbl")]
ms.push(MemoryArea::new_identity(0x10000000, 0x10000008, MemoryAttr::default(), "serial"));
ms.push(MemoryArea::new_identity(stext as usize, etext as usize, MemoryAttr::default().execute().readonly(), "text"));
ms.push(MemoryArea::new_identity(sdata as usize, edata as usize, MemoryAttr::default(), "data"));
ms.push(MemoryArea::new_identity(srodata as usize, erodata as usize, MemoryAttr::default().readonly(), "rodata"));
ms.push(MemoryArea::new_identity(sbss as usize, ebss as usize, MemoryAttr::default(), "bss"));
unsafe { ms.activate(); }
unsafe { SATP = ms.token(); }
mem::forget(ms);
info!("kernel remap end");
}
// First core stores its SATP here.
// Other cores load it later.
static mut SATP: usize = 0;
// Symbols provided by linker script
extern {
fn stext();
fn etext();
fn sdata();
fn edata();
fn srodata();
fn erodata();
fn sbss();
fn ebss();
fn start();
fn end();
fn bootstack();
fn bootstacktop();
}