summaryrefslogtreecommitdiff
path: root/trap.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-06-04 14:20:37 -0400
committerRobert Morris <[email protected]>2019-06-04 14:20:37 -0400
commita82772594e1807632b3650bff111108f250de3b7 (patch)
tree98581a6fa9bfd5ecbabe8052b112c4166c7f9e9e /trap.c
parentcff3ce6e04ce4a353324630df788df21566807a6 (diff)
downloadxv6-labs-a82772594e1807632b3650bff111108f250de3b7.tar.gz
xv6-labs-a82772594e1807632b3650bff111108f250de3b7.tar.bz2
xv6-labs-a82772594e1807632b3650bff111108f250de3b7.zip
timer interrupts -> supervisor software interrupt
Diffstat (limited to 'trap.c')
-rw-r--r--trap.c59
1 files changed, 48 insertions, 11 deletions
diff --git a/trap.c b/trap.c
index 47739ac..e17f8fe 100644
--- a/trap.c
+++ b/trap.c
@@ -14,6 +14,8 @@ extern char trampout[], trampin[];
// in kernelvec.S, calls kerneltrap().
void kernelvec();
+extern int devintr();
+
void
trapinit(void)
{
@@ -22,6 +24,8 @@ trapinit(void)
// set up to take exceptions and traps while in the kernel.
w_stvec((uint64)kernelvec);
+ // time, cycle, instret CSRs
+
initlock(&tickslock, "time");
}
@@ -39,6 +43,10 @@ usertrap(void)
// since we're now in the kernel.
w_stvec((uint64)kernelvec);
+ //printf("mtimecmp %x mtime %x\n", *(uint64*)CLINT_MTIMECMP0, *(uint64*)CLINT_MTIME);
+
+ *(uint64*)CLINT_MTIMECMP0 = *(uint64*)CLINT_MTIME + 10000;
+
struct proc *p = myproc();
// save user program counter.
@@ -54,8 +62,10 @@ usertrap(void)
p->tf->epc += 4;
syscall();
+ } else if(devintr()){
+ // ok
} else {
- printf("usertrap(): unexpected scause 0x%x pid=%d\n", r_scause(), p->pid);
+ printf("usertrap(): unexpected scause 0x%p pid=%d\n", r_scause(), p->pid);
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
p->killed = 1;
}
@@ -120,6 +130,28 @@ kerneltrap()
if((sstatus & SSTATUS_SPP) == 0)
panic("kerneltrap: not from supervisor mode");
+ if(devintr() == 0){
+ printf("scause 0x%p\n", scause);
+ printf("sepc=%p stval=%p\n", r_sepc(), r_stval());
+ panic("kerneltrap");
+ }
+
+ // turn off interrupts to ensure we
+ // return with the correct sstatus.
+ intr_off();
+
+ // restore previous interrupt status.
+ w_sstatus(sstatus);
+}
+
+// check if it's an external interrupt or software interrupt,
+// and handle it.
+// returns 1 if handled, 0 if not recognized.
+int
+devintr()
+{
+ uint64 scause = r_scause();
+
if((scause & 0x8000000000000000L) &&
(scause & 0xff) == 9){
// supervisor external interrupt, via PLIC.
@@ -132,16 +164,21 @@ kerneltrap()
}
plic_complete(irq);
+ return 1;
+ } else if(scause == 0x8000000000000001){
+ // software interrupt from a machine-mode timer interrupt.
+
+ acquire(&tickslock);
+ ticks++;
+ wakeup(&ticks);
+ release(&tickslock);
+
+ // acknowledge.
+ w_sip(r_sip() & ~2);
+
+ return 1;
} else {
- printf("scause 0x%p\n", scause);
- printf("sepc=%p stval=%p\n", r_sepc(), r_stval());
- panic("kerneltrap");
+ return 0;
}
-
- // turn off interrupts to ensure we
- // return with the correct sstatus.
- intr_off();
-
- // restore previous interrupt status.
- w_sstatus(sstatus);
}
+