diff options
author | Robert Morris <[email protected]> | 2019-06-04 14:20:37 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-06-04 14:20:37 -0400 |
commit | a82772594e1807632b3650bff111108f250de3b7 (patch) | |
tree | 98581a6fa9bfd5ecbabe8052b112c4166c7f9e9e /trap.c | |
parent | cff3ce6e04ce4a353324630df788df21566807a6 (diff) | |
download | xv6-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.c | 59 |
1 files changed, 48 insertions, 11 deletions
@@ -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); } + |