mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 10:15:03 +00:00
在riscv输出hello world (#466)
增加了以下内容: - SBI驱动 - 把内核的rust工具链升级到2023-08-15版本 - 输出riscv的helloworld - 设置内核是PIC的
This commit is contained in:
parent
fca83acef4
commit
1a72a751b1
4
Makefile
4
Makefile
@ -76,7 +76,11 @@ clean-docs:
|
||||
bash -c "cd docs && make clean && cd .."
|
||||
|
||||
gdb:
|
||||
ifeq ($(ARCH), x86_64)
|
||||
rust-gdb -n -x tools/.gdbinit
|
||||
else
|
||||
gdb-multiarch -n -x tools/.gdbinit
|
||||
endif
|
||||
|
||||
# 写入磁盘镜像
|
||||
write_diskimage:
|
||||
|
@ -17,7 +17,7 @@ impl CFilesArch for RiscV64CFilesArch {
|
||||
}
|
||||
|
||||
fn setup_files(&self, _c: &mut cc::Build, files: &mut Vec<std::path::PathBuf>) {
|
||||
files.push(PathBuf::from("src/arch/riscv64/boot/head.S"));
|
||||
files.push(PathBuf::from("src/arch/riscv64/asm/head.S"));
|
||||
files.append(&mut FileUtils::list_all_files(
|
||||
&arch_path("asm"),
|
||||
Some("c"),
|
||||
|
@ -26,7 +26,7 @@ impl CFilesBuilder {
|
||||
c.flag("-fno-builtin")
|
||||
.flag("-nostdlib")
|
||||
.flag("-fno-stack-protector")
|
||||
.flag("-fno-pie")
|
||||
.flag("-static-pie")
|
||||
.flag("-Wno-expansion-to-defined")
|
||||
.flag("-Wno-unused-parameter")
|
||||
.flag("-O1");
|
||||
|
4
env.mk
4
env.mk
@ -22,7 +22,9 @@ export OBJCOPY=$(DragonOS_GCC)/x86_64-elf-objcopy
|
||||
else ifeq ($(ARCH), riscv64)
|
||||
|
||||
export CC=riscv64-unknown-elf-gcc
|
||||
export LD=riscv64-unknown-elf-ld
|
||||
# binutils版本需要>=2.38
|
||||
# 而ubuntu的unknown-elf的版本比较旧,所以使用了riscv64-linux-gnu-ld
|
||||
export LD=riscv64-linux-gnu-ld
|
||||
export AS=riscv64-unknown-elf-as
|
||||
export NM=riscv64-unknown-elf-nm
|
||||
export AR=riscv64-unknown-elf-ar
|
||||
|
@ -6,7 +6,7 @@ export ARCH ?= x86_64
|
||||
ifeq ($(ARCH), x86_64)
|
||||
export TARGET_JSON=arch/x86_64/x86_64-unknown-none.json
|
||||
else ifeq ($(ARCH), riscv64)
|
||||
export TARGET_JSON=riscv64imac-unknown-none-elf
|
||||
export TARGET_JSON=arch/riscv64/riscv64imac-unknown-none-elf.json
|
||||
endif
|
||||
|
||||
export CARGO_ZBUILD=-Z build-std=core,alloc,compiler_builtins -Z build-std-features=compiler-builtins-mem
|
||||
@ -33,8 +33,8 @@ check: ECHO
|
||||
# @echo "Checking kernel... ARCH=$(ARCH)"
|
||||
# @exit 1
|
||||
ifeq ($(ARCH), x86_64)
|
||||
@cargo +nightly-2023-01-21 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)
|
||||
@cargo +nightly-2023-01-21 check --workspace $(CARGO_ZBUILD) --message-format=json --target $(TARGET_JSON)
|
||||
@cargo +nightly-2023-08-15 check --workspace $(CARGO_ZBUILD) --message-format=json --target ./src/$(TARGET_JSON)
|
||||
endif
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2023-01-21"
|
||||
channel = "nightly-2023-08-15"
|
||||
components = ["rust-src"]
|
@ -40,11 +40,8 @@ kernel_subdirs := common driver debug exception smp syscall ktest libs time
|
||||
|
||||
|
||||
kernel_rust:
|
||||
ifeq ($(ARCH), riscv64)
|
||||
RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2023-01-21 $(CARGO_ZBUILD) build --release --target riscv64imac-unknown-none-elf
|
||||
else
|
||||
RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2023-01-21 $(CARGO_ZBUILD) build --release --target $(TARGET_JSON)
|
||||
endif
|
||||
RUSTFLAGS="$(RUSTFLAGS)" cargo +nightly-2023-08-15 $(CARGO_ZBUILD) build --release --target $(TARGET_JSON)
|
||||
|
||||
|
||||
all: kernel
|
||||
|
||||
|
34
kernel/src/arch/riscv64/asm/head.S
Normal file
34
kernel/src/arch/riscv64/asm/head.S
Normal file
@ -0,0 +1,34 @@
|
||||
#include "common/asm.h"
|
||||
|
||||
.section .bootstrap
|
||||
|
||||
#define CSR_SIE 0x104
|
||||
#define CSR_SIP 0x144
|
||||
|
||||
#define CSR_IE CSR_SIE
|
||||
#define CSR_IP CSR_SIP
|
||||
|
||||
// 内核入口(从DragonStub跳转到这里)
|
||||
// 参数:
|
||||
// a0: hartid (核心ID)
|
||||
// a1: fdt (平坦设备树)
|
||||
.global _start
|
||||
.type _start, @function
|
||||
ENTRY(_start)
|
||||
/* Mask all interrupts */
|
||||
csrw CSR_IE, zero
|
||||
csrw CSR_IP, zero
|
||||
/* Load the global pointer */
|
||||
.option push
|
||||
.option norelax
|
||||
la sp, BSP_IDLE_STACK_SPACE
|
||||
li t0, 32768
|
||||
add sp, sp, t0
|
||||
.option pop
|
||||
/* Call the kernel */
|
||||
call kernel_main
|
||||
nop
|
||||
_loop:
|
||||
j _loop
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
#include "common/asm.h"
|
||||
|
||||
.section .bootstrap
|
||||
|
||||
.global _start
|
||||
.type _start, @function
|
||||
ENTRY(_start)
|
||||
loop:
|
||||
j loop
|
1
kernel/src/arch/riscv64/driver/mod.rs
Normal file
1
kernel/src/arch/riscv64/driver/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod sbi;
|
220
kernel/src/arch/riscv64/driver/sbi/ecall.rs
Normal file
220
kernel/src/arch/riscv64/driver/sbi/ecall.rs
Normal file
@ -0,0 +1,220 @@
|
||||
#![allow(dead_code)]
|
||||
use super::SbiError;
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行零参数的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 不接受任何参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall0(extension_id: usize, function_id: usize) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
lateout("a0") error,
|
||||
lateout("a1") value,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行单参数的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall1(
|
||||
arg: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg => error,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
lateout("a1") value,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 一个带有给定扩展和函数ID的两参数`ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数ID接受两个参数时,才安全调用此函数。否则,行为将是未定义的,
|
||||
/// 因为将额外的中断寄存器传递给SBI实现时,其内容将是未定义的。
|
||||
#[inline]
|
||||
pub unsafe fn ecall2(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行 3参数 的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall3(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
arg2: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a2") arg2,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行 4参数 的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall4(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
arg2: usize,
|
||||
arg3: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a2") arg2,
|
||||
in("a3") arg3,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行 5参数 的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall5(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
arg2: usize,
|
||||
arg3: usize,
|
||||
arg4: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a2") arg2,
|
||||
in("a3") arg3,
|
||||
in("a4") arg4,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行 6参数 的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub unsafe fn ecall6(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
arg2: usize,
|
||||
arg3: usize,
|
||||
arg4: usize,
|
||||
arg5: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a2") arg2,
|
||||
in("a3") arg3,
|
||||
in("a4") arg4,
|
||||
in("a5") arg5,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
194
kernel/src/arch/riscv64/driver/sbi/legacy.rs
Normal file
194
kernel/src/arch/riscv64/driver/sbi/legacy.rs
Normal file
@ -0,0 +1,194 @@
|
||||
use crate::{
|
||||
arch::driver::sbi::ecall::{ecall0, ecall1},
|
||||
mm::VirtAddr,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
/// `sbi_set_timer` extension ID
|
||||
pub const SET_TIMER_EID: usize = 0x00;
|
||||
/// `sbi_console_putchar` extension ID
|
||||
pub const CONSOLE_PUTCHAR_EID: usize = 0x01;
|
||||
/// `sbi_console_getchar` extension ID
|
||||
pub const CONSOLE_GETCHAR_EID: usize = 0x02;
|
||||
/// `sbi_clear_ipi` extension ID
|
||||
pub const CLEAR_IPI_EID: usize = 0x03;
|
||||
/// `sbi_send_ipi` extension ID
|
||||
pub const SEND_IPI_EID: usize = 0x04;
|
||||
/// `sbi_remote_fence_i` extension ID
|
||||
pub const REMOTE_FENCE_I_EID: usize = 0x05;
|
||||
/// `sbi_remote_sfence_vma` extension ID
|
||||
pub const REMOTE_SFENCE_VMA_EID: usize = 0x06;
|
||||
/// `sbi_remote_sfence_vma_asid` extension ID
|
||||
pub const REMOTE_SFENCE_VMA_ASID_EID: usize = 0x07;
|
||||
/// `sbi_shutdown` extension ID
|
||||
pub const SHUTDOWN_EID: usize = 0x08;
|
||||
|
||||
/// 计划在未来的某个时间触发中断。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `stime`:要触发中断的绝对时间,以滴答为单位。如果`stime`小于当前时间,则不会触发中断。
|
||||
///
|
||||
/// ## 详情
|
||||
///
|
||||
/// 要清除计时器中断而不预约另一个计时器事件,可以将时间设置为无限远(`u64::MAX`)或
|
||||
/// mask `sie` CSR的`STIE` 位。此函数将清除待处理计时器中断位。
|
||||
///
|
||||
/// 注意:`time` 是一个绝对时间,不是从调用时刻开始的偏移量。这意味着如果您想要设置一个未来`n`和tick之后
|
||||
/// 触发的时钟,您需要首先读取 `time` CSR,然后将滴答数添加到该值。关于如何确定每个滴答的时间,
|
||||
/// 这是平台依赖的,而时钟频率应在 CPU 节点的 `timebase-frequency` 属性中表达,如果可用的话。
|
||||
#[inline]
|
||||
pub unsafe fn set_timer(stime: u64) {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
ecall1(stime as usize, SET_TIMER_EID, 0).ok();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inout ("a0") stime as usize => _,
|
||||
inout ("a1") (stime >> 32) as usize => _,
|
||||
in("a7") SET_TIMER_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 将字符写入调试控制台。如果仍有待处理的控制台输出,此调用将阻塞。如果不存在控制台,则不会执行任何操作。
|
||||
#[inline]
|
||||
pub unsafe fn console_putchar(c: u8) {
|
||||
unsafe {
|
||||
ecall1(c.into(), CONSOLE_PUTCHAR_EID, 0).ok();
|
||||
}
|
||||
}
|
||||
|
||||
/// 尝试从调试控制台获取一个字符。
|
||||
/// 如果没有任何字符等待阅读,或者没有调试控制台设备,则此函数将返回[`None`]。
|
||||
#[inline]
|
||||
pub unsafe fn console_getchar() -> Option<u8> {
|
||||
let mut ret: i8;
|
||||
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
lateout("a0") ret,
|
||||
in("a7") CONSOLE_GETCHAR_EID,
|
||||
);
|
||||
}
|
||||
|
||||
match ret {
|
||||
-1 => None,
|
||||
_ => Some(ret as u8),
|
||||
}
|
||||
}
|
||||
|
||||
/// 清除current核心的待处理中断(IPIs)。
|
||||
#[inline]
|
||||
#[deprecated = "S模式可以直接清除`sip.SSIP` CSR位,因此无需调用此函数。"]
|
||||
pub unsafe fn clear_ipi() {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") CLEAR_IPI_EID,
|
||||
lateout("a0") _,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 向所有由`hart_mask`位掩码指定的核心发送中断(IPI)。接收到的中断表示为监视器软件中断。
|
||||
///
|
||||
/// ## 参数
|
||||
/// - `hart_mask`: 一个长度为`n_harts / size_of::<usize>()`的二进制位向量,向上取整到下一个`usize`。
|
||||
#[inline]
|
||||
pub unsafe fn send_ipi(hart_mask: &[usize]) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("a0") hart_mask.as_ptr() => _,
|
||||
in("a7") SEND_IPI_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 对指定的心脏(hart)执行 `FENCE.I` 指令
|
||||
///
|
||||
/// ## 参数
|
||||
/// - `hart_mask`: 一个长度为 `n_harts / size_of::<usize>()` 的位矢量,
|
||||
/// 向上取整到下一个 `usize」。
|
||||
#[inline]
|
||||
pub unsafe fn remote_fence_i(hart_mask: &[usize]) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("a0") hart_mask.as_ptr() => _,
|
||||
in("a7") REMOTE_FENCE_I_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 在指定的hart上执行`SFENCE.VMA`指令
|
||||
/// 为指定的虚拟内存范围(由`start`和`size`指定)执行。
|
||||
///
|
||||
/// ## 参数
|
||||
/// - `hart_mask`: 一个长度为`n_harts / size_of::<usize>()`的二进制向量,
|
||||
/// 向上取整到下一个`usize`。
|
||||
/// - `start`: 要执行`SFENCE.VMA`的起始虚拟地址。
|
||||
/// - `size`: 要对`start`执行的`SFENCE.VMA`的字节大小。例如,要失效一个
|
||||
/// 包含2个4-KiB页面的区域,您会为`size`传递`8192`。
|
||||
///
|
||||
/// 如果`start`和`size`都为`0`,或者如果`size`为[`usize::MAX`],则将执行完整的
|
||||
/// `SFENCE.VMA`,而不仅仅是一个或多个页面大小的`SFENCE.VMA`。
|
||||
#[inline]
|
||||
pub unsafe fn remote_sfence_vma(hart_mask: &[usize], start: VirtAddr, size: usize) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("a0") hart_mask.as_ptr() => _,
|
||||
in("a1") start.data(),
|
||||
in("a2") size,
|
||||
in("a7") REMOTE_SFENCE_VMA_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 在指定的hart上执行SFENCE.VMA指令
|
||||
///
|
||||
/// 仅针对指定的地址空间ID(ASID)执行虚拟内存范围指定的
|
||||
/// start和size的hart_mask位掩码。
|
||||
///
|
||||
/// ## 参数
|
||||
/// - `hart_mask`: 一个长度为`n_harts / size_of::<usize>()`的二进制向量,
|
||||
/// 向上取整到下一个`usize`。
|
||||
/// - `start`: 要执行`SFENCE.VMA`的起始虚拟地址。
|
||||
/// - `size`: 要对`start`执行的`SFENCE.VMA`的字节大小。例如,要失效一个
|
||||
/// 包含2个4-KiB页面的区域,您会为`size`传递`8192`。
|
||||
/// - `asid`: 要执行`SFENCE.VMA`的地址空间ID。
|
||||
///
|
||||
/// 如果start和size都为0,或者如果size为[usize::MAX],则将执行全
|
||||
/// 部SFENCE.VMA,而不是多个页面大小的SFENCE.VMA`。
|
||||
#[inline]
|
||||
pub unsafe fn remote_sfence_vma_asid(hart_mask: &[usize], start: usize, size: usize, asid: usize) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("a0") hart_mask.as_ptr() => _,
|
||||
in("a1") start,
|
||||
in("a2") size,
|
||||
in("a3") asid,
|
||||
in("a7") REMOTE_SFENCE_VMA_ASID_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 将所有核心置于关闭状态,此时处理器的执行模式比当前监督模式具有更高的特权。此调用不会返回。
|
||||
#[inline]
|
||||
pub unsafe fn shutdown() -> ! {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") SHUTDOWN_EID,
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
}
|
93
kernel/src/arch/riscv64/driver/sbi/mod.rs
Normal file
93
kernel/src/arch/riscv64/driver/sbi/mod.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use self::legacy::console_putchar;
|
||||
|
||||
/// The SBI S-mode driver.
|
||||
///
|
||||
/// Some code takes from `https://github.com/repnop/sbi.git`
|
||||
mod ecall;
|
||||
pub mod legacy;
|
||||
|
||||
/// Error codes returned by SBI calls
|
||||
///
|
||||
/// note: `SBI_SUCCESS` is not represented here since this is to be used as the
|
||||
/// error type in a `Result`
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum SbiError {
|
||||
/// The SBI call failed
|
||||
Failed,
|
||||
/// The SBI call is not implemented or the functionality is not available
|
||||
NotSupported,
|
||||
/// An invalid parameter was passed
|
||||
InvalidParameter,
|
||||
/// The SBI implementation has denied execution of the call functionality
|
||||
Denied,
|
||||
/// An invalid address was passed
|
||||
InvalidAddress,
|
||||
/// The resource is already available
|
||||
AlreadyAvailable,
|
||||
/// The resource was previously started
|
||||
AlreadyStarted,
|
||||
/// The resource was previously stopped
|
||||
AlreadyStopped,
|
||||
}
|
||||
|
||||
impl SbiError {
|
||||
#[inline]
|
||||
fn new(n: isize) -> Self {
|
||||
match n {
|
||||
-1 => SbiError::Failed,
|
||||
-2 => SbiError::NotSupported,
|
||||
-3 => SbiError::InvalidParameter,
|
||||
-4 => SbiError::Denied,
|
||||
-5 => SbiError::InvalidAddress,
|
||||
-6 => SbiError::AlreadyAvailable,
|
||||
-7 => SbiError::AlreadyStarted,
|
||||
-8 => SbiError::AlreadyStopped,
|
||||
n => unreachable!("bad SBI error return value: {}", n),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for SbiError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
SbiError::AlreadyAvailable => "resource is already available",
|
||||
SbiError::Denied => "SBI implementation denied execution",
|
||||
SbiError::Failed => "call to SBI failed",
|
||||
SbiError::InvalidAddress => "invalid address passed",
|
||||
SbiError::InvalidParameter => "invalid parameter passed",
|
||||
SbiError::NotSupported => "SBI call not implemented or functionality not available",
|
||||
SbiError::AlreadyStarted => "resource was already started",
|
||||
SbiError::AlreadyStopped => "resource was already stopped",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// 向控制台打印字符串。
|
||||
///
|
||||
/// 该函数接受一个字节切片 `s` 作为输入,并迭代切片中的每个字节 `c`。
|
||||
/// 然后调用 `console_putchar` 函数,将 `c` 的值作为参数传递给它。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 该函数被标记为 `unsafe`,因为它调用了 `console_putchar` 函数,
|
||||
/// 而假设该函数执行可能有副作用或违反内存安全的底层操作。
|
||||
/// 调用者有责任确保 `s` 切片是有效的并且正确终止的。
|
||||
///
|
||||
/// # 参数
|
||||
///
|
||||
/// * `s` - 表示要打印的字符串的字节切片。
|
||||
///
|
||||
/// # 示例
|
||||
///
|
||||
/// ```
|
||||
/// let message = b"Hello, World!";
|
||||
/// console_putstr(message);
|
||||
/// ```
|
||||
pub unsafe fn console_putstr(s: &[u8]) {
|
||||
for c in s {
|
||||
unsafe { console_putchar(*c) };
|
||||
}
|
||||
}
|
14
kernel/src/arch/riscv64/init/mod.rs
Normal file
14
kernel/src/arch/riscv64/init/mod.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use core::intrinsics::unreachable;
|
||||
|
||||
use crate::{
|
||||
driver::tty::serial::serial8250::send_to_default_serial8250_port, init::init_before_mem_init,
|
||||
kdebug,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn kernel_main(hartid: usize, fdt_addr: usize) -> ! {
|
||||
init_before_mem_init();
|
||||
send_to_default_serial8250_port(&b"Hello, world! RISC-V!\n"[..]);
|
||||
loop {}
|
||||
unreachable()
|
||||
}
|
@ -10,8 +10,8 @@ ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
KERNEL_VMA = 0xffffffc000000000;
|
||||
//KERNEL_VMA = 0;
|
||||
//KERNEL_VMA = 0xffffffc000000000;
|
||||
KERNEL_VMA = 0;
|
||||
. = 0x1000000;
|
||||
|
||||
.boot.text :
|
||||
@ -44,7 +44,8 @@ SECTIONS
|
||||
_data = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
|
||||
*(.got.plt)
|
||||
*(.got)
|
||||
_edata = .;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
pub mod asm;
|
||||
pub mod cpu;
|
||||
pub mod driver;
|
||||
mod init;
|
||||
pub mod interrupt;
|
||||
pub mod ipc;
|
||||
mod kvm;
|
||||
|
@ -10,6 +10,19 @@ use super::interrupt::TrapFrame;
|
||||
pub mod kthread;
|
||||
pub mod syscall;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(align(32768))]
|
||||
union InitProcUnion {
|
||||
/// 用于存放idle进程的内核栈
|
||||
idle_stack: [u8; 32768],
|
||||
}
|
||||
|
||||
#[link_section = ".data.init_proc_union"]
|
||||
#[no_mangle]
|
||||
static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion {
|
||||
idle_stack: [0; 32768],
|
||||
};
|
||||
|
||||
pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
|
||||
unimplemented!("RiscV64 arch_switch_to_user")
|
||||
}
|
||||
|
18
kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json
Normal file
18
kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"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"
|
||||
}
|
@ -67,7 +67,7 @@ impl Hpet {
|
||||
let tm_num = hpet.timers_num();
|
||||
kinfo!("HPET has {} timers", tm_num);
|
||||
hpet_info.hpet_number = tm_num as u8;
|
||||
drop(hpet);
|
||||
|
||||
drop(mmio);
|
||||
if tm_num == 0 {
|
||||
return Err(SystemError::ENODEV);
|
||||
@ -118,7 +118,6 @@ impl Hpet {
|
||||
|
||||
unsafe { regs.write_main_counter_value(0) };
|
||||
|
||||
drop(regs);
|
||||
drop(inner_guard);
|
||||
|
||||
let (inner_guard, timer_reg) = unsafe { self.timer_mut(0).ok_or(SystemError::ENODEV) }?;
|
||||
@ -130,7 +129,6 @@ impl Hpet {
|
||||
volwrite!(timer_reg, config, 0x004c);
|
||||
volwrite!(timer_reg, comparator_value, ticks);
|
||||
}
|
||||
drop(timer_reg);
|
||||
drop(inner_guard);
|
||||
|
||||
// todo!("register irq in C");
|
||||
@ -142,7 +140,6 @@ impl Hpet {
|
||||
// 置位旧设备中断路由兼容标志位、定时器组使能标志位
|
||||
unsafe { regs.write_general_config(3) };
|
||||
|
||||
drop(regs);
|
||||
drop(inner_guard);
|
||||
|
||||
kinfo!("HPET enabled");
|
||||
@ -208,7 +205,7 @@ impl Hpet {
|
||||
pub fn main_counter_value(&self) -> u64 {
|
||||
let (inner_guard, regs) = unsafe { self.hpet_regs() };
|
||||
let value = regs.main_counter_value();
|
||||
drop(regs);
|
||||
|
||||
drop(inner_guard);
|
||||
return value;
|
||||
}
|
||||
@ -217,7 +214,7 @@ impl Hpet {
|
||||
let (inner_guard, regs) = unsafe { self.hpet_regs() };
|
||||
let period = regs.counter_clock_period();
|
||||
kdebug!("HPET period: {}", period);
|
||||
drop(regs);
|
||||
|
||||
drop(inner_guard);
|
||||
return period;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ pub struct KSet {
|
||||
}
|
||||
|
||||
impl Hash for KSet {
|
||||
fn hash<H: ~const core::hash::Hasher>(&self, state: &mut H) {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.self_ref.as_ptr().hash(state);
|
||||
self.inner.read().name.hash(state);
|
||||
}
|
||||
@ -123,7 +123,7 @@ impl KSet {
|
||||
#[allow(dead_code)]
|
||||
pub fn cleanup_weak(&self) {
|
||||
let mut kobjects = self.kobjects.write();
|
||||
kobjects.drain_filter(|x| x.upgrade().is_none());
|
||||
kobjects.retain(|x| x.upgrade().is_some());
|
||||
}
|
||||
|
||||
pub fn as_kobject(&self) -> Arc<dyn KObject> {
|
||||
|
@ -59,12 +59,17 @@ pub(super) fn serial8250_manager() -> &'static Serial8250Manager {
|
||||
&Serial8250Manager
|
||||
}
|
||||
|
||||
/// 标记serial8250是否已经初始化
|
||||
static mut INITIALIZED: bool = false;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct Serial8250Manager;
|
||||
|
||||
impl Serial8250Manager {
|
||||
/// 初始化串口设备(在内存管理初始化之前)
|
||||
pub fn early_init(&self) -> Result<(), SystemError> {
|
||||
// todo: riscv64: 串口设备初始化
|
||||
#[cfg(not(target_arch = "riscv64"))]
|
||||
serial8250_pio_port_early_init()?;
|
||||
return Ok(());
|
||||
}
|
||||
@ -101,10 +106,14 @@ impl Serial8250Manager {
|
||||
return e;
|
||||
})?;
|
||||
|
||||
// todo: 把驱动注册到platform总线
|
||||
// 把驱动注册到platform总线
|
||||
platform_driver_manager()
|
||||
.register(serial8250_isa_driver.clone() as Arc<dyn PlatformDriver>)?;
|
||||
|
||||
unsafe {
|
||||
INITIALIZED = true;
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -469,7 +478,7 @@ impl Driver for Serial8250ISADriver {
|
||||
fn delete_device(&self, device: &Arc<dyn Device>) {
|
||||
let mut inner = self.inner.write();
|
||||
|
||||
inner.devices.drain_filter(|d| Arc::ptr_eq(d, device));
|
||||
inner.devices.retain(|d| !Arc::ptr_eq(d, device));
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
@ -539,5 +548,15 @@ impl KObject for Serial8250ISADriver {
|
||||
|
||||
/// 临时函数,用于向默认的串口发送数据
|
||||
pub fn send_to_default_serial8250_port(s: &[u8]) {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
send_to_serial8250_pio_com1(s);
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
{
|
||||
if unsafe { INITIALIZED } {
|
||||
todo!("riscv64: send_to_default_serial8250_port")
|
||||
} else {
|
||||
unsafe { crate::arch::driver::sbi::console_putstr(s) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,11 +170,14 @@ impl VideoRefreshManager {
|
||||
return self.device_buffer.read();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化显示驱动
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
/// 在riscv64平台下暂时不支持
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub unsafe fn video_init() -> Result<(), SystemError> {
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
/// 此函数用于初始化显示驱动,为后续的图形输出做好准备。
|
||||
#[cfg(not(target_arch = "riscv64"))]
|
||||
pub unsafe fn video_init() -> Result<(), SystemError> {
|
||||
static INIT: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
|
@ -148,7 +148,7 @@ impl Softirq {
|
||||
/// @param irq_num 中断向量号码
|
||||
pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) {
|
||||
// kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64);
|
||||
let table_guard = &mut self.table.write();
|
||||
let mut table_guard = self.table.write();
|
||||
// 将软中断向量清空
|
||||
table_guard[softirq_num as usize] = None;
|
||||
drop(table_guard);
|
||||
|
@ -625,7 +625,6 @@ impl FATDir {
|
||||
// todo: 设置创建、访问时间
|
||||
dot_entry.flush(&fs, fs.cluster_bytes_offset(first_cluster) + offset)?;
|
||||
|
||||
drop(dot_entry);
|
||||
// 偏移量加上一个目录项的长度
|
||||
offset += FATRawDirEntry::DIR_ENTRY_LEN;
|
||||
|
||||
|
@ -115,7 +115,8 @@ impl ProcFSInode {
|
||||
/// @brief 去除Vec中所有的\0,并在结尾添加\0
|
||||
#[inline]
|
||||
fn trim_string(&self, data: &mut Vec<u8>) {
|
||||
data.drain_filter(|x: &mut u8| *x == 0);
|
||||
data.retain(|x| *x != 0);
|
||||
|
||||
data.push(0);
|
||||
}
|
||||
// todo:其他数据获取函数实现
|
||||
@ -420,15 +421,9 @@ impl IndexNode for LockedProcFSInode {
|
||||
if let FileType::Dir = guard.metadata.file_type {
|
||||
return Ok(());
|
||||
}
|
||||
// 获取数据信息
|
||||
let private_data = match data {
|
||||
FilePrivateData::Procfs(p) => p,
|
||||
_ => {
|
||||
panic!("ProcFS: FilePrivateData mismatch!");
|
||||
}
|
||||
};
|
||||
// 释放资源
|
||||
drop(private_data);
|
||||
// 释放data
|
||||
*data = FilePrivateData::Procfs(ProcfsFilePrivateData::new());
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ fn init_intertrait() {
|
||||
}
|
||||
|
||||
/// 在内存管理初始化之前,执行的初始化
|
||||
fn init_before_mem_init() {
|
||||
pub fn init_before_mem_init() {
|
||||
tty_early_init().expect("tty early init failed");
|
||||
unsafe { VideoRefreshManager::video_init().ok() };
|
||||
scm_init();
|
||||
let video_ok = unsafe { VideoRefreshManager::video_init().is_ok() };
|
||||
scm_init(video_ok);
|
||||
}
|
||||
|
@ -423,17 +423,8 @@ impl SigPending {
|
||||
/// @brief 从sigpending中删除mask中被置位的信号。也就是说,比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
|
||||
pub fn flush_by_mask(&mut self, mask: &SigSet) {
|
||||
// 定义过滤器,从sigqueue中删除mask中被置位的信号
|
||||
let filter = |x: &mut SigInfo| {
|
||||
if mask.contains(SigSet::from_bits_truncate(x.sig_no as u64)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
let filter_result: Vec<SigInfo> = self.queue.q.drain_filter(filter).collect();
|
||||
// 回收这些siginfo
|
||||
for x in filter_result {
|
||||
drop(x)
|
||||
}
|
||||
let filter = |x: &SigInfo| !mask.contains(SigSet::from_bits_truncate(x.sig_no as u64));
|
||||
self.queue.q.retain(filter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,7 +487,7 @@ impl SigQueue {
|
||||
return false;
|
||||
};
|
||||
// 从sigqueue中过滤出结果
|
||||
let mut filter_result: Vec<SigInfo> = self.q.drain_filter(filter).collect();
|
||||
let mut filter_result: Vec<SigInfo> = self.q.extract_if(filter).collect();
|
||||
// 筛选出的结果不能大于1个
|
||||
assert!(filter_result.len() <= 1);
|
||||
|
||||
|
@ -105,7 +105,7 @@ impl Syscall {
|
||||
) -> Result<usize, SystemError> {
|
||||
// 请注意:用户态传进来的user_sigaction结构体类型,请注意,这个结构体与内核实际的不一样
|
||||
let act: *mut UserSigaction = new_act as *mut UserSigaction;
|
||||
let mut old_act = old_act as *mut UserSigaction;
|
||||
let old_act = old_act as *mut UserSigaction;
|
||||
let mut new_ka: Sigaction = Default::default();
|
||||
let mut old_sigaction: Sigaction = Default::default();
|
||||
// 如果传入的,新的sigaction不为空
|
||||
|
@ -7,11 +7,9 @@
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_refs_to_cell)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(cstr_from_bytes_until_nul)]
|
||||
#![feature(c_void_variant)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(extract_if)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(is_some_and)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(ptr_internals)]
|
||||
@ -22,7 +20,6 @@
|
||||
#![feature(ptr_to_from_bits)]
|
||||
#![feature(concat_idents)]
|
||||
#![cfg_attr(target_os = "none", no_std)]
|
||||
#![feature(atomic_mut_ptr)]
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
|
@ -659,8 +659,6 @@ impl BinaryLoader for ElfLoader {
|
||||
return Err(ExecError::InvalidParemeter);
|
||||
}
|
||||
|
||||
drop(p_vaddr);
|
||||
|
||||
// end vaddr of this segment(code+data+bss)
|
||||
let seg_end_vaddr_f = self.elf_page_align_up(VirtAddr::new(
|
||||
(seg_to_load.p_vaddr + seg_to_load.p_filesz) as usize,
|
||||
@ -683,8 +681,6 @@ impl BinaryLoader for ElfLoader {
|
||||
end_data = Some(seg_end_vaddr_f);
|
||||
}
|
||||
|
||||
drop(seg_end_vaddr_f);
|
||||
|
||||
let seg_end_vaddr = VirtAddr::new((seg_to_load.p_vaddr + seg_to_load.p_memsz) as usize);
|
||||
|
||||
if seg_end_vaddr > elf_brk {
|
||||
|
@ -124,7 +124,9 @@ impl FutexHashBucket {
|
||||
|
||||
/// 将FutexObj从bucket中删除
|
||||
pub fn remove(&mut self, futex: Arc<FutexObj>) {
|
||||
self.chain.drain_filter(|x| Arc::ptr_eq(x, &futex));
|
||||
self.chain
|
||||
.extract_if(|x| Arc::ptr_eq(x, &futex))
|
||||
.for_each(drop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,7 +176,7 @@ pub struct PrivateKey {
|
||||
}
|
||||
|
||||
impl Hash for PrivateKey {
|
||||
fn hash<H: ~const Hasher>(&self, state: &mut H) {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.address.hash(state);
|
||||
}
|
||||
}
|
||||
@ -284,7 +286,6 @@ impl Futex {
|
||||
kwarn!("error:{e:?}");
|
||||
e
|
||||
})?;
|
||||
drop(bucket_mut);
|
||||
drop(futex_map_guard);
|
||||
drop(irq_guard);
|
||||
sched();
|
||||
@ -368,7 +369,6 @@ impl Futex {
|
||||
// 从队列中唤醒
|
||||
let count = bucket_mut.wake_up(key.clone(), Some(bitset), nr_wake)?;
|
||||
|
||||
drop(bucket_mut);
|
||||
drop(binding);
|
||||
|
||||
FutexData::try_remove(&key);
|
||||
@ -427,7 +427,6 @@ impl Futex {
|
||||
// 唤醒nr_wake个进程
|
||||
let bucket_1_mut = futex_data_guard.get_mut(&key1).ok_or(SystemError::EINVAL)?;
|
||||
let ret = bucket_1_mut.wake_up(key1.clone(), None, nr_wake as u32)?;
|
||||
drop(bucket_1_mut);
|
||||
// 将bucket1中最多nr_requeue个任务转移到bucket2
|
||||
for _ in 0..nr_requeue {
|
||||
let bucket_1_mut = futex_data_guard.get_mut(&key1).ok_or(SystemError::EINVAL)?;
|
||||
@ -615,7 +614,7 @@ impl Futex {
|
||||
|
||||
let atomic_addr = AtomicU64::new(uaddr.data() as u64);
|
||||
// 这个指针是指向指针的指针
|
||||
let ptr = atomic_addr.as_mut_ptr();
|
||||
let ptr = atomic_addr.as_ptr();
|
||||
match op {
|
||||
FutexOP::FUTEX_OP_SET => unsafe {
|
||||
*((*ptr) as *mut u32) = oparg;
|
||||
|
@ -10,12 +10,15 @@ use crate::{
|
||||
driver::{
|
||||
tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
|
||||
},
|
||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||
libs::{lib_ui::textui::textui_is_enable_put_to_window, rwlock::RwLock, spinlock::SpinLock},
|
||||
mm::VirtAddr,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
use super::textui_no_alloc::textui_init_no_alloc;
|
||||
use super::{
|
||||
textui::{textui_disable_put_to_window, textui_enable_put_to_window},
|
||||
textui_no_alloc::textui_init_no_alloc,
|
||||
};
|
||||
|
||||
/// 全局的UI框架列表
|
||||
pub static SCM_FRAMEWORK_LIST: SpinLock<LinkedList<Arc<dyn ScmUiFramework>>> =
|
||||
@ -274,10 +277,14 @@ pub trait ScmUiFramework: Sync + Send + Debug {
|
||||
/// ## 调用时机
|
||||
///
|
||||
/// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。
|
||||
pub fn scm_init() {
|
||||
pub fn scm_init(enable_put_to_window: bool) {
|
||||
SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲
|
||||
|
||||
textui_init_no_alloc();
|
||||
if enable_put_to_window {
|
||||
textui_enable_put_to_window();
|
||||
} else {
|
||||
textui_disable_put_to_window();
|
||||
}
|
||||
textui_init_no_alloc(enable_put_to_window);
|
||||
|
||||
send_to_default_serial8250_port("\nfinish_scm_init\n\0".as_bytes());
|
||||
}
|
||||
@ -370,7 +377,7 @@ pub fn scm_enable_double_buffer() -> Result<i32, SystemError> {
|
||||
pub fn scm_enable_put_to_window() {
|
||||
// mm之前要继续往窗口打印信息时,因为没有动态内存分配(textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
|
||||
if CURRENT_FRAMEWORK.read().is_none() {
|
||||
super::textui::ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst);
|
||||
textui_enable_put_to_window();
|
||||
} else {
|
||||
let r = CURRENT_FRAMEWORK
|
||||
.write()
|
||||
@ -387,8 +394,8 @@ pub fn scm_enable_put_to_window() {
|
||||
pub fn scm_disable_put_to_window() {
|
||||
// mm之前要停止往窗口打印信息时,因为没有动态内存分配(rwlock与otion依然能用,但是textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
|
||||
if CURRENT_FRAMEWORK.read().is_none() {
|
||||
super::textui::ENABLE_PUT_TO_WINDOW.store(false, Ordering::SeqCst);
|
||||
assert!(super::textui::ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst) == false);
|
||||
textui_disable_put_to_window();
|
||||
assert!(textui_is_enable_put_to_window() == false);
|
||||
} else {
|
||||
let r = CURRENT_FRAMEWORK
|
||||
.write()
|
||||
|
@ -37,7 +37,25 @@ pub const TEXTUI_CHAR_HEIGHT: u32 = 16;
|
||||
|
||||
pub static mut TEXTUI_IS_INIT: bool = false;
|
||||
|
||||
pub static ENABLE_PUT_TO_WINDOW: AtomicBool = AtomicBool::new(true);
|
||||
static ENABLE_PUT_TO_WINDOW: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// 启用将文本输出到窗口的功能。
|
||||
pub fn textui_enable_put_to_window() {
|
||||
ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
/// 禁用将文本输出到窗口的功能。
|
||||
pub fn textui_disable_put_to_window() {
|
||||
ENABLE_PUT_TO_WINDOW.store(false, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
/// 检查是否启用了将文本输出到窗口的功能。
|
||||
///
|
||||
/// # 返回
|
||||
/// 如果启用了将文本输出到窗口的功能,则返回 `true`,否则返回 `false`。
|
||||
pub fn textui_is_enable_put_to_window() -> bool {
|
||||
ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
/// 获取TEXTUI_FRAMEWORK的可变实例
|
||||
pub fn textui_framework() -> Arc<TextUiFramework> {
|
||||
@ -904,12 +922,12 @@ impl ScmUiFramework for TextUiFramework {
|
||||
}
|
||||
// 启用ui框架的回调函数
|
||||
fn enable(&self) -> Result<i32, SystemError> {
|
||||
ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst);
|
||||
textui_enable_put_to_window();
|
||||
return Ok(0);
|
||||
}
|
||||
// 禁用ui框架的回调函数
|
||||
fn disable(&self) -> Result<i32, SystemError> {
|
||||
ENABLE_PUT_TO_WINDOW.store(false, Ordering::SeqCst);
|
||||
textui_disable_put_to_window();
|
||||
|
||||
return Ok(0);
|
||||
}
|
||||
@ -986,7 +1004,7 @@ pub fn textui_putchar(
|
||||
character,
|
||||
fr_color,
|
||||
bk_color,
|
||||
ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst),
|
||||
textui_is_enable_put_to_window(),
|
||||
);
|
||||
} else {
|
||||
//未初始化暴力输出
|
||||
@ -994,7 +1012,7 @@ pub fn textui_putchar(
|
||||
character,
|
||||
fr_color,
|
||||
bk_color,
|
||||
ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst),
|
||||
textui_is_enable_put_to_window(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1021,14 +1039,14 @@ pub fn textui_putstr(
|
||||
character,
|
||||
fr_color,
|
||||
bk_color,
|
||||
ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst),
|
||||
textui_is_enable_put_to_window(),
|
||||
)?;
|
||||
} else {
|
||||
no_init_textui_putchar_window(
|
||||
character,
|
||||
fr_color,
|
||||
bk_color,
|
||||
ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst),
|
||||
textui_is_enable_put_to_window(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
@ -21,12 +21,14 @@ pub static NO_ALLOC_OPERATIONS_LINE: AtomicI32 = AtomicI32::new(0);
|
||||
pub static NO_ALLOC_OPERATIONS_INDEX: AtomicI32 = AtomicI32::new(0);
|
||||
|
||||
/// 当系统刚启动的时候,由于内存管理未初始化,而texiui需要动态内存分配。因此只能暂时暴力往屏幕(video_frame_buffer_info)输出信息
|
||||
pub fn textui_init_no_alloc() {
|
||||
let height = video_refresh_manager().device_buffer().height();
|
||||
let width = video_refresh_manager().device_buffer().width();
|
||||
TRUE_LINE_NUM.store((height / TEXTUI_CHAR_HEIGHT) as i32, Ordering::SeqCst);
|
||||
pub fn textui_init_no_alloc(video_enabled: bool) {
|
||||
if video_enabled {
|
||||
let height = video_refresh_manager().device_buffer().height();
|
||||
let width = video_refresh_manager().device_buffer().width();
|
||||
TRUE_LINE_NUM.store((height / TEXTUI_CHAR_HEIGHT) as i32, Ordering::SeqCst);
|
||||
|
||||
CHAR_PER_LINE.store((width / TEXTUI_CHAR_WIDTH) as i32, Ordering::SeqCst);
|
||||
CHAR_PER_LINE.store((width / TEXTUI_CHAR_WIDTH) as i32, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_init_textui_putchar_window(
|
||||
|
@ -65,9 +65,7 @@ impl<V: Clone + Copy, T> NotifierChain<V, T> {
|
||||
|
||||
/// @brief 在通知链中取消注册节点
|
||||
pub fn unregister(&mut self, block: Arc<dyn NotifierBlock<V, T>>) -> Result<(), SystemError> {
|
||||
let remove = self
|
||||
.0
|
||||
.drain_filter(|b| Arc::as_ptr(&block) == Arc::as_ptr(b));
|
||||
let remove = self.0.extract_if(|b| Arc::as_ptr(&block) == Arc::as_ptr(b));
|
||||
match remove.count() {
|
||||
0 => return Err(SystemError::ENOENT),
|
||||
_ => return Ok(()),
|
||||
|
@ -354,7 +354,7 @@ impl MmioBuddyMemPool {
|
||||
// element 只会有一个元素
|
||||
let mut element: Vec<MmioBuddyAddrRegion> = list_guard
|
||||
.list
|
||||
.drain_filter(|x| x.vaddr == buddy_vaddr)
|
||||
.extract_if(|x| x.vaddr == buddy_vaddr)
|
||||
.collect();
|
||||
if element.len() == 1 {
|
||||
list_guard.num_free -= 1;
|
||||
|
@ -305,7 +305,6 @@ impl Socket for RawSocket {
|
||||
}
|
||||
}
|
||||
}
|
||||
drop(socket);
|
||||
drop(socket_set_guard);
|
||||
SOCKET_WAITQUEUE.sleep();
|
||||
}
|
||||
@ -371,8 +370,6 @@ impl Socket for RawSocket {
|
||||
// 发送数据包
|
||||
socket.send_slice(&buffer).unwrap();
|
||||
|
||||
drop(socket);
|
||||
|
||||
iface.poll(&mut socket_set_guard).ok();
|
||||
|
||||
drop(socket_set_guard);
|
||||
@ -489,7 +486,6 @@ impl Socket for UdpSocket {
|
||||
|
||||
if socket.can_recv() {
|
||||
if let Ok((size, remote_endpoint)) = socket.recv_slice(buf) {
|
||||
drop(socket);
|
||||
drop(socket_set_guard);
|
||||
poll_ifaces();
|
||||
return (Ok(size), Endpoint::Ip(Some(remote_endpoint)));
|
||||
@ -498,7 +494,6 @@ impl Socket for UdpSocket {
|
||||
// 如果socket没有连接,则忙等
|
||||
// return (Err(SystemError::ENOTCONN), Endpoint::Ip(None));
|
||||
}
|
||||
drop(socket);
|
||||
drop(socket_set_guard);
|
||||
SOCKET_WAITQUEUE.sleep();
|
||||
}
|
||||
@ -545,7 +540,6 @@ impl Socket for UdpSocket {
|
||||
match socket.send_slice(&buf, *remote_endpoint) {
|
||||
Ok(()) => {
|
||||
// kdebug!("udp write: send ok");
|
||||
drop(socket);
|
||||
drop(socket_set_guard);
|
||||
poll_ifaces();
|
||||
return Ok(buf.len());
|
||||
@ -731,7 +725,6 @@ impl Socket for TcpSocket {
|
||||
return (Err(SystemError::ENOTCONN), Endpoint::Ip(None));
|
||||
};
|
||||
|
||||
drop(socket);
|
||||
drop(socket_set_guard);
|
||||
poll_ifaces();
|
||||
return (Ok(size), Endpoint::Ip(Some(endpoint)));
|
||||
@ -751,7 +744,6 @@ impl Socket for TcpSocket {
|
||||
} else {
|
||||
return (Err(SystemError::ENOTCONN), Endpoint::Ip(None));
|
||||
}
|
||||
drop(socket);
|
||||
drop(socket_set_guard);
|
||||
SOCKET_WAITQUEUE.sleep();
|
||||
}
|
||||
@ -765,7 +757,6 @@ impl Socket for TcpSocket {
|
||||
if socket.can_send() {
|
||||
match socket.send_slice(buf) {
|
||||
Ok(size) => {
|
||||
drop(socket);
|
||||
drop(socket_set_guard);
|
||||
poll_ifaces();
|
||||
return Ok(size);
|
||||
@ -825,7 +816,6 @@ impl Socket for TcpSocket {
|
||||
// avoid deadlock
|
||||
drop(inner_iface);
|
||||
drop(iface);
|
||||
drop(socket);
|
||||
drop(sockets);
|
||||
loop {
|
||||
poll_ifaces();
|
||||
@ -837,7 +827,6 @@ impl Socket for TcpSocket {
|
||||
return Ok(());
|
||||
}
|
||||
tcp::State::SynSent => {
|
||||
drop(socket);
|
||||
drop(sockets);
|
||||
SOCKET_WAITQUEUE.sleep();
|
||||
}
|
||||
@ -916,7 +905,6 @@ impl Socket for TcpSocket {
|
||||
if socket.is_active() {
|
||||
// kdebug!("tcp accept: socket.is_active()");
|
||||
let remote_ep = socket.remote_endpoint().ok_or(SystemError::ENOTCONN)?;
|
||||
drop(socket);
|
||||
|
||||
let new_socket = {
|
||||
// Initialize the TCP socket's buffers.
|
||||
@ -965,7 +953,6 @@ impl Socket for TcpSocket {
|
||||
|
||||
return Ok((new_socket, Endpoint::Ip(Some(remote_ep))));
|
||||
}
|
||||
drop(socket);
|
||||
drop(sockets);
|
||||
SOCKET_WAITQUEUE.sleep();
|
||||
}
|
||||
|
@ -59,6 +59,13 @@ unsafe extern "C" fn rs_current_pcb_thread_rbp() -> u64 {
|
||||
return ProcessManager::current_pcb().arch_info_irqsave().rbp() as u64;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe extern "C" fn rs_current_pcb_thread_rbp() -> u64 {
|
||||
// 不应该实现这个函数
|
||||
unimplemented!("rs_current_pcb_thread_rbp")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rs_preempt_disable() {
|
||||
return ProcessManager::preempt_disable();
|
||||
|
@ -915,7 +915,7 @@ impl Drop for ProcessControlBlock {
|
||||
.unwrap_or_else(|e| panic!("procfs_unregister_pid failed: error: {e:?}"));
|
||||
|
||||
if let Some(ppcb) = self.parent_pcb.read().upgrade() {
|
||||
ppcb.children.write().drain_filter(|pid| *pid == self.pid());
|
||||
ppcb.children.write().retain(|pid| *pid != self.pid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ impl Timer {
|
||||
/// @brief 将定时器插入到定时器链表中
|
||||
pub fn activate(&self) {
|
||||
let inner_guard = self.0.lock();
|
||||
let timer_list = &mut TIMER_LIST.lock();
|
||||
let mut timer_list = TIMER_LIST.lock();
|
||||
|
||||
// 链表为空,则直接插入
|
||||
if timer_list.is_empty() {
|
||||
@ -133,7 +133,8 @@ impl Timer {
|
||||
pub fn cancel(&self) -> bool {
|
||||
TIMER_LIST
|
||||
.lock()
|
||||
.drain_filter(|x| Arc::<Timer>::as_ptr(&x) == self as *const Timer);
|
||||
.extract_if(|x| Arc::<Timer>::as_ptr(&x) == self as *const Timer)
|
||||
.for_each(|p| drop(p));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ install_ubuntu_debian_pkg()
|
||||
lsb-release \
|
||||
llvm-dev libclang-dev clang gcc-multilib \
|
||||
gcc build-essential fdisk dosfstools dnsmasq bridge-utils iptables libssl-dev pkg-config \
|
||||
sphinx gcc-riscv64-unknown-elf
|
||||
sphinx gcc-riscv64-unknown-elf gcc-riscv64-linux-gnu gdb-multiarch
|
||||
|
||||
# 如果python3没有安装
|
||||
if [ -z "$(which python3)" ]; then
|
||||
|
Loading…
x
Reference in New Issue
Block a user