MIT 6.S081---Lab: traps

小知识

qemu打印page table

ctrl a + c
info mem

RISC-V assembly (easy)

  • Which registers contain arguments to functions? For example, which register holds 13 in main’s call to printf?

汇编代码如下图所示(可参考RISC-V常用汇编指令):
MIT 6.S081---Lab: traps_第1张图片
可以从代码第45~47行代码可以看出,main函数调用printf系统调用时传入的参数是通过a0 ~ a2 来传入的。

  • 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.)

函数f的汇编代码在上图的第26~35行;而函数g的汇编代码位于第13~22行,经过对比代码一模一样,其原因是函数f在调用函数g时编译器采用了inline的方式直接将g函数内联展开了,节省了一次函数调用的时间。

  • At what address is the function printf located?

根据第50行代码可得,printf的地址为ra+1536=pc+1536
(ra是当前pc指针的值)

  • What value is in the register ra just after the jalr to printf in main?

由于ra会存放函数的返回地址,所以此时应该是等于pc+4

  • Run the following code.
    unsigned int i = 0x00646c72;
    printf(“H%x Wo%s”, 57616, &i);
    What is the output? Here’s an ASCII table that maps bytes to characters.

最终输出为:
在这里插入图片描述

  • 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? Would you need to change 57616 to a different value?

大端序的话地址需要以字节为一组进行翻转,即改为0x726c6400,而57616不用改,因为编译器会让它以正确的形式展示出来。

  • 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);

    结果如下:
    在这里插入图片描述
    可见y可能是一个随机的值,一个没有被初始化过的未定义的值。

Backtrace (moderate)

  1. 修改kernel/riscv.h,添加r_fp函数,通过内联汇编的方式获取s0寄存器的值:
static inline uint64
r_fp()
{
  uint64 x;
  asm volatile("mv %0, s0" : "=r" (x) );
  return x;
}
  1. 修改kernel/printf.c,新建函数backtrace(),并在sys_sleep内进行调用:
void backtrace() {
  uint64 sp = r_fp();
  uint64 edge = PGROUNDUP(sp);
  printf("backtrace:\n");
  while (sp != edge) {
    printf("%p\n", *((uint64*)(sp - 8)));
    sp = *((uint64*)(sp - 16));
  }
}
  1. 在kernel/defs.h中新增backtrace函数定义:
void            backtrace(void);
  1. 在kernel/sysproc.c中的sys_sleep函数中调用backtrace():
    MIT 6.S081---Lab: traps_第2张图片

测试结果如下:
MIT 6.S081---Lab: traps_第3张图片
MIT 6.S081---Lab: traps_第4张图片
能work之后,将其加入到kernel/printf中的panic函数中:
MIT 6.S081---Lab: traps_第5张图片

Alarm (hard)

test0: invoke handler

  1. 修改kernel/proc.h,在struct proc中添加三个字段:
    MIT 6.S081---Lab: traps_第6张图片

  2. 修改kernel/sysproc.c,新增系统调用函数sys_sigalarm和sys_sigreturn:

int 
sys_sigalarm(void) 
{
  int n;
  uint64 addr;
  if (argint(0, &n) < 0 || argaddr(1, &addr))
    return -1;
  struct proc* mp = myproc();
  mp->elaps_ticks = 0;
  mp->target_ticks = n;
  mp->fn = (void(*)(void))addr;
  return 0;
}

int 
sys_sigreturn(void)
{
  return 0;
}
  1. 修改user/usys.pl,新增sigalarm:
    MIT 6.S081---Lab: traps_第7张图片

  2. 修改kernel/syscall.c,新增系统调用:
    MIT 6.S081---Lab: traps_第8张图片
    MIT 6.S081---Lab: traps_第9张图片

  3. 修改kernel/syscall.h:
    MIT 6.S081---Lab: traps_第10张图片

  4. 修改user/user.h,添加函数原型:
    MIT 6.S081---Lab: traps_第11张图片

  5. 修改kernel/trap.c:
    MIT 6.S081---Lab: traps_第12张图片

  6. 修改kernel/proc.c中的allocproc函数:
    MIT 6.S081---Lab: traps_第13张图片
    运行结果如下:
    MIT 6.S081---Lab: traps_第14张图片

test1/test2(): resume interrupted code

  1. 修改kernel/proc.h,新增字段:
    MIT 6.S081---Lab: traps_第15张图片

  2. 修改kernel/sysproc.c:
    MIT 6.S081---Lab: traps_第16张图片

  3. 修改kernel/trap.c中的usertrap函数:
    MIT 6.S081---Lab: traps_第17张图片

  4. 修改kernel/proc.c中的allocproc函数: MIT 6.S081---Lab: traps_第18张图片
    MIT 6.S081---Lab: traps_第19张图片

和freeproc函数:
MIT 6.S081---Lab: traps_第20张图片

测试结果如下:
MIT 6.S081---Lab: traps_第21张图片

你可能感兴趣的:(#,6.S081,android,linux,c语言,操作系统)