int fault(uintptr addr, int read) { Segment *s; char *sps; if(up == nil) panic("fault: nil up"); if(up->nlocks.ref) print("fault: addr %#p: nlocks %ld\n", addr, up->nlocks.ref); sps = up->psstate; up->psstate = "Fault"; spllo(); m->pfault++; for(;;) { s = seg(up, addr, 1); /* leaves s->lk qlocked if seg != nil */ if(s == 0) { up->psstate = sps; return -1; } if(!read && (s->type&SG_RONLY)) { qunlock(&s->lk); up->psstate = sps; return -1; } if(fixfault(s, addr, read, 1) == 0) /* qunlocks s->lk */ break; } up->psstate = sps; return 0; }
void trap(void *pc, int type) { uint32_t fsr; void *addr; if (up == nil) { printf("Trapped with an unknown process!\n"); panic("Probably an in kernel problem.\n"); } switch(type) { case ABORT_INTERRUPT: irqhandler(); return; /* Note the return. */ case ABORT_INSTRUCTION: printf("%i bad instruction at 0x%h\n", up->pid, pc); break; case ABORT_PREFETCH: if (fixfault((void *) pc)) { return; } printf("%i prefetch abort 0x%h\n", up->pid, pc); break; case ABORT_DATA: addr = faultaddr(); fsr = fsrstatus() & 0xf; switch (fsr) { case 0x5: /* section translation */ case 0x7: /* page translation */ /* Try add page */ if (fixfault(addr)) { return; } break; case 0x0: /* vector */ case 0x1: /* alignment */ case 0x3: /* also alignment */ case 0x2: /* terminal */ case 0x4: /* external linefetch section */ case 0x6: /* external linefetch page */ case 0x8: /* external non linefetch section */ case 0xa: /* external non linefetch page */ case 0x9: /* domain section */ case 0xb: /* domain page */ case 0xc: /* external translation l1 */ case 0xe: /* external translation l2 */ case 0xd: /* section permission */ case 0xf: /* page permission */ default: break; } printf("%i data abort 0x%h (type 0x%h)\n", up->pid, addr, fsr); break; } printf("kill proc %i (trap %i, at 0x%h)\n", up->pid, type, pc); procexit(up, -1); schedule(); /* Never reached */ }