1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * (C) Copyright 2013 4 * David Feng <fenghua@phytium.com.cn> 5 */ 6 7#include <asm-offsets.h> 8#include <config.h> 9#include <asm/ptrace.h> 10#include <asm/macro.h> 11#include <linux/linkage.h> 12 13/* 14 * AArch64 exception vectors: 15 * We have four types of exceptions: 16 * - synchronous: traps, data aborts, undefined instructions, ... 17 * - IRQ: group 1 (normal) interrupts 18 * - FIQ: group 0 or secure interrupts 19 * - SError: fatal system errors 20 * There are entries for all four of those for different contexts: 21 * - from same exception level, when using the SP_EL0 stack pointer 22 * - from same exception level, when using the SP_ELx stack pointer 23 * - from lower exception level, when this is AArch64 24 * - from lower exception level, when this is AArch32 25 * Each of those 16 entries have space for 32 instructions, each entry must 26 * be 128 byte aligned, the whole table must be 2K aligned. 27 * The 32 instructions are not enough to save and restore all registers and 28 * to branch to the actual handler, so we split this up: 29 * Each entry saves the LR, branches to the save routine, then to the actual 30 * handler, then to the restore routine. The save and restore routines are 31 * each split in half and stuffed in the unused gap between the entries. 32 * Also as we do not run anything in a lower exception level, we just provide 33 * the first 8 entries for exceptions from the same EL. 34 */ 35 .align 11 36 .globl vectors 37vectors: 38 .align 7 /* Current EL Synchronous Thread */ 39 stp x29, x30, [sp, #-16]! 40 bl _exception_entry 41 bl do_bad_sync 42 b exception_exit 43 44/* 45 * Save (most of) the GP registers to the stack frame. 46 * This is the first part of the shared routine called into from all entries. 47 */ 48_exception_entry: 49 stp x27, x28, [sp, #-16]! 50 stp x25, x26, [sp, #-16]! 51 stp x23, x24, [sp, #-16]! 52 stp x21, x22, [sp, #-16]! 53 stp x19, x20, [sp, #-16]! 54 stp x17, x18, [sp, #-16]! 55 stp x15, x16, [sp, #-16]! 56 stp x13, x14, [sp, #-16]! 57 stp x11, x12, [sp, #-16]! 58 stp x9, x10, [sp, #-16]! 59 stp x7, x8, [sp, #-16]! 60 stp x5, x6, [sp, #-16]! 61 stp x3, x4, [sp, #-16]! 62 stp x1, x2, [sp, #-16]! 63 b _save_el_regs /* jump to the second part */ 64 65 .align 7 /* Current EL IRQ Thread */ 66 stp x29, x30, [sp, #-16]! 67 bl _exception_entry 68 bl do_bad_irq 69 b exception_exit 70 71/* 72 * Save exception specific context: ESR and ELR, for all exception levels. 73 * This is the second part of the shared routine called into from all entries. 74 */ 75_save_el_regs: 76 /* Could be running at EL3/EL2/EL1 */ 77 switch_el x11, 3f, 2f, 1f 783: mrs x1, esr_el3 79 mrs x2, elr_el3 80 b 0f 812: mrs x1, esr_el2 82 mrs x2, elr_el2 83 b 0f 841: mrs x1, esr_el1 85 mrs x2, elr_el1 860: 87 stp x2, x0, [sp, #-16]! 88 mov x0, sp 89 ret 90 91 .align 7 /* Current EL FIQ Thread */ 92 stp x29, x30, [sp, #-16]! 93 bl _exception_entry 94 bl do_bad_fiq 95 /* falling through to _exception_exit */ 96/* 97 * Restore the exception return address, for all exception levels. 98 * This is the first part of the shared routine called into from all entries. 99 */ 100exception_exit: 101 ldp x2, x0, [sp],#16 102 switch_el x11, 3f, 2f, 1f 1033: msr elr_el3, x2 104 b _restore_regs 1052: msr elr_el2, x2 106 b _restore_regs 1071: msr elr_el1, x2 108 b _restore_regs /* jump to the second part */ 109 110 .align 7 /* Current EL Error Thread */ 111 stp x29, x30, [sp, #-16]! 112 bl _exception_entry 113 bl do_bad_error 114 b exception_exit 115 116/* 117 * Restore the general purpose registers from the exception stack, then return. 118 * This is the second part of the shared routine called into from all entries. 119 */ 120_restore_regs: 121 ldp x1, x2, [sp],#16 122 ldp x3, x4, [sp],#16 123 ldp x5, x6, [sp],#16 124 ldp x7, x8, [sp],#16 125 ldp x9, x10, [sp],#16 126 ldp x11, x12, [sp],#16 127 ldp x13, x14, [sp],#16 128 ldp x15, x16, [sp],#16 129 ldp x17, x18, [sp],#16 130 ldp x19, x20, [sp],#16 131 ldp x21, x22, [sp],#16 132 ldp x23, x24, [sp],#16 133 ldp x25, x26, [sp],#16 134 ldp x27, x28, [sp],#16 135 ldp x29, x30, [sp],#16 136 eret 137 138 .align 7 /* Current EL (SP_ELx) Synchronous Handler */ 139 stp x29, x30, [sp, #-16]! 140 bl _exception_entry 141 bl do_sync 142 b exception_exit 143 144 .align 7 /* Current EL (SP_ELx) IRQ Handler */ 145 stp x29, x30, [sp, #-16]! 146 bl _exception_entry 147 bl do_irq 148 b exception_exit 149 150 .align 7 /* Current EL (SP_ELx) FIQ Handler */ 151 stp x29, x30, [sp, #-16]! 152 bl _exception_entry 153 bl do_fiq 154 b exception_exit 155 156 .align 7 /* Current EL (SP_ELx) Error Handler */ 157 stp x29, x30, [sp, #-16]! 158 bl _exception_entry 159 bl do_error 160 b exception_exit 161