160ffc30dSCatalin Marinas /* 260ffc30dSCatalin Marinas * Based on arch/arm/include/asm/traps.h 360ffc30dSCatalin Marinas * 460ffc30dSCatalin Marinas * Copyright (C) 2012 ARM Ltd. 560ffc30dSCatalin Marinas * 660ffc30dSCatalin Marinas * This program is free software; you can redistribute it and/or modify 760ffc30dSCatalin Marinas * it under the terms of the GNU General Public License version 2 as 860ffc30dSCatalin Marinas * published by the Free Software Foundation. 960ffc30dSCatalin Marinas * 1060ffc30dSCatalin Marinas * This program is distributed in the hope that it will be useful, 1160ffc30dSCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 1260ffc30dSCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1360ffc30dSCatalin Marinas * GNU General Public License for more details. 1460ffc30dSCatalin Marinas * 1560ffc30dSCatalin Marinas * You should have received a copy of the GNU General Public License 1660ffc30dSCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 1760ffc30dSCatalin Marinas */ 1860ffc30dSCatalin Marinas #ifndef __ASM_TRAP_H 1960ffc30dSCatalin Marinas #define __ASM_TRAP_H 2060ffc30dSCatalin Marinas 219b79f52dSPunit Agrawal #include <linux/list.h> 226bf0dcfdSJames Morse #include <asm/esr.h> 23ee78fdc7SJames Morse #include <asm/sections.h> 249b79f52dSPunit Agrawal 259b79f52dSPunit Agrawal struct pt_regs; 269b79f52dSPunit Agrawal 279b79f52dSPunit Agrawal struct undef_hook { 289b79f52dSPunit Agrawal struct list_head node; 299b79f52dSPunit Agrawal u32 instr_mask; 309b79f52dSPunit Agrawal u32 instr_val; 319b79f52dSPunit Agrawal u64 pstate_mask; 329b79f52dSPunit Agrawal u64 pstate_val; 339b79f52dSPunit Agrawal int (*fn)(struct pt_regs *regs, u32 instr); 349b79f52dSPunit Agrawal }; 359b79f52dSPunit Agrawal 369b79f52dSPunit Agrawal void register_undef_hook(struct undef_hook *hook); 379b79f52dSPunit Agrawal void unregister_undef_hook(struct undef_hook *hook); 38bc0ee476SDave Martin void force_signal_inject(int signal, int code, struct pt_regs *regs, 39bc0ee476SDave Martin unsigned long address); 409b79f52dSPunit Agrawal 41390bf177SAndre Przywara void arm64_notify_segfault(struct pt_regs *regs, unsigned long addr); 42390bf177SAndre Przywara 436436beeeSJulien Thierry /* 446436beeeSJulien Thierry * Move regs->pc to next instruction and do necessary setup before it 456436beeeSJulien Thierry * is executed. 466436beeeSJulien Thierry */ 476436beeeSJulien Thierry void arm64_skip_faulting_instruction(struct pt_regs *regs, unsigned long size); 486436beeeSJulien Thierry 499a5ad7d0SJungseok Lee static inline int __in_irqentry_text(unsigned long ptr) 509a5ad7d0SJungseok Lee { 519a5ad7d0SJungseok Lee return ptr >= (unsigned long)&__irqentry_text_start && 529a5ad7d0SJungseok Lee ptr < (unsigned long)&__irqentry_text_end; 539a5ad7d0SJungseok Lee } 549a5ad7d0SJungseok Lee 5560ffc30dSCatalin Marinas static inline int in_exception_text(unsigned long ptr) 5660ffc30dSCatalin Marinas { 579a5ad7d0SJungseok Lee int in; 5860ffc30dSCatalin Marinas 599a5ad7d0SJungseok Lee in = ptr >= (unsigned long)&__exception_text_start && 6060ffc30dSCatalin Marinas ptr < (unsigned long)&__exception_text_end; 619a5ad7d0SJungseok Lee 629a5ad7d0SJungseok Lee return in ? : __in_irqentry_text(ptr); 6360ffc30dSCatalin Marinas } 6460ffc30dSCatalin Marinas 6573267498SArd Biesheuvel static inline int in_entry_text(unsigned long ptr) 6673267498SArd Biesheuvel { 6773267498SArd Biesheuvel return ptr >= (unsigned long)&__entry_text_start && 6873267498SArd Biesheuvel ptr < (unsigned long)&__entry_text_end; 6973267498SArd Biesheuvel } 706bf0dcfdSJames Morse 716bf0dcfdSJames Morse /* 726bf0dcfdSJames Morse * CPUs with the RAS extensions have an Implementation-Defined-Syndrome bit 736bf0dcfdSJames Morse * to indicate whether this ESR has a RAS encoding. CPUs without this feature 746bf0dcfdSJames Morse * have a ISS-Valid bit in the same position. 756bf0dcfdSJames Morse * If this bit is set, we know its not a RAS SError. 766bf0dcfdSJames Morse * If its clear, we need to know if the CPU supports RAS. Uncategorized RAS 776bf0dcfdSJames Morse * errors share the same encoding as an all-zeros encoding from a CPU that 786bf0dcfdSJames Morse * doesn't support RAS. 796bf0dcfdSJames Morse */ 806bf0dcfdSJames Morse static inline bool arm64_is_ras_serror(u32 esr) 816bf0dcfdSJames Morse { 826bf0dcfdSJames Morse WARN_ON(preemptible()); 836bf0dcfdSJames Morse 846bf0dcfdSJames Morse if (esr & ESR_ELx_IDS) 856bf0dcfdSJames Morse return false; 866bf0dcfdSJames Morse 876bf0dcfdSJames Morse if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN)) 886bf0dcfdSJames Morse return true; 896bf0dcfdSJames Morse else 906bf0dcfdSJames Morse return false; 916bf0dcfdSJames Morse } 926bf0dcfdSJames Morse 936bf0dcfdSJames Morse /* 946bf0dcfdSJames Morse * Return the AET bits from a RAS SError's ESR. 956bf0dcfdSJames Morse * 966bf0dcfdSJames Morse * It is implementation defined whether Uncategorized errors are containable. 976bf0dcfdSJames Morse * We treat them as Uncontainable. 986bf0dcfdSJames Morse * Non-RAS SError's are reported as Uncontained/Uncategorized. 996bf0dcfdSJames Morse */ 1006bf0dcfdSJames Morse static inline u32 arm64_ras_serror_get_severity(u32 esr) 1016bf0dcfdSJames Morse { 1026bf0dcfdSJames Morse u32 aet = esr & ESR_ELx_AET; 1036bf0dcfdSJames Morse 1046bf0dcfdSJames Morse if (!arm64_is_ras_serror(esr)) { 1056bf0dcfdSJames Morse /* Not a RAS error, we can't interpret the ESR. */ 1066bf0dcfdSJames Morse return ESR_ELx_AET_UC; 1076bf0dcfdSJames Morse } 1086bf0dcfdSJames Morse 1096bf0dcfdSJames Morse /* 1106bf0dcfdSJames Morse * AET is RES0 if 'the value returned in the DFSC field is not 1116bf0dcfdSJames Morse * [ESR_ELx_FSC_SERROR]' 1126bf0dcfdSJames Morse */ 1136bf0dcfdSJames Morse if ((esr & ESR_ELx_FSC) != ESR_ELx_FSC_SERROR) { 1146bf0dcfdSJames Morse /* No severity information : Uncategorized */ 1156bf0dcfdSJames Morse return ESR_ELx_AET_UC; 1166bf0dcfdSJames Morse } 1176bf0dcfdSJames Morse 1186bf0dcfdSJames Morse return aet; 1196bf0dcfdSJames Morse } 1206bf0dcfdSJames Morse 1216bf0dcfdSJames Morse bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr); 1226bf0dcfdSJames Morse void __noreturn arm64_serror_panic(struct pt_regs *regs, u32 esr); 12360ffc30dSCatalin Marinas #endif 124