diff options
author | Frans Kaashoek <[email protected]> | 2019-07-02 14:19:31 -0400 |
---|---|---|
committer | Frans Kaashoek <[email protected]> | 2019-07-02 14:19:31 -0400 |
commit | 1e4d7065d6582fd57d251dfe405afbbe68a55309 (patch) | |
tree | f5ba795c113d04f43fd49744d04519aeef3df4ef /kernel/trap.c | |
parent | 84c759fc02c7843b64a1bafc843cd80fe3c9d7ee (diff) | |
parent | f59c1bf1d82da4b445c1cff10c228ea55fa035d4 (diff) | |
download | xv6-labs-1e4d7065d6582fd57d251dfe405afbbe68a55309.tar.gz xv6-labs-1e4d7065d6582fd57d251dfe405afbbe68a55309.tar.bz2 xv6-labs-1e4d7065d6582fd57d251dfe405afbbe68a55309.zip |
Merge branch 'riscv' into riscv-proc
Diffstat (limited to 'kernel/trap.c')
-rw-r--r-- | kernel/trap.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/kernel/trap.c b/kernel/trap.c index 6c0d04b..018b7db 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -37,7 +37,7 @@ void usertrap(void) { int which_dev = 0; - + if((r_sstatus() & SSTATUS_SPP) != 0) panic("usertrap: not from user mode"); @@ -49,8 +49,6 @@ usertrap(void) // save user program counter. p->tf->epc = r_sepc(); - - intr_on(); if(r_scause() == 8){ // system call @@ -59,11 +57,15 @@ usertrap(void) // but we want to return to the next instruction. p->tf->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 } else { - printf("usertrap(): unexpected scause 0x%p pid=%d\n", r_scause(), p->pid); + 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; } @@ -121,12 +123,14 @@ usertrapret(void) ((void (*)(uint64,uint64))TRAMPOLINE)(TRAMPOLINE - PGSIZE, satp); } -// interrupts and exceptions from kernel code go here, +// interrupts and exceptions from kernel code go here via kernelvec, // on whatever the current kernel stack is. // must be 4-byte aligned to fit in stvec. void kerneltrap() { + int which_dev = 0; + uint64 sepc = r_sepc(); uint64 sstatus = r_sstatus(); uint64 scause = r_scause(); @@ -135,11 +139,20 @@ kerneltrap() if(intr_get() != 0) panic("kerneltrap: interrupts enabled"); - if(devintr() == 0){ - printf("scause 0x%p\n", scause); + if((which_dev = devintr()) == 0){ + printf("scause %p\n", scause); printf("sepc=%p stval=%p\n", r_sepc(), r_stval()); panic("kerneltrap"); } + + // give up the CPU if this is a timer interrupt. + if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING) + yield(); + + // the yield() may have caused some traps to occur, + // so restore trap registers for use by kernelvec.S's sepc instruction. + w_sepc(sepc); + w_sstatus(sstatus); } // check if it's an external interrupt or software interrupt, |