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->trapframe->epc = r_sepc();
if(r_scause() == 8){
// system call
if(p->killed)
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 sstatus &c registers,
// so don't enable until done with those registers.
intr_on();
syscall();
} else if((which_dev = devintr()) != 0){
// ok
} else if(r_scause() == 15 || r_scause() == 13) {
// char *mem;
// uint64 errAddr = r_stval();
// mem = (char *)kalloc();
// if(mem == 0) {
// printf("usertrap:kalloc()");
// p->killed = 1;
// } else if(errAddr < p->sz){
// memset(mem,0,PGSIZE);
// uint64 va = PGROUNDDOWN(errAddr);
// if(mappages(p->pagetable, va, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){
// kfree(mem);
// printf("usertrap(): mappages\n");
// p->killed = 1;
// }
// } else {
// p->killed = 1;
// kfree(mem);
// printf("usertrap(): unknow error\n");
// }
char *mem;
uint64 errAddr = r_stval();
if(errAddr < p->sz && PGROUNDUP(p->trapframe->sp) - 1 < errAddr && (mem = kalloc()) != 0) {
memset(mem,0,PGSIZE);
uint64 va = PGROUNDDOWN(errAddr);
if(mappages(p->pagetable, va, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){
kfree(mem);
printf("usertrap(): mappages\n");
p->killed = 1;
}
} else {
p->killed = 1;
}
}else {
printf("usertrap(): unexpected scause %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(-1);
// give up the CPU if this is a timer interrupt.
if(which_dev == 2)
yield();
usertrapret();
}