1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 .file "trap.s" 13 14 #include <sys/asm_linkage.h> 15 #include <sys/cpu_asm.h> 16 17 /* 18 * Create a section into which to place the exception vector, such that we can 19 * force it to be mapped where it needs to be. 20 * 21 * Each instruction in the vector jumps to its own address + 24, which is the 22 * matching entry in exception_table. We do this to insure that we get 23 * effectively infinite displacement, which we can't achieve in one 24 * instruction otherwise (and gas complains). 25 * 26 * The handler for each exception type saves a trap frame (struct regs, though 27 * with some bits unusual) and calls the associated handler from trap_table. 28 * 29 * XXX: On CPUs with the security extensions, there are actually 2 additional 30 * exception vectors: secure, and monitor. We ignore them. 31 */ 32 .pushsection ".exception_vector", "ax" 33 ldr pc, [pc, #24] 34 ldr pc, [pc, #24] 35 ldr pc, [pc, #24] 36 ldr pc, [pc, #24] 37 ldr pc, [pc, #24] 38 ldr pc, [pc, #24] 39 ldr pc, [pc, #24] 40 ldr pc, [pc, #24] 41 .exception_table: 42 .word handle_reset /* Reset */ 43 .word handle_undef /* Undefined insn */ 44 .word handle_svc /* Supervisor Call */ 45 .word handle_prefetchabt /* Prefetch abort */ 46 .word handle_dataabt /* Data abort */ 47 .word 0x00000014 /* Reserved (infinite loops) */ 48 .word handle_irq /* IRQ */ 49 .word handle_fiq /* FIQ */ 50 .popsection 51 52 /* Clobbers r0 */ 53 #define CALL_HANDLER(scratch, trapno) \ 54 ldr scratch, =(trap_table + (4 * trapno)); \ 55 ldr scratch, [scratch]; \ 56 cmp scratch, #0; \ 57 beq 1f; \ 58 mov r0, sp; /* Pass our saved frame to the handler */ \ 59 blx scratch; /* Call the handler */ \ 60 1: 61 62 /* 63 * XXX: Note that we go to some contortions here to save in 'struct regs' style. 64 * 65 * This includes saving our own lr/spsr, for our own return _and_ saving them 66 * into the 'struct regs', and doing the register save unusually such that we 67 * get the 'struct regs' in order. 68 * 69 * Depending on the exact nature of 'struct regs', perhaps we should be 70 * bending it to our will, rather than letting it bend us? 71 * 72 * XXX: Note also that we're saving the current registers assuming that we 73 * came from supervisor mode. We should probably be saving the banked 74 * registers based on the mode in the spsr. (or we'll screw up when nested, 75 * or when userland traps, or...) 76 */ 77 #define PUSH_TRAP_FRAME(scratch) \ 78 srsdb sp!, #(CPU_MODE_SVC); /* Save lr and spsr for ourselves */ \ 79 cps #(CPU_MODE_SVC); \ 80 ldr lr, [sp]; /* Get lr back for the trap frame */ \ 81 sub sp, sp, #(4 * 17); /* Space for all our registers */ \ 82 stmia sp, {r0-r14}; /* XXX: Note we don't save pc */ \ 83 ldr scratch, [sp, #(4 * 18)]; /* skip 17 regs and the lr */ \ 84 str scratch, [sp, #(4 * 16)]; 85 86 #define POP_TRAP_FRAME_AND_RET() \ 87 ldmia sp, {r0-r14}; \ 88 add sp, sp, #(4 * 19); /* 17 regs + 2 for lr and spsr */ \ 89 rfedb sp; /* Return */ 90 91 /* 92 * XXX: None of these handlers are even vaguely aware that usermode exists, 93 * and make no effort to do the traditional things we would probably do on 94 * returning to user mode. They will need to be rethought at such a time 95 */ 96 .globl trap_table 97 98 #define DEFINE_HANDLER(name, code) \ 99 ENTRY(name) \ 100 PUSH_TRAP_FRAME(r0) \ 101 CALL_HANDLER(r1, code) \ 102 POP_TRAP_FRAME_AND_RET() \ 103 SET_SIZE(name) 104 105 DEFINE_HANDLER(handle_reset, ARM_EXCPT_RESET) 106 107 /* 108 * XXX: Note that in practice, if we use this for emulation, things 109 * might look pretty different, but I think that giving the handler the 110 * entire real frame which we restore gives us the flexibility to do it 111 * this way. 112 */ 113 DEFINE_HANDLER(handle_undef, ARM_EXCPT_UNDINS) 114 115 DEFINE_HANDLER(handle_svc, ARM_EXCPT_SVC) 116 DEFINE_HANDLER(handle_prefetchabt, ARM_EXCPT_PREFETCH) 117 DEFINE_HANDLER(handle_dataabt, ARM_EXCPT_DATA) 118 119 /* 120 * XXX: These assume that we really want vectored interrupts, and thus that 121 * we'll only ever see these if something went wrong (we took a 122 * non-vectored interrupt 123 * 124 * They may need extension (to pull info from the PIC this early, or 125 * whatever.) if we choose to use non-vectored interrupts. 126 */ 127 DEFINE_HANDLER(handle_irq, ARM_EXCPT_IRQ) 128 DEFINE_HANDLER(handle_fiq, ARM_EXCPT_FIQ)