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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 373 additions and 229 deletions

1
.gitignore vendored
View File

@ -20,4 +20,3 @@ Cargo.lock
.cache
compile_commands.json
/logs/
.vscode

View File

@ -152,7 +152,7 @@
"./tools/Cargo.toml",
],
// "rust-analyzer.cargo.target": "riscv64imac-unknown-none-elf",
// "rust-analyzer.cargo.target": "riscv64gc-unknown-none-elf",
"rust-analyzer.cargo.target": "x86_64-unknown-none",
"rust-analyzer.check.overrideCommand": [
"make",

View File

@ -31,8 +31,9 @@ impl CFilesArch for RiscV64CFilesArch {
// // c.flag("-march=rv64imafdc");
// c.no_default_flags(true);
c.flag("-mcmodel=medany");
c.flag("-mabi=lp64");
c.flag("-march=rv64imac");
c.flag("-mabi=lp64d");
c.flag("-march=rv64gc");
}
}

View File

@ -1,3 +1,5 @@
#![feature(cfg_target_abi)]
#[macro_use]
extern crate lazy_static;
extern crate cc;

View File

@ -9,7 +9,7 @@
为了能支持vscode的调试功能我们需要修改`.vscode/settings.json`文件的以下行:
```
"rust-analyzer.cargo.target": "riscv64imac-unknown-none-elf",
"rust-analyzer.cargo.target": "riscv64gc-unknown-none-elf",
// "rust-analyzer.cargo.target": "x86_64-unknown-none",
```

View File

@ -6,7 +6,7 @@ include ./env.mk
ifeq ($(ARCH), x86_64)
export TARGET_JSON=arch/x86_64/x86_64-unknown-none.json
else ifeq ($(ARCH), riscv64)
export TARGET_JSON=arch/riscv64/riscv64imac-unknown-none-elf.json
export TARGET_JSON=riscv64gc-unknown-none-elf
endif
export CARGO_ZBUILD=-Z build-std=core,alloc,compiler_builtins -Z build-std-features=compiler-builtins-mem
@ -38,7 +38,7 @@ check: ECHO
ifeq ($(ARCH), x86_64)
@cargo +nightly-2023-08-15 check --workspace $(CARGO_ZBUILD) --message-format=json --target ./src/$(TARGET_JSON)
else ifeq ($(ARCH), riscv64)
@cargo +nightly-2023-08-15 check --workspace $(CARGO_ZBUILD) --message-format=json --target ./src/$(TARGET_JSON)
@cargo +nightly-2023-08-15 check --workspace $(CARGO_ZBUILD) --message-format=json --target $(TARGET_JSON)
endif
test:

View File

