From 23ef2b33d1e3cfd2506eb7449a33df4ec42f11d3 Mon Sep 17 00:00:00 2001 From: LoGin Date: Sat, 6 Apr 2024 22:13:26 +0800 Subject: [PATCH] =?UTF-8?q?riscv:=20=E6=8A=8A=E5=86=85=E6=A0=B8=E7=BC=96?= =?UTF-8?q?=E8=AF=91target=E6=94=B9=E4=B8=BAriscv64gc=20&=20=E8=8E=B7?= =?UTF-8?q?=E5=8F=96time=20csr=E7=9A=84=E9=A2=91=E7=8E=87=20&=20=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E6=B5=AE=E7=82=B9=E4=BF=9D=E5=AD=98=E4=B8=8E=E6=81=A2?= =?UTF-8?q?=E5=A4=8D=E7=9A=84=E6=B1=87=E7=BC=96=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20(#699)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 1. 把内核编译target改为riscv64gc 2. fix: 修正浮点保存与恢复的汇编的问题 * riscv: 获取time csr的频率 --- .gitignore | 1 - .vscode/settings.json | 2 +- .../kernel_build/src/cfiles/arch/riscv64.rs | 5 +- build-scripts/kernel_build/src/lib.rs | 2 + docs/kernel/configuration/arch.md | 2 +- kernel/Makefile | 4 +- kernel/env.mk | 2 +- kernel/src/Makefile | 2 +- kernel/src/arch/riscv64/cpu.rs | 1 - kernel/src/arch/riscv64/driver/mod.rs | 1 + kernel/src/arch/riscv64/driver/of.rs | 40 +++ kernel/src/arch/riscv64/init/mod.rs | 8 +- kernel/src/arch/riscv64/interrupt/handle.rs | 30 ++- kernel/src/arch/riscv64/mm/mod.rs | 19 +- kernel/src/arch/riscv64/process/mod.rs | 230 ++++++++---------- .../riscv64/riscv64imac-unknown-none-elf.json | 18 -- kernel/src/arch/riscv64/syscall/mod.rs | 30 ++- kernel/src/arch/riscv64/time.rs | 54 +++- kernel/src/arch/x86_64/mm/mod.rs | 5 +- kernel/src/arch/x86_64/time.rs | 4 + kernel/src/driver/open_firmware/fdt.rs | 44 +++- kernel/src/init/init.rs | 2 + kernel/src/mm/init.rs | 1 + kernel/src/mm/mmio_buddy.rs | 58 +++-- kernel/src/mm/mod.rs | 10 + kernel/src/mm/page.rs | 5 + kernel/src/process/mod.rs | 3 +- kernel/src/sched/clock.rs | 19 +- 28 files changed, 373 insertions(+), 229 deletions(-) create mode 100644 kernel/src/arch/riscv64/driver/of.rs delete mode 100644 kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json diff --git a/.gitignore b/.gitignore index ed295766..52e685b5 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,3 @@ Cargo.lock .cache compile_commands.json /logs/ -.vscode \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index f7a476bc..fbf3caea 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -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", diff --git a/build-scripts/kernel_build/src/cfiles/arch/riscv64.rs b/build-scripts/kernel_build/src/cfiles/arch/riscv64.rs index 5d213dcb..1f0565c8 100644 --- a/build-scripts/kernel_build/src/cfiles/arch/riscv64.rs +++ b/build-scripts/kernel_build/src/cfiles/arch/riscv64.rs @@ -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"); } } diff --git a/build-scripts/kernel_build/src/lib.rs b/build-scripts/kernel_build/src/lib.rs index 21844c53..d0de77f8 100644 --- a/build-scripts/kernel_build/src/lib.rs +++ b/build-scripts/kernel_build/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(cfg_target_abi)] + #[macro_use] extern crate lazy_static; extern crate cc; diff --git a/docs/kernel/configuration/arch.md b/docs/kernel/configuration/arch.md index ce01d35f..2fdb667d 100644 --- a/docs/kernel/configuration/arch.md +++ b/docs/kernel/configuration/arch.md @@ -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", ``` diff --git a/kernel/Makefile b/kernel/Makefile index ee56ef56..c50007c6 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -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: diff --git a/kernel/env.mk b/kernel/env.mk index 2b2d9eaf..666dcc5f 100644 --- a/kernel/env.mk +++ b/kernel/env.mk @@ -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) diff --git a/kernel/src/Makefile b/kernel/src/Makefile index 1cbb40bd..40299bc9 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -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" diff --git a/kernel/src/arch/riscv64/cpu.rs b/kernel/src/arch/riscv64/cpu.rs index ae3cb1d1..12293cca 100644 --- a/kernel/src/arch/riscv64/cpu.rs +++ b/kernel/src/arch/riscv64/cpu.rs @@ -3,7 +3,6 @@ use sbi_rt::HartMask; use crate::{ init::boot_params, - kdebug, mm::percpu::{PerCpu, PerCpuVar}, smp::cpu::{ProcessorId, SmpCpuManager}, }; diff --git a/kernel/src/arch/riscv64/driver/mod.rs b/kernel/src/arch/riscv64/driver/mod.rs index 433d396d..8e2d4602 100644 --- a/kernel/src/arch/riscv64/driver/mod.rs +++ b/kernel/src/arch/riscv64/driver/mod.rs @@ -1 +1,2 @@ +pub mod of; pub mod sbi; diff --git a/kernel/src/arch/riscv64/driver/of.rs b/kernel/src/arch/riscv64/driver/of.rs new file mode 100644 index 00000000..9d21f69c --- /dev/null +++ b/kernel/src/arch/riscv64/driver/of.rs @@ -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(()); + } +} diff --git a/kernel/src/arch/riscv64/init/mod.rs b/kernel/src/arch/riscv64/init/mod.rs index 25482915..078ac21a 100644 --- a/kernel/src/arch/riscv64/init/mod.rs +++ b/kernel/src/arch/riscv64/init/mod.rs @@ -18,6 +18,7 @@ pub struct ArchBootParams { /// 启动时的fdt物理地址 pub fdt_paddr: PhysAddr, pub fdt_vaddr: Option, + 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() }; diff --git a/kernel/src/arch/riscv64/interrupt/handle.rs b/kernel/src/arch/riscv64/interrupt/handle.rs index 3035e33f..851d988d 100644 --- a/kernel/src/arch/riscv64/interrupt/handle.rs +++ b/kernel/src/arch/riscv64/interrupt/handle.rs @@ -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(); } diff --git a/kernel/src/arch/riscv64/mm/mod.rs b/kernel/src/arch/riscv64/mm/mod.rs index 8e2f727a..7b28b054 100644 --- a/kernel/src/arch/riscv64/mm/mod.rs +++ b/kernel/src/arch/riscv64/mm/mod.rs @@ -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()); } diff --git a/kernel/src/arch/riscv64/process/mod.rs b/kernel/src/arch/riscv64/process/mod.rs index 56152895..5ac46360 100644 --- a/kernel/src/arch/riscv64/process/mod.rs +++ b/kernel/src/arch/riscv64/process/mod.rs @@ -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 { @@ -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); diff --git a/kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json b/kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json deleted file mode 100644 index fb178263..00000000 --- a/kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json +++ /dev/null @@ -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" -} diff --git a/kernel/src/arch/riscv64/syscall/mod.rs b/kernel/src/arch/riscv64/syscall/mod.rs index eb896d97..cf3c2c2b 100644 --- a/kernel/src/arch/riscv64/syscall/mod.rs +++ b/kernel/src/arch/riscv64/syscall/mod.rs @@ -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 + ); } diff --git a/kernel/src/arch/riscv64/time.rs b/kernel/src/arch/riscv64/time.rs index 6defdfce..568bdb88 100644 --- a/kernel/src/arch/riscv64/time.rs +++ b/kernel/src/arch/riscv64/time.rs @@ -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 } } } diff --git a/kernel/src/arch/x86_64/mm/mod.rs b/kernel/src/arch/x86_64/mm/mod.rs index 1ef63618..51341f08 100644 --- a/kernel/src/arch/x86_64/mm/mod.rs +++ b/kernel/src/arch/x86_64/mm/mod.rs @@ -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" { diff --git a/kernel/src/arch/x86_64/time.rs b/kernel/src/arch/x86_64/time.rs index 3879f7c4..e0e6c652 100644 --- a/kernel/src/arch/x86_64/time.rs +++ b/kernel/src/arch/x86_64/time.rs @@ -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 { diff --git a/kernel/src/driver/open_firmware/fdt.rs b/kernel/src/driver/open_firmware/fdt.rs index 7e47097d..b7014ff3 100644 --- a/kernel/src/driver/open_firmware/fdt.rs +++ b/kernel/src/driver/open_firmware/fdt.rs @@ -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 = RwLock::new(FdtGlobalData::new()); @@ -40,22 +42,48 @@ impl FdtGlobalData { } } -pub struct OpenFirmwareFdtDriver; +#[allow(dead_code)] +pub struct OpenFirmwareFdtDriver { + inner: RwLock, +} + +#[allow(dead_code)] +pub struct InnerOpenFirmwareFdtDriver { + /// FDT自身映射的MMIO空间 + fdt_map_guard: Option, +} 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) { + self.inner.write().fdt_map_guard = guard; + } + + /// 获取FDT的引用 + pub fn fdt_ref(&self) -> Result, 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) { diff --git a/kernel/src/init/init.rs b/kernel/src/init/init.rs index 19fd6b86..c1f2f602 100644 --- a/kernel/src/init/init.rs +++ b/kernel/src/init/init.rs @@ -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(); diff --git a/kernel/src/mm/init.rs b/kernel/src/mm/init.rs index 515c2b35..faaaaebe 100644 --- a/kernel/src/mm/init.rs +++ b/kernel/src/mm/init.rs @@ -58,6 +58,7 @@ pub unsafe fn mm_init() { Ordering::SeqCst, ) .unwrap(); + MMArch::arch_post_init(); kinfo!("mm init done."); } diff --git a/kernel/src/mm/mmio_buddy.rs b/kernel/src/mm/mmio_buddy.rs index 94037f61..88eac529 100644 --- a/kernel/src/mm/mmio_buddy.rs +++ b/kernel/src/mm/mmio_buddy.rs @@ -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 = 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 { - let list_guard: &mut SpinLockGuard = - &mut self.free_regions[exp2index(exp)].lock(); - match self.query_addr_region(exp, list_guard) { + let mut list_guard: SpinLockGuard = + 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" ); diff --git a/kernel/src/mm/mod.rs b/kernel/src/mm/mod.rs index d3b5f671..c2dae170 100644 --- a/kernel/src/mm/mod.rs +++ b/kernel/src/mm/mod.rs @@ -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(address: VirtAddr) -> T { diff --git a/kernel/src/mm/page.rs b/kernel/src/mm/page.rs index 2cf0b8ae..edf3b9ce 100644 --- a/kernel/src/mm/page.rs +++ b/kernel/src/mm/page.rs @@ -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> = None; diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 4b1c1c16..9d92d28b 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -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(); } diff --git a/kernel/src/sched/clock.rs b/kernel/src/sched/clock.rs index 7e279b90..d203e9d1 100644 --- a/kernel/src/sched/clock.rs +++ b/kernel/src/sched/clock.rs @@ -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; + } } }