Skip to content

Commit 576c4e5

Browse files
committed
ch3 ok
1 parent b3b9465 commit 576c4e5

File tree

4 files changed

+134
-7
lines changed

4 files changed

+134
-7
lines changed

os/src/syscall/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,26 @@
1111
//! submodules, and you should also implement syscalls this way.
1212
1313
/// write syscall
14-
const SYSCALL_WRITE: usize = 64;
14+
pub const SYSCALL_WRITE: usize = 64;
1515
/// exit syscall
16-
const SYSCALL_EXIT: usize = 93;
16+
pub const SYSCALL_EXIT: usize = 93;
1717
/// yield syscall
18-
const SYSCALL_YIELD: usize = 124;
18+
pub const SYSCALL_YIELD: usize = 124;
1919
/// gettime syscall
20-
const SYSCALL_GET_TIME: usize = 169;
20+
pub const SYSCALL_GET_TIME: usize = 169;
2121
/// trace syscall
22-
const SYSCALL_TRACE: usize = 410;
22+
pub const SYSCALL_TRACE: usize = 410;
2323

2424
mod fs;
2525
mod process;
2626

2727
use fs::*;
2828
use process::*;
29+
use crate::task::add_syscall_counter;
2930

3031
/// handle syscall exception with `syscall_id` and other arguments
3132
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
33+
add_syscall_counter(syscall_id);
3234
match syscall_id {
3335
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
3436
SYSCALL_EXIT => sys_exit(args[0] as i32),

os/src/syscall/process.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Process management syscalls
22
use crate::{
3-
task::{exit_current_and_run_next, suspend_current_and_run_next},
3+
task::{exit_current_and_run_next, suspend_current_and_run_next, get_syscall_counter},
44
timer::get_time_us,
55
};
66

@@ -41,5 +41,18 @@ pub fn sys_get_time(ts: *mut TimeVal, _tz: usize) -> isize {
4141
// TODO: implement the syscall
4242
pub fn sys_trace(_trace_request: usize, _id: usize, _data: usize) -> isize {
4343
trace!("kernel: sys_trace");
44-
-1
44+
// 向claude3.7请教了通过裸指针操作内存的方法
45+
match _trace_request {
46+
0 => {
47+
let ptr : *const u8 = _id as *const u8;
48+
unsafe { (*ptr).into() }
49+
},
50+
1 => {
51+
let ptr : *mut u8 = _id as *mut u8;
52+
unsafe { *ptr = _data as u8 ; };
53+
0
54+
},
55+
2 => get_syscall_counter(_id),
56+
_ => -1
57+
}
4558
}

os/src/task/mod.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use switch::__switch;
2222
pub use task::{TaskControlBlock, TaskStatus};
2323

2424
pub use context::TaskContext;
25+
use crate::syscall::{SYSCALL_EXIT, SYSCALL_GET_TIME, SYSCALL_TRACE, SYSCALL_WRITE, SYSCALL_YIELD};
2526

2627
/// The task manager, where all the tasks are managed.
2728
///
@@ -44,6 +45,11 @@ pub struct TaskManagerInner {
4445
/// task list
4546
tasks: [TaskControlBlock; MAX_APP_NUM],
4647
/// id of current `Running` task
48+
syscall_write_counter: [usize; MAX_APP_NUM],
49+
syscall_exit_counter: [usize; MAX_APP_NUM],
50+
syscall_yield_counter: [usize; MAX_APP_NUM],
51+
syscall_get_time_counter: [usize; MAX_APP_NUM],
52+
syscall_trace_counter: [usize; MAX_APP_NUM],
4753
current_task: usize,
4854
}
4955

@@ -64,6 +70,11 @@ lazy_static! {
6470
inner: unsafe {
6571
UPSafeCell::new(TaskManagerInner {
6672
tasks,
73+
syscall_write_counter: [0; MAX_APP_NUM],
74+
syscall_exit_counter: [0; MAX_APP_NUM],
75+
syscall_yield_counter: [0; MAX_APP_NUM],
76+
syscall_get_time_counter: [0; MAX_APP_NUM],
77+
syscall_trace_counter: [0; MAX_APP_NUM],
6778
current_task: 0,
6879
})
6980
},
@@ -135,6 +146,32 @@ impl TaskManager {
135146
panic!("All applications completed!");
136147
}
137148
}
149+
150+
fn add_syscall_counter(&self, syscall_id: usize) {
151+
let mut inner = self.inner.exclusive_access();
152+
let current = inner.current_task;
153+
match syscall_id {
154+
SYSCALL_WRITE => inner.syscall_write_counter[current] += 1,
155+
SYSCALL_EXIT => inner.syscall_exit_counter[current] += 1,
156+
SYSCALL_YIELD => inner.syscall_yield_counter[current] += 1,
157+
SYSCALL_GET_TIME => inner.syscall_get_time_counter[current] += 1,
158+
SYSCALL_TRACE => inner.syscall_trace_counter[current] += 1,
159+
_ => panic!("Unsupported syscall_id: {}", syscall_id),
160+
}
161+
}
162+
163+
fn get_syscall_counter(&self, syscall_id: usize) -> usize {
164+
let inner = self.inner.exclusive_access();
165+
let current = inner.current_task;
166+
match syscall_id {
167+
SYSCALL_WRITE => inner.syscall_write_counter[current],
168+
SYSCALL_EXIT => inner.syscall_exit_counter[current],
169+
SYSCALL_YIELD => inner.syscall_yield_counter[current],
170+
SYSCALL_GET_TIME => inner.syscall_get_time_counter[current],
171+
SYSCALL_TRACE => inner.syscall_trace_counter[current],
172+
_ => panic!("Unsupported syscall_id: {}", syscall_id),
173+
}
174+
}
138175
}
139176

140177
/// Run the first task in task list.
@@ -169,3 +206,13 @@ pub fn exit_current_and_run_next() {
169206
mark_current_exited();
170207
run_next_task();
171208
}
209+
210+
/// Add the current 'Running' task's syscall counter by syscall_id.
211+
pub fn add_syscall_counter(syscall_id: usize) {
212+
TASK_MANAGER.add_syscall_counter(syscall_id);
213+
}
214+
215+
/// Get the current 'Running' task's syscall counter by syscall_id.
216+
pub fn get_syscall_counter(syscall_id: usize) -> isize {
217+
TASK_MANAGER.get_syscall_counter(syscall_id).try_into().unwrap()
218+
}

reports/lab1.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
### 总结实现的功能
2+
`sys_trace`实现了三个功能:
3+
1. 根据传入的参数(_id)读取对应内存地址的值并返回
4+
2. 根据传入的参数(_id, _data)向对应地址写入值
5+
3. 获取传入的参数(_id)对应的系统调用执行的次数
6+
7+
为了实现第3个功能,我修改了`TaskManagerInner`结构体,向里面添加了对应不同系统调用的计数器,用于统计不同系统调用的执行次数。并且,提供了两个函数`add_syscall_counter``get_syscall_counter`用于修改和查询系统调用的执行次数。
8+
9+
### 问答题
10+
#### 1. 正确进入 U 态后,程序的特征还应有:使用 S 态特权指令,访问 S 态寄存器后会报错。 请同学们可以自行测试这些内容(运行 三个 bad 测例 (ch2b_bad_*.rs) ), 描述程序出错行为,同时注意注明你使用的 sbi 及其版本。
11+
12+
使用RustSBI,版本号:version 0.4.0-alpha.1
13+
14+
- ch2b_bad_address.rs: OS首先输出`PageFault`异常,这表明程序尝试请求非法的内存地址,OS提示该地址`bad addr = 0x0`,且该错误的指令存储在这个位置:`bad instruction = 0x804003a4`
15+
16+
如果同时运行三个bad测例,则后两个测例的输出为:`IllegalInstruction in application, kernel killed it.`
17+
18+
我尝试单独运行后两个测例后,可得到以下输出:
19+
- ch2b_bad_instructions.rs: OS会输出`InstructionFault`非法指令异常,此时`stval = 0x0`
20+
- ch2b_bad_register.rs: 此测例会在进行系统调用时提示不支持的trap异常,`scause`的输出信息为`LoadFault``stval = 0x10`,这表明程序在U模式尝试访问了S模式的寄存器,导致程序出错。
21+
22+
#### 2.深入理解 trap.S 中两个函数 __alltraps 和 __restore 的作用,并回答如下问题:
23+
1. L40:刚进入 __restore 时,sp 代表了什么值。请指出 __restore 的两种使用情景。
24+
- sp指向了内核栈的TrapContext结构体的起始位置,也就是内核态的栈指针
25+
- 使用场景:
26+
- 在任务上下文切换中,__restore会成为__switch返回后继续执行的函数
27+
- Trap处理后的返回
28+
29+
2. L43-L48:这几行汇编代码特殊处理了哪些寄存器?这些寄存器的的值对于进入用户态有何意义?请分别解释。
30+
分别处理了以下寄存器:
31+
- sstatus: 记录和控制当前特权级别以及在异常发生前的特权级别,同时还能够恢复用户程序的中断使能状态。
32+
- sepc: 将内核TrapContext的pc值保存,在后面执行`sret`指令从S态返回时,pc寄存器将从sepc寄存器中读取该值。
33+
- sscratch: 在特权级切换的过程中,sscratch和sp寄存器会互相交换值,从而保存用户态或者内核态的栈指针
34+
35+
3. L50-L56:为何跳过了 x2 和 x4?
36+
- x2 寄存器就是 sp寄存器,我们通过 csrrw 指令将sp寄存器和sscratch寄存器的值进行交换保存了
37+
- x4 寄存器是 tp寄存器,用于支持线程局部存储,这个寄存器只有在某些特殊用途的情况下会用到。
38+
39+
4. L60:该指令之后,sp 和 sscratch 中的值分别有什么意义?
40+
- sp: 存储的是用户态的栈指针
41+
- sscratch: 暂存了内核态的栈指针
42+
43+
5. __restore:中发生状态切换在哪一条指令?为何该指令执行之后会进入用户态?
44+
- 状态切换发生在`sret`指令
45+
- `sret`指令会将特权级别切换到`sstatus.SPP`指定的特权级别。从用户态进入内核态时,硬件会自动将`sstatus.SPP`设置为0,表示之前是用户态。所以执行`sret`后会进入用户态。并且,在执行`sret`之前,我们已经正确设置了sepc和sstatus寄存器,从而使得进入用户态后,程序能够跳转到正确的地址执行。
46+
47+
6. L13:该指令之后,sp 和 sscratch 中的值分别有什么意义?
48+
- sp: 指向了内核栈的TrapContext结构体的起始位置,也就是内核态的栈指针
49+
- sscratch: 暂存了用户态TrapContext结构体的起始位置,也就是用户态的栈指针
50+
51+
7. 从 U 态进入 S 态是哪一条指令发生的?
52+
`ecall`
53+
54+
### 荣誉准则
55+
1. 在完成本次实验的过程(含此前学习的过程)中,我曾分别与 以下各位 就(与本次实验相关的)以下方面做过交流,还在代码中对应的位置以注释形式记录了具体的交流对象及内容:
56+
57+
向claude3.7老师请教了许多问题,感谢它的帮助
58+
59+
2. 此外,我也参考了 以下资料 ,还在代码中对应的位置以注释形式记录了具体的参考来源及内容:
60+
61+
参考了 https://cheats.rs/ 手册的一些语法细节。
62+
63+
3. 我独立完成了本次实验除以上方面之外的所有工作,包括代码与文档。 我清楚地知道,从以上方面获得的信息在一定程度上降低了实验难度,可能会影响起评分。
64+
65+
4. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。

0 commit comments

Comments
 (0)