Skip to content

Commit

Permalink
riscv: 把内核编译target改为riscv64gc & 获取time csr的频率 & 修正浮点保存与恢复的汇编的问题 (Drag…
Browse files Browse the repository at this point in the history
…onOS-Community#699)

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

* riscv: 获取time csr的频率
  • Loading branch information
fslongjin authored Apr 6, 2024
1 parent f0c87a8 commit 23ef2b3
Show file tree
Hide file tree
Showing 28 changed files with 373 additions and 229 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@ Cargo.lock
.cache
compile_commands.json
/logs/
.vscode
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 3 additions & 2 deletions build-scripts/kernel_build/src/cfiles/arch/riscv64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}

Expand Down
2 changes: 2 additions & 0 deletions build-scripts/kernel_build/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![feature(cfg_target_abi)]

#[macro_use]
extern crate lazy_static;
extern crate cc;
Expand Down
2 changes: 1 addition & 1 deletion docs/kernel/configuration/arch.md
Original file line number Diff line number Diff line change
Expand Up @@ -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",
```

Expand Down
4 changes: 2 additions & 2 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion kernel/env.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion kernel/src/arch/riscv64/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use sbi_rt::HartMask;

use crate::{
init::boot_params,
kdebug,
mm::percpu::{PerCpu, PerCpuVar},
smp::cpu::{ProcessorId, SmpCpuManager},
};
Expand Down
1 change: 1 addition & 0 deletions kernel/src/arch/riscv64/driver/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod of;
pub mod sbi;
40 changes: 40 additions & 0 deletions kernel/src/arch/riscv64/driver/of.rs
Original file line number Diff line number Diff line change
@@ -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(());
}
}
8 changes: 6 additions & 2 deletions kernel/src/arch/riscv64/init/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand All @@ -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),
};

Expand Down Expand Up @@ -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);
Expand All @@ -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() };
Expand Down
30 changes: 23 additions & 7 deletions kernel/src/arch/riscv64/interrupt/handle.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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
Expand All @@ -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();
}
Expand Down
19 changes: 16 additions & 3 deletions kernel/src/arch/riscv64/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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,
},
Expand Down Expand Up @@ -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());
}
Expand Down
Loading

0 comments on commit 23ef2b3

Please sign in to comment.