1/*- 2 * Copyright (c) 2014 Andrew Turner 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <machine/asm.h> 29#include <machine/armreg.h> 30__FBSDID("$FreeBSD$"); 31 32#include "assym.inc" 33 34 .text 35 36.macro save_registers el 37.if \el == 1 38 mov x18, sp 39 sub sp, sp, #128 40.endif 41 sub sp, sp, #(TF_SIZE + 16) 42 stp x29, x30, [sp, #(TF_SIZE)] 43 stp x28, x29, [sp, #(TF_X + 28 * 8)] 44 stp x26, x27, [sp, #(TF_X + 26 * 8)] 45 stp x24, x25, [sp, #(TF_X + 24 * 8)] 46 stp x22, x23, [sp, #(TF_X + 22 * 8)] 47 stp x20, x21, [sp, #(TF_X + 20 * 8)] 48 stp x18, x19, [sp, #(TF_X + 18 * 8)] 49 stp x16, x17, [sp, #(TF_X + 16 * 8)] 50 stp x14, x15, [sp, #(TF_X + 14 * 8)] 51 stp x12, x13, [sp, #(TF_X + 12 * 8)] 52 stp x10, x11, [sp, #(TF_X + 10 * 8)] 53 stp x8, x9, [sp, #(TF_X + 8 * 8)] 54 stp x6, x7, [sp, #(TF_X + 6 * 8)] 55 stp x4, x5, [sp, #(TF_X + 4 * 8)] 56 stp x2, x3, [sp, #(TF_X + 2 * 8)] 57 stp x0, x1, [sp, #(TF_X + 0 * 8)] 58 mrs x10, elr_el1 59 mrs x11, spsr_el1 60 mrs x12, esr_el1 61.if \el == 0 62 mrs x18, sp_el0 63.endif 64 str x10, [sp, #(TF_ELR)] 65 stp w11, w12, [sp, #(TF_SPSR)] 66 stp x18, lr, [sp, #(TF_SP)] 67 mrs x18, tpidr_el1 68 add x29, sp, #(TF_SIZE) 69.endm 70 71.macro restore_registers el 72.if \el == 1 73 msr daifset, #2 74 /* 75 * Disable interrupts, x18 may change in the interrupt exception 76 * handler. For EL0 exceptions, do_ast already did this. 77 */ 78.endif 79 ldp x18, lr, [sp, #(TF_SP)] 80 ldp x10, x11, [sp, #(TF_ELR)] 81.if \el == 0 82 msr sp_el0, x18 83.endif 84 msr spsr_el1, x11 85 msr elr_el1, x10 86 ldp x0, x1, [sp, #(TF_X + 0 * 8)] 87 ldp x2, x3, [sp, #(TF_X + 2 * 8)] 88 ldp x4, x5, [sp, #(TF_X + 4 * 8)] 89 ldp x6, x7, [sp, #(TF_X + 6 * 8)] 90 ldp x8, x9, [sp, #(TF_X + 8 * 8)] 91 ldp x10, x11, [sp, #(TF_X + 10 * 8)] 92 ldp x12, x13, [sp, #(TF_X + 12 * 8)] 93 ldp x14, x15, [sp, #(TF_X + 14 * 8)] 94 ldp x16, x17, [sp, #(TF_X + 16 * 8)] 95.if \el == 0 96 /* 97 * We only restore the callee saved registers when returning to 98 * userland as they may have been updated by a system call or signal. 99 */ 100 ldp x18, x19, [sp, #(TF_X + 18 * 8)] 101 ldp x20, x21, [sp, #(TF_X + 20 * 8)] 102 ldp x22, x23, [sp, #(TF_X + 22 * 8)] 103 ldp x24, x25, [sp, #(TF_X + 24 * 8)] 104 ldp x26, x27, [sp, #(TF_X + 26 * 8)] 105 ldp x28, x29, [sp, #(TF_X + 28 * 8)] 106.else 107 ldr x29, [sp, #(TF_X + 29 * 8)] 108.endif 109.if \el == 0 110 add sp, sp, #(TF_SIZE + 16) 111.else 112 mov sp, x18 113 mrs x18, tpidr_el1 114.endif 115.endm 116 117.macro do_ast 118 mrs x19, daif 119 /* Make sure the IRQs are enabled before calling ast() */ 120 bic x19, x19, #PSR_I 1211: 122 /* Disable interrupts */ 123 msr daifset, #2 124 125 /* Read the current thread flags */ 126 ldr x1, [x18, #PC_CURTHREAD] /* Load curthread */ 127 ldr x2, [x1, #TD_FLAGS] 128 129 /* Check if we have either bits set */ 130 mov x3, #((TDF_ASTPENDING|TDF_NEEDRESCHED) >> 8) 131 lsl x3, x3, #8 132 and x2, x2, x3 133 cbz x2, 2f 134 135 /* Restore interrupts */ 136 msr daif, x19 137 138 /* handle the ast */ 139 mov x0, sp 140 bl _C_LABEL(ast) 141 142 /* Re-check for new ast scheduled */ 143 b 1b 1442: 145.endm 146 147ENTRY(handle_el1h_sync) 148 save_registers 1 149 ldr x0, [x18, #PC_CURTHREAD] 150 mov x1, sp 151 bl do_el1h_sync 152 restore_registers 1 153 eret 154END(handle_el1h_sync) 155 156ENTRY(handle_el1h_irq) 157 save_registers 1 158 mov x0, sp 159 bl intr_irq_handler 160 restore_registers 1 161 eret 162END(handle_el1h_irq) 163 164ENTRY(handle_el0_sync) 165 save_registers 0 166 ldr x0, [x18, #PC_CURTHREAD] 167 mov x1, sp 168 str x1, [x0, #TD_FRAME] 169 bl do_el0_sync 170 do_ast 171 restore_registers 0 172 eret 173END(handle_el0_sync) 174 175ENTRY(handle_el0_irq) 176 save_registers 0 177 mov x0, sp 178 bl intr_irq_handler 179 do_ast 180 restore_registers 0 181 eret 182END(handle_el0_irq) 183 184ENTRY(handle_serror) 185 save_registers 0 186 mov x0, sp 1871: bl do_serror 188 b 1b 189END(handle_serror) 190 191ENTRY(handle_empty_exception) 192 save_registers 0 193 mov x0, sp 1941: bl unhandled_exception 195 b 1b 196END(handle_unhandled_exception) 197 198.macro vempty 199 .align 7 200 b handle_empty_exception 201.endm 202 203.macro vector name 204 .align 7 205 b handle_\name 206.endm 207 208 .align 11 209 .globl exception_vectors 210exception_vectors: 211 vempty /* Synchronous EL1t */ 212 vempty /* IRQ EL1t */ 213 vempty /* FIQ EL1t */ 214 vempty /* Error EL1t */ 215 216 vector el1h_sync /* Synchronous EL1h */ 217 vector el1h_irq /* IRQ EL1h */ 218 vempty /* FIQ EL1h */ 219 vector serror /* Error EL1h */ 220 221 vector el0_sync /* Synchronous 64-bit EL0 */ 222 vector el0_irq /* IRQ 64-bit EL0 */ 223 vempty /* FIQ 64-bit EL0 */ 224 vector serror /* Error 64-bit EL0 */ 225 226 vector el0_sync /* Synchronous 32-bit EL0 */ 227 vector el0_irq /* IRQ 32-bit EL0 */ 228 vempty /* FIQ 32-bit EL0 */ 229 vector serror /* Error 32-bit EL0 */ 230 231