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
3 changes: 3 additions & 0 deletions os/src/arch/cpu_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ pub trait CpuOps: 'static {
/// 显式启用中断
fn enable_interrupts();

/// 当前中断是否处于启用状态
fn interrupts_enabled() -> bool;

/// 检查 `disable_interrupts()` 返回的 flags 中中断是否处于启用状态
///
/// 默认实现假定 flags 的 bit 0 表示中断启用状态。
Expand Down
56 changes: 6 additions & 50 deletions os/src/arch/loongarch/boot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,18 @@ use core::arch::global_asm;

global_asm!(include_str!("entry.S"));

use crate::{
arch::{intr, platform, timer, trap},
earlyprintln,
kernel::{self, current_cpu, time},
mm,
sync::PreemptGuard,
test::run_early_tests,
};
use crate::kernel;

/// LoongArch 主核启动入口
pub fn main(hartid: usize) {
kernel::boot::clear_bss();
let mut ops = kernel::boot::PrimaryBootOps::new("LoongArch", "CPU");
ops.after_clear_bss = enable_base_fp;
kernel::boot::run_primary_boot(hartid, ops);
}

fn enable_base_fp(_hartid: usize) {
// Enable base floating-point instructions (EUEN.FPE). Many LoongArch Linux-ABI
// user programs are built with floating-point enabled and may execute FP
// instructions very early during startup.
loongArch64::register::euen::set_fpe(true);

run_early_tests();

earlyprintln!("[Boot] Hello, world!");
earlyprintln!("[Boot] LoongArch CPU {} is up!", hartid);

let kernel_space = mm::init();

// 激活内核地址空间
{
let _guard = PreemptGuard::new();
current_cpu().switch_space(kernel_space);
}

#[cfg(test)]
crate::test_main();

// 早期引导陷阱(覆盖平台初始化窗口)
trap::init_boot_trap();
platform::init();
time::init();
timer::init();

// 创建 idle 并设为当前任务(KScratch0 就绪)
let idle = kernel::boot::create_idle_task(0, kernel::boot::idle_loop);
{
let _guard = PreemptGuard::new();
current_cpu().idle_task = Some(idle.clone());
current_cpu().switch_task(idle);
}

// 完整陷阱处理(KScratch0 已有效)
trap::init();

// 创建 init 任务并入队(中断仍禁用,避免竞争)
kernel::boot::rest_init();

// 启用中断并进入 idle 循环
// 时钟中断触发后调度器自动选中 init 并切换上下文
unsafe { intr::enable_interrupts() };
kernel::boot::idle_loop();
}
23 changes: 17 additions & 6 deletions os/src/arch/loongarch/cpu_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! 将现有的 CSR 内联汇编操作映射到 trait 方法。

use crate::arch::CpuOps;
use crate::arch::constant::{CSR_CRMD_IE, SSTATUS_SIE};
use crate::arch::constant::CSR_CRMD_IE;

/// LoongArch64 架构标记类型
pub struct LoongArch64;
Expand Down Expand Up @@ -68,10 +68,8 @@ impl CpuOps for LoongArch64 {
/// 根据保存的 CRMD 值恢复 IE 位。
#[inline]
fn restore_interrupt_state(flags: usize) {
if flags & SSTATUS_SIE != 0 {
unsafe {
Self::enable_interrupts();
}
if flags & CSR_CRMD_IE != 0 {
Self::enable_interrupts();
}
}

Expand All @@ -96,8 +94,21 @@ impl CpuOps for LoongArch64 {
}
}

#[inline]
fn interrupts_enabled() -> bool {
let crmd: usize;
unsafe {
core::arch::asm!(
"csrrd {crmd}, 0x0",
crmd = out(reg) crmd,
options(nostack, preserves_flags)
);
}
crmd & CSR_CRMD_IE != 0
}

#[inline]
fn interrupt_was_enabled(flags: usize) -> bool {
flags & SSTATUS_SIE != 0
flags & CSR_CRMD_IE != 0
}
}
30 changes: 27 additions & 3 deletions os/src/arch/loongarch/kernel/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,16 @@ pub fn setup_exec_stack_layout(
}

