1/* $OpenBSD: exception.S,v 1.17 2024/03/12 13:32:53 kettenis Exp $ */ 2/*- 3 * Copyright (c) 2014 Andrew Turner 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <machine/asm.h> 29#include <machine/armreg.h> 30 31#include "assym.h" 32 33 .text 34 35.macro save_registers el 36.if \el == 1 37 mov x18, sp 38 sub sp, sp, #128 39.endif 40 sub sp, sp, #(TF_SIZE + 16) 41 stp x28, x29, [sp, #(TF_X + 28 * 8)] 42 stp x26, x27, [sp, #(TF_X + 26 * 8)] 43 stp x24, x25, [sp, #(TF_X + 24 * 8)] 44 stp x22, x23, [sp, #(TF_X + 22 * 8)] 45 stp x20, x21, [sp, #(TF_X + 20 * 8)] 46 stp x18, x19, [sp, #(TF_X + 18 * 8)] 47 stp x16, x17, [sp, #(TF_X + 16 * 8)] 48 stp x14, x15, [sp, #(TF_X + 14 * 8)] 49 stp x12, x13, [sp, #(TF_X + 12 * 8)] 50 stp x10, x11, [sp, #(TF_X + 10 * 8)] 51 stp x8, x9, [sp, #(TF_X + 8 * 8)] 52 stp x6, x7, [sp, #(TF_X + 6 * 8)] 53 stp x4, x5, [sp, #(TF_X + 4 * 8)] 54 stp x2, x3, [sp, #(TF_X + 2 * 8)] 55 stp x0, x1, [sp, #(TF_X + 0 * 8)] 56 mrs x10, elr_el1 57 mrs x11, spsr_el1 58.if \el == 0 59 mrs x18, sp_el0 60.endif 61 stp x10, x11, [sp, #(TF_ELR)] 62 stp x18, lr, [sp, #(TF_SP)] 63 stp fp, x10, [sp, #(TF_SIZE)] 64 mrs x18, tpidr_el1 65 add fp, sp, #(TF_SIZE) 66.endm 67 68.macro restore_registers el 69.if \el == 1 70 msr daifset, #3 71 /* 72 * Disable interrupts, x18 may change in the interrupt exception 73 * handler. For EL0 exceptions, do_ast already did this. 74 */ 75.endif 76 ldp x18, lr, [sp, #(TF_SP)] 77 ldp x10, x11, [sp, #(TF_ELR)] 78.if \el == 0 79 msr sp_el0, x18 80.endif 81 msr spsr_el1, x11 82 msr elr_el1, x10 83 ldp x0, x1, [sp, #(TF_X + 0 * 8)] 84 ldp x2, x3, [sp, #(TF_X + 2 * 8)] 85 ldp x4, x5, [sp, #(TF_X + 4 * 8)] 86 ldp x6, x7, [sp, #(TF_X + 6 * 8)] 87 ldp x8, x9, [sp, #(TF_X + 8 * 8)] 88 ldp x10, x11, [sp, #(TF_X + 10 * 8)] 89 ldp x12, x13, [sp, #(TF_X + 12 * 8)] 90 ldp x14, x15, [sp, #(TF_X + 14 * 8)] 91 ldp x16, x17, [sp, #(TF_X + 16 * 8)] 92.if \el == 0 93 /* 94 * We only restore the callee saved registers when returning to 95 * userland as they may have been updated by a system call or signal. 96 */ 97 ldp x18, x19, [sp, #(TF_X + 18 * 8)] 98 ldp x20, x21, [sp, #(TF_X + 20 * 8)] 99 ldp x22, x23, [sp, #(TF_X + 22 * 8)] 100 ldp x24, x25, [sp, #(TF_X + 24 * 8)] 101 ldp x26, x27, [sp, #(TF_X + 26 * 8)] 102 ldp x28, x29, [sp, #(TF_X + 28 * 8)] 103.else 104 ldr x29, [sp, #(TF_X + 29 * 8)] 105.endif 106.if \el == 0 107 add sp, sp, #(TF_SIZE + 16) 108.else 109 mov sp, x18 110 mrs x18, tpidr_el1 111.endif 112.endm 113 114.macro do_ast 115 /* Disable interrupts */ 116 mrs x19, daif 1171: 118 msr daifset, #3 119 120 /* Check for astpending */ 121 mrs x18, tpidr_el1 122 ldr x1, [x18, #CI_CURPROC] 123 cbz x1, 2f 124 ldr w2, [x1, #P_ASTPENDING] 125 cbz w2, 2f 126 127 // clear astpending before enabling interrupts. 128 str wzr, [x1, #P_ASTPENDING] 129 130 /* Restore interrupts */ 131 msr daif, x19 132 133 /* handle the ast */ 134 mov x0, sp 135 bl ast 136 b 1b 1372: 138.endm 139 140.macro disable_ss 141 mrs x2, mdscr_el1 142 and x2, x2, #(~DBG_MDSCR_SS) 143 msr mdscr_el1, x2 144.endm 145 146.macro allow_ss 147 mrs x2, tpidr_el1 148 ldr x2, [x2, #(CI_CURPCB)] 149 ldr w2, [x2, #(PCB_FLAGS)] 150 tbz w2, #1, 1f /* PCB_SINGLESTEP bit */ 151 mrs x2, mdscr_el1 152 orr x2, x2, #(DBG_MDSCR_SS) 153 msr mdscr_el1, x2 1541: 155.endm 156 157 .globl handle_el1h_sync 158 .type handle_el1h_sync,@function 159handle_el1h_sync: 160 save_registers 1 161 mov x0, sp 162 bl do_el1h_sync 163 restore_registers 1 164 eret 165 dsb nsh 166 isb 167 168 .globl handle_el1h_irq 169 .type handle_el1h_irq,@function 170handle_el1h_irq: 171 save_registers 1 172 mov x0, sp 173 bl arm_cpu_irq 174 restore_registers 1 175 eret 176 dsb nsh 177 isb 178 179 .globl handle_el1h_fiq 180 .type handle_el1h_fiq,@function 181handle_el1h_fiq: 182 save_registers 1 183 mov x0, sp 184 bl arm_cpu_fiq 185 restore_registers 1 186 eret 187 dsb nsh 188 isb 189 190 .globl handle_el1h_error 191 .type handle_el1h_error,@function 192handle_el1h_error: 193 save_registers 1 194 mov x0, sp 195 bl do_el1h_error 196 brk 0xf13 197 1: b 1b 198 199.macro return 200 msr tpidrro_el0, x18 201 mrs x18, tpidr_el1 202 ldr x18, [x18, #CI_TRAMPOLINE_VECTORS] 203 msr vbar_el1, x18 204 isb 205 b tramp_return 206.endm 207 208 .globl handle_el0_sync 209 .type handle_el0_sync,@function 210handle_el0_sync: 211 save_registers 0 212 disable_ss 213 mov x0, sp 214 bl do_el0_sync 215 do_ast 216 allow_ss 217 restore_registers 0 218 return 219 220 .globl handle_el0_irq 221 .type handle_el0_irq,@function 222handle_el0_irq: 223 save_registers 0 224 disable_ss 225 mov x0, sp 226 bl arm_cpu_irq 227 do_ast 228 allow_ss 229 restore_registers 0 230 return 231 232 .globl handle_el0_fiq 233 .type handle_el0_fiq,@function 234handle_el0_fiq: 235 save_registers 0 236 disable_ss 237 mov x0, sp 238 bl arm_cpu_fiq 239 do_ast 240 allow_ss 241 restore_registers 0 242 return 243 244 .globl handle_el0_error 245 .type handle_el0_error,@function 246handle_el0_error: 247 save_registers 0 248 disable_ss 249 mov x0, sp 250 bl do_el0_error 251 brk 0xf23 252 1: b 1b 253 254ENTRY(syscall_return) 255 do_ast 256 restore_registers 0 257 return 258 259.macro vempty 260 .align 7 261 brk 0xfff 262 1: b 1b 263.endm 264 265.macro vector name 266 .align 7 267 b handle_\name 268.endm 269 270 .align 11 271 .globl exception_vectors 272exception_vectors: 273 vempty /* Synchronous EL1t */ 274 vempty /* IRQ EL1t */ 275 vempty /* FIQ EL1t */ 276 vempty /* Error EL1t */ 277 278 vector el1h_sync /* Synchronous EL1h */ 279 vector el1h_irq /* IRQ EL1h */ 280 vector el1h_fiq /* FIQ EL1h */ 281 vector el1h_error /* Error EL1h */ 282 283 vempty /* Synchronous 64-bit EL0 */ 284 vempty /* IRQ 64-bit EL0 */ 285 vempty /* FIQ 64-bit EL0 */ 286 vempty /* Error 64-bit EL0 */ 287 288 vempty /* Synchronous 32-bit EL0 */ 289 vempty /* IRQ 32-bit EL0 */ 290 vempty /* FIQ 32-bit EL0 */ 291 vempty /* Error 32-bit EL0 */ 292