1/* 2 * arm exception handlers 3 */ 4#include "arm.s" 5 6/* 7 * exception vectors, copied by trapinit() to somewhere useful 8 */ 9TEXT vectors(SB), 1, $-4 10 MOVW 0x18(R15), R15 /* reset */ 11 MOVW 0x18(R15), R15 /* undefined instr. */ 12 MOVW 0x18(R15), R15 /* SWI & SMC */ 13 MOVW 0x18(R15), R15 /* prefetch abort */ 14 MOVW 0x18(R15), R15 /* data abort */ 15 MOVW 0x18(R15), R15 /* reserved */ 16 MOVW 0x18(R15), R15 /* IRQ */ 17 MOVW 0x18(R15), R15 /* FIQ */ 18 19TEXT vtable(SB), 1, $-4 20 WORD $_vsvc(SB) /* reset, in svc mode already */ 21 WORD $_vund(SB) /* undefined, switch to svc mode */ 22 WORD $_vsvc(SB) /* swi, in svc mode already */ 23 WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */ 24 WORD $_vdabt(SB) /* data abort, switch to svc mode */ 25 WORD $_vsvc(SB) /* reserved */ 26 WORD $_virq(SB) /* IRQ, switch to svc mode */ 27 WORD $_vfiq(SB) /* FIQ, switch to svc mode */ 28 29TEXT _vsvc(SB), 1, $-4 /* SWI */ 30 MOVW.W R14, -4(R13) /* ureg->pc = interrupted PC */ 31 MOVW SPSR, R14 /* ureg->psr = SPSR */ 32 MOVW.W R14, -4(R13) /* ... */ 33 MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */ 34 MOVW.W R14, -4(R13) /* ... */ 35 36 /* avoid the ambiguity described in notes/movm.w. */ 37 MOVM.DB.S [R0-R14], (R13) /* save user level registers */ 38 SUB $(15*4), R13 /* r13 now points to ureg */ 39 40 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ 41 42// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */ 43 MOVW $(MACHADDR), R10 /* m */ 44 MOVW 8(R10), R9 /* up */ 45 46 MOVW R13, R0 /* first arg is pointer to ureg */ 47 SUB $8, R13 /* space for argument+link */ 48 49 BL syscall(SB) 50 51 ADD $(8+4*15), R13 /* make r13 point to ureg->type */ 52 MOVW 8(R13), R14 /* restore link */ 53 MOVW 4(R13), R0 /* restore SPSR */ 54 MOVW R0, SPSR /* ... */ 55 MOVM.DB.S (R13), [R0-R14] /* restore registers */ 56 ADD $8, R13 /* pop past ureg->{type+psr} */ 57 RFE /* MOVM.IA.S.W (R13), [R15] */ 58 59TEXT _vund(SB), 1, $-4 /* undefined */ 60 MOVM.IA [R0-R4], (R13) /* free some working space */ 61 MOVW $PsrMund, R0 62 B _vswitch 63 64TEXT _vpabt(SB), 1, $-4 /* prefetch abort */ 65 MOVM.IA [R0-R4], (R13) /* free some working space */ 66 MOVW $PsrMabt, R0 /* r0 = type */ 67 B _vswitch 68 69TEXT _vdabt(SB), 1, $-4 /* data abort */ 70 MOVM.IA [R0-R4], (R13) /* free some working space */ 71 MOVW $(PsrMabt+1), R0 /* r0 = type */ 72 B _vswitch 73 74TEXT _virq(SB), 1, $-4 /* IRQ */ 75 MOVM.IA [R0-R4], (R13) /* free some working space */ 76 MOVW $PsrMirq, R0 /* r0 = type */ 77 B _vswitch 78 79 /* 80 * come here with type in R0 and R13 pointing above saved [r0-r4]. 81 * we'll switch to SVC mode and then call trap. 82 */ 83_vswitch: 84 MOVW SPSR, R1 /* save SPSR for ureg */ 85 MOVW R14, R2 /* save interrupted pc for ureg */ 86 MOVW R13, R3 /* save pointer to where the original [R0-R4] are */ 87 88 /* 89 * switch processor to svc mode. this switches the banked registers 90 * (r13 [sp] and r14 [link]) to those of svc mode. 91 */ 92 MOVW CPSR, R14 93 BIC $PsrMask, R14 94 ORR $(PsrDirq|PsrMsvc), R14 95 MOVW R14, CPSR /* switch! */ 96 97 AND.S $0xf, R1, R4 /* interrupted code kernel or user? */ 98 BEQ _userexcep 99 100 /* here for trap from SVC mode */ 101 MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */ 102 MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */ 103 104 /* 105 * avoid the ambiguity described in notes/movm.w. 106 * In order to get a predictable value in R13 after the stores, 107 * separate the store-multiple from the stack-pointer adjustment. 108 * We'll assume that the old value of R13 should be stored on the stack. 109 */ 110 /* save kernel level registers, at end r13 points to ureg */ 111 MOVM.DB [R0-R14], (R13) 112 SUB $(15*4), R13 /* SP now points to saved R0 */ 113 114 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ 115 116 MOVW R13, R0 /* first arg is pointer to ureg */ 117 SUB $(4*2), R13 /* space for argument+link (for debugger) */ 118 MOVW $0xdeaddead, R11 /* marker */ 119 120 BL trap(SB) 121 122 ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */ 123 MOVW 8(R13), R14 /* restore link */ 124 MOVW 4(R13), R0 /* restore SPSR */ 125 MOVW R0, SPSR /* ... */ 126 127 MOVM.DB (R13), [R0-R14] /* restore registers */ 128 129 ADD $(4*2), R13 /* pop past ureg->{type+psr} to pc */ 130 RFE /* MOVM.IA.S.W (R13), [R15] */ 131 132 /* here for trap from USER mode */ 133_userexcep: 134 MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */ 135 MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */ 136 137 /* avoid the ambiguity described in notes/movm.w. */ 138 MOVM.DB.S [R0-R14], (R13) /* save kernel level registers */ 139 SUB $(15*4), R13 /* r13 now points to ureg */ 140 141 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ 142 143// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */ 144 MOVW $(MACHADDR), R10 /* m */ 145 MOVW 8(R10), R9 /* up */ 146 147 MOVW R13, R0 /* first arg is pointer to ureg */ 148 SUB $(4*2), R13 /* space for argument+link (for debugger) */ 149 150 BL trap(SB) 151 152 ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */ 153 MOVW 8(R13), R14 /* restore link */ 154 MOVW 4(R13), R0 /* restore SPSR */ 155 MOVW R0, SPSR /* ... */ 156 MOVM.DB.S (R13), [R0-R14] /* restore registers */ 157 ADD $(4*2), R13 /* pop past ureg->{type+psr} */ 158 RFE /* MOVM.IA.S.W (R13), [R15] */ 159 160TEXT _vfiq(SB), 1, $-4 /* FIQ */ 161 MOVW $PsrMfiq, R8 /* trap type */ 162 MOVW SPSR, R9 /* interrupted psr */ 163 MOVW R14, R10 /* interrupted pc */ 164 MOVM.DB.W [R8-R10], (R13) /* save in ureg */ 165 MOVM.DB.W.S [R0-R14], (R13) /* save interrupted regs */ 166 MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ 167 MOVW $(MACHADDR), R10 /* m */ 168 MOVW 8(R10), R9 /* up */ 169 MOVW R13, R0 /* first arg is pointer to ureg */ 170 SUB $(4*2), R13 /* space for argument+link (for debugger) */ 171 172 BL fiq(SB) 173 174 ADD $(8+4*15), R13 /* make r13 point to ureg->type */ 175 MOVW 8(R13), R14 /* restore link */ 176 MOVW 4(R13), R0 /* restore SPSR */ 177 MOVW R0, SPSR /* ... */ 178 MOVM.DB.S (R13), [R0-R14] /* restore registers */ 179 ADD $8, R13 /* pop past ureg->{type+psr} */ 180 RFE /* MOVM.IA.S.W (R13), [R15] */ 181 182/* 183 * set the stack value for the mode passed in R0 184 */ 185TEXT setr13(SB), 1, $-4 186 MOVW 4(FP), R1 187 188 MOVW CPSR, R2 189 BIC $PsrMask, R2, R3 190 ORR R0, R3 191 MOVW R3, CPSR /* switch to new mode */ 192 193 MOVW R13, R0 /* return old sp */ 194 MOVW R1, R13 /* install new one */ 195 196 MOVW R2, CPSR /* switch back to old mode */ 197 RET 198