/// Restore a freshly scheduled task for the first time.
pub unsafe fn forkret_restore(tf_ptr: *mut crate::arch::trap::TrapFrame, is_kernel_thread: bool) {
if is_kernel_thread {
let (entry, sp) = unsafe { ((*tf_ptr).era, (*tf_ptr).kernel_sp) };
pub unsafe fn forkret_restore(tf_ptr: *mut crate::arch::trap::TrapFrame, _is_kernel_thread: bool) {
if unsafe { is_kernel_entry(tf_ptr) } {
let (entry, sp, ra) = unsafe { ((*tf_ptr).era, (*tf_ptr).kernel_sp, (*tf_ptr).regs[1]) };
unsafe {
core::arch::asm!(
"addi.d $sp, {sp}, 0",
"addi.d $ra, {ra}, 0",
"jirl $zero, {entry}, 0",
sp = in(reg) sp,
ra = in(reg) ra,
entry = in(reg) entry,
options(noreturn)
);
Expand All @@ -239,6 +241,28 @@ pub unsafe fn forkret_restore(tf_ptr: *mut crate::arch::trap::TrapFrame, is_kern
crate::arch::trap::restore(unsafe { &*tf_ptr });
}

unsafe fn is_kernel_entry(tf_ptr: *mut crate::arch::trap::TrapFrame) -> bool {
unsafe { (*tf_ptr).era >= crate::arch::constant::KERNEL_BASE }
}

/// Initialize the trap frame used to enter a kernel task.
pub unsafe fn init_kernel_trap_frame(
tf_ptr: *mut crate::arch::trap::TrapFrame,
entry: usize,
terminal: usize,
kernel_sp: usize,
) {
unsafe {
core::ptr::write(tf_ptr, crate::arch::trap::TrapFrame::zero_init());
(*tf_ptr).set_kernel_trap_frame(entry, terminal, kernel_sp);
let cpu_ptr = {
let _guard = crate::sync::PreemptGuard::new();
crate::kernel::current_cpu() as *const _ as usize
};
crate::arch::trap::set_trap_frame_cpu_ptr(tf_ptr, cpu_ptr);
}
}

/// Final architecture-specific preparation before restoring to user mode.
pub unsafe fn prepare_user_restore(
tfp: *mut crate::arch::trap::TrapFrame,
Expand Down
20 changes: 7 additions & 13 deletions os/src/arch/loongarch/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,15 @@ pub fn set_next_trigger() {

unsafe {
// 1. 先彻底关闭定时器并清除周期模式 (TCFG bit 0 and 1 = 0) 防止配置过程中的竞争
core::arch::asm!("csrwr $r0, 0x410");
core::arch::asm!("csrwr $r0, {tcfg}", tcfg = const CSR_TCFG);

// 2. 写入 TVAL (0x420)
// 在 En=0 时写入 TVAL 会直接重置当前倒计时器
// 2. 开启定时器,设为周期模式。
// TCFG[63:2] 存放初始计数值;TVAL 是只读当前计数值,不能用于重装。
let cfg = (delta & !0b11usize) | 0b11usize;
core::arch::asm!(
"csrwr {val}, 0x420",
val = in(reg) delta
);

// 3. 开启定时器,设为单次触发模式 (En=1, Periodic=0)
// 这样定时器倒数到 0 后会停下并触发中断
let cfg = 0b01usize;
core::arch::asm!(
"csrwr {val}, 0x410",
val = in(reg) cfg
"csrwr {val}, {tcfg}",
val = in(reg) cfg,
tcfg = const CSR_TCFG
);
}
}
Expand Down
3 changes: 2 additions & 1 deletion os/src/arch/loongarch/trap/trap_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,9 @@ impl TrapFrame {
}

/// 设置内核态陷阱帧
pub fn set_kernel_trap_frame(&mut self, entry: usize, _terminal: usize, kernel_sp: usize) {
pub fn set_kernel_trap_frame(&mut self, entry: usize, terminal: usize, kernel_sp: usize) {
self.era = entry;
self.regs[1] = terminal; // ra
self.regs[3] = kernel_sp; // sp
self.kernel_sp = kernel_sp;
}
Expand Down
7 changes: 7 additions & 0 deletions os/src/arch/mock/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ impl CpuOps for MockCpuOps {
fn restore_interrupt_state(_flags: usize) {}

fn enable_interrupts() {}

fn interrupts_enabled() -> bool {
false
}
}

// ============================================================================
Expand Down Expand Up @@ -175,6 +179,9 @@ impl CpuOps for MockArch {
fn enable_interrupts() {
MockCpuOps::enable_interrupts()
}
fn interrupts_enabled() -> bool {
MockCpuOps::interrupts_enabled()
}
}

impl VirtualMemory for MockArch {
Expand Down
13 changes: 13 additions & 0 deletions os/src/arch/mock/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ pub mod task {
unsafe { crate::arch::trap::restore(&*tf_ptr) };
}

pub unsafe fn init_kernel_trap_frame(
tf_ptr: *mut crate::arch::trap::TrapFrame,
entry: usize,
terminal: usize,
kernel_sp: usize,
) {
unsafe {
core::ptr::write(tf_ptr, crate::arch::trap::TrapFrame::zero_init());
(*tf_ptr).set_kernel_trap_frame(entry, terminal, kernel_sp);
crate::arch::trap::set_trap_frame_cpu_ptr(tf_ptr, 0);
}
}

pub unsafe fn prepare_user_restore(
_tfp: *mut crate::arch::trap::TrapFrame,
_initial_pc: VA,
Expand Down
4 changes: 4 additions & 0 deletions os/src/arch/mock/trap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use crate::uapi::signal::MContextT;

pub fn init_boot_trap() {}

pub fn init() {}

/// Mock trap frame for host compilation
#[repr(C)]
#[derive(Debug, Clone, Copy)]
Expand Down
6 changes: 6 additions & 0 deletions os/src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ pub fn enable_interrupts() {
ArchImpl::enable_interrupts()
}

/// 当前中断是否处于启用状态
#[inline]
pub fn interrupts_enabled() -> bool {
ArchImpl::interrupts_enabled()
}

/// 禁用中断并返回之前的中断状态
#[inline]
pub fn disable_interrupts() -> usize {
Expand Down
Loading
Loading