sfence.vma zero, zero
csrw satp, a0
sfence.vma zero, zero
li a0, TRAPFRAME
ld a0, 112(a0)
sret
addi sp, sp, -256
// set up to take exceptions and traps while in the kernel.
void
trapinithart(void)
{
w_stvec((uint64)kernelvec);
}
void
kerneltrap()
{
int which_dev = 0;
uint64 sepc = r_sepc();
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((which_dev = devintr()) == 0){
// interrupt or trap from an unknown source
printf("scause=0x%lx sepc=0x%lx stval=0x%lx\n", scause, r_sepc(), r_stval());
panic("kerneltrap");
}
// give up the CPU if this is a timer interrupt.
if(which_dev == 2 && myproc() != 0)
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);
}
if((r_sstatus() & SSTATUS_SPP) != 0)
panic("usertrap: not from user mode");
w_stvec((uint64)kernelvec);
struct proc *p = myproc();
// save user program counter.
p->trapframe->epc = r_sepc();
if(r_scause() == 8){
// system call
if(killed(p))
exit(-1);
// sepc points to the ecall instruction,
// but we want to return to the next instruction.
p->trapframe->epc += 4;
// an interrupt will change sepc, scause, and sstatus,
// so enable only now that we're done with those registers.
intr_on();
syscall();
} else if((which_dev = devintr()) != 0){
// ok
} else if (r_scause() == 15){
uint64 va = r_stval();
printf("page fault %p\n", (void *)va);
uint64 ka = (uint64) kalloc();
if (ka == 0){
p->killed = 1;
} else {
memset((char*)ka, 0, PGSIZE);
va = PGROUNDDOWN(va);
if (mappages(p->pagetable, va, PGSIZE, ka, PTE_W | PTE_U | PTE_R) != 0){
kfree((void*)ka);
p->killed = 1;
}
}
} else {
printf("usertrap(): unexpected scause 0x%lx pid=%d\n", r_scause(), p->pid);
printf(" sepc=0x%lx stval=0x%lx\n", r_sepc(), r_stval());
setkilled(p);
}