我是靠谱客的博主 英勇滑板,最近开发中收集的这篇文章主要介绍MIT6.S081 Lab4: Trap,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

RISC-V assembly(easy)

  1. a0-a7. a2

  2. 无函数调用

  3. 位于0x630

  4. ra中是0x00

  5. 输出为 He110 World,如果是大段存储,i应该为0x726c64,57616不需要改

Backtrace(moderate)

  1. kernel/defs.h中添加函数声明void backtrace(void)

  2. kernel/riscv.h中添加以下字段:

    // get frame pointer
    static inline uint64
    r_fp()
    {
    uint64 x;
    asm volatile("mv %0, s0" : "=r" (x));
    return x;
    }
    
  3. kernel/printf.h中定义backtrace函数:

    void
    backtrace(void) {
    uint64 fp = r_fp();
    uint64 end = PGROUNDUP(fp); // end >= fp
    printf("backtrace:n");
    while(fp != end) {
    printf("%pn", *(uint64*)((char*)fp-8));
    fp = *(uint64*)((void*)fp-16);
    }
    }
    
  4. kernel/sysproc.csys_sleep函数中增加字段:

    uint64
    sys_sleep(void)
    {
    int n;
    uint ticks0;
    backtrace(); // ←←←←←←←←
    if(argint(0, &n) < 0)
    return -1;
    acquire(&tickslock);
    ticks0 = ticks;
    while(ticks - ticks0 < n){
    if(myproc()->killed){
    release(&tickslock);
    return -1;
    }
    sleep(&ticks, &tickslock);
    }
    release(&tickslock);
    return 0;
    }
    

Alarm(Hard)