@ -36,7 +36,7 @@ export GLOBAL_CFLAGS := -fno-builtin -fno-stack-protector -D $(CFLAGS_DEFINE_ARC
ifeq ($(ARCH), x86_64)
GLOBAL_CFLAGS += -mcmodel=large -m64
else ifeq ($(ARCH), riscv64)
GLOBAL_CFLAGS += -mcmodel=medany -march=rv64imac -mabi=lp64
GLOBAL_CFLAGS += -mcmodel=medany -march=rv64gc -mabi=lp64d
endif
ifeq ($(DEBUG), DEBUG)

View File

@ -65,7 +65,7 @@ kernel: $(kernel_subdirs) kernel_rust
__link_riscv64_kernel:
@echo "Linking kernel..."
$(LD) -b elf64-littleriscv -z muldefs $(LDFLAGS_UNWIND) -o kernel $(shell find . -name "*.o") ../target/riscv64imac-unknown-none-elf/release/libdragonos_kernel.a -T arch/riscv64/link.ld --no-relax
$(LD) -b elf64-littleriscv -z muldefs $(LDFLAGS_UNWIND) -o kernel $(shell find . -name "*.o") ../target/riscv64gc-unknown-none-elf/release/libdragonos_kernel.a -T arch/riscv64/link.ld --no-relax
$(OBJCOPY) -I elf64-littleriscv -O elf64-littleriscv -R ".eh_frame" kernel ../../bin/kernel/kernel.elf
@rm kernel
$(MAKE) __dragon_stub PAYLOAD_ELF="$(shell pwd)/../../bin/kernel/kernel.elf"

View File

@ -3,7 +3,6 @@ use sbi_rt::HartMask;
use crate::{
init::boot_params,
kdebug,
mm::percpu::{PerCpu, PerCpuVar},
smp::cpu::{ProcessorId, SmpCpuManager},
};

View File

@ -1 +1,2 @@
pub mod of;
pub mod sbi;

View File

@ -0,0 +1,40 @@
use system_error::SystemError;
use crate::{
driver::open_firmware::fdt::OpenFirmwareFdtDriver,
init::boot_params,
libs::align::page_align_up,
mm::{mmio_buddy::mmio_pool, MemoryManagementArch, PhysAddr},
};
impl OpenFirmwareFdtDriver {
#[allow(dead_code)]
pub unsafe fn map_fdt(&self) -> Result<(), SystemError> {
let bp_guard = boot_params().read();
let fdt_size = bp_guard.arch.fdt_size;
let fdt_paddr = bp_guard.arch.fdt_paddr;
let offset = fdt_paddr.data() & crate::arch::MMArch::PAGE_OFFSET_MASK;
let map_size = page_align_up(fdt_size + offset);
let map_paddr = PhysAddr::new(fdt_paddr.data() & crate::arch::MMArch::PAGE_MASK);
// kdebug!(
// "map_fdt paddr: {:?}, map_pa: {:?},fdt_size: {}, size: {:?}",
// fdt_paddr,
// map_paddr,
// fdt_size,
// map_size
// );
let mmio_guard = mmio_pool().create_mmio(map_size)?;
// drop the boot params guard in order to avoid deadlock
drop(bp_guard);
mmio_guard.map_phys(map_paddr, map_size)?;
let mut bp_guard = boot_params().write();
let vaddr = mmio_guard.vaddr() + offset;
self.set_fdt_map_guard(Some(mmio_guard));
bp_guard.arch.fdt_vaddr.replace(vaddr);
return Ok(());
}
}

View File

@ -18,6 +18,7 @@ pub struct ArchBootParams {
/// 启动时的fdt物理地址
pub fdt_paddr: PhysAddr,
pub fdt_vaddr: Option<VirtAddr>,
pub fdt_size: usize,
pub boot_hartid: ProcessorId,
}
@ -26,6 +27,7 @@ impl ArchBootParams {
pub const DEFAULT: Self = ArchBootParams {
fdt_paddr: PhysAddr::new(0),
fdt_vaddr: None,
fdt_size: 0,
boot_hartid: ProcessorId::new(0),
};
@ -103,8 +105,12 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
let hartid = unsafe { BOOT_HARTID };
let fdt_paddr = unsafe { BOOT_FDT_PADDR };
let fdt =
unsafe { fdt::Fdt::from_ptr(fdt_paddr.data() as *const u8).expect("Failed to parse fdt!") };
let mut arch_boot_params_guard = boot_params().write();
arch_boot_params_guard.arch.fdt_paddr = fdt_paddr;
arch_boot_params_guard.arch.fdt_size = fdt.total_size();
arch_boot_params_guard.arch.boot_hartid = ProcessorId::new(hartid);
drop(arch_boot_params_guard);
@ -116,8 +122,6 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
);
mm_early_init();
let fdt =
unsafe { fdt::Fdt::from_ptr(fdt_paddr.data() as *const u8).expect("Failed to parse fdt!") };
print_node(fdt.find_node("/").unwrap(), 0);
unsafe { parse_dtb() };

View File

@ -1,8 +1,11 @@
//! 处理中断和异常
//!
//! 架构相关的处理逻辑参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/kernel/traps.c
use core::hint::spin_loop;
use system_error::SystemError;
use crate::{kdebug, kerror};
use crate::{arch::syscall::syscall_handler, kdebug, kerror};
use super::TrapFrame;
@ -136,11 +139,16 @@ fn do_trap_store_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemE
}
/// 处理环境调用异常 #8
fn do_trap_user_env_call(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
kerror!("riscv64_do_irq: do_trap_user_env_call");
loop {
spin_loop();
fn do_trap_user_env_call(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
if trap_frame.is_from_user() {
let syscall_num = trap_frame.a7;
trap_frame.epc += 4;
trap_frame.origin_a0 = trap_frame.a0;
syscall_handler(syscall_num, trap_frame);
} else {
panic!("do_trap_user_env_call: not from user mode")
}
Ok(())
}
// 9-11 reserved
@ -154,8 +162,16 @@ fn do_trap_insn_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemErro
}
/// 处理页加载错误异常 #13
fn do_trap_load_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
kerror!("riscv64_do_irq: do_trap_load_page_fault");
fn do_trap_load_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
let vaddr = trap_frame.badaddr;
let cause = trap_frame.cause;
let epc = trap_frame.epc;
kerror!(
"riscv64_do_irq: do_trap_load_page_fault: epc: {epc:#x}, vaddr={:#x}, cause={:?}",
vaddr,
cause
);
loop {
spin_loop();
}

View File

@ -5,6 +5,7 @@ use system_error::SystemError;
use crate::{
arch::MMArch,
driver::open_firmware::fdt::open_firmware_fdt_driver,
kdebug,
libs::spinlock::SpinLock,
mm::{
@ -13,7 +14,7 @@ use crate::{
page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
},
kernel_mapper::KernelMapper,
page::{PageEntry, PageFlags},
page::{PageEntry, PageFlags, PAGE_1G_SHIFT},
ucontext::UserMapper,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
},
@ -130,16 +131,28 @@ impl MemoryManagementArch for RiscV64MMArch {
const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000);
/// 在距离sv39的顶端还有1G的位置设置为FIXMAP的起始地址
const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000);
/// 在距离sv39的顶端还有64M的位置设置为FIXMAP的起始地址
const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_fc00_0000);
/// 设置1MB的fixmap空间
const FIXMAP_SIZE: usize = 256 * 4096;
/// 在距离sv39的顶端还有2G的位置设置为MMIO空间的起始地址
const MMIO_BASE: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000);
/// 设置1g的MMIO空间
const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT;
#[inline(never)]
unsafe fn init() {
riscv_mm_init().expect("init kernel memory management architecture failed");
}
unsafe fn arch_post_init() {
// 映射fdt
open_firmware_fdt_driver()
.map_fdt()
.expect("openfirmware map fdt failed");
}
unsafe fn invalidate_page(address: VirtAddr) {
riscv::asm::sfence_vma(0, address.data());
}

