diff options
author | Mole Shang <[email protected]> | 2024-02-11 14:41:35 +0800 |
---|---|---|
committer | Mole Shang <[email protected]> | 2024-02-11 14:41:35 +0800 |
commit | 48a5e34fcd07852b4a68825ce8e37feb6f6d04d7 (patch) | |
tree | b6ec41ca1889db0122d754b0083c7d1d87cb0818 | |
parent | 3673a2cdfb30e1e3936e695a3fb8adee74488d6b (diff) | |
download | xv6-labs-traps.tar.gz xv6-labs-traps.tar.bz2 xv6-labs-traps.zip |
lab traps: finishtraps
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | answers-traps.txt | 6 | ||||
-rw-r--r-- | kernel/defs.h | 1 | ||||
-rw-r--r-- | kernel/printf.c | 17 | ||||
-rw-r--r-- | kernel/proc.c | 19 | ||||
-rw-r--r-- | kernel/proc.h | 5 | ||||
-rw-r--r-- | kernel/riscv.h | 9 | ||||
-rw-r--r-- | kernel/syscall.c | 6 | ||||
-rw-r--r-- | kernel/sysproc.c | 26 | ||||
-rw-r--r-- | kernel/trap.c | 23 | ||||
-rw-r--r-- | user/user.h | 2 | ||||
-rwxr-xr-x | user/usys.pl | 2 |
12 files changed, 116 insertions, 3 deletions
@@ -208,7 +208,8 @@ endif ifeq ($(LAB),traps) UPROGS += \ $U/_call\ - $U/_bttest + $U/_bttest\ + $U/_alarmtest endif ifeq ($(LAB),lazy) diff --git a/answers-traps.txt b/answers-traps.txt new file mode 100644 index 0000000..dbb40f1 --- /dev/null +++ b/answers-traps.txt @@ -0,0 +1,6 @@ +a0~a7, a2 +0x26 (optimized during compile time), 0x14 (inline, unfolded) +0x666 +0x38 (next instruction) +He110 World +the value in register a2 diff --git a/kernel/defs.h b/kernel/defs.h index bd85d1f..04a0276 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -82,6 +82,7 @@ int pipewrite(struct pipe*, uint64, int); void printf(char*, ...); void panic(char*) __attribute__((noreturn)); void printfinit(void); +void backtrace(void); // proc.c int cpuid(void); diff --git a/kernel/printf.c b/kernel/printf.c index 1a50203..509c1c5 100644 --- a/kernel/printf.c +++ b/kernel/printf.c @@ -122,6 +122,8 @@ panic(char *s) printf("panic: "); printf(s); printf("\n"); + backtrace(); + panicked = 1; // freeze uart output from other CPUs for(;;) ; @@ -133,3 +135,18 @@ printfinit(void) initlock(&pr.lock, "pr"); pr.locking = 1; } + +void +backtrace(void) +{ + uint64 fp = r_fp(); + printf("backtrace:\n"); + uint64 stackpg = PGROUNDDOWN(fp); + // Whereever fp points to should always live in the stack page + while(PGROUNDDOWN(fp) == stackpg){ + // print the return addr (stored in fp-8) + printf("%p\n", *(uint64 *)(fp-8)); + // load previous (upper stack) fp + fp = *(uint64 *)(fp-16); + } +} diff --git a/kernel/proc.c b/kernel/proc.c index 3d215a5..9a9bae9 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -39,6 +39,7 @@ proc_mapstacks(pagetable_t kpgtbl) if(pa == 0) panic("kalloc"); uint64 va = KSTACK((int) (p - proc)); + p->alarm_tickspassed = 0; kvmmap(kpgtbl, va, (uint64)pa, PGSIZE, PTE_R | PTE_W); } } @@ -140,6 +141,17 @@ found: } p->usyscall->pid = p->pid; + // reset sigalarm props + p->alarm_interval = 0; + p->alarm_handler = 0; + p->alarm_tickspassed = 0; + p->alarm_caninvoke = 1; + if((p->atpfm = (struct trapframe *)kalloc()) == 0){ + freeproc(p); + release(&p->lock); + return 0; + } + // An empty user page table. p->pagetable = proc_pagetable(p); if(p->pagetable == 0){ @@ -171,6 +183,13 @@ freeproc(struct proc *p) p->usyscall = 0; if(p->pagetable) proc_freepagetable(p->pagetable, p->sz); + if(p->atpfm) + kfree((void*)p->atpfm); + p->atpfm = 0; + p->alarm_interval = 0; + p->alarm_handler = 0; + p->alarm_tickspassed = 0; + p->alarm_caninvoke = 1; p->pagetable = 0; p->sz = 0; p->pid = 0; diff --git a/kernel/proc.h b/kernel/proc.h index c816ae2..a195b02 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -106,4 +106,9 @@ struct proc { struct file *ofile[NOFILE]; // Open files struct inode *cwd; // Current directory char name[16]; // Process name (debugging) + int alarm_interval; // sigalarm syscall interval + uint64 alarm_handler; // sigalarm syscall handler + int alarm_tickspassed; // record how many ticks passed since last sigalarm handler call + int alarm_caninvoke; // prevent re-entrant calls to handler + struct trapframe *atpfm; // trapframe to resume after handling, must hold p->lock }; diff --git a/kernel/riscv.h b/kernel/riscv.h index 33fa9ee..5ede50a 100644 --- a/kernel/riscv.h +++ b/kernel/riscv.h @@ -327,6 +327,15 @@ sfence_vma() asm volatile("sfence.vma zero, zero"); } +// read the frame pointer of currently executing func +static inline uint64 +r_fp() +{ + uint64 x; + asm volatile("mv %0, s0" : "=r" (x) ); + return x; +} + typedef uint64 pte_t; typedef uint64 *pagetable_t; // 512 PTEs diff --git a/kernel/syscall.c b/kernel/syscall.c index 394b980..8392eb4 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -110,6 +110,8 @@ extern uint64 sys_connect(void); #ifdef LAB_PGTBL extern uint64 sys_pgaccess(void); #endif +extern uint64 sys_sigalarm(void); +extern uint64 sys_sigreturn(void); // An array mapping syscall numbers from syscall.h // to the function that handles the system call. @@ -143,6 +145,8 @@ static uint64 (*syscalls[])(void) = { #endif [SYS_trace] sys_trace, [SYS_sysinfo] sys_sysinfo, +[SYS_sigalarm] sys_sigalarm, +[SYS_sigreturn] sys_sigreturn, }; // syscall name maps for SYS_trace: @@ -176,6 +180,8 @@ static char *syscall_names[] = { #endif [SYS_trace] "trace", [SYS_sysinfo] "sysinfo", +[SYS_sigalarm] "sigalarm", +[SYS_sigreturn] "sigreturn", }; diff --git a/kernel/sysproc.c b/kernel/sysproc.c index bd9d0f0..fac1d83 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -65,6 +65,9 @@ sys_sleep(void) } sleep(&ticks, &tickslock); } + + backtrace(); + release(&tickslock); return 0; } @@ -124,3 +127,26 @@ sys_sysinfo(void) return sys_info(si); } +uint64 +sys_sigalarm(void) +{ + struct proc *p = myproc(); + uint64 handler; + + argint(0, &p->alarm_interval); + argaddr(1, &handler); + p->alarm_handler = handler; + + return 0; +} + +uint64 sys_sigreturn(void) +{ + struct proc *p = myproc(); + // retore saved trapframe to resume + memmove(p->trapframe, p->atpfm, sizeof(struct trapframe)); + p->alarm_tickspassed = 0; + p->alarm_caninvoke = 1; + // make sure return the original a0 in trapframe to pass test3 + return p->trapframe->a0; +} diff --git a/kernel/trap.c b/kernel/trap.c index 512c850..eb8009f 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -6,6 +6,12 @@ #include "proc.h" #include "defs.h" +/* + * Always remember that RISC-V disables interrupts when it starts to take a trap, + * so there's no need to call intr_off() at the beginning of trap handling. + * Reference: xv6-riscv-book 4.5 + */ + struct spinlock tickslock; uint ticks; @@ -76,9 +82,22 @@ usertrap(void) if(killed(p)) exit(-1); - // give up the CPU if this is a timer interrupt. - if(which_dev == 2) + if(which_dev == 2){ + // timer interrupt + if(p->alarm_interval > 0 && p->alarm_caninvoke){ + // record sigalarm + p->alarm_tickspassed++; + if(p->alarm_tickspassed == p->alarm_interval){ + // store original trapframe in p->atpfm + memmove(p->atpfm, p->trapframe, sizeof(struct trapframe)); + p->alarm_tickspassed = 0; + p->alarm_caninvoke = 0; + p->trapframe->epc = p->alarm_handler; + } + } + // give up the CPU. yield(); + } usertrapret(); } diff --git a/user/user.h b/user/user.h index a076f37..34591fd 100644 --- a/user/user.h +++ b/user/user.h @@ -33,6 +33,8 @@ int ugetpid(void); #endif int trace(int); int sysinfo(struct sysinfo*); +int sigalarm(int ticks, void (*handler)()); +int sigreturn(void); // ulib.c int stat(const char*, struct stat*); diff --git a/user/usys.pl b/user/usys.pl index f084c63..33af0ad 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -40,3 +40,5 @@ entry("trace"); entry("sysinfo"); entry("connect"); entry("pgaccess"); +entry("sigalarm"); +entry("sigreturn"); |