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("%p\n", *(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=%d\n", r_scause(), p->pid);
        printf("            sepc=%p stval=%p\n", 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=%d\n", r_scause(), p->pid);
        printf("            sepc=%p stval=%p\n", r_sepc(), r_stval());
        p->killed = 1;
    }
    

你可能感兴趣的:(6.S081,Lab,linux)