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常用汇编指令):

可以从代码第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():
    在这里插入图片描述

测试结果如下:
在这里插入图片描述
在这里插入图片描述
能work之后,将其加入到kernel/printf中的panic函数中:
在这里插入图片描述

Alarm (hard)

test0: invoke handler

  1. 修改kernel/proc.h,在struct proc中添加三个字段:
    在这里插入图片描述

  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:
    在这里插入图片描述

  2. 修改kernel/syscall.c,新增系统调用:
    在这里插入图片描述
    在这里插入图片描述

  3. 修改kernel/syscall.h:
    在这里插入图片描述

  4. 修改user/user.h,添加函数原型:
    在这里插入图片描述

  5. 修改kernel/trap.c:
    在这里插入图片描述

  6. 修改kernel/proc.c中的allocproc函数:
    在这里插入图片描述
    运行结果如下:
    在这里插入图片描述

test1/test2(): resume interrupted code

  1. 修改kernel/proc.h,新增字段:
    在这里插入图片描述

  2. 修改kernel/sysproc.c:
    在这里插入图片描述

  3. 修改kernel/trap.c中的usertrap函数:
    在这里插入图片描述

  4. 修改kernel/proc.c中的allocproc函数: 在这里插入图片描述
    在这里插入图片描述

和freeproc函数:
在这里插入图片描述

测试结果如下:
在这里插入图片描述

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值