summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/kernelvec.S2
-rw-r--r--kernel/trap.c17
2 files changed, 15 insertions, 4 deletions
diff --git a/kernel/kernelvec.S b/kernel/kernelvec.S
index 4f52688..e9b0ced 100644
--- a/kernel/kernelvec.S
+++ b/kernel/kernelvec.S
@@ -47,7 +47,7 @@ kernelvec:
ld ra, 0(sp)
ld sp, 8(sp)
ld gp, 16(sp)
- ld tp, 24(sp)
+ // not this, in case we moved CPUs: ld tp, 24(sp)
ld t0, 32(sp)
ld t1, 40(sp)
ld t2, 48(sp)
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,