riscv: 把内核编译target改为riscv64gc & 获取time csr的频率 & 修正浮点保存与恢复的汇编的问题 (#699)
* 1. 把内核编译target改为riscv64gc 2. fix: 修正浮点保存与恢复的汇编的问题 * riscv: 获取time csr的频率
This commit is contained in:
parent
f0c87a897f
commit
23ef2b33d1
|
@ -20,4 +20,3 @@ Cargo.lock
|
|||
.cache
|
||||
compile_commands.json
|
||||
/logs/
|
||||
.vscode
|
|
@ -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",
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(cfg_target_abi)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate cc;
|
||||
|
|
|
@ -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",
|
||||
```
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -3,7 +3,6 @@ use sbi_rt::HartMask;
|
|||
|
||||
use crate::{
|
||||
init::boot_params,
|
||||
kdebug,
|
||||
mm::percpu::{PerCpu, PerCpuVar},
|
||||
smp::cpu::{ProcessorId, SmpCpuManager},
|
||||
};
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
pub mod of;
|
||||
pub mod sbi;
|
||||
|
|
|
@ -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(());
|
||||
}
|
||||
}
|
|
@ -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() };
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -58,6 +58,7 @@ pub unsafe fn mm_init() {
|
|||
Ordering::SeqCst,
|
||||
)
|
||||
.unwrap();
|
||||
MMArch::arch_post_init();
|
||||
kinfo!("mm init done.");
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue