Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion os/src/arch/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,43 @@
//! 注意:此 trait 使用关联类型来避免直接引用内核数据结构,
//! 确保架构层与内核其余部分的解耦。

use crate::arch::{address::UA, cpu_ops::CpuOps, virtual_memory::VirtualMemory};
use core::fmt::Debug;

use crate::{
arch::{address::UA, cpu_ops::CpuOps, task::ExecStackLayout, virtual_memory::VirtualMemory},
kernel::syscall::syscall_frame::SyscallFrame,
uapi::signal::MContextT,
};

/// 架构陷阱帧的统一接口。
pub trait HwTrapFrame: Copy + Debug + Send + Sync + SyscallFrame + 'static {
fn zero_init() -> Self;
fn set_kernel_trap_frame(&mut self, entry: usize, terminal: usize, kernel_sp: usize);
fn set_exec_trap_frame_from_layout(
&mut self,
entry: usize,
kernel_sp: usize,
layout: &ExecStackLayout,
);
unsafe fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
);
unsafe fn set_fork_trap_frame(&mut self, parent_frame: &Self);
Comment on lines +29 to +35

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since HwTrapFrame requires Copy (as specified by pub trait HwTrapFrame: Copy + ...), any implementing type is guaranteed to be Copy. Therefore, copying the trap frame can be done safely using simple struct assignment (e.g., *self = *parent_frame;) instead of core::ptr::copy_nonoverlapping. This allows us to remove the unsafe keyword from these trait methods entirely, improving safety and maintainability.

Suggested change
unsafe fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
);
unsafe fn set_fork_trap_frame(&mut self, parent_frame: &Self);
fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
);
fn set_fork_trap_frame(&mut self, parent_frame: &Self);

fn get_sp(&self) -> usize;
fn set_sp(&mut self, val: usize);
fn set_a0(&mut self, val: usize);
fn set_a1(&mut self, val: usize);
fn set_a2(&mut self, val: usize);
fn set_ra(&mut self, val: usize);
fn set_sepc(&mut self, pc: usize);
fn get_sepc(&self) -> usize;
fn set_tls(&mut self, tls: usize);
fn to_mcontext(&self) -> MContextT;
fn restore_from_mcontext(&mut self, mcontext: &MContextT);
}

/// 顶层架构抽象 trait。
///
Expand All @@ -25,6 +61,9 @@ pub trait Arch: CpuOps + VirtualMemory {
/// 用户上下文类型(保存/恢复寄存器状态)
type UserContext: Sized + Send + Sync + Clone;

/// 硬件陷阱帧类型。
type TrapFrame: HwTrapFrame;

// ---- 进程 / 上下文切换 ----

/// 创建新的用户上下文(设置入口点和栈顶)
Expand Down
3 changes: 2 additions & 1 deletion os/src/arch/arch_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ macro_rules! impl_arch {

impl $crate::arch::arch::Arch for $arch {
type UserContext = kernel::context::Context;
type TrapFrame = trap::TrapFrame;

fn new_user_context(entry_point: usize, stack_top: usize) -> Self::UserContext {
let mut ctx = kernel::context::Context::zero_init();
Expand Down Expand Up @@ -188,7 +189,7 @@ macro_rules! impl_platform {
($arch:ty) => {
impl $crate::arch::plat::Platform for $arch {
fn console_putchar(c: u8) {
lib::console_putchar(c as usize);
lib::console_putchar(c);
}

fn console_getchar() -> Option<u8> {
Expand Down
3 changes: 3 additions & 0 deletions os/src/arch/loongarch/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ pub const USER_BASE: usize = 0x0000_0000_0000_0000;
pub const USER_TOP: usize = 0x0000_003f_ffff_ffff;
pub const KERNEL_BASE: usize = 0x9000_0000_0000_0000;

/// Direct mapped uncached window for MMIO.
pub const DMW0_BASE: usize = 0x8000_0000_0000_0000;

/// 兼容 RISC-V 的地址空间常量
/// 用于与架构无关代码的兼容
pub const SV39_TOP_HALF_TOP: usize = 0xffff_ffff_ffff_ffff;
Expand Down
12 changes: 6 additions & 6 deletions os/src/arch/loongarch/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@
//! 兼容性别名 `sbi` 模块用于共享代码调用路径的过渡,
//! 待 HAL trait 覆盖这些功能后可移除。

use super::platform::UART_BASE;
use super::{constant::DMW0_BASE, platform::UART_BASE};

/// 通过 DMW0 映射的 UART 虚拟地址
/// DMW0: 0x8000_xxxx_xxxx_xxxx -> 物理地址 (uncached, 用于 MMIO)
const UART_VADDR: usize = UART_BASE | 0x8000_0000_0000_0000;
const UART_VADDR: usize = UART_BASE | DMW0_BASE;

/// 输出字符到控制台
pub fn console_putchar(c: usize) {
pub fn console_putchar(c: u8) {
unsafe {
// 等待 UART 发送缓冲区空闲 (LSR bit 5)
let ptr = UART_VADDR as *mut u8;
while ptr.add(5).read_volatile() & (1 << 5) == 0 {}
ptr.write_volatile(c as u8);
ptr.write_volatile(c);
}
}

Expand Down Expand Up @@ -51,7 +51,7 @@ const ACPI_GED_VALUE_REBOOT: u8 = 0x42; // reboot { value = <0x42> }
/// 关机实现
pub fn shutdown(_failure: bool) -> ! {
// 映射到 LoongArch 的虚地址 (DMW0: 0x8000...)
let base_vaddr = VIRT_GED_REG_ADDR | 0x8000_0000_0000_0000;
let base_vaddr = VIRT_GED_REG_ADDR | DMW0_BASE;

unsafe {
let ptr = base_vaddr as *mut u8;
Expand All @@ -77,7 +77,7 @@ pub fn shutdown(_failure: bool) -> ! {

/// 重启实现
pub fn restart() -> ! {
let base_vaddr = VIRT_GED_REG_ADDR | 0x8000_0000_0000_0000;
let base_vaddr = VIRT_GED_REG_ADDR | DMW0_BASE;

unsafe {
let ptr = base_vaddr as *mut u8;
Expand Down
6 changes: 3 additions & 3 deletions os/src/arch/loongarch/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use core::sync::atomic::{AtomicUsize, Ordering};

use crate::{arch::intr::enable_timer_interrupt, earlyprintln};
use crate::arch::intr::enable_timer_interrupt;

/// 定时器滴答计数
pub static TIMER_TICKS: AtomicUsize = AtomicUsize::new(0);
Expand All @@ -19,10 +19,10 @@ const CSR_TICLR: u32 = 0x44;

/// 初始化定时器
pub fn init() {
earlyprintln!("[Timer] Initializing timer");
crate::println!("[Timer] Initializing timer");
// 允许外部在平台层设置真实频率;此处仅开启本地定时器中断
unsafe { enable_timer_interrupt() };
earlyprintln!("[Timer] Timer interrupt enabled");
crate::println!("[Timer] Timer interrupt enabled");
set_next_trigger();
}

Expand Down
76 changes: 76 additions & 0 deletions os/src/arch/loongarch/trap/trap_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,79 @@ impl crate::kernel::syscall::syscall_frame::SyscallFrame for TrapFrame {
self.regs[4] = val;
}
}

impl crate::arch::HwTrapFrame for TrapFrame {
fn zero_init() -> Self {
TrapFrame::zero_init()
}

fn set_kernel_trap_frame(&mut self, entry: usize, terminal: usize, kernel_sp: usize) {
TrapFrame::set_kernel_trap_frame(self, entry, terminal, kernel_sp)
}

fn set_exec_trap_frame_from_layout(
&mut self,
entry: usize,
kernel_sp: usize,
layout: &crate::arch::task::ExecStackLayout,
) {
TrapFrame::set_exec_trap_frame_from_layout(self, entry, kernel_sp, layout)
}

unsafe fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
) {
unsafe { TrapFrame::set_clone_trap_frame(self, parent_frame, kernel_sp, user_sp) }
}

unsafe fn set_fork_trap_frame(&mut self, parent_frame: &Self) {
unsafe { TrapFrame::set_fork_trap_frame(self, parent_frame) }
}
Comment on lines +315 to +326

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Implement the safe version of set_clone_trap_frame and set_fork_trap_frame for TrapFrame under the HwTrapFrame trait. Note that the underlying inherent methods can also be refactored to be safe by replacing copy_nonoverlapping with simple struct assignment *self = *parent_frame;.

Suggested change
unsafe fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
) {
unsafe { TrapFrame::set_clone_trap_frame(self, parent_frame, kernel_sp, user_sp) }
}
unsafe fn set_fork_trap_frame(&mut self, parent_frame: &Self) {
unsafe { TrapFrame::set_fork_trap_frame(self, parent_frame) }
}
fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
) {
unsafe { TrapFrame::set_clone_trap_frame(self, parent_frame, kernel_sp, user_sp) }
}
fn set_fork_trap_frame(&mut self, parent_frame: &Self) {
unsafe { TrapFrame::set_fork_trap_frame(self, parent_frame) }
}
References
  1. Prioritize consistency with existing architecture implementations (like RISC-V) when adding support for a new architecture (like LoongArch).


fn get_sp(&self) -> usize {
TrapFrame::get_sp(self)
}

fn set_sp(&mut self, val: usize) {
TrapFrame::set_sp(self, val)
}

fn set_a0(&mut self, val: usize) {
TrapFrame::set_a0(self, val)
}

fn set_a1(&mut self, val: usize) {
TrapFrame::set_a1(self, val)
}

fn set_a2(&mut self, val: usize) {
TrapFrame::set_a2(self, val)
}

fn set_ra(&mut self, val: usize) {
TrapFrame::set_ra(self, val)
}

fn set_sepc(&mut self, pc: usize) {
TrapFrame::set_sepc(self, pc)
}

fn get_sepc(&self) -> usize {
TrapFrame::get_sepc(self)
}

fn set_tls(&mut self, tls: usize) {
TrapFrame::set_tls(self, tls)
}

fn to_mcontext(&self) -> MContextT {
TrapFrame::to_mcontext(self)
}

fn restore_from_mcontext(&mut self, mcontext: &MContextT) {
TrapFrame::restore_from_mcontext(self, mcontext)
}
}
23 changes: 14 additions & 9 deletions os/src/arch/loongarch/trap/trap_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@ use crate::arch::timer::{
TIMER_TICKS, ack_timer_interrupt, clock_freq, get_time, set_next_trigger,
};
use crate::arch::trap::restore;
use crate::earlyprintln;
use crate::ipc::check_signal;
use crate::kernel::syscall::dispatch::dispatch_syscall;
use crate::kernel::{TIMER, TIMER_QUEUE, schedule, send_signal_process, wake_up_task};

use super::TrapFrame;

macro_rules! emergency_println {
($fmt: literal $(, $($arg: tt)+)?) => {
crate::console::emergency_print(format_args!(concat!($fmt, "\n") $(, $($arg)+)?))
};
}

/// 仅在单核环境下使用的默认 TrapFrame;后续可由调度器替换为 per-CPU/任务帧
#[unsafe(no_mangle)]
pub static mut BOOT_TRAP_FRAME: TrapFrame = TrapFrame::empty();
Expand Down Expand Up @@ -237,14 +242,14 @@ fn user_panic(estat: usize, era: usize, trap_frame: &TrapFrame) {
core::arch::asm!("csrrd {0}, {csr}", out(reg) badv, csr = const CSR_BADV, options(nostack, preserves_flags));
core::arch::asm!("csrrd {0}, {csr}", out(reg) badi, csr = const CSR_BADI, options(nostack, preserves_flags));
}
earlyprintln!("\n===============================================");
earlyprintln!(" UNEXPECTED TRAP IN USER MODE (PLV>0)");
earlyprintln!("===============================================");
earlyprintln!("estat: {:#x}", estat);
earlyprintln!("era : {:#x}", era);
earlyprintln!("badv : {:#x}", badv);
earlyprintln!("badi : {:#x}", badi);
earlyprintln!("regs : {:#x?}", trap_frame.regs);
emergency_println!("\n===============================================");
emergency_println!(" UNEXPECTED TRAP IN USER MODE (PLV>0)");
emergency_println!("===============================================");
emergency_println!("estat: {:#x}", estat);
emergency_println!("era : {:#x}", era);
emergency_println!("badv : {:#x}", badv);
emergency_println!("badi : {:#x}", badi);
emergency_println!("regs : {:#x?}", trap_frame.regs);
panic!(
"Unexpected trap in user mode: estat={:#x}, era={:#x}, badv={:#x}, badi={:#x}",
estat, era, badv, badi
Expand Down
10 changes: 5 additions & 5 deletions os/src/arch/memory_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ macro_rules! impl_virtual_memory {
($process_type:ident, $kernel_type:ident) => {
use alloc::vec::Vec;

use crate::arch::virtual_memory::{
KernAddressSpace, PageFrame, PageInfo, PhysMemoryRegion, PtePermissions,
UserAddressSpace, VirtMemoryRegion,
};
use crate::config::PAGE_SIZE;
use crate::mm::address::{
ConvertablePA, PA, PageNum, Ppn, UsizeConvert, VA, Vpn, VpnRange,
};
use crate::mm::memory_space::{MemorySpace, with_kernel_space};
use crate::mm::page_table::PageTableInner;
use crate::mm::page_table::{PageSize, UniversalPTEFlag};
use $crate::arch::virtual_memory::{
KernAddressSpace, PageFrame, PageInfo, PhysMemoryRegion, PtePermissions,
UserAddressSpace, VirtMemoryRegion,
};
use $crate::config::PAGE_SIZE;

pub struct $process_type {
#[allow(dead_code)]
Expand Down
1 change: 1 addition & 0 deletions os/src/arch/mock/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ mod mock_arch_impl {

impl Arch for MockArch {
type UserContext = MockUserContext;
type TrapFrame = crate::arch::mock::trap::TrapFrame;

fn new_user_context(entry_point: usize, stack_top: usize) -> Self::UserContext {
let mut ctx = MockUserContext::zero_init();
Expand Down
2 changes: 1 addition & 1 deletion os/src/arch/mock/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub fn restart() -> ! {
}
}

pub fn console_putchar(_c: usize) {}
pub fn console_putchar(_c: u8) {}

pub fn console_getchar() -> usize {
usize::MAX
Expand Down
76 changes: 76 additions & 0 deletions os/src/arch/mock/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,82 @@ impl crate::kernel::syscall::syscall_frame::SyscallFrame for TrapFrame {
}
}

impl crate::arch::HwTrapFrame for TrapFrame {
fn zero_init() -> Self {
TrapFrame::zero_init()
}

fn set_kernel_trap_frame(&mut self, entry: usize, terminal: usize, kernel_sp: usize) {
TrapFrame::set_kernel_trap_frame(self, entry, terminal, kernel_sp)
}

fn set_exec_trap_frame_from_layout(
&mut self,
entry: usize,
kernel_sp: usize,
layout: &crate::arch::task::ExecStackLayout,
) {
TrapFrame::set_exec_trap_frame_from_layout(self, entry, kernel_sp, layout)
}

unsafe fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
) {
unsafe { TrapFrame::set_clone_trap_frame(self, parent_frame, kernel_sp, user_sp) }
}

unsafe fn set_fork_trap_frame(&mut self, parent_frame: &Self) {
unsafe { TrapFrame::set_fork_trap_frame(self, parent_frame) }
}
Comment on lines +246 to +257

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Implement the safe version of set_clone_trap_frame and set_fork_trap_frame for TrapFrame under the HwTrapFrame trait.

Suggested change
unsafe fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
) {
unsafe { TrapFrame::set_clone_trap_frame(self, parent_frame, kernel_sp, user_sp) }
}
unsafe fn set_fork_trap_frame(&mut self, parent_frame: &Self) {
unsafe { TrapFrame::set_fork_trap_frame(self, parent_frame) }
}
fn set_clone_trap_frame(
&mut self,
parent_frame: &Self,
kernel_sp: usize,
user_sp: usize,
) {
unsafe { TrapFrame::set_clone_trap_frame(self, parent_frame, kernel_sp, user_sp) }
}
fn set_fork_trap_frame(&mut self, parent_frame: &Self) {
unsafe { TrapFrame::set_fork_trap_frame(self, parent_frame) }
}


fn get_sp(&self) -> usize {
TrapFrame::get_sp(self)
}

fn set_sp(&mut self, val: usize) {
TrapFrame::set_sp(self, val)
}

fn set_a0(&mut self, val: usize) {
TrapFrame::set_a0(self, val)
}

fn set_a1(&mut self, val: usize) {
TrapFrame::set_a1(self, val)
}

fn set_a2(&mut self, val: usize) {
TrapFrame::set_a2(self, val)
}

fn set_ra(&mut self, val: usize) {
TrapFrame::set_ra(self, val)
}

fn set_sepc(&mut self, pc: usize) {
TrapFrame::set_sepc(self, pc)
}

fn get_sepc(&self) -> usize {
TrapFrame::get_sepc(self)
}

fn set_tls(&mut self, tls: usize) {
TrapFrame::set_tls(self, tls)
}

fn to_mcontext(&self) -> MContextT {
TrapFrame::to_mcontext(self)
}

fn restore_from_mcontext(&mut self, mcontext: &MContextT) {
TrapFrame::restore_from_mcontext(self, mcontext)
}
}

pub struct SumGuard;
impl SumGuard {
pub fn new() -> Self {
Expand Down
Loading
Loading