os/arch/riscv/boot/
mod.rs

1//! RISC-V 架构相关的启动代码
2
3use core::sync::atomic::Ordering;
4
5use alloc::sync::Arc;
6use riscv::register::sscratch;
7
8use crate::{
9    arch::{intr, mm::vaddr_to_paddr, platform, timer, trap},
10    earlyprintln,
11    ipc::{SignalHandlerTable, SignalPending},
12    kernel::{
13        FsStruct, SCHEDULER, Scheduler, TASK_MANAGER, TaskManagerTrait, TaskStruct, current_cpu,
14        current_memory_space, current_task, kernel_execve, kthread_spawn, kworker,
15        sleep_task_with_block, time, yield_task,
16    },
17    mm::{
18        self,
19        frame_allocator::{alloc_contig_frames, alloc_frame},
20    },
21    pr_err, pr_info, println,
22    sync::SpinLock,
23    test::run_early_tests,
24    uapi::{
25        resource::{INIT_RLIMITS, RlimitStruct},
26        signal::SignalFlags,
27        uts_namespace::UtsNamespace,
28    },
29    vfs::{create_stdio_files, fd_table, get_root_dentry},
30};
31
32/// 内核的第一个任务启动函数
33/// 并且当这个函数结束时,应该切换到第一个任务的上下文
34pub fn rest_init() {
35    let tid = TASK_MANAGER.lock().allocate_tid();
36    let kstack_tracker = alloc_contig_frames(4).expect("kthread_spawn: failed to alloc kstack");
37    let trap_frame_tracker = alloc_frame().expect("kthread_spawn: failed to alloc trap_frame");
38    let fd_table = fd_table::FDTable::new();
39    let (stdin, stdout, stderr) = create_stdio_files();
40    fd_table
41        .install_at(0, stdin)
42        .expect("Failed to install stdin");
43    fd_table
44        .install_at(1, stdout)
45        .expect("Failed to install stdout");
46    fd_table
47        .install_at(2, stderr)
48        .expect("Failed to install stderr");
49    let cwd = get_root_dentry().ok();
50    let root = cwd.clone();
51    let fs = Arc::new(SpinLock::new(FsStruct::new(cwd, root)));
52    let mut task = TaskStruct::ktask_create(
53        tid,
54        tid,
55        0,
56        TaskStruct::empty_children(),
57        kstack_tracker,
58        trap_frame_tracker,
59        Arc::new(SpinLock::new(SignalHandlerTable::new())),
60        SignalFlags::empty(),
61        Arc::new(SpinLock::new(SignalPending::empty())),
62        Arc::new(SpinLock::new(UtsNamespace::default())),
63        Arc::new(SpinLock::new(RlimitStruct::new(INIT_RLIMITS))),
64        Arc::new(fd_table),
65        fs,
66    ); // init 没有父任务
67
68    let tf = task.trap_frame_ptr.load(Ordering::SeqCst);
69    // Safety: 此时 trap_frame_tracker 已经分配完毕且不可变更,所有权在 task 中,指针有效
70    unsafe {
71        (*tf).set_kernel_trap_frame(init as usize, 0, task.kstack_base);
72    }
73
74    let ra = task.context.ra;
75    let sp = task.context.sp;
76    let ptr = task.trap_frame_ptr.load(Ordering::SeqCst);
77    // init 进程不同于其他内核线程,需要有一个独立的内存空间
78    task.memory_space = Some(current_memory_space());
79    let task = task.into_shared();
80    unsafe {
81        sscratch::write(ptr as usize);
82    }
83    TASK_MANAGER.lock().add_task(task.clone());
84    current_cpu().lock().switch_task(task);
85
86    // 切入 kinit:设置 sp 并跳到 ra;此调用不返回
87    // SAFETY: 在 Task 创建时已正确初始化 ra 和 sp
88    unsafe {
89        core::arch::asm!(
90            "mv sp, {sp}",
91            "jr {ra}",
92            sp = in(reg) sp,
93            ra = in(reg) ra,
94            options(noreturn)
95        );
96    }
97}
98
99/// 内核的第一个任务
100/// PID = 1
101/// 负责进行剩余的初始化工作
102/// 创建 kthreadd 任务
103/// 并在一切结束后转化为第一个用户态任务
104fn init() {
105    super::trap::init();
106
107    create_kthreadd();
108
109    // 初始化 Ext4 文件系统(从真实块设备)
110    // 必须在任务上下文中进行,因为 VFS 需要 current_task()
111    if let Err(e) = crate::fs::init_ext4_from_block_device() {
112        pr_err!(
113            "[Init] Warning: Failed to initialize Ext4 filesystem: {:?}",
114            e
115        );
116        pr_info!("[Init] Continuing without filesystem...");
117    }
118
119    // // 挂载 /dev 并创建设备节点
120    // if let Err(e) = crate::fs::mount_tmpfs("/dev", 0) {
121    //     pr_err!("[Init] Failed to mount /dev: {:?}", e);
122    // } else if let Err(e) = crate::fs::init_dev() {
123    //     pr_err!("[Init] Failed to create devices: {:?}", e);
124    // }
125
126    kernel_execve("/sbin/init", &["/sbin/init"], &[]);
127}
128
129/// 内核守护线程
130/// PID = 2
131/// 负责创建内核任务,回收僵尸任务等工作
132fn kthreadd() {
133    kthread_spawn(kworker);
134    loop {
135        // 休眠等待任务
136        sleep_task_with_block(current_task(), true);
137        yield_task();
138    }
139}
140
141/// 创建内核守护线程 kthreadd
142fn create_kthreadd() {
143    let tid = TASK_MANAGER.lock().allocate_tid();
144    let kstack_tracker = alloc_contig_frames(4).expect("kthread_spawn: failed to alloc kstack");
145    let trap_frame_tracker = alloc_frame().expect("kthread_spawn: failed to alloc trap_frame");
146    let (uts, rlimit, fd_table, fs) = {
147        let task = current_task();
148        let t = task.lock();
149        (
150            t.uts_namespace.clone(),
151            t.rlimit.clone(),
152            t.fd_table.clone_table(),
153            t.fs.lock().clone(),
154        )
155    };
156    let task = TaskStruct::ktask_create(
157        tid,
158        tid,
159        0,
160        TaskStruct::empty_children(),
161        kstack_tracker,
162        trap_frame_tracker,
163        Arc::new(SpinLock::new(SignalHandlerTable::new())),
164        SignalFlags::empty(),
165        Arc::new(SpinLock::new(SignalPending::empty())),
166        uts,
167        rlimit,
168        Arc::new(fd_table),
169        Arc::new(SpinLock::new(fs)),
170    ); // kthreadd 没有父任务
171
172    let tf = task.trap_frame_ptr.load(Ordering::SeqCst);
173    // Safety: 此时 trap_frame_tracker 已经分配完毕且不可变更,所有权在 task 中,指针有效
174    unsafe {
175        (*tf).set_kernel_trap_frame(kthreadd as usize, 0, task.kstack_base);
176    }
177    let task = task.into_shared();
178    TASK_MANAGER.lock().add_task(task.clone());
179    SCHEDULER.lock().add_task(task);
180}
181
182pub fn main(hartid: usize) {
183    clear_bss();
184
185    run_early_tests();
186
187    earlyprintln!("[Boot] Hello, world!");
188    earlyprintln!("[Boot] RISC-V Hart {} is up!", hartid);
189
190    mm::init();
191
192    #[cfg(test)]
193    crate::test_main();
194
195    // 初始化工作
196    trap::init_boot_trap();
197    platform::init();
198    time::init();
199    timer::init();
200    unsafe { intr::enable_interrupts() };
201
202    rest_init();
203}
204
205/// 清除 BSS 段,将其全部置零
206/// BSS 段包含所有未初始化的静态变量
207/// 在进入 Rust 代码之前调用此函数非常重要
208fn clear_bss() {
209    unsafe extern "C" {
210        fn sbss();
211        fn ebss();
212    }
213
214    let sbss_paddr = unsafe { vaddr_to_paddr(sbss as usize) };
215    let ebss_paddr = unsafe { vaddr_to_paddr(ebss as usize) };
216
217    (sbss_paddr..ebss_paddr).for_each(|a| unsafe {
218        // 访问物理地址需要通过 paddr_to_vaddr 转换
219        let va = crate::arch::mm::paddr_to_vaddr(a);
220        (va as *mut u8).write_volatile(0)
221    });
222}
223
224// 由于最近的更新使得create_kthreadd内部会调用current_task等函数
225// 该单元测试已无法在不完整的测试环境下运行
226// #[cfg(test)]
227// mod tests {
228
229//     use core::sync::atomic::Ordering;
230
231//     // 测试 create_kthreadd:应创建一个任务并加入 TASK_MANAGER
232//     use crate::{
233//         arch::boot::{create_kthreadd, kthreadd},
234//         kassert,
235//         kernel::{TASK_MANAGER, TaskManagerTrait},
236//         test_case,
237//     };
238
239//     test_case!(test_create_kthreadd, {
240//         // 记录当前已有任务数量
241//         let before_count = {
242//             let mgr = TASK_MANAGER.lock();
243//             mgr.task_count()
244//         };
245//         create_kthreadd();
246//         // 找到新增的任务(PID=tid,入口=kthreadd)
247//         let after_count = {
248//             let mgr = TASK_MANAGER.lock();
249//             mgr.task_count()
250//         };
251//         kassert!(after_count == before_count + 1);
252//         // 查找新 tid
253//         let new_tid = after_count as u32; // 简单假设 tid 连续分配
254//         let task = TASK_MANAGER.lock().get_task(new_tid).expect("task missing");
255//         let g = task.lock();
256//         let tf = g.trap_frame_ptr.load(Ordering::SeqCst);
257//         kassert!(g.tid == new_tid);
258//         kassert!(g.pid == new_tid); // kthreadd 设 pid=tid
259//         kassert!(unsafe { (*tf).sepc } as usize == kthreadd as usize);
260//     });
261
262//     // 由于 kernel_execve / rest_init / init / kthreadd 涉及不可返回的流控与实际陷入/页表切换,
263//     // 在单元测试环境下不执行它们(需要集成测试或仿真环境)。
264// }