Skip to content

Commit 70da8e5

Browse files
committed
ch4 ok
1 parent d299383 commit 70da8e5

File tree

8 files changed

+198
-26
lines changed

8 files changed

+198
-26
lines changed

os/src/mm/memory_set.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,40 @@ impl MemorySet {
300300
false
301301
}
302302
}
303+
304+
/// find target area by start_va, then insert it to areas
305+
pub fn find_area_insert(&mut self, start_va: VirtAddr, end_va: VirtAddr, permission: MapPermission) -> bool {
306+
if let Some(_area) = self.areas.iter().find(|area| {
307+
debug!("=============== insert ===============");
308+
debug!("area start: {}, end: {}", area.vpn_range.get_start().0, area.vpn_range.get_end().0);
309+
debug!("target area start: {}, end: {}", start_va.floor().0, end_va.ceil().0);
310+
debug!("======================================");
311+
area.vpn_range.get_start() < end_va.ceil() && area.vpn_range.get_end() > start_va.floor()
312+
}) {
313+
debug!("!!! find area has been used !!!");
314+
false
315+
} else {
316+
debug!("!!! area not be used, insert it!!!");
317+
self.insert_framed_area(start_va, end_va, permission);
318+
true
319+
}
320+
}
321+
/// find target area by start_va, then remove it from areas
322+
pub fn find_area_remove(&mut self, start_va: VirtAddr, end_va: VirtAddr) -> bool {
323+
if let Some(index) = self.areas.iter().position(|area| {
324+
debug!("=============== remove ===============");
325+
debug!("area start: {}, end: {}", area.vpn_range.get_start().0, area.vpn_range.get_end().0);
326+
debug!("target area start: {}, end: {}", start_va.floor().0, end_va.ceil().0);
327+
debug!("======================================");
328+
area.vpn_range.get_start() == start_va.floor() && area.vpn_range.get_end() == end_va.ceil()
329+
}) {
330+
self.areas[index].unmap(&mut self.page_table);
331+
self.areas.remove(index);
332+
true
333+
} else {
334+
false
335+
}
336+
}
303337
}
304338
/// map area structure, controls a contiguous piece of virtual memory
305339
pub struct MapArea {

os/src/mm/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ use address::{StepByOne, VPNRange};
1616
pub use frame_allocator::{frame_alloc, FrameTracker};
1717
pub use memory_set::remap_test;
1818
pub use memory_set::{MapPermission, MemorySet, KERNEL_SPACE};
19-
pub use page_table::{translated_byte_buffer, translated_refmut, translated_str, PageTableEntry};
20-
use page_table::{PTEFlags, PageTable};
19+
pub use page_table::{translated_byte_buffer, translated_refmut, translated_physaddr, translated_str, PageTableEntry};
20+
pub use page_table::{PTEFlags, PageTable};
21+
2122
/// initiate heap allocator, frame allocator and kernel space
2223
pub fn init() {
2324
heap_allocator::init_heap();

os/src/mm/page_table.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ pub fn translated_str(token: usize, ptr: *const u8) -> String {
202202
}
203203
string
204204
}
205+
205206
/// Translate a ptr[u8] array through page table and return a mutable reference of T
206207
pub fn translated_refmut<T>(token: usize, ptr: *mut T) -> &'static mut T {
207208
//trace!("into translated_refmut!");
@@ -213,3 +214,16 @@ pub fn translated_refmut<T>(token: usize, ptr: *mut T) -> &'static mut T {
213214
.unwrap()
214215
.get_mut()
215216
}
217+
218+
/// translate a ptr and return its mut
219+
pub fn translated_physaddr(token: usize, ptr: *const u8) -> PhysAddr {
220+
let page_table = PageTable::from_token(token);
221+
let va = VirtAddr::from(ptr as usize);
222+
let vpn = va.floor();
223+
let ppn: PhysPageNum = page_table.translate(vpn).unwrap().ppn();
224+
let pa: PhysAddr = ppn.into();
225+
226+
let offset = va.page_offset();
227+
let pa_offset = (pa.0 + offset).into();
228+
return pa_offset;
229+
}

os/src/syscall/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ mod process;
4343

4444
use fs::*;
4545
use process::*;
46+
4647
/// handle syscall exception with `syscall_id` and other arguments
4748
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
4849
match syscall_id {

os/src/syscall/process.rs

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@
22
use alloc::sync::Arc;
33

44
use crate::{
5-
loader::get_app_data_by_name,
6-
mm::{translated_refmut, translated_str},
7-
task::{
8-
add_task, current_task, current_user_token, exit_current_and_run_next,
9-
suspend_current_and_run_next,
10-
},
5+
loader::get_app_data_by_name, mm::{translated_physaddr, translated_refmut, translated_str, MapPermission, VirtAddr}, task::{add_task, current_task, current_user_token, exit_current_and_run_next, suspend_current_and_run_next}, timer::get_time_us
116
};
127

138
#[repr(C)]
@@ -106,29 +101,83 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
106101
/// HINT: You might reimplement it with virtual memory management.
107102
/// HINT: What if [`TimeVal`] is splitted by two pages ?
108103
pub fn sys_get_time(_ts: *mut TimeVal, _tz: usize) -> isize {
109-
trace!(
110-
"kernel:pid[{}] sys_get_time NOT IMPLEMENTED",
111-
current_task().unwrap().pid.0
112-
);
113-
-1
104+
trace!("kernel: sys_get_time");
105+
let pa = translated_physaddr(current_user_token(), _ts as *const u8);
106+
let phy_ts = pa.0 as *mut TimeVal;
107+
108+
let us = get_time_us();
109+
let time_val = TimeVal {
110+
sec : us / 1_000_000,
111+
usec: us % 1_000_000,
112+
};
113+
114+
unsafe { *phy_ts = time_val };
115+
0
114116
}
115117

116-
/// YOUR JOB: Implement mmap.
118+
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
119+
pub struct Flag(pub usize);
120+
121+
impl Flag {
122+
pub fn is_readable(&self) -> bool {
123+
self.0 & 0x1 == 0x1
124+
}
125+
126+
pub fn is_writeable(&self) -> bool {
127+
self.0 & 0x2 == 0x2
128+
}
129+
130+
pub fn is_execute(&self) -> bool {
131+
self.0 & 0x4 == 0x4
132+
}
133+
}
134+
135+
// YOUR JOB: Implement mmap.
117136
pub fn sys_mmap(_start: usize, _len: usize, _port: usize) -> isize {
118-
trace!(
119-
"kernel:pid[{}] sys_mmap NOT IMPLEMENTED",
120-
current_task().unwrap().pid.0
121-
);
122-
-1
137+
trace!("kernel: sys_mmap ");
138+
139+
debug!("mmap start: {}, len: {}, port: {}", _start, _len, _port);
140+
141+
let start_va = VirtAddr::from(_start);
142+
if !start_va.aligned() {
143+
return -1;
144+
}
145+
let end_va: VirtAddr = (_start + _len).into();
146+
if _port & !0x7 != 0 || _port & 0x7 == 0 {
147+
return -1;
148+
}
149+
150+
let mut map_perm: MapPermission = MapPermission::U;
151+
let pte_flag = Flag(_port);
152+
if pte_flag.is_readable() {
153+
map_perm |= MapPermission::R;
154+
}
155+
if pte_flag.is_writeable() {
156+
map_perm |= MapPermission::W;
157+
}
158+
if pte_flag.is_execute() {
159+
map_perm |= MapPermission::X;
160+
}
161+
162+
if !current_task().unwrap().find_area_insert(start_va, end_va, map_perm) {
163+
return -1;
164+
}
165+
return 0;
123166
}
124167

125168
/// YOUR JOB: Implement munmap.
126169
pub fn sys_munmap(_start: usize, _len: usize) -> isize {
127-
trace!(
128-
"kernel:pid[{}] sys_munmap NOT IMPLEMENTED",
129-
current_task().unwrap().pid.0
130-
);
131-
-1
170+
trace!("kernel: sys_munmap ");
171+
let start_va = VirtAddr::from(_start);
172+
if !start_va.aligned() {
173+
return -1;
174+
}
175+
let end_va: VirtAddr = (_start + _len).into();
176+
177+
if !current_task().unwrap().find_area_remove(start_va, end_va) {
178+
return -1;
179+
}
180+
return 0;
132181
}
133182

134183
/// change data segment size

os/src/task/task.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Types related to task management & Functions for completely changing TCB
22
use super::TaskContext;
33
use super::{kstack_alloc, pid_alloc, KernelStack, PidHandle};
4+
use crate::mm::{MapPermission, MemorySet, PhysPageNum, VirtAddr, KERNEL_SPACE};
45
use crate::config::TRAP_CONTEXT_BASE;
5-
use crate::mm::{MemorySet, PhysPageNum, VirtAddr, KERNEL_SPACE};
66
use crate::sync::UPSafeCell;
77
use crate::trap::{trap_handler, TrapContext};
88
use alloc::sync::{Arc, Weak};
@@ -236,6 +236,14 @@ impl TaskControlBlock {
236236
None
237237
}
238238
}
239+
/// find area of memory set to insert
240+
pub fn find_area_insert(&self, start_va: VirtAddr, end_va: VirtAddr, permission: MapPermission) -> bool {
241+
self.inner_exclusive_access().memory_set.find_area_insert(start_va, end_va, permission)
242+
}
243+
/// find area of memory set to remove
244+
pub fn find_area_remove(&self, start_va: VirtAddr, end_va: VirtAddr) -> bool {
245+
self.inner_exclusive_access().memory_set.find_area_remove(start_va, end_va)
246+
}
239247
}
240248

241249
#[derive(Copy, Clone, PartialEq)]

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”分计。

reports/lab2.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,4 @@ SV39页表页表项(PTE),由64位组成,
8585

8686
3. 我独立完成了本次实验除以上方面之外的所有工作,包括代码与文档。 我清楚地知道,从以上方面获得的信息在一定程度上降低了实验难度,可能会影响起评分。
8787

88-
4. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。
88+
4. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。

0 commit comments

Comments
 (0)