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 .cache
compile_commands.json compile_commands.json
/logs/ /logs/
.vscode

View File

@ -152,7 +152,7 @@
"./tools/Cargo.toml", "./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.cargo.target": "x86_64-unknown-none",
"rust-analyzer.check.overrideCommand": [ "rust-analyzer.check.overrideCommand": [
"make", "make",

View File

@ -31,8 +31,9 @@ impl CFilesArch for RiscV64CFilesArch {
// // c.flag("-march=rv64imafdc"); // // c.flag("-march=rv64imafdc");
// c.no_default_flags(true); // c.no_default_flags(true);
c.flag("-mcmodel=medany"); 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] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
extern crate cc; extern crate cc;

View File

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

View File

@ -6,7 +6,7 @@ include ./env.mk
ifeq ($(ARCH), x86_64) ifeq ($(ARCH), x86_64)
export TARGET_JSON=arch/x86_64/x86_64-unknown-none.json export TARGET_JSON=arch/x86_64/x86_64-unknown-none.json
else ifeq ($(ARCH), riscv64) else ifeq ($(ARCH), riscv64)
export TARGET_JSON=arch/riscv64/riscv64imac-unknown-none-elf.json export TARGET_JSON=riscv64gc-unknown-none-elf
endif endif
export CARGO_ZBUILD=-Z build-std=core,alloc,compiler_builtins -Z build-std-features=compiler-builtins-mem 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) ifeq ($(ARCH), x86_64)
@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 ./src/$(TARGET_JSON)
else ifeq ($(ARCH), riscv64) 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 endif
test: test:

View File

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

View File

@ -65,7 +65,7 @@ kernel: $(kernel_subdirs) kernel_rust
__link_riscv64_kernel: __link_riscv64_kernel:
@echo "Linking 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 $(OBJCOPY) -I elf64-littleriscv -O elf64-littleriscv -R ".eh_frame" kernel ../../bin/kernel/kernel.elf
@rm kernel @rm kernel
$(MAKE) __dragon_stub PAYLOAD_ELF="$(shell pwd)/../../bin/kernel/kernel.elf" $(MAKE) __dragon_stub PAYLOAD_ELF="$(shell pwd)/../../bin/kernel/kernel.elf"

View File

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

View File

@ -1 +1,2 @@
pub mod of;
pub mod sbi; 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物理地址 /// 启动时的fdt物理地址
pub fdt_paddr: PhysAddr, pub fdt_paddr: PhysAddr,
pub fdt_vaddr: Option<VirtAddr>, pub fdt_vaddr: Option<VirtAddr>,
pub fdt_size: usize,
pub boot_hartid: ProcessorId, pub boot_hartid: ProcessorId,
} }
@ -26,6 +27,7 @@ impl ArchBootParams {
pub const DEFAULT: Self = ArchBootParams { pub const DEFAULT: Self = ArchBootParams {
fdt_paddr: PhysAddr::new(0), fdt_paddr: PhysAddr::new(0),
fdt_vaddr: None, fdt_vaddr: None,
fdt_size: 0,
boot_hartid: ProcessorId::new(0), boot_hartid: ProcessorId::new(0),
}; };
@ -103,8 +105,12 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
let hartid = unsafe { BOOT_HARTID }; let hartid = unsafe { BOOT_HARTID };
let fdt_paddr = unsafe { BOOT_FDT_PADDR }; 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(); let mut arch_boot_params_guard = boot_params().write();
arch_boot_params_guard.arch.fdt_paddr = fdt_paddr; 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); arch_boot_params_guard.arch.boot_hartid = ProcessorId::new(hartid);
drop(arch_boot_params_guard); drop(arch_boot_params_guard);
@ -116,8 +122,6 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
); );
mm_early_init(); 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); print_node(fdt.find_node("/").unwrap(), 0);
unsafe { parse_dtb() }; 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 core::hint::spin_loop;
use system_error::SystemError; use system_error::SystemError;
use crate::{kdebug, kerror}; use crate::{arch::syscall::syscall_handler, kdebug, kerror};
use super::TrapFrame; use super::TrapFrame;
@ -136,11 +139,16 @@ fn do_trap_store_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemE
} }
/// 处理环境调用异常 #8 /// 处理环境调用异常 #8
fn do_trap_user_env_call(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> { fn do_trap_user_env_call(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
kerror!("riscv64_do_irq: do_trap_user_env_call"); if trap_frame.is_from_user() {
loop { let syscall_num = trap_frame.a7;
spin_loop(); 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 // 9-11 reserved
@ -154,8 +162,16 @@ fn do_trap_insn_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemErro
} }
/// 处理页加载错误异常 #13 /// 处理页加载错误异常 #13
fn do_trap_load_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> { fn do_trap_load_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
kerror!("riscv64_do_irq: do_trap_load_page_fault"); 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 { loop {
spin_loop(); spin_loop();
} }

View File

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

View File

@ -23,10 +23,10 @@ use crate::{
mm::VirtAddr, mm::VirtAddr,
process::{ process::{
fork::{CloneFlags, KernelCloneArgs}, fork::{CloneFlags, KernelCloneArgs},
KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager, PROCESS_SWITCH_RESULT, switch_finish_hook, KernelStack, ProcessControlBlock, ProcessFlags, ProcessManager,
PROCESS_SWITCH_RESULT,
}, },
smp::cpu::ProcessorId, smp::cpu::ProcessorId,
syscall::Syscall,
}; };
use super::{ 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 s10, {off_s10}(a1)
ld s11, {off_s11}(a1) ld s11, {off_s11}(a1)
// 将ra设置为标签1并跳转到{switch_finish_hook} // 将ra设置为标签1并跳转到before_switch_finish_hook
la ra, 1f la ra, 1f
j {switch_finish_hook} j {before_switch_finish_hook}
1: 1:
ld sp, {off_sp}(a1) 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_s9 = const(offset_of!(ArchPCBInfo, s9)),
off_s10 = const(offset_of!(ArchPCBInfo, s10)), off_s10 = const(offset_of!(ArchPCBInfo, s10)),
off_s11 = const(offset_of!(ArchPCBInfo, s11)), 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)); options(noreturn));
} }
/// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数否则会出现relocation truncated to fit: R_RISCV_JAL错误)
unsafe extern "C" fn before_switch_finish_hook() {
switch_finish_hook();
}
impl ProcessControlBlock { impl ProcessControlBlock {
/// 获取当前进程的pcb /// 获取当前进程的pcb
pub fn arch_current_pcb() -> Arc<Self> { pub fn arch_current_pcb() -> Arc<Self> {
@ -375,73 +380,50 @@ impl FpDExtState {
asm!("frcsr {0}", lateout(reg) self.fcsr); asm!("frcsr {0}", lateout(reg) self.fcsr);
asm!(concat!( asm!(concat!(
" "
fsd f0, {0} // 为原来的a0寄存器的值在堆栈上分配空间
fsd f1, {1} addi sp, sp, -8
fsd f2, {2} sd a0, 0(sp)
fsd f3, {3} mv a0, {0}
fsd f4, {4}
fsd f5, {5} fsd f0, 0(a0)
fsd f6, {6} fsd f1, 8(a0)
fsd f7, {7} fsd f2, 16(a0)
fsd f8, {8} fsd f3, 24(a0)
fsd f9, {9} fsd f4, 32(a0)
fsd f10, {10} fsd f5, 40(a0)
fsd f11, {11} fsd f6, 48(a0)
fsd f12, {12} fsd f7, 56(a0)
fsd f13, {13} fsd f8, 64(a0)
fsd f14, {14} fsd f9, 72(a0)
fsd f15, {15} fsd f10, 80(a0)
fsd f16, {16} fsd f11, 88(a0)
fsd f17, {17} fsd f12, 96(a0)
fsd f18, {18} fsd f13, 104(a0)
fsd f19, {19} fsd f14, 112(a0)
fsd f20, {20} fsd f15, 120(a0)
fsd f21, {21} fsd f16, 128(a0)
fsd f22, {22} fsd f17, 136(a0)
fsd f23, {23} fsd f18, 144(a0)
fsd f24, {24} fsd f19, 152(a0)
fsd f25, {25} fsd f20, 160(a0)
fsd f26, {26} fsd f21, 168(a0)
fsd f27, {27} fsd f22, 176(a0)
fsd f28, {28} fsd f23, 184(a0)
fsd f29, {29} fsd f24, 192(a0)
fsd f30, {30} fsd f25, 200(a0)
fsd f31, {31} 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], in (reg) &self.f as *const _,
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],
); );
riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off); riscv::register::sstatus::set_fs(riscv::register::sstatus::FS::Off);
} }
@ -457,72 +439,50 @@ impl FpDExtState {
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
asm!(concat!( asm!(concat!(
" "
fld f0, {0} // 为原来的a0寄存器的值在堆栈上分配空间
fld f1, {1} addi sp, sp, -8
fld f2, {2} sd a0, 0(sp)
fld f3, {3} mv a0, {0}
fld f4, {4}
fld f5, {5} fld f0, 0(a0)
fld f6, {6} fld f1, 8(a0)
fld f7, {7} fld f2, 16(a0)
fld f8, {8} fld f3, 24(a0)
fld f9, {9} fld f4, 32(a0)
fld f10, {10} fld f5, 40(a0)
fld f11, {11} fld f6, 48(a0)
fld f12, {12} fld f7, 56(a0)
fld f13, {13} fld f8, 64(a0)
fld f14, {14} fld f9, 72(a0)
fld f15, {15} fld f10, 80(a0)
fld f16, {16} fld f11, 88(a0)
fld f17, {17} fld f12, 96(a0)
fld f18, {18} fld f13, 104(a0)
fld f19, {19} fld f14, 112(a0)
fld f20, {20} fld f15, 120(a0)
fld f21, {21} fld f16, 128(a0)
fld f22, {22} fld f17, 136(a0)
fld f23, {23} fld f18, 144(a0)
fld f24, {24} fld f19, 152(a0)
fld f25, {25} fld f20, 160(a0)
fld f26, {26} fld f21, 168(a0)
fld f27, {27} fld f22, 176(a0)
fld f28, {28} fld f23, 184(a0)
fld f29, {29} fld f24, 192(a0)
fld f30, {30} fld f25, 200(a0)
fld f31, {31} 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 as *const _,
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],
); );
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
asm!("fscsr {0}", in(reg) fcsr); 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; pub mod nr;
use system_error::SystemError; use system_error::SystemError;
use crate::exception::InterruptArch; use crate::{exception::InterruptArch, process::ProcessManager, syscall::Syscall};
use super::{interrupt::TrapFrame, CurrentIrqArch}; use super::{interrupt::TrapFrame, CurrentIrqArch};
@ -11,10 +11,32 @@ pub fn arch_syscall_init() -> Result<(), SystemError> {
return Ok(()); return Ok(());
} }
#[no_mangle] macro_rules! syscall_return {
pub extern "C" fn syscall_handler(frame: &mut TrapFrame) -> () { ($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 { unsafe {
CurrentIrqArch::interrupt_enable(); 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; pub struct RiscV64TimeArch;
/// 这个是系统jiffies时钟源的固有频率不是调频之后的 /// 这个是系统jiffies时钟源的固有频率不是调频之后的
pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000; 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 { impl TimeArch for RiscV64TimeArch {
fn get_cycles() -> usize { fn get_cycles() -> usize {
riscv::register::cycle::read() riscv::register::time::read()
} }
fn cal_expire_cycles(ns: usize) -> usize { fn cal_expire_cycles(ns: usize) -> usize {
todo!() Self::get_cycles() + ns * unsafe { TIME_FREQ } / 1000000000
} }
/// 将CPU的时钟周期数转换为纳秒 /// 将CPU的时钟周期数转换为纳秒
#[inline(always)] #[inline(always)]
fn cycles2ns(cycles: usize) -> usize { 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::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::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
use crate::{kdebug, kinfo, kwarn}; use crate::{kdebug, kinfo, kwarn};
use system_error::SystemError; use system_error::SystemError;
@ -122,6 +122,9 @@ impl MemoryManagementArch for X86_64MMArch {
/// 设置FIXMAP区域大小为1M /// 设置FIXMAP区域大小为1M
const FIXMAP_SIZE: usize = 256 * 4096; const FIXMAP_SIZE: usize = 256 * 4096;
const MMIO_BASE: VirtAddr = VirtAddr::new(0xffffa10000000000);
const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT;
/// @brief 获取物理内存区域 /// @brief 获取物理内存区域
unsafe fn init() { unsafe fn init() {
extern "C" { extern "C" {

View File

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

View File

@ -9,12 +9,14 @@ use system_error::SystemError;
use crate::{ use crate::{
init::boot_params, init::boot_params,
libs::rwlock::RwLock, 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)] #[inline(always)]
pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver { pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
&OpenFirmwareFdtDriver &OPEN_FIRMWARE_FDT_DRIVER
} }
static FDT_GLOBAL_DATA: RwLock<FdtGlobalData> = RwLock::new(FdtGlobalData::new()); 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 { impl OpenFirmwareFdtDriver {
const fn new() -> Self {
Self {
inner: RwLock::new(InnerOpenFirmwareFdtDriver {
fdt_map_guard: None,
}),
}
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn early_scan_device_tree(&self) -> Result<(), SystemError> { 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_vaddr = boot_params().read().fdt().unwrap();
let fdt = unsafe { let fdt: Fdt<'_> = unsafe {
fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| { fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
kerror!("failed to parse fdt, err={:?}", e); kerror!("failed to parse fdt, err={:?}", e);
SystemError::EINVAL SystemError::EINVAL
}) })
}?; }?;
Ok(fdt)
self.early_init_scan_nodes(&fdt);
return Ok(());
} }
fn early_init_scan_nodes(&self, fdt: &Fdt) { fn early_init_scan_nodes(&self, fdt: &Fdt) {

View File

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

View File

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

View File

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

View File

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

View File

@ -21,6 +21,11 @@ use super::{
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, 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; 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(); ProcessManager::switch_finish_hook();
} }
#[cfg(target_arch = "riscv64")] #[cfg(target_arch = "riscv64")]
pub unsafe extern "C" fn switch_finish_hook() { #[inline(always)]
pub unsafe fn switch_finish_hook() {
ProcessManager::switch_finish_hook(); ProcessManager::switch_finish_hook();
} }

View File

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