-
Notifications
You must be signed in to change notification settings - Fork 45
Expand file tree
/
Copy pathmain.rs
More file actions
143 lines (127 loc) · 4.36 KB
/
main.rs
File metadata and controls
143 lines (127 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#![no_std]
#![no_main]
#![deny(warnings)]
#[macro_use]
extern crate rcore_console;
use impls::{Console, SyscallContext};
use kernel_context::LocalContext;
use rcore_console::log;
use riscv::register::*;
use sbi_rt::*;
use syscall::{Caller, SyscallId};
// 用户程序内联进来。
core::arch::global_asm!(include_str!(env!("APP_ASM")));
// 定义内核入口。
linker::boot0!(rust_main; stack = 4 * 4096);
extern "C" fn rust_main() -> ! {
// bss 段清零
unsafe { linker::KernelLayout::locate().zero_bss() };
// 初始化 `console`
rcore_console::init_console(&Console);
rcore_console::set_log_level(option_env!("LOG"));
rcore_console::test_log();
// 初始化 syscall
syscall::init_io(&SyscallContext);
syscall::init_process(&SyscallContext);
// 批处理
for (i, app) in linker::AppMeta::locate().iter().enumerate() {
let app_base = app.as_ptr() as usize;
log::info!("load app{i} to {app_base:#x}");
// 初始化上下文
let mut ctx = LocalContext::user(app_base);
// 设置用户栈(使用 MaybeUninit 避免 release 模式下零初始化的问题)
let mut user_stack: core::mem::MaybeUninit<[usize; 256]> = core::mem::MaybeUninit::uninit();
let user_stack_ptr = user_stack.as_mut_ptr() as *mut usize;
*ctx.sp_mut() = unsafe { user_stack_ptr.add(256) } as usize;
loop {
unsafe { ctx.execute() };
use scause::{Exception, Trap};
match scause::read().cause() {
Trap::Exception(Exception::UserEnvCall) => {
use SyscallResult::*;
match handle_syscall(&mut ctx) {
Done => continue,
Exit(code) => log::info!("app{i} exit with code {code}"),
Error(id) => log::error!("app{i} call an unsupported syscall {}", id.0),
}
}
trap => log::error!("app{i} was killed because of {trap:?}"),
}
// 清除指令缓存
unsafe { core::arch::asm!("fence.i") };
break;
}
// 防止 user_stack 被优化
let _ = core::hint::black_box(&user_stack);
println!();
}
system_reset(Shutdown, NoReason);
unreachable!()
}
/// Rust 异常处理函数,以异常方式关机。
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
println!("{info}");
system_reset(Shutdown, SystemFailure);
loop {}
}
enum SyscallResult {
Done,
Exit(usize),
Error(SyscallId),
}
/// 处理系统调用,返回是否应该终止程序。
fn handle_syscall(ctx: &mut LocalContext) -> SyscallResult {
use syscall::{SyscallId as Id, SyscallResult as Ret};
let id = ctx.a(7).into();
let args = [ctx.a(0), ctx.a(1), ctx.a(2), ctx.a(3), ctx.a(4), ctx.a(5)];
match syscall::handle(Caller { entity: 0, flow: 0 }, id, args) {
Ret::Done(ret) => match id {
Id::EXIT => SyscallResult::Exit(ctx.a(0)),
_ => {
*ctx.a_mut(0) = ret as _;
ctx.move_next();
SyscallResult::Done
}
},
Ret::Unsupported(id) => SyscallResult::Error(id),
}
}
/// 各种接口库的实现
mod impls {
use syscall::{STDDEBUG, STDOUT};
pub struct Console;
impl rcore_console::Console for Console {
#[inline]
fn put_char(&self, c: u8) {
#[allow(deprecated)]
sbi_rt::legacy::console_putchar(c as _);
}
}
pub struct SyscallContext;
impl syscall::IO for SyscallContext {
fn write(&self, _caller: syscall::Caller, fd: usize, buf: usize, count: usize) -> isize {
match fd {
STDOUT | STDDEBUG => {
print!("{}", unsafe {
core::str::from_utf8_unchecked(core::slice::from_raw_parts(
buf as *const u8,
count,
))
});
count as _
}
_ => {
rcore_console::log::error!("unsupported fd: {fd}");
-1
}
}
}
}
impl syscall::Process for SyscallContext {
#[inline]
fn exit(&self, _caller: syscall::Caller, _status: usize) -> isize {
0
}
}
}