View File

@ -23,10 +23,10 @@ use crate::{
mm::VirtAddr,
process::{
fork::{CloneFlags, KernelCloneArgs},
KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager, PROCESS_SWITCH_RESULT,
switch_finish_hook, KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager,
PROCESS_SWITCH_RESULT,
},
smp::cpu::ProcessorId,
syscall::Syscall,
};
use super::{
@ -213,9 +213,9 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI
ld s10, {off_s10}(a1)
ld s11, {off_s11}(a1)
// 将ra设置为标签1并跳转到{switch_finish_hook}
// 将ra设置为标签1并跳转到before_switch_finish_hook
la ra, 1f
j {switch_finish_hook}
j {before_switch_finish_hook}
1:
ld sp, {off_sp}(a1)
@ -238,10 +238,15 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI
off_s9 = const(offset_of!(ArchPCBInfo, s9)),
off_s10 = const(offset_of!(ArchPCBInfo, s10)),
off_s11 = const(offset_of!(ArchPCBInfo, s11)),
switch_finish_hook = sym crate::process::switch_finish_hook,
before_switch_finish_hook = sym before_switch_finish_hook,
options(noreturn));
}
/// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数否则会出现relocation truncated to fit: R_RISCV_JAL错误)
unsafe extern "C" fn before_switch_finish_hook() {
switch_finish_hook();
}
impl ProcessControlBlock {
/// 获取当前进程的pcb
pub fn arch_current_pcb() -> Arc<Self> {
@ -375,73 +380,50 @@ impl FpDExtState {
asm!("frcsr {0}", lateout(reg) self.fcsr);
asm!(concat!(
"
fsd f0, {0}
fsd f1, {1}
fsd f2, {2}
fsd f3, {3}
fsd f4, {4}
fsd f5, {5}
fsd f6, {6}
fsd f7, {7}
fsd f8, {8}
fsd f9, {9}
fsd f10, {10}
fsd f11, {11}
fsd f12, {12}
fsd f13, {13}
fsd f14, {14}
fsd f15, {15}
fsd f16, {16}
fsd f17, {17}
fsd f18, {18}
fsd f19, {19}
fsd f20, {20}
fsd f21, {21}
fsd f22, {22}
fsd f23, {23}
fsd f24, {24}
fsd f25, {25}
fsd f26, {26}
fsd f27, {27}
fsd f28, {28}
fsd f29, {29}
fsd f30, {30}
fsd f31, {31}
// 为原来的a0寄存器的值在堆栈上分配空间
addi sp, sp, -8
sd a0, 0(sp)
mv a0, {0}
fsd f0, 0(a0)
fsd f1, 8(a0)
fsd f2, 16(a0)
fsd f3, 24(a0)
fsd f4, 32(a0)
fsd f5, 40(a0)
fsd f6, 48(a0)
fsd f7, 56(a0)
fsd f8, 64(a0)
fsd f9, 72(a0)
fsd f10, 80(a0)
fsd f11, 88(a0)
fsd f12, 96(a0)
fsd f13, 104(a0)
fsd f14, 112(a0)
fsd f15, 120(a0)
fsd f16, 128(a0)
fsd f17, 136(a0)
fsd f18, 144(a0)
fsd f19, 152(a0)
fsd f20, 160(a0)
fsd f21, 168(a0)
fsd f22, 176(a0)
fsd f23, 184(a0)
fsd f24, 192(a0)
fsd f25, 200(a0)
fsd f26, 208(a0)
fsd f27, 216(a0)
fsd f28, 224(a0)
fsd f29, 232(a0)
fsd f30, 240(a0)
fsd f31, 248(a0)
// 恢复a0寄存器的值
ld a0, 0(sp)
addi sp, sp, 8
"
),
lateout(reg) self.f[0],
lateout(reg) self.f[1],
lateout(reg) self.f[2],
lateout(reg) self.f[3],
lateout(reg) self.f[4],
lateout(reg) self.f[5],
lateout(reg) self.f[6],
lateout(reg) self.f[7],
lateout(reg) self.f[8],
lateout(reg) self.f[9],
lateout(reg) self.f[10],
lateout(reg) self.f[11],
lateout(reg) self.f[12],
lateout(reg) self.f[13],
lateout(reg) self.f[14],
lateout(reg) self.f[15],
lateout(reg) self.f[16],
lateout(reg) self.f[17],
lateout(reg) self.f[18],
lateout(reg) self.f[19],
lateout(reg) self.f[20],
lateout(reg) self.f[21],
lateout(reg) self.f[22],
lateout(reg) self.f[23],
lateout(reg) self.f[24],
lateout(reg) self.f[25],
lateout(reg) self.f[26],
lateout(reg) self.f[27],
lateout(reg) self.f[28],
lateout(reg) self.f[29],
lateout(reg) self.f[30],
lateout(reg) self.f[31],
in (reg) &self.f as *const _,
);
riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
}
@ -457,72 +439,50 @@ impl FpDExtState {
compiler_fence(Ordering::SeqCst);
asm!(concat!(
"
fld f0, {0}
fld f1, {1}
fld f2, {2}
fld f3, {3}
fld f4, {4}
fld f5, {5}
fld f6, {6}
fld f7, {7}
fld f8, {8}
fld f9, {9}
fld f10, {10}
fld f11, {11}
fld f12, {12}
fld f13, {13}
fld f14, {14}
fld f15, {15}
fld f16, {16}
fld f17, {17}
fld f18, {18}
fld f19, {19}
fld f20, {20}
fld f21, {21}
fld f22, {22}
fld f23, {23}
fld f24, {24}
fld f25, {25}
fld f26, {26}
fld f27, {27}
fld f28, {28}
fld f29, {29}
fld f30, {30}
fld f31, {31}
"
// 为原来的a0寄存器的值在堆栈上分配空间
addi sp, sp, -8
sd a0, 0(sp)
mv a0, {0}
fld f0, 0(a0)
fld f1, 8(a0)
fld f2, 16(a0)
fld f3, 24(a0)
fld f4, 32(a0)
fld f5, 40(a0)
fld f6, 48(a0)
fld f7, 56(a0)
fld f8, 64(a0)
fld f9, 72(a0)
fld f10, 80(a0)
fld f11, 88(a0)
fld f12, 96(a0)
fld f13, 104(a0)
fld f14, 112(a0)
fld f15, 120(a0)
fld f16, 128(a0)
fld f17, 136(a0)
fld f18, 144(a0)
fld f19, 152(a0)
fld f20, 160(a0)
fld f21, 168(a0)
fld f22, 176(a0)
fld f23, 184(a0)
fld f24, 192(a0)
fld f25, 200(a0)
fld f26, 208(a0)
fld f27, 216(a0)
fld f28, 224(a0)
fld f29, 232(a0)
fld f30, 240(a0)
fld f31, 248(a0)
// 恢复a0寄存器的值
ld a0, 0(sp)
addi sp, sp, 8
"
),
in(reg) self.f[0],
in(reg) self.f[1],
in(reg) self.f[2],
in(reg) self.f[3],
in(reg) self.f[4],
in(reg) self.f[5],
in(reg) self.f[6],
in(reg) self.f[7],
in(reg) self.f[8],
in(reg) self.f[9],
in(reg) self.f[10],
in(reg) self.f[11],
in(reg) self.f[12],
in(reg) self.f[13],
in(reg) self.f[14],
in(reg) self.f[15],
in(reg) self.f[16],
in(reg) self.f[17],
in(reg) self.f[18],
in(reg) self.f[19],
in(reg) self.f[20],
in(reg) self.f[21],
in(reg) self.f[22],
in(reg) self.f[23],
in(reg) self.f[24],
in(reg) self.f[25],
in(reg) self.f[26],
in(reg) self.f[27],
in(reg) self.f[28],
in(reg) self.f[29],
in(reg) self.f[30],
in(reg) self.f[31],
in (reg) &self.f as *const _,
);
compiler_fence(Ordering::SeqCst);
asm!("fscsr {0}", in(reg) fcsr);

View File

@ -1,18 +0,0 @@
{
"arch": "riscv64",
"code-model": "medium",
"cpu": "generic-rv64",
"data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
"eh-frame-header": false,
"emit-debug-gdb-scripts": false,
"features": "+m,+a,+c",
"is-builtin": false,
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"llvm-target": "riscv64",
"max-atomic-width": 64,
"panic-strategy": "abort",
"relocation-model": "pic",
"position-independent-executables": true,
"target-pointer-width": "64"
}

View File

@ -2,7 +2,7 @@
pub mod nr;
use system_error::SystemError;
use crate::exception::InterruptArch;
use crate::{exception::InterruptArch, process::ProcessManager, syscall::Syscall};
use super::{interrupt::TrapFrame, CurrentIrqArch};
@ -11,10 +11,32 @@ pub fn arch_syscall_init() -> Result<(), SystemError> {
return Ok(());
}
#[no_mangle]
pub extern "C" fn syscall_handler(frame: &mut TrapFrame) -> () {
macro_rules! syscall_return {
($val:expr, $regs:expr, $show:expr) => {{
let ret = $val;
$regs.a0 = ret;
if $show {
let pid = ProcessManager::current_pcb().pid();
crate::kdebug!("syscall return:pid={:?},ret= {:?}\n", pid, ret as isize);
}
unsafe {
CurrentIrqArch::interrupt_disable();
}
return;
}};
}
pub(super) fn syscall_handler(syscall_num: usize, frame: &mut TrapFrame) -> () {
unsafe {
CurrentIrqArch::interrupt_enable();
}
unimplemented!("syscall_handler")
let args = [frame.a0, frame.a1, frame.a2, frame.a3, frame.a4, frame.a5];
syscall_return!(
Syscall::handle(syscall_num, &args, frame).unwrap_or_else(|e| e.to_posix_errno() as usize),
frame,
false
);
}

View File

@ -1,20 +1,66 @@
use crate::time::{clocksource::HZ, TimeArch};
use crate::{
driver::open_firmware::fdt::open_firmware_fdt_driver,
kinfo,
time::{clocksource::HZ, TimeArch},
};
pub struct RiscV64TimeArch;
/// 这个是系统jiffies时钟源的固有频率不是调频之后的
pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000;
static mut TIME_FREQ: usize = 0;
/// 获取CPU的time寄存器频率
///
/// todo: 支持从acpi中获取
fn init_time_freq() {
let fdt = open_firmware_fdt_driver().fdt_ref();
if fdt.is_err() {
panic!("init_time_freq: failed to get fdt");
}
let fdt = fdt.unwrap();
let cpu_node = fdt.find_node("/cpus");
if cpu_node.is_none() {
panic!("init_time_freq: failed to find /cpus node");
}
let cpu_node = cpu_node.unwrap();
let time_freq = cpu_node
.property("timebase-frequency")
.map(|prop| prop.as_usize())
.flatten();
if time_freq.is_none() {
panic!("init_time_freq: failed to get timebase-frequency");
}
let time_freq: usize = time_freq.unwrap();
kinfo!("init_time_freq: timebase-frequency: {}", time_freq);
unsafe {
TIME_FREQ = time_freq;
}
}
pub fn time_init() {
// 初始化cpu time register频率
init_time_freq();
}
impl TimeArch for RiscV64TimeArch {
fn get_cycles() -> usize {
riscv::register::cycle::read()
riscv::register::time::read()
}
fn cal_expire_cycles(ns: usize) -> usize {
todo!()
Self::get_cycles() + ns * unsafe { TIME_FREQ } / 1000000000
}
/// 将CPU的时钟周期数转换为纳秒
#[inline(always)]
fn cycles2ns(cycles: usize) -> usize {
todo!()
if unsafe { TIME_FREQ == 0 } {
return 0;
}
cycles * 1000000000 / unsafe { TIME_FREQ }
}
}

View File

@ -23,7 +23,7 @@ use crate::{
};
use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::page::{PageEntry, PageFlags};
use crate::mm::page::{PageEntry, PageFlags, PAGE_1G_SHIFT};
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
use crate::{kdebug, kinfo, kwarn};
use system_error::SystemError;
@ -122,6 +122,9 @@ impl MemoryManagementArch for X86_64MMArch {
/// 设置FIXMAP区域大小为1M
const FIXMAP_SIZE: usize = 256 * 4096;
const MMIO_BASE: VirtAddr = VirtAddr::new(0xffffa10000000000);
const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT;
/// @brief 获取物理内存区域
unsafe fn init() {
extern "C" {

View File

@ -5,6 +5,10 @@ use super::driver::tsc::TSCManager;
/// 这个是系统jiffies时钟源的固有频率不是调频之后的
pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000;
pub fn time_init() {
// do nothing
}
pub struct X86_64TimeArch;
impl TimeArch for X86_64TimeArch {

View File

@ -9,12 +9,14 @@ use system_error::SystemError;
use crate::{
init::boot_params,
libs::rwlock::RwLock,
mm::{memblock::mem_block_manager, PhysAddr},
mm::{memblock::mem_block_manager, mmio_buddy::MMIOSpaceGuard, PhysAddr},
};
static OPEN_FIRMWARE_FDT_DRIVER: OpenFirmwareFdtDriver = OpenFirmwareFdtDriver::new();
#[inline(always)]
pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
&OpenFirmwareFdtDriver
&OPEN_FIRMWARE_FDT_DRIVER
}
static FDT_GLOBAL_DATA: RwLock<FdtGlobalData> = RwLock::new(FdtGlobalData::new());
@ -40,22 +42,48 @@ impl FdtGlobalData {
}
}
pub struct OpenFirmwareFdtDriver;
#[allow(dead_code)]
pub struct OpenFirmwareFdtDriver {
inner: RwLock<InnerOpenFirmwareFdtDriver>,
}
#[allow(dead_code)]
pub struct InnerOpenFirmwareFdtDriver {
/// FDT自身映射的MMIO空间
fdt_map_guard: Option<MMIOSpaceGuard>,
}
impl OpenFirmwareFdtDriver {
const fn new() -> Self {
Self {
inner: RwLock::new(InnerOpenFirmwareFdtDriver {
fdt_map_guard: None,
}),
}
}
#[allow(dead_code)]
pub fn early_scan_device_tree(&self) -> Result<(), SystemError> {
let fdt = self.fdt_ref()?;
self.early_init_scan_nodes(&fdt);
return Ok(());
}
pub unsafe fn set_fdt_map_guard(&self, guard: Option<MMIOSpaceGuard>) {
self.inner.write().fdt_map_guard = guard;
}
/// 获取FDT的引用
pub fn fdt_ref(&self) -> Result<Fdt<'static>, SystemError> {
let fdt_vaddr = boot_params().read().fdt().unwrap();
let fdt = unsafe {
let fdt: Fdt<'_> = unsafe {
fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
kerror!("failed to parse fdt, err={:?}", e);
SystemError::EINVAL
})
}?;
self.early_init_scan_nodes(&fdt);
return Ok(());
Ok(fdt)
}
fn early_init_scan_nodes(&self, fdt: &Fdt) {

View File

@ -1,6 +1,7 @@
use crate::{
arch::{
init::{early_setup_arch, setup_arch, setup_arch_post},
time::time_init,
CurrentIrqArch, CurrentSMPArch, CurrentSchedArch,
},
driver::{base::init::driver_init, serial::serial_early_init, video::VideoRefreshManager},
@ -70,6 +71,7 @@ fn do_start_kernel() {
softirq_init().expect("softirq init failed");
Syscall::init().expect("syscall init failed");
timekeeping_init();
time_init();
timer_init();
kthread_init();
clocksource_boot_finish();

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;

View File

@ -493,7 +493,8 @@ pub unsafe extern "sysv64" fn switch_finish_hook() {
ProcessManager::switch_finish_hook();
}
#[cfg(target_arch = "riscv64")]
pub unsafe extern "C" fn switch_finish_hook() {
#[inline(always)]
pub unsafe fn switch_finish_hook() {
ProcessManager::switch_finish_hook();
}

View File

@ -1,11 +1,6 @@
/*
*/
#[cfg(target_arch = "x86_64")]
use crate::{
arch::{driver::tsc::TSCManager, CurrentTimeArch},
time::TimeArch,
};
//! 这个文件实现的是调度过程中涉及到的时钟
//!
use crate::{arch::CurrentTimeArch, time::TimeArch};
pub struct SchedClock;
@ -14,15 +9,17 @@ impl SchedClock {
pub fn sched_clock_cpu(_cpu: usize) -> u64 {
#[cfg(target_arch = "x86_64")]
{
if TSCManager::cpu_khz() == 0 {
// TCS no init
if crate::arch::driver::tsc::TSCManager::cpu_khz() == 0 {
// TSC not calibrated yet
return 0;
}
return CurrentTimeArch::cycles2ns(CurrentTimeArch::get_cycles()) as u64;
}
#[cfg(target_arch = "riscv64")]
todo!()
{
return CurrentTimeArch::cycles2ns(CurrentTimeArch::get_cycles()) as u64;
}
}
}