diff options
author | Robert Morris <[email protected]> | 2019-06-11 09:57:14 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-06-11 09:57:14 -0400 |
commit | 5753553213df8f9de851adb68377db43faecb91f (patch) | |
tree | 3b629ff54897fca414146677532cb459a2ed11ba /trap.c | |
parent | 91ba81110acd3163f7de3580b677eece0c57f5e7 (diff) | |
download | xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.gz xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.bz2 xv6-labs-5753553213df8f9de851adb68377db43faecb91f.zip |
separate source into kernel/ user/ mkfs/
Diffstat (limited to 'trap.c')
-rw-r--r-- | trap.c | 184 |
1 files changed, 0 insertions, 184 deletions
@@ -1,184 +0,0 @@ -#include "types.h" -#include "param.h" -#include "memlayout.h" -#include "riscv.h" -#include "proc.h" -#include "spinlock.h" -#include "defs.h" - -struct spinlock tickslock; -uint ticks; - -extern char trampout[], trampin[]; - -// in kernelvec.S, calls kerneltrap(). -void kernelvec(); - -extern int devintr(); - -void -trapinit(void) -{ - initlock(&tickslock, "time"); -} - -// set up to take exceptions and traps while in the kernel. -void -trapinithart(void) -{ - w_stvec((uint64)kernelvec); -} - -// -// handle an interrupt, exception, or system call from user space. -// called from trampoline.S -// -void -usertrap(void) -{ - int which_dev = 0; - - if((r_sstatus() & SSTATUS_SPP) != 0) - panic("usertrap: not from user mode"); - - // send interrupts and exceptions to kerneltrap(), - // since we're now in the kernel. - w_stvec((uint64)kernelvec); - - struct proc *p = myproc(); - - // save user program counter. - p->tf->epc = r_sepc(); - - intr_on(); - - if(r_scause() == 8){ - // system call - - // sepc points to the ecall instruction, - // but we want to return to the next instruction. - p->tf->epc += 4; - - syscall(); - } else if((which_dev = devintr()) != 0){ - // ok - } else { - 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; - } - - if(p->killed) - exit(); - - // give up the CPU if this is a timer interrupt. - if(which_dev == 2) - yield(); - - usertrapret(); -} - -// -// return to user space -// -void -usertrapret(void) -{ - struct proc *p = myproc(); - - // turn off interrupts, since we're switching - // now from kerneltrap() to usertrap(). - intr_off(); - - // send interrupts and exceptions to trampoline.S - w_stvec(TRAMPOLINE + (trampin - trampout)); - - // set up values that trampoline.S will need when - // the process next re-enters the kernel. - p->tf->kernel_satp = r_satp(); - p->tf->kernel_sp = (uint64)p->kstack + PGSIZE; - p->tf->kernel_trap = (uint64)usertrap; - p->tf->hartid = r_tp(); - - // set up the registers that trampoline.S's sret will use - // to get to user space. - - // set S Previous Privilege mode to User. - unsigned long x = r_sstatus(); - x &= ~SSTATUS_SPP; // clear SPP to 0 for user mode - x |= SSTATUS_SPIE; // enable interrupts in user mode - w_sstatus(x); - - // set S Exception Program Counter to the saved user pc. - w_sepc(p->tf->epc); - - // tell trampline.S the user page table to switch to. - uint64 satp = MAKE_SATP(p->pagetable); - - // jump to trampoline.S at the top of memory, which - // switches to the user page table, restores user registers, - // and switches to user mode with sret. - ((void (*)(uint64,uint64))TRAMPOLINE)(TRAMPOLINE - PGSIZE, satp); -} - -// interrupts and exceptions from kernel code go here, -// on whatever the current kernel stack is. -// must be 4-byte aligned to fit in stvec. -void -kerneltrap() -{ - uint64 sstatus = r_sstatus(); - uint64 scause = r_scause(); - - if((sstatus & SSTATUS_SPP) == 0) - panic("kerneltrap: not from supervisor mode"); - if(intr_get() != 0) - panic("kerneltrap: interrupts enabled"); - - if(devintr() == 0){ - printf("scause 0x%p\n", scause); - printf("sepc=%p stval=%p\n", r_sepc(), r_stval()); - panic("kerneltrap"); - } -} - -// check if it's an external interrupt or software interrupt, -// and handle it. -// returns 2 if timer interrupt, -// 1 if other device, -// 0 if not recognized. -int -devintr() -{ - uint64 scause = r_scause(); - - if((scause & 0x8000000000000000L) && - (scause & 0xff) == 9){ - // supervisor external interrupt, via PLIC. - int irq = plic_claim(); - - if(irq == UART0_IRQ){ - uartintr(); - } - - plic_complete(irq); - return 1; - } else if(scause == 0x8000000000000001){ - // software interrupt from a machine-mode timer interrupt. - - if(cpuid() == 0){ - acquire(&tickslock); - ticks++; - wakeup(&ticks); - release(&tickslock); - } - - // acknowledge. - w_sip(r_sip() & ~2); - - return 2; - } else { - return 0; - } -} - |