test0: invoke handler

  1. Makefile中增加字段:

    UPROGS=
    $U/_cat
    $U/_echo
    $U/_forktest
    $U/_grep
    $U/_init
    $U/_kill
    $U/_ln
    $U/_ls
    $U/_mkdir
    $U/_rm
    $U/_sh
    $U/_stressfs
    $U/_usertests
    $U/_grind
    $U/_wc
    $U/_zombie
    $U/_alarmtest # ←←←←←←←←
    
  2. user/user.h中增加字段:

    int sigalarm(int, void (*)(void));
    int sigreturn(void);
    
  3. user/usys.pl中增加字段:

    entry("sigalarm");
    entry("sigreturn");
    
  4. kernel/syscall.hkernel/syscall.c中增加字段:

    #define SYS_sigalarm 22
    #define SYS_sigreturn 23
    
    extern uint64 sys_sigalarm(void);
    extern uint64 sys_sigreturn(void);
    
    [SYS_sigalarm] sys_sigalarm,
    [SYS_sigreturn]
    sys_sigreturn,
    
  5. kernel/proc.h中的struct proc结构增加字段:

    int alarm;
    int count;
    uint64 callback;
    
  6. kernel/proc.c中给allocproc函数增加字段:

    p->alarm = 0;
    p->count = 0;
    p->callback = 0;
    
  7. kernel/sysproc.c中增加sigalarmsigreturn函数定义:

    uint64 sys_sigalarm(void) {
    int arg1;
    uint64 arg2;
    struct proc* p = myproc();
    if(argint(0, &arg1) < 0)
    return -1;
    if(argaddr(1, &arg2) < 0)
    return -1;
    p->alarm = arg1;
    p->callback = arg2;
    return 0;
    }
    uint64 sys_sigreturn(void) {
    return 0;
    }
    
  8. kernel/trap.c中增加字段:

    if(r_scause() == 8){
    // system call
    if(p->killed)
    exit(-1);
    // sepc points to the ecall instruction,
    // but we want to return to the next instruction.
    p->trapframe->epc += 4;
    // an interrupt will change sstatus &c registers,
    // so don't enable until done with those registers.
    intr_on();
    syscall();
    } else if((which_dev = devintr()) != 0){
    // ok
    // ↓↓↓↓↓↓↓↓
    if(which_dev == 2) {
    if(p->alarm) {
    p->count = (p->count+1) % p->alarm;
    if(!p->count){
    p->trapframe->epc = p->callback;
    }
    }
    }
    // ↑↑↑↑↑↑↑↑
    } else {
    printf("usertrap(): unexpected scause %p pid=%dn", r_scause(), p->pid);
    printf("
    sepc=%p stval=%pn", r_sepc(), r_stval());
    p->killed = 1;
    }
    

test1/test2(): resume interrupted code

  1. kernel/def.h增加函数声明void savetrapframe(struct trapframe*, struct trapframe*),声明结构体struct trapframe

  2. kernel/trap.c中增加函数定义:

    void savetrapframe(struct trapframe* dst, struct trapframe* src) {
    dst->epc = src->epc;
    dst->kernel_hartid = src->kernel_hartid;
    dst->kernel_satp = src->kernel_satp;
    dst->kernel_sp = src->kernel_sp;
    dst->kernel_trap = src->kernel_trap;
    dst->a0 = src->a0;
    dst->a1 = src->a1;
    dst->a2 = src->a2;
    dst->a3 = src->a3;
    dst->a4 = src->a4;
    dst->a5 = src->a5;
    dst->a6 = src->a6;
    dst->a7 = src->a7;
    dst->ra = src->ra;
    dst->sp = src->sp;
    dst->gp = src->gp;
    dst->tp = src->tp;
    dst->t0 = src->t0;
    dst->t1 = src->t1;
    dst->t2 = src->t2;
    dst->t3 = src->t3;
    dst->t4 = src->t4;
    dst->t5 = src->t5;
    dst->t6 = src->t6;
    dst->s0 = src->s0;
    dst->s1 = src->s1;
    dst->s2 = src->s2;
    dst->s3 = src->s3;
    dst->s4 = src->s4;
    dst->s5 = src->s5;
    dst->s6 = src->s6;
    dst->s7 = src->s7;
    dst->s8 = src->s8;
    dst->s9 = src->s9;
    dst->s10 = src->s10;
    dst->s11 = src->s11;
    }
    
  3. kernel/proc.h中的struct proc结构增加字段:

    struct trapframe *trapframe_dup; // a context copy
    int callback_once_flag;
    
  4. kernel/proc.c中的allocprocfreeproc函数增加字段:

    // Allocate a trapframe_dup page.
    if((p->trapframe_dup = (struct trapframe *)kalloc()) == 0){
    release(&p->lock);
    return 0;
    }
    p->callback_once_flag = 0;
    
    if(p->trapframe_dup)
    kfree((void*)p->trapframe_dup);
    p->trapframe_dup = 0;
    
  5. 修改sigreturnusertrap函数:

    uint64 sys_sigreturn(void) {
    struct proc* p = myproc();
    savetrapframe(p->trapframe, p->trapframe_dup);
    p->callback_once_flag = 0;
    return 0;
    }
    
    if(r_scause() == 8){
    // system call
    if(p->killed)
    exit(-1);
    // sepc points to the ecall instruction,
    // but we want to return to the next instruction.
    p->trapframe->epc += 4;
    // an interrupt will change sstatus &c registers,
    // so don't enable until done with those registers.
    intr_on();
    syscall();
    } else if((which_dev = devintr()) != 0){
    // ok
    if(which_dev == 2) {
    if(p->alarm && !p->callback_once_flag) {
    p->count = (p->count+1) % p->alarm;
    if(!p->count){
    savetrapframe(p->trapframe_dup, p->trapframe);
    p->callback_once_flag = 1;
    p->trapframe->epc = p->callback;
    }
    }
    }
    } else {
    printf("usertrap(): unexpected scause %p pid=%dn", r_scause(), p->pid);
    printf("
    sepc=%p stval=%pn", r_sepc(), r_stval());
    p->killed = 1;
    }
    

最后

以上就是英勇滑板为你收集整理的MIT6.S081 Lab4: Trap的全部内容,希望文章能够帮你解决MIT6.S081 Lab4: Trap所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部