首页 > 其他分享 >【XV6】 traps

【XV6】 traps

时间:2024-02-14 19:12:02浏览次数:23  
标签:uint64 fp traps backtrace void XV6 trapframe alarmtest

代码:https://github.com/JasenChao/xv6-labs.git

backtrace

题目要求实现backtrace来对堆栈上调用发生错误的地方进行跟踪。寄存器s0包含指向当前堆栈帧的指针,那么返回地址就位于帧指针的固定偏移量-8,前一个fp地址的偏移量为-16。

riscv.h文件中增加提示中的代码:

static inline uint64
r_fp()
{
    uint64 x;
    asm volatile("mv %0, s0" : "=r" (x) );
    return x;
}

printf.c文件中实现backtrace()函数:

void
backtrace(void)
{
    uint64 fp = r_fp();
    uint64 high = PGROUNDUP(fp), low = PGROUNDDOWN(fp);
    printf("backtrace:\n");
    while(fp >= low && fp < high)
    {
      printf("%p\n", *((uint64*)(fp - 8)));
      fp = *((uint64*)(fp - 16));
    }
}

defs.h文件中增加函数声明void backtrace(void)

测试程序是运行sleep函数调用backtrace,因此在sysproc.c文件中的sys_sleep函数末尾调用backtrace()

使用make GRADEFLAGS=backtrace grade测试结果是否正确。

alarm

题目要求基于给出的alarmtest函数,实现两个系统调用sigalarmsigreturn,在程序消耗n个ticks之后调用处理程序。

首先在Makefile中添加测试程序$U/_alarmtest\

user.h中添加声明,同样在usys.plsyscall.hsyscall.c中添加相应的内容:

// user.h
int sigalarm(int ticks, void (*handler)());
int sigreturn(void);

// usys.pl
entry("sigalarm");
entry("sigreturn");

// syscall.h
#define SYS_sigalarm 22
#define SYS_sigreturn 23

// syscall.c
extern uint64 sys_sigalarm(void);
extern uint64 sys_sigreturn(void);

static uint64 (*syscalls[])(void) = {
...
[SYS_sigalarm]   sys_sigalarm,
[SYS_sigreturn]   sys_sigreturn,
};

proc.h中的struct proc中增加成员:

struct trapframe *pre_trapframe;
int interval;                // 触发alarm的中断数量
int ticks;                   // 时钟中断数量
uint64 handler;              // 处理alarm的函数地址

为了让pre_trapframe保存上一个trapframe,需要对proc.c中的allocprocfreeproc进行修改:

// allocproc
if((p->pre_trapframe = (struct trapframe *)kalloc()) == 0){
  freeproc(p);
  release(&p->lock);
  return 0;
}

// freeproc
if(p->pre_trapframe)
  kfree((void*)p->pre_trapframe);
p->pre_trapframe = 0;

sysproc.c文件中实现sigalarmsigreturn函数:

uint64
sys_sigalarm(void){
  int interval;
  uint64 f_addr;
  struct proc *p = myproc();

  argint(0,&interval);
  argaddr(1,&f_addr);
  // 保存触发次数和函数地址
  p->interval = interval;
  p->handler = f_addr;
  p->ticks = 0;  

  return 0;
}

uint64
sys_sigreturn(void){
  struct proc* p = myproc();
  *p->trapframe = *p->pre_trapframe;
  p->ticks = 0;
  return p->pre_trapframe->a0;
}

修改trap.c中的usertrap函数,当触发时间中断时进行判断,如果满足触发次数则执行触发函数:

// give up the CPU if this is a timer interrupt.
if(which_dev == 2) {
  p->ticks++;
  if(p->ticks == p->interval && 0 < p->interval) {
    *p->pre_trapframe = *p->trapframe;
    p->trapframe->epc = p->handler;
  } else {
    yield();
  }
}

使用make GRADEFLAGS=alarmtest grade命令测试是否通过。

测试结果

使用make grade测试,结果如下:

== Test backtrace test ==
$ make qemu-gdb
backtrace test: OK (1.6s)
== Test running alarmtest ==
$ make qemu-gdb
(3.6s)
== Test   alarmtest: test0 ==
  alarmtest: test0: OK
== Test   alarmtest: test1 ==
  alarmtest: test1: OK
== Test   alarmtest: test2 ==
  alarmtest: test2: OK
== Test   alarmtest: test3 ==
  alarmtest: test3: OK
