diff --git a/Makefile b/Makefile index 3bc16637..e3e73f0e 100644 --- a/Makefile +++ b/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: diff --git a/build-scripts/kernel_build/src/cfiles/arch/riscv64.rs b/build-scripts/kernel_build/src/cfiles/arch/riscv64.rs index f72b6691..5d213dcb 100644 --- a/build-scripts/kernel_build/src/cfiles/arch/riscv64.rs +++ b/build-scripts/kernel_build/src/cfiles/arch/riscv64.rs @@ -17,7 +17,7 @@ impl CFilesArch for RiscV64CFilesArch { } fn setup_files(&self, _c: &mut cc::Build, files: &mut Vec) { - 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"), diff --git a/build-scripts/kernel_build/src/cfiles/mod.rs b/build-scripts/kernel_build/src/cfiles/mod.rs index 94d91416..de3efbc5 100644 --- a/build-scripts/kernel_build/src/cfiles/mod.rs +++ b/build-scripts/kernel_build/src/cfiles/mod.rs @@ -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"); diff --git a/env.mk b/env.mk index c25873af..16680119 100644 --- a/env.mk +++ b/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 diff --git a/kernel/Makefile b/kernel/Makefile index a8b93c4f..ed15a179 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -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 diff --git a/kernel/rust-toolchain.toml b/kernel/rust-toolchain.toml index 3d808158..5eaf8e30 100644 --- a/kernel/rust-toolchain.toml +++ b/kernel/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-01-21" +channel = "nightly-2023-08-15" components = ["rust-src"] \ No newline at end of file diff --git a/kernel/src/Makefile b/kernel/src/Makefile index 60072f74..fb7be7e9 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -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 diff --git a/kernel/src/arch/riscv64/asm/head.S b/kernel/src/arch/riscv64/asm/head.S new file mode 100644 index 00000000..01ae7ad9 --- /dev/null +++ b/kernel/src/arch/riscv64/asm/head.S @@ -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 + + diff --git a/kernel/src/arch/riscv64/boot/head.S b/kernel/src/arch/riscv64/boot/head.S deleted file mode 100644 index 430a2285..00000000 --- a/kernel/src/arch/riscv64/boot/head.S +++ /dev/null @@ -1,9 +0,0 @@ -#include "common/asm.h" - -.section .bootstrap - -.global _start -.type _start, @function -ENTRY(_start) -loop: - j loop diff --git a/kernel/src/arch/riscv64/driver/mod.rs b/kernel/src/arch/riscv64/driver/mod.rs new file mode 100644 index 00000000..433d396d --- /dev/null +++ b/kernel/src/arch/riscv64/driver/mod.rs @@ -0,0 +1 @@ +pub mod sbi; diff --git a/kernel/src/arch/riscv64/driver/sbi/ecall.rs b/kernel/src/arch/riscv64/driver/sbi/ecall.rs new file mode 100644 index 00000000..0dc0ce47 --- /dev/null +++ b/kernel/src/arch/riscv64/driver/sbi/ecall.rs @@ -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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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)), + } +} diff --git a/kernel/src/arch/riscv64/driver/sbi/legacy.rs b/kernel/src/arch/riscv64/driver/sbi/legacy.rs new file mode 100644 index 00000000..0384db97 --- /dev/null +++ b/kernel/src/arch/riscv64/driver/sbi/legacy.rs @@ -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 { + 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`。 +#[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」。 +#[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`。 +/// - `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`。 +/// - `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) + ); + } +} diff --git a/kernel/src/arch/riscv64/driver/sbi/mod.rs b/kernel/src/arch/riscv64/driver/sbi/mod.rs new file mode 100644 index 00000000..f79bb46f --- /dev/null +++ b/kernel/src/arch/riscv64/driver/sbi/mod.rs @@ -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) }; + } +} diff --git a/kernel/src/arch/riscv64/init/mod.rs b/kernel/src/arch/riscv64/init/mod.rs new file mode 100644 index 00000000..b822b3bf --- /dev/null +++ b/kernel/src/arch/riscv64/init/mod.rs @@ -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() +} diff --git a/kernel/src/arch/riscv64/link.ld b/kernel/src/arch/riscv64/link.ld index f22f2bf2..5f98fbd3 100644 --- a/kernel/src/arch/riscv64/link.ld +++ b/kernel/src/arch/riscv64/link.ld @@ -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 = .; } diff --git a/kernel/src/arch/riscv64/mod.rs b/kernel/src/arch/riscv64/mod.rs index b7917194..22c14cec 100644 --- a/kernel/src/arch/riscv64/mod.rs +++ b/kernel/src/arch/riscv64/mod.rs @@ -1,5 +1,7 @@ pub mod asm; pub mod cpu; +pub mod driver; +mod init; pub mod interrupt; pub mod ipc; mod kvm; diff --git a/kernel/src/arch/riscv64/process/mod.rs b/kernel/src/arch/riscv64/process/mod.rs index c5fa8032..dcc037c9 100644 --- a/kernel/src/arch/riscv64/process/mod.rs +++ b/kernel/src/arch/riscv64/process/mod.rs @@ -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, envp: Vec) -> ! { unimplemented!("RiscV64 arch_switch_to_user") } diff --git a/kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json b/kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json new file mode 100644 index 00000000..fb178263 --- /dev/null +++ b/kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json @@ -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" +} diff --git a/kernel/src/arch/x86_64/driver/hpet.rs b/kernel/src/arch/x86_64/driver/hpet.rs index d389392f..53c3f5e1 100644 --- a/kernel/src/arch/x86_64/driver/hpet.rs +++ b/kernel/src/arch/x86_64/driver/hpet.rs @@ -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; } diff --git a/kernel/src/driver/base/kset.rs b/kernel/src/driver/base/kset.rs index 5c97a5fc..daee885a 100644 --- a/kernel/src/driver/base/kset.rs +++ b/kernel/src/driver/base/kset.rs @@ -30,7 +30,7 @@ pub struct KSet { } impl Hash for KSet { - fn hash(&self, state: &mut H) { + fn hash(&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 { diff --git a/kernel/src/driver/tty/serial/serial8250/mod.rs b/kernel/src/driver/tty/serial/serial8250/mod.rs index 6342e946..fa13faeb 100644 --- a/kernel/src/driver/tty/serial/serial8250/mod.rs +++ b/kernel/src/driver/tty/serial/serial8250/mod.rs @@ -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)?; + unsafe { + INITIALIZED = true; + } + return Ok(()); } @@ -469,7 +478,7 @@ impl Driver for Serial8250ISADriver { fn delete_device(&self, device: &Arc) { 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> { @@ -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) }; + } + } } diff --git a/kernel/src/driver/video/mod.rs b/kernel/src/driver/video/mod.rs index 590cc160..e8462c00 100644 --- a/kernel/src/driver/video/mod.rs +++ b/kernel/src/driver/video/mod.rs @@ -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); diff --git a/kernel/src/exception/softirq.rs b/kernel/src/exception/softirq.rs index 893fd5a4..b916ca16 100644 --- a/kernel/src/exception/softirq.rs +++ b/kernel/src/exception/softirq.rs @@ -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); diff --git a/kernel/src/filesystem/fat/entry.rs b/kernel/src/filesystem/fat/entry.rs index 30135a3d..deaac6cb 100644 --- a/kernel/src/filesystem/fat/entry.rs +++ b/kernel/src/filesystem/fat/entry.rs @@ -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; diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index 5b106717..3d915a7c 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -115,7 +115,8 @@ impl ProcFSInode { /// @brief 去除Vec中所有的\0,并在结尾添加\0 #[inline] fn trim_string(&self, data: &mut Vec) { - 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(()); } diff --git a/kernel/src/init/mod.rs b/kernel/src/init/mod.rs index 767ff185..42bae686 100644 --- a/kernel/src/init/mod.rs +++ b/kernel/src/init/mod.rs @@ -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); } diff --git a/kernel/src/ipc/signal_types.rs b/kernel/src/ipc/signal_types.rs index 8c3cabb5..b0011dc4 100644 --- a/kernel/src/ipc/signal_types.rs +++ b/kernel/src/ipc/signal_types.rs @@ -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 = 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 = self.q.drain_filter(filter).collect(); + let mut filter_result: Vec = self.q.extract_if(filter).collect(); // 筛选出的结果不能大于1个 assert!(filter_result.len() <= 1); diff --git a/kernel/src/ipc/syscall.rs b/kernel/src/ipc/syscall.rs index 4eacc55f..50972215 100644 --- a/kernel/src/ipc/syscall.rs +++ b/kernel/src/ipc/syscall.rs @@ -105,7 +105,7 @@ impl Syscall { ) -> Result { // 请注意:用户态传进来的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不为空 diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index fec0fdb8..3539c80f 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -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] diff --git a/kernel/src/libs/elf.rs b/kernel/src/libs/elf.rs index 77eb5507..ae4dbb9d 100644 --- a/kernel/src/libs/elf.rs +++ b/kernel/src/libs/elf.rs @@ -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 { diff --git a/kernel/src/libs/futex/futex.rs b/kernel/src/libs/futex/futex.rs index 65b100af..9064834a 100644 --- a/kernel/src/libs/futex/futex.rs +++ b/kernel/src/libs/futex/futex.rs @@ -124,7 +124,9 @@ impl FutexHashBucket { /// 将FutexObj从bucket中删除 pub fn remove(&mut self, futex: Arc) { - 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(&self, state: &mut H) { + fn hash(&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; diff --git a/kernel/src/libs/lib_ui/screen_manager.rs b/kernel/src/libs/lib_ui/screen_manager.rs index bfb18f90..25383bd2 100644 --- a/kernel/src/libs/lib_ui/screen_manager.rs +++ b/kernel/src/libs/lib_ui/screen_manager.rs @@ -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>> = @@ -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 { 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() diff --git a/kernel/src/libs/lib_ui/textui.rs b/kernel/src/libs/lib_ui/textui.rs index 0ca83d74..9aca7579 100644 --- a/kernel/src/libs/lib_ui/textui.rs +++ b/kernel/src/libs/lib_ui/textui.rs @@ -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 { @@ -904,12 +922,12 @@ impl ScmUiFramework for TextUiFramework { } // 启用ui框架的回调函数 fn enable(&self) -> Result { - ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst); + textui_enable_put_to_window(); return Ok(0); } // 禁用ui框架的回调函数 fn disable(&self) -> Result { - 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(), )?; } } diff --git a/kernel/src/libs/lib_ui/textui_no_alloc.rs b/kernel/src/libs/lib_ui/textui_no_alloc.rs index 2c0c332f..60fb66fb 100644 --- a/kernel/src/libs/lib_ui/textui_no_alloc.rs +++ b/kernel/src/libs/lib_ui/textui_no_alloc.rs @@ -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( diff --git a/kernel/src/libs/notifier.rs b/kernel/src/libs/notifier.rs index 59ee1d66..1f06954b 100644 --- a/kernel/src/libs/notifier.rs +++ b/kernel/src/libs/notifier.rs @@ -65,9 +65,7 @@ impl NotifierChain { /// @brief 在通知链中取消注册节点 pub fn unregister(&mut self, block: Arc>) -> 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(()), diff --git a/kernel/src/mm/mmio_buddy.rs b/kernel/src/mm/mmio_buddy.rs index 12cea565..65a1043c 100644 --- a/kernel/src/mm/mmio_buddy.rs +++ b/kernel/src/mm/mmio_buddy.rs @@ -354,7 +354,7 @@ impl MmioBuddyMemPool { // element 只会有一个元素 let mut element: Vec = 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; diff --git a/kernel/src/net/socket.rs b/kernel/src/net/socket.rs index 3fd90314..30c620ae 100644 --- a/kernel/src/net/socket.rs +++ b/kernel/src/net/socket.rs @@ -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(); } diff --git a/kernel/src/process/c_adapter.rs b/kernel/src/process/c_adapter.rs index 3a0caab7..1ee3ea2f 100644 --- a/kernel/src/process/c_adapter.rs +++ b/kernel/src/process/c_adapter.rs @@ -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(); diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index a60d1ea8..00c70382 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -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()); } } } diff --git a/kernel/src/time/timer.rs b/kernel/src/time/timer.rs index ca8cdb1a..3eb1f796 100644 --- a/kernel/src/time/timer.rs +++ b/kernel/src/time/timer.rs @@ -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::::as_ptr(&x) == self as *const Timer); + .extract_if(|x| Arc::::as_ptr(&x) == self as *const Timer) + .for_each(|p| drop(p)); true } } diff --git a/tools/bootstrap.sh b/tools/bootstrap.sh index c9d09d82..6b2f4087 100644 --- a/tools/bootstrap.sh +++ b/tools/bootstrap.sh @@ -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