Now we can study the C part of handling interrupts. But before we start remember that we need to install stack pointers to appropriate modes:
1void
2trapinit(void)
3{
4 Vpage0 *vpage0;
5 /* set up the exception vectors */
6 vpage0 = (Vpage0*)HVECTORS;
7 memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
8 memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
9
10 setr13(PsrMfiq, m->fiqstack+nelem(m->fiqstack));
11 setr13(PsrMirq, m->irqstack+nelem(m->irqstack));
12 setr13(PsrMabt, m->abtstack+nelem(m->abtstack));
13 setr13(PsrMund, m->undstack+nelem(m->undstack));
14}
1TEXT setr13(SB), $-4
2 MOVW 4(FP), R1
3 MOVW CPSR, R2
4 BIC $PsrMask, R2, R3
5 ORR R0, R3
6 MOVW R3, CPSR /* switch to new mode */
7 MOVW SP, R0 /* return old sp */
8 MOVW R1, SP /* install new one */
9 MOVW R2, CPSR /* switch back to old mode */
10 RET
Have a look at *trap(Ureg ). First worth to check that kernel stack is not overflow, otherwise we have no choice than “death screen”:
1int rem, itype;
2
3if(up != nil)
4 rem = ((char*)ureg)-up->kstack;
5else rem = ((char*)ureg)-(char*)m->stack;
6
7if(ureg->type != PsrMfiq && rem < 256) {
8 panic("trap %d stack bytes remaining (%s), "\
9 "up=#%8.8lux ureg=#%8.8lux pc=#%8.8ux"
10 ,rem, up?up->text:"", up, ureg, ureg->pc);
11 for(;;);
12}
(Later we can use delay() and reboot() in such case to prevent frozing)
Adjust ureg->pc
1itype = ureg->type;
2/* All interrupts/exceptions should be resumed at ureg->pc-4,
3 except for Data Abort which resumes at ureg->pc-8. */
4if(itype == PsrMabt+1)
5 ureg->pc -= 8;
6else ureg->pc -= 4;
7
8if(up){
9 up->pc = ureg->pc;
10 up->dbgreg = ureg;
11}
Now we can have a switch of type. Break from switch will mean kernel panic:
1 default:
2faultpanic:
3 setpanic();
4 dumpregs(ureg);
5 panic("exception %uX %s\n", ureg->type, trapname(ureg->type));
6 break;
7 }
All cases:
1 switch(itype) {
2 case PsrMirq:
3 t = m->ticks; /* CPU time per proc */
4 up = nil; /* no process at interrupt level */
5
6 //todo:irq(ureg);
7
8 up = m->proc;
9 preemption(m->ticks - t);
10 break;
11
12 case PsrMund:
13 panic("Undefined instruction");
14 if(*(ulong*)ureg->pc == BREAK && breakhandler) {
15 int s;
16 Proc *p;
17
18 p = up;
19 s = breakhandler(ureg, p);
20 if(s == BrkSched) {
21 p->preempted = 0;
22 sched();
23 } else if(s == BrkNoSched) {
24 /* stop it being preempted until next instruction */
25 p->preempted = 1;
26 if(up)
27 up->dbgreg = 0;
28 return;
29 }
30 break;
31 }
32 if(up == nil) goto faultpanic;
33 spllo();
34 if(waserror()) {
35 if(waslo(ureg->psr) && up->type == Interp)
36 disfault(ureg, up->env->errstr);
37 setpanic();
38 dumpregs(ureg);
39 panic("%s", up->env->errstr);
40 }
41// if(!fpiarm(ureg)) {
42// dumpregs(ureg);
43// sys_trap_error(ureg->type);
44// }
45 poperror();
46 break;
47
48 case PsrMsvc: /* Jump through 0 or SWI */
49 if(waslo(ureg->psr) && up && up->type == Interp) {
50 spllo();
51 dumpregs(ureg);
52 sys_trap_error(ureg->type);
53 }
54 setpanic();
55 dumpregs(ureg);
56 panic("SVC/SWI exception");
57 break;
58
59 case PsrMabt: /* Prefetch abort */
60 if(catchdbg && catchdbg(ureg, 0))
61 break;
62 /* FALL THROUGH */
63 case PsrMabt+1: /* Data abort */
64 if(waslo(ureg->psr) && up && up->type == Interp) {
65 spllo();
66 faultarm(ureg);
67 }
68 print("Data Abort\n");
69 /* FALL THROUGH */
Check booting that nothing is broken:
## Starting application at 0x00008000 ...
Entered main() at 00009074 with SP=00002FE8
Clearing Mach: 00002000-00002060
Clearing edata: 00065708-0006C830
Conf: top=134217728, npage0=32659, ialloc=26750976, nproc=735
ARM 0 MHz id 410fb767
Inferno OS Fourth Edition (20121207) Vita Nuova
to inifinite loop
FILES: