Skip to content

Commit f1bc83d

Browse files
committed
complete answer and test CI
1 parent 34b525c commit f1bc83d

15 files changed

Lines changed: 998 additions & 129 deletions

File tree

ch3/src/main.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extern "C" fn rust_main() -> ! {
4040
for (i, app) in tg_linker::AppMeta::locate().iter().enumerate() {
4141
let entry = app.as_ptr() as usize;
4242
log::info!("load app{i} to {entry:#x}");
43-
tcbs[i].init(entry);
43+
tcbs[i].init(i, entry);
4444
index_mod += 1;
4545
}
4646
println!();
@@ -183,17 +183,28 @@ mod impls {
183183
}
184184

185185
impl Trace for SyscallContext {
186-
// TODO: 实现 trace 系统调用
186+
// 实现 trace 系统调用
187187
#[inline]
188-
fn trace(
189-
&self,
190-
_caller: tg_syscall::Caller,
191-
_trace_request: usize,
192-
_id: usize,
193-
_data: usize,
194-
) -> isize {
195-
tg_console::log::info!("trace: not implemented");
196-
-1
188+
fn trace(&self, _caller: tg_syscall::Caller, trace_request: usize, id: usize, data: usize) -> isize {
189+
match trace_request {
190+
// 读取 id 地址处一个字节的值
191+
0 => {
192+
let ptr = id as *const u8;
193+
unsafe { *ptr as isize }
194+
}
195+
// 写入 data(作为 u8)到 id 地址处
196+
1 => {
197+
let ptr = id as *mut u8;
198+
unsafe { *ptr = data as u8 };
199+
0
200+
}
201+
// 查询系统调用次数(本次调用已在 handle_syscall 中计入)
202+
2 => {
203+
crate::task::get_syscall_count(id)
204+
}
205+
// 其他情况返回 -1
206+
_ => -1,
207+
}
197208
}
198209
}
199210
}

ch3/src/task.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
use tg_kernel_context::LocalContext;
22
use tg_syscall::{Caller, SyscallId};
33

4+
/// 系统调用计数器数组大小(覆盖所需系统调用号,SYS_TRACE = 410 + 1)
5+
const SYSCALL_COUNT_SIZE: usize = 420;
6+
7+
/// 最大任务数量
8+
const MAX_TASKS: usize = 32;
9+
10+
/// 静态分配的系统调用计数器数组(避免栈溢出)
11+
static mut SYSCALL_COUNTS: [[usize; SYSCALL_COUNT_SIZE]; MAX_TASKS] = [[0; SYSCALL_COUNT_SIZE]; MAX_TASKS];
12+
13+
/// 当前任务 ID
14+
static mut CURRENT_TASK_ID: usize = 0;
15+
416
/// 任务控制块。
517
///
618
/// 包含任务的上下文、状态和资源。
719
pub struct TaskControlBlock {
820
ctx: LocalContext,
921
pub finish: bool,
1022
stack: [usize; 256],
23+
/// 任务 ID,用于索引静态系统调用计数器
24+
task_id: usize,
1125
}
1226

1327
/// 调度事件。
@@ -23,12 +37,18 @@ impl TaskControlBlock {
2337
ctx: LocalContext::empty(),
2438
finish: false,
2539
stack: [0; 256],
40+
task_id: 0,
2641
};
2742

2843
/// 初始化一个任务。
29-
pub fn init(&mut self, entry: usize) {
44+
pub fn init(&mut self, task_id: usize, entry: usize) {
3045
self.stack.fill(0);
3146
self.finish = false;
47+
self.task_id = task_id;
48+
// 清零该任务的系统调用计数器
49+
unsafe {
50+
SYSCALL_COUNTS[task_id].fill(0);
51+
}
3252
self.ctx = LocalContext::user(entry);
3353
*self.ctx.sp_mut() = self.stack.as_ptr() as usize + core::mem::size_of_val(&self.stack);
3454
}
@@ -44,7 +64,7 @@ impl TaskControlBlock {
4464
use tg_syscall::{SyscallId as Id, SyscallResult as Ret};
4565
use SchedulingEvent as Event;
4666

47-
let id = self.ctx.a(7).into();
67+
let id: SyscallId = self.ctx.a(7).into();
4868
let args = [
4969
self.ctx.a(0),
5070
self.ctx.a(1),
@@ -53,6 +73,17 @@ impl TaskControlBlock {
5373
self.ctx.a(4),
5474
self.ctx.a(5),
5575
];
76+
77+
// 统计系统调用次数(在处理前增加计数,这样 trace 查询时能包含本次调用)
78+
let syscall_num = id.0;
79+
unsafe {
80+
if syscall_num < SYSCALL_COUNT_SIZE && self.task_id < MAX_TASKS {
81+
SYSCALL_COUNTS[self.task_id][syscall_num] += 1;
82+
}
83+
// 设置当前任务 ID,让 trace 系统调用能访问当前任务的计数器
84+
CURRENT_TASK_ID = self.task_id;
85+
}
86+
5687
match tg_syscall::handle(Caller { entity: 0, flow: 0 }, id, args) {
5788
Ret::Done(ret) => match id {
5889
Id::EXIT => Event::Exit(self.ctx.a(0)),
@@ -71,3 +102,14 @@ impl TaskControlBlock {
71102
}
72103
}
73104
}
105+
106+
/// 获取当前任务指定系统调用的调用次数
107+
pub fn get_syscall_count(syscall_id: usize) -> isize {
108+
unsafe {
109+
if syscall_id >= SYSCALL_COUNT_SIZE || CURRENT_TASK_ID >= MAX_TASKS {
110+
-1
111+
} else {
112+
SYSCALL_COUNTS[CURRENT_TASK_ID][syscall_id] as isize
113+
}
114+
}
115+
}

ch4/src/main.rs

Lines changed: 116 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -365,36 +365,129 @@ mod impls {
365365
}
366366

367367
impl Trace for SyscallContext {
368-
// TODO: 实现 trace 系统调用
368+
// 实现 trace 系统调用
369369
#[inline]
370-
fn trace(&self, _caller: Caller, _trace_request: usize, _id: usize, _data: usize) -> isize {
371-
tg_console::log::info!("trace: not implemented");
372-
-1
370+
fn trace(&self, caller: tg_syscall::Caller, trace_request: usize, id: usize, data: usize) -> isize {
371+
let process = unsafe { PROCESSES.get_mut().get(caller.entity) }.unwrap();
372+
373+
match trace_request {
374+
// 读取 id 地址处一个字节的值
375+
0 => {
376+
// 检查地址是否用户可见且可读(需要 U、R、V 标志)
377+
const READABLE: VmFlags<Sv39> = VmFlags::build_from_str("U__RV");
378+
if let Some(ptr) = process.address_space.translate::<u8>(VAddr::new(id), READABLE) {
379+
unsafe { *ptr.as_ptr() as isize }
380+
} else {
381+
-1
382+
}
383+
}
384+
// 写入 data(作为 u8)到 id 地址处
385+
1 => {
386+
// 检查地址是否用户可见且可写(需要 U、W、V 标志)
387+
const WRITABLE: VmFlags<Sv39> = VmFlags::build_from_str("U_WRV");
388+
if let Some(mut ptr) = process.address_space.translate::<u8>(VAddr::new(id), WRITABLE) {
389+
unsafe { *ptr.as_mut() = data as u8 };
390+
0
391+
} else {
392+
-1
393+
}
394+
}
395+
// 其他情况返回 -1
396+
_ => -1,
397+
}
373398
}
374399
}
375400

376401
impl Memory for SyscallContext {
377-
// TODO: 实现 mmap 系统调用
378-
fn mmap(
379-
&self,
380-
_caller: Caller,
381-
addr: usize,
382-
len: usize,
383-
prot: i32,
384-
_flags: i32,
385-
_fd: i32,
386-
_offset: usize,
387-
) -> isize {
388-
tg_console::log::info!(
389-
"mmap: addr = {addr:#x}, len = {len}, prot = {prot}, not implemented"
390-
);
391-
-1
402+
// 实现 mmap 系统调用
403+
fn mmap(&self, caller: Caller, addr: usize, len: usize, prot: i32, _flags: i32, _fd: i32, _offset: usize) -> isize {
404+
const PAGE_SIZE: usize = 1 << Sv39::PAGE_BITS;
405+
406+
// 检查 addr 是否页对齐
407+
if addr & (PAGE_SIZE - 1) != 0 {
408+
return -1;
409+
}
410+
411+
// 检查 prot 参数
412+
// prot & !0x7 != 0 (prot 其余位必须为 0)
413+
if prot & !0x7 != 0 {
414+
return -1;
415+
}
416+
// prot & 0x7 == 0 (这样的内存无意义)
417+
if prot & 0x7 == 0 {
418+
return -1;
419+
}
420+
421+
// len 为 0 时直接返回成功
422+
if len == 0 {
423+
return 0;
424+
}
425+
426+
// 计算页范围(向上取整)
427+
let start_vpn = VPN::<Sv39>::new(addr >> Sv39::PAGE_BITS);
428+
let end_addr = addr + len;
429+
let end_vpn = VPN::<Sv39>::new((end_addr + PAGE_SIZE - 1) >> Sv39::PAGE_BITS);
430+
let range = start_vpn..end_vpn;
431+
432+
let process = unsafe { PROCESSES.get_mut().get_mut(caller.entity) }.unwrap();
433+
434+
// 检查是否与已有映射重叠
435+
if process.address_space.overlaps(&range) {
436+
return -1;
437+
}
438+
439+
// 构建 VmFlags
440+
// prot: bit 0 = 可读(R), bit 1 = 可写(W), bit 2 = 可执行(X)
441+
// RISC-V PTE: bit 0 = V, bit 1 = R, bit 2 = W, bit 3 = X, bit 4 = U
442+
let mut flags_str: [u8; 5] = *b"U___V";
443+
if prot & 0x4 != 0 {
444+
flags_str[1] = b'X';
445+
}
446+
if prot & 0x2 != 0 {
447+
flags_str[2] = b'W';
448+
}
449+
if prot & 0x1 != 0 {
450+
flags_str[3] = b'R';
451+
}
452+
let flags = VmFlags::build_from_str(unsafe { core::str::from_utf8_unchecked(&flags_str) });
453+
454+
// 分配物理页并建立映射
455+
process.address_space.map_alloc(range, flags);
456+
457+
0
392458
}
393459

394-
// TODO: 实现 munmap 系统调用
395-
fn munmap(&self, _caller: Caller, addr: usize, len: usize) -> isize {
396-
tg_console::log::info!("munmap: addr = {addr:#x}, len = {len}, not implemented");
397-
-1
460+
// 实现 munmap 系统调用
461+
fn munmap(&self, caller: Caller, addr: usize, len: usize) -> isize {
462+
const PAGE_SIZE: usize = 1 << Sv39::PAGE_BITS;
463+
464+
// 检查 addr 是否页对齐
465+
if addr & (PAGE_SIZE - 1) != 0 {
466+
return -1;
467+
}
468+
469+
// len 为 0 时直接返回成功
470+
if len == 0 {
471+
return 0;
472+
}
473+
474+
// 计算页范围(向上取整)
475+
let start_vpn = VPN::<Sv39>::new(addr >> Sv39::PAGE_BITS);
476+
let end_addr = addr + len;
477+
let end_vpn = VPN::<Sv39>::new((end_addr + PAGE_SIZE - 1) >> Sv39::PAGE_BITS);
478+
let range = start_vpn..end_vpn;
479+
480+
let process = unsafe { PROCESSES.get_mut().get_mut(caller.entity) }.unwrap();
481+
482+
// 检查该范围是否完全被映射
483+
if !process.address_space.fully_mapped(&range) {
484+
return -1;
485+
}
486+
487+
// 取消映射
488+
process.address_space.unmap(range);
489+
490+
0
398491
}
399492
}
400493
}

0 commit comments

Comments
 (0)