summaryrefslogtreecommitdiff
path: root/kernel/trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trap.c')
-rw-r--r--kernel/trap.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/kernel/trap.c b/kernel/trap.c
index 586f123..06fc4b3 100644
--- a/kernel/trap.c
+++ b/kernel/trap.c
@@ -121,12 +121,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 +137,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,