1. Which registers contain arguments to functions? a0 ~ a7 For example, which register holds 13 in main's call to printf? a2 2. Where is the call to function f in the assembly code for main? Where is the call to g? (Hint: the compiler may inline functions.) 26: 45b1 li a1,12 12 = 11 + 1 = g(8) + 1 = f(8) + 1 3. At what address is the function printf located? 30: 00000097 auipc ra,0x0 34: 612080e7 jalr 1554(ra) thus the address should be 0x30 + 1554(0x612) = 0x642 4. What value is in the register ra just after the jalr to printf in main? 0x38(0x34 + 4) 5. Run the following code. unsigned int i = 0x00646c72; printf("H%x Wo%s", 57616, &i); What is the output? He110 World The output depends on that fact that the RISC-V is little-endian. If the RISC-V were instead big-endian what would you set i to in order to yield the same output? unsigned int i = 0x726c6400; Would you need to change 57616 to a different value? No 6. In the following code, what is going to be printed after 'y='? (note: the answer is not a specific value.) Why does this happen? printf("x=%d y=%d", 3); a rubbish value(actually that is left in register a2 at the time printf is called.)
Backtrace
Implement a backtrace() function in kernel/printf.c. Insert a call to this function in sys_sleep, and then run bttest, which calls sys_sleep.
In this exercise you’ll add a feature to xv6 that periodically alerts a process as it uses CPU time. This might be useful for compute-bound processes that want to limit how much CPU time they chew up, or for processes that want to compute but also want to take some periodic action. More generally, you’ll be implementing a primitive form of user-level interrupt/fault handlers; you could use something similar to handle page faults in the application, for example. Your solution is correct if it passes alarmtest and ‘usertests -q’
这部分是该实验的重头戏,需要对特权级转换时的机制足够了解。首先扩充结构体 proc 的定义:
1 2 3 4 5 6
... int ticks; // Ticks since the last call int interval; // Interval for SIGALARM uint64 handler; // Handler for SIGALARM struct trapframe *trapframe_dup; // copy of the trapframe uint8 uie; // user interrupt enable
if(which_dev == 2) { if (p->interval) { p->ticks++; if (p->ticks >= p->interval) { if (p->uie) { // If the user interrupt is enabled // reset ticks, copy the trapframe and trap to the handler // finally set uie to 0(disable user interrupt) p->ticks = 0; *(p->trapframe_dup) = *(p->trapframe); // save the trapframe p->trapframe->epc = p->handler; p->uie = 0; } else { // If the user interrupt is not enabled // don't da anything(waiting for the user call sigreturn) // actually it return to the user program } } } yield(); }