== Test usertests ==
$ make qemu-gdb
usertests: OK (39.9s)

这部分题目太难了,参考了 https://zhuanlan.zhihu.com/p/624606664 的大神详解。

标签:uint64,fp,traps,backtrace,void,XV6,trapframe,alarmtest
From: https://www.cnblogs.com/JasenChao/p/18015449

相关文章

  • 【XV6】 file system
    代码:https://github.com/JasenChao/xv6-labs.git支持大文件XV6目前只支持268个blocks大小的文件,一个block(BSIZE)为1024,文件块inode包含12个一级地址和1个二级地址,二级地址指向另一个block,其中存放了256个一级地址,因此一共是268个。题目要求支持大文件(65803个blocks),提示通过三级......
  • 【XV6】 locks
    代码:https://github.com/JasenChao/xv6-labs.git内存分配器单个空闲内存列表可能引起多个CPU的频繁锁争用,题目要求设计内存分配器,让每个CPU维护一个空闲内存列表,不同CPU的分配和释放可以并行执行,但如果一个CPU可用列表为空,而其他CPU可用列表不为空,则这个CPU必须窃取其他CPU的空......
  • 【XV6】 networking
    代码:https://github.com/JasenChao/xv6-labs.gitE1000网络设备驱动题目已经在kernel/e1000.c中给出了E1000的初始化函数和发送接收函数,要求完善发送和接收的功能。其他相关的代码,上层的网络协议在kernel/net.c和kernel/net.h中。PCI总线上搜索网卡的代码在kernel/pci.c中://t......
  • [MIT 6.S081] Lab: Copy-on-Write Fork for xv6
    Lab:Copy-on-WriteForkforxv6在这个实验中,我们要为xv6实现cowfork。Implementcopy-onwrite根据写时复制的方式,我们在复制页面的时候应该采用的是将父级的物理页面映射到子级的页面,因此我们需要修改kernel/vm.c中的uvmcopy,将页面复制修改为映射的方式,同时应当将......
  • MIT 6.1810 Lab: Copy-on-Write Fork for xv6
    lab网址:https://pdos.csail.mit.edu/6.828/2022/labs/cow.htmlxv6Book:https://pdos.csail.mit.edu/6.828/2022/xv6/book-riscv-rev3.pdfImplementcopy-on-writefork这部分需要我们实现写时拷贝,题目给出解决方案为,当fork时,将父子进程的页表项都设置为只度,当发生写错误时,在处......
  • [MIT 6.S081] Lab: xv6 lazy page allocation
    Lab:xv6lazypageallocationEliminateallocationfromsbrk()这一步比较简单,直接在sys_sbrk中将分配内存改为对内存大小进行修改而不分配内存即可。uint64sys_sbrk(void){intaddr;intn;if(argint(0,&n)<0)return-1;addf=myproc()->sz;my......
  • MIT 6.1810 Lab: traps
    lab网址:https://pdos.csail.mit.edu/6.828/2022/labs/traps.htmlxv6Book:https://pdos.csail.mit.edu/6.828/2022/xv6/book-riscv-rev3.pdf写前思考我们都知道,在用户进程执行系统调用时,内核代替用户进程执行,那么这种代替是一种什么样的代替。这个过程是还属于用户进程,只是执......
  • [MIT 6.S081] Lab: traps
    Lab:trapsRISC-Vassembly在这个任务中我们需要观察call.asm汇编。intg(intx){0: 1141 addi sp,sp,-162: e422 sd s0,8(sp)4: 0800 addi s0,sp,16returnx+3;}6: 250d addiw a0,a0......
  • xv6book阅读 chapter3
    页表是硬件提供进程间隔离的方法之一,并通过它来实现虚拟地址和物理地址之间的转换,通过页表可以决定进程能够访问物理内存的哪些部分,xv6提供了一些小技巧,比如在不同的地址空间中可以映射相同的trampolinepage,trampoline是用来辅助用户模式进入内核模式的,所以它可被共用。1分页硬......
  • [MIT 6.S081] Lab: Xv6 and Unix utilities
    Lab:Xv6andUnixutilitiesGradesleepsleep格式如下sleep5这边需要使用kernal/stat.h中的sleep系统调用,并将参数转化为传入。#include"kernel/types.h"#include"kernel/stat.h"#include"user/user.h"intmain(intargc,char*argv[]){if(......