L34: value for trapframe.err (CPU pushes for some traps, e.g., page fault).
L35: value for trapframe.trapno (used by trap() to dispatch).
L36: All vectors jump to alltraps.
mmu.h
``` c
147 // Gate descriptors for interrupts and traps
struct gatedesc { ... };
~~~
#define SETGATE(gate, istrap, sel, off, d) ...
```
>
Intel SDM Vol 3 Ch.6
With the IDT set, next see what happens when a trap actually occurs. Every handler jumps to alltraps.
alltraps builds a trapframe on the stack, then calls trap() with it.
x86.h
``` c
147 // Layout of the trap frame built on the stack ... passed to trap().
struct trapframe {
// pushed by pusha
uint edi, esi, ebp, oesp, ebx, edx, ecx, eax;
// rest
ushort gs; ushort padding1; ushort fs; ushort padding2;
ushort es; ushort padding3; ushort ds; ushort padding4;
uint trapno;
// by hardware
uint err; uint eip; ushort cs; ushort padding5; uint es;
// when crossing rings
uint esp; ushort ss; ushort padding6;
};
```
By the time `alltraps` runs, everything from `ss` up through `trapno` is already on the stack.
trapasm.S
``` c
3 # vectors.S sends all traps here.
4 .globl alltraps
5 alltraps:
6 # Build trap frame.
7 pushl %ds
8 pushl %es
9 pushl %fs
10 pushl %gs
11 pushal
13 # Set up data segments.
14 movw $(SEG_KDATA<<3), %ax
15 movw %ax, %ds
16 movw %ax, %es
18 # Call trap(tf), where tf=%esp
19 pushl %esp
20 call trap
21 addl $4, %esp
23 # Return falls through to trapret...
24 .globl trapret
25 trapret:
26 popal
27 popl %gs
28 popl %fs
29 popl %es
30 popl %ds
31 addl $0x8, %esp # trapno and errcode
32 iret
```
- L6-11: Build the rest of the `trapframe`.
- L15-16: Set data segments (`%ds`, `%es`).
>
Stack after L16
Source: [commentary/textbook](https://pdos.csail.mit.edu/6.828/2018/xv6/book-rev11.pdf)
- L18-20: Call `trap()` with pointer to the built `trapframe` (`%esp`).
- L26-30: Pop what was pushed at L6-11.
- L31: Skip `trapno` and `errcode`.
- L32: `iret` — pops `%cs` `%eip` `%eflags` `%esp` `%ss` (for ring changes) and resumes the interrupted program.
Helper for args: argint() Syscall arguments are on the user stack (tf->esp). Example usage:
``` c
286 int
287 sys_open(void)
288 {
289 char *path;
290 int fd, omode;
291 struct file *f;
292 struct inode *ip;
294 if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
295 return -1;
```
- First argument is the index, second is where to store the value.
syscall.c
``` c
48 // Fetch the nth 32-bit system call argument.
49 int
50 argint(int n, int *ip)
51 {
52 return fetchint((myproc()->tf->esp) + 4 + 4*n, ip);
}
```
- `+4`: skip return address pushed by `call`.
- `+4*n`: advance to the nth argument.
syscall.c
``` c
16 // Fetch the int at addr from the current process.
17 int
18 fetchint(uint addr, int *ip)
19 {
20 struct proc *curproc = myproc();
22 if(addr >= curproc->sz || addr+4 > curproc->sz)
23 return -1;
24 *ip = *(int*)(addr);
25 return 0;
}
```
L22: Validate user-space address.
L24: Read it.
Other helpers include argptr(), argstr(), argfd().
Add a new system call to get the current UTC time and return it to the user program. You may want to use the helper function cmostime (7552) to read the real-time clock. The file date.h contains the definition of struct rtcdate (0950), which you will provide as an argument to cmostime as a pointer.