riscv: 把内核编译target改为riscv64gc & 获取time csr的频率 & 修正浮点保存与恢复的汇编的问题 (#699)

* 1. 把内核编译target改为riscv64gc
2. fix: 修正浮点保存与恢复的汇编的问题

* riscv: 获取time csr的频率
This commit is contained in:
LoGin
2024-04-06 22:13:26 +08:00
committed by GitHub
parent f0c87a897f
commit 23ef2b33d1
28 changed files with 373 additions and 229 deletions

View File

@ -58,6 +58,7 @@ pub unsafe fn mm_init() {
Ordering::SeqCst,
)
.unwrap();
MMArch::arch_post_init();
kinfo!("mm init done.");
}

View File

@ -1,8 +1,9 @@
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::page::{PAGE_1G_SHIFT, PAGE_4K_SHIFT};
use crate::process::ProcessManager;
use crate::{
include::bindings::bindings::{PAGE_1G_SHIFT, PAGE_4K_SHIFT, PAGE_4K_SIZE},
include::bindings::bindings::PAGE_4K_SIZE,
kdebug,
mm::{MMArch, MemoryManagementArch},
};
@ -10,22 +11,19 @@ use crate::{kerror, kinfo, kwarn};
use alloc::{collections::LinkedList, vec::Vec};
use core::mem;
use core::mem::MaybeUninit;
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
use core::sync::atomic::{AtomicBool, Ordering};
use system_error::SystemError;
use super::page::PageFlags;
use super::{PhysAddr, VirtAddr};
// 最大的伙伴块的幂
const MMIO_BUDDY_MAX_EXP: u32 = PAGE_1G_SHIFT;
const MMIO_BUDDY_MAX_EXP: u32 = PAGE_1G_SHIFT as u32;
// 最小的伙伴块的幂
const MMIO_BUDDY_MIN_EXP: u32 = PAGE_4K_SHIFT;
const MMIO_BUDDY_MIN_EXP: u32 = PAGE_4K_SHIFT as u32;
// 内存池数组的范围
const MMIO_BUDDY_REGION_COUNT: u32 = MMIO_BUDDY_MAX_EXP - MMIO_BUDDY_MIN_EXP + 1;
const MMIO_BASE: VirtAddr = VirtAddr::new(0xffffa10000000000);
const MMIO_TOP: VirtAddr = VirtAddr::new(0xffffa20000000000);
const PAGE_1G_SIZE: usize = 1 << 30;
static mut __MMIO_POOL: Option<MmioBuddyMemPool> = None;
@ -65,26 +63,35 @@ impl MmioBuddyMemPool {
};
let pool = MmioBuddyMemPool {
pool_start_addr: MMIO_BASE,
pool_size: MMIO_TOP - MMIO_BASE,
pool_start_addr: MMArch::MMIO_BASE,
pool_size: MMArch::MMIO_SIZE,
free_regions,
};
assert!(pool.pool_start_addr.data() % PAGE_1G_SIZE == 0);
kdebug!("MMIO buddy pool init: created");
let cnt_1g_blocks = (MMIO_TOP - MMIO_BASE) >> 30;
let mut vaddr_base = MMIO_BASE;
kdebug!("total 1G blocks: {cnt_1g_blocks}");
for _i in 0..cnt_1g_blocks {
compiler_fence(Ordering::SeqCst);
match pool.give_back_block(vaddr_base, PAGE_1G_SHIFT) {
Ok(_) => {
vaddr_base += PAGE_1G_SIZE;
}
Err(_) => {
let mut vaddr_base = MMArch::MMIO_BASE;
let mut remain_size = MMArch::MMIO_SIZE;
kdebug!(
"BASE: {:?}, TOP: {:?}, size: {:?}",
MMArch::MMIO_BASE,
MMArch::MMIO_TOP,
MMArch::MMIO_SIZE
);
for shift in (PAGE_4K_SHIFT..=PAGE_1G_SHIFT).rev() {
if remain_size & (1 << shift) != 0 {
let ok = pool.give_back_block(vaddr_base, shift as u32).is_ok();
if ok {
vaddr_base += 1 << shift;
remain_size -= 1 << shift;
} else {
panic!("MMIO buddy pool init failed");
}
}
}
kdebug!("MMIO buddy pool init success");
return pool;
}
@ -297,9 +304,9 @@ impl MmioBuddyMemPool {
/// @return Ok(MmioBuddyAddrRegion)符合要求的内存块信息结构体。
/// @return Err(MmioResult) 没有满足要求的内存块时返回__query_addr_region的错误码。
fn mmio_buddy_query_addr_region(&self, exp: u32) -> Result<MmioBuddyAddrRegion, MmioResult> {
let list_guard: &mut SpinLockGuard<MmioFreeRegionList> =
&mut self.free_regions[exp2index(exp)].lock();
match self.query_addr_region(exp, list_guard) {
let mut list_guard: SpinLockGuard<MmioFreeRegionList> =
self.free_regions[exp2index(exp)].lock();
match self.query_addr_region(exp, &mut list_guard) {
Ok(ret) => return Ok(ret),
Err(err) => {
kdebug!("mmio_buddy_query_addr_region failed");
@ -487,9 +494,9 @@ impl MmioBuddyMemPool {
let mut new_size = size;
// 对齐要申请的空间大小
// 如果要申请的空间大小小于4k则分配4k
if size_exp < PAGE_4K_SHIFT {
if size_exp < PAGE_4K_SHIFT as u32 {
new_size = PAGE_4K_SIZE as usize;
size_exp = PAGE_4K_SHIFT;
size_exp = PAGE_4K_SHIFT as u32;
} else if (new_size & (!(1 << size_exp))) != 0 {
// 向左对齐空间大小
size_exp += 1;
@ -630,7 +637,8 @@ impl MMIOSpaceGuard {
"MMIO space vaddr must be aligned with size"
);
assert!(
vaddr.data() >= MMIO_BASE.data() && vaddr.data() + size <= MMIO_TOP.data(),
vaddr.data() >= MMArch::MMIO_BASE.data()
&& vaddr.data() + size <= MMArch::MMIO_TOP.data(),
"MMIO space must be in MMIO region"
);

View File

@ -492,10 +492,20 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
const FIXMAP_END_VADDR: VirtAddr =
VirtAddr::new(Self::FIXMAP_START_VADDR.data() + Self::FIXMAP_SIZE);
/// MMIO虚拟空间的基地址
const MMIO_BASE: VirtAddr;
/// MMIO虚拟空间的大小
const MMIO_SIZE: usize;
/// MMIO虚拟空间的顶端地址不包含
const MMIO_TOP: VirtAddr = VirtAddr::new(Self::MMIO_BASE.data() + Self::MMIO_SIZE);
/// @brief 用于初始化内存管理模块与架构相关的信息。
/// 该函数应调用其他模块的接口把可用内存区域添加到memblock提供给BumpAllocator使用
unsafe fn init();
/// 内存管理初始化完成后,调用该函数
unsafe fn arch_post_init() {}
/// @brief 读取指定虚拟地址的值并假设它是类型T的指针
#[inline(always)]
unsafe fn read<T>(address: VirtAddr) -> T {

View File

@ -21,6 +21,11 @@ use super::{
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
};
pub const PAGE_4K_SHIFT: usize = 12;
#[allow(dead_code)]
pub const PAGE_2M_SHIFT: usize = 21;
pub const PAGE_1G_SHIFT: usize = 30;
/// 全局物理页信息管理器
pub static mut PAGE_MANAGER: Option<SpinLock<PageManager>> = None;