This lab explores how system calls are implemented using traps.
Part 1 Assembly
This part is a warm-up exercise to let you know a little more about Risc-v Assemble.
Part 2 Backtrace
A helper function in kernel . BackTrace helps us to print a list of functions calls on the stack. According to the hints ,we do it step by step. Using the r-tp to get the frame pointer of the current stack frame .
Note that the return address lives at a fixed offset (-8) from the frame pointer of a stack frame, and that the saved frame pointer lives at fixed offset (-16) from the frame pointer.
The operation on the pointer.
Xv6 allocates one page for each stack in the xv6 kernel at PAGE-aligned address. If the fp not satisfied the one PGSIZE , the fp will at the bottom of the call stack
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// lab4 part2 // backtrace voidbacktrace(void) { uint64 * currentfp = (uint64 *)r_fp(); uint64 up ; uint64 down ; do { printf("%p\n", *(currentfp-1)); currentfp = (uint64*)(*(currentfp-2)); up = PGROUNDUP((uint64)currentfp); down = PGROUNDDOWN((uint64)currentfp); } while (up-down==PGSIZE); }
Part 3 Alarm
In this part , we want to add two system call to xv6 .
Once in user code we invoke system call , The mode will convert from user mode - > kernel mode .`` ecall->usertrap->usertrapret->sret, after exiting the kernel mode ,thepcwill jump to thep->tramframe->epcwhich saves thesepc. So we know when to callhandlerfunction (time interrupt) , afterinterrupt we need to jump thehandlerfunction ,which means we fix the value inp->tramframe->epc` .
The function pointer aka the address of the function ,aka the value of epc.
In user code , we invoke sigalarm. In this system call implementation, we need to save the interval and function pointer in proc structure , an return user code , the p->tramfram->epc will be the next of ecall.
When we have a timer interrupt ,we need the epc be the function pointer , for resuming the interrupted user code . Because usually we return the interrupted user code, this time ,we need to jump tohandler function ,we need to reserve the p->tramframe->* and change the p->tramframe->epc be the function pointer . In handler function ,we invoke sigreturn system call. In this implementation , we restore the saved registers when interrupted ,and jump to the original p->tramframe->epc resume the user code .
perimission is similar likely Non-reentrant function, we set the permission flag to forbid the entrant of the handler function of signal.