syscall trace finished
This commit is contained in:
18
answers-syscall.txt
Normal file
18
answers-syscall.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
在xv6中,当执行到地址 `0x3ffffff11c` 处的 `sret` 指令时,特权级和执行流程的变化如下:
|
||||||
|
|
||||||
|
1. **特权级变化**
|
||||||
|
- **执行前**:核心态(S模式,特权级 `1`)
|
||||||
|
- **执行后**:用户态(U模式,特权级 `0`)
|
||||||
|
`sret` 指令会从 `sstatus` 寄存器中恢复之前的特权级(由 `SPP` 位决定)。在进入陷阱处理时,处理器已自动将用户态的特权级(`0`)保存到 `sstatus.SPP`,因此 `sret` 会将特权级切换回用户态。
|
||||||
|
|
||||||
|
2. **恢复点地址**
|
||||||
|
恢复点地址由 `sepc` 寄存器指定。在进入陷阱处理时,`sepc` 被设置为触发 `ecall` 的下一条指令地址(即 `0x14`)。因此,`sret` 执行后,程序会跳转到 `0x14` 处继续执行用户代码。
|
||||||
|
|
||||||
|
3. **执行的函数**
|
||||||
|
`sret` 返回后,用户程序会从 `0x14` 处继续执行。根据 `initcode.S` 的代码,`0x14` 是 `ecall` 指令的下一条地址。若 `exec` 系统调用成功,用户地址空间会被替换为新程序(如 `init`),此时 `sret` 返回后直接进入新程序的入口点。若 `exec` 失败(理论上不会发生),则会继续执行 `initcode.S` 中 `ecall` 后的代码(但实际代码中 `ecall` 后无其他指令)。
|
||||||
|
|
||||||
|
**总结**
|
||||||
|
- **特权级**:核心态(`1`)→ 用户态(`0`)
|
||||||
|
- **恢复点地址**:`0x14`(用户代码中 `ecall` 的下一条指令)
|
||||||
|
- **执行函数**:若 `exec` 成功,执行新程序(如 `init`);否则继续 `initcode.S` 的后续代码(实际无后续指令)。
|
||||||
|
|
||||||
0
grade-lab-syscall
Normal file → Executable file
0
grade-lab-syscall
Normal file → Executable file
@@ -146,6 +146,9 @@ found:
|
|||||||
p->context.ra = (uint64)forkret;
|
p->context.ra = (uint64)forkret;
|
||||||
p->context.sp = p->kstack + PGSIZE;
|
p->context.sp = p->kstack + PGSIZE;
|
||||||
|
|
||||||
|
// 初始化计数器
|
||||||
|
memset(p->syscall_counts, 0, sizeof(p->syscall_counts));
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "defs.h"
|
||||||
// Saved registers for kernel context switches.
|
// Saved registers for kernel context switches.
|
||||||
struct context {
|
struct context {
|
||||||
uint64 ra;
|
uint64 ra;
|
||||||
@@ -105,4 +106,5 @@ struct proc {
|
|||||||
struct file *ofile[NOFILE]; // Open files
|
struct file *ofile[NOFILE]; // Open files
|
||||||
struct inode *cwd; // Current directory
|
struct inode *cwd; // Current directory
|
||||||
char name[16]; // Process name (debugging)
|
char name[16]; // Process name (debugging)
|
||||||
|
int syscall_counts[24]; // 每个系统调用的调用次数
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -147,7 +147,9 @@ syscall(void)
|
|||||||
// and store its return value in p->trapframe->a0
|
// and store its return value in p->trapframe->a0
|
||||||
p->trapframe->a0 = syscalls[num]();
|
p->trapframe->a0 = syscalls[num]();
|
||||||
if (p->tracemask & (1 << num)) {
|
if (p->tracemask & (1 << num)) {
|
||||||
printf("%d: syscall %s -> %d\n",p->pid, syscalls_name[num], p->trapframe->a0);
|
p->syscall_counts[num]++;
|
||||||
|
printf("%d: syscall %s(trace counts: %d) -> %d\n",
|
||||||
|
p->pid, syscalls_name[num], p->syscall_counts[num], p->trapframe->a0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("%d %s: unknown sys call %d\n",
|
printf("%d %s: unknown sys call %d\n",
|
||||||
|
|||||||
Reference in New Issue
Block a user