xref: /openbmc/linux/arch/arm64/include/asm/traps.h (revision caab277b)
1caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
260ffc30dSCatalin Marinas /*
360ffc30dSCatalin Marinas  * Based on arch/arm/include/asm/traps.h
460ffc30dSCatalin Marinas  *
560ffc30dSCatalin Marinas  * Copyright (C) 2012 ARM Ltd.
660ffc30dSCatalin Marinas  */
760ffc30dSCatalin Marinas #ifndef __ASM_TRAP_H
860ffc30dSCatalin Marinas #define __ASM_TRAP_H
960ffc30dSCatalin Marinas 
109b79f52dSPunit Agrawal #include <linux/list.h>
116bf0dcfdSJames Morse #include <asm/esr.h>
12ee78fdc7SJames Morse #include <asm/sections.h>
139b79f52dSPunit Agrawal 
149b79f52dSPunit Agrawal struct pt_regs;
159b79f52dSPunit Agrawal 
169b79f52dSPunit Agrawal struct undef_hook {
179b79f52dSPunit Agrawal 	struct list_head node;
189b79f52dSPunit Agrawal 	u32 instr_mask;
199b79f52dSPunit Agrawal 	u32 instr_val;
209b79f52dSPunit Agrawal 	u64 pstate_mask;
219b79f52dSPunit Agrawal 	u64 pstate_val;
229b79f52dSPunit Agrawal 	int (*fn)(struct pt_regs *regs, u32 instr);
239b79f52dSPunit Agrawal };
249b79f52dSPunit Agrawal 
259b79f52dSPunit Agrawal void register_undef_hook(struct undef_hook *hook);
269b79f52dSPunit Agrawal void unregister_undef_hook(struct undef_hook *hook);
272c9120f3SWill Deacon void force_signal_inject(int signal, int code, unsigned long address);
282c9120f3SWill Deacon void arm64_notify_segfault(unsigned long addr);
29feca355bSEric W. Biederman void arm64_force_sig_fault(int signo, int code, void __user *addr, const char *str);
30b4d5557cSEric W. Biederman void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, const char *str);
31f3a900b3SEric W. Biederman void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
32390bf177SAndre Przywara 
336436beeeSJulien Thierry /*
346436beeeSJulien Thierry  * Move regs->pc to next instruction and do necessary setup before it
356436beeeSJulien Thierry  * is executed.
366436beeeSJulien Thierry  */
376436beeeSJulien Thierry void arm64_skip_faulting_instruction(struct pt_regs *regs, unsigned long size);
386436beeeSJulien Thierry 
399a5ad7d0SJungseok Lee static inline int __in_irqentry_text(unsigned long ptr)
409a5ad7d0SJungseok Lee {
419a5ad7d0SJungseok Lee 	return ptr >= (unsigned long)&__irqentry_text_start &&
429a5ad7d0SJungseok Lee 	       ptr < (unsigned long)&__irqentry_text_end;
439a5ad7d0SJungseok Lee }
449a5ad7d0SJungseok Lee 
4560ffc30dSCatalin Marinas static inline int in_exception_text(unsigned long ptr)
4660ffc30dSCatalin Marinas {
479a5ad7d0SJungseok Lee 	int in;
4860ffc30dSCatalin Marinas 
499a5ad7d0SJungseok Lee 	in = ptr >= (unsigned long)&__exception_text_start &&
5060ffc30dSCatalin Marinas 	     ptr < (unsigned long)&__exception_text_end;
519a5ad7d0SJungseok Lee 
529a5ad7d0SJungseok Lee 	return in ? : __in_irqentry_text(ptr);
5360ffc30dSCatalin Marinas }
5460ffc30dSCatalin Marinas 
5573267498SArd Biesheuvel static inline int in_entry_text(unsigned long ptr)
5673267498SArd Biesheuvel {
5773267498SArd Biesheuvel 	return ptr >= (unsigned long)&__entry_text_start &&
5873267498SArd Biesheuvel 	       ptr < (unsigned long)&__entry_text_end;
5973267498SArd Biesheuvel }
606bf0dcfdSJames Morse 
616bf0dcfdSJames Morse /*
626bf0dcfdSJames Morse  * CPUs with the RAS extensions have an Implementation-Defined-Syndrome bit
636bf0dcfdSJames Morse  * to indicate whether this ESR has a RAS encoding. CPUs without this feature
646bf0dcfdSJames Morse  * have a ISS-Valid bit in the same position.
656bf0dcfdSJames Morse  * If this bit is set, we know its not a RAS SError.
666bf0dcfdSJames Morse  * If its clear, we need to know if the CPU supports RAS. Uncategorized RAS
676bf0dcfdSJames Morse  * errors share the same encoding as an all-zeros encoding from a CPU that
686bf0dcfdSJames Morse  * doesn't support RAS.
696bf0dcfdSJames Morse  */
706bf0dcfdSJames Morse static inline bool arm64_is_ras_serror(u32 esr)
716bf0dcfdSJames Morse {
726bf0dcfdSJames Morse 	WARN_ON(preemptible());
736bf0dcfdSJames Morse 
746bf0dcfdSJames Morse 	if (esr & ESR_ELx_IDS)
756bf0dcfdSJames Morse 		return false;
766bf0dcfdSJames Morse 
776bf0dcfdSJames Morse 	if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN))
786bf0dcfdSJames Morse 		return true;
796bf0dcfdSJames Morse 	else
806bf0dcfdSJames Morse 		return false;
816bf0dcfdSJames Morse }
826bf0dcfdSJames Morse 
836bf0dcfdSJames Morse /*
846bf0dcfdSJames Morse  * Return the AET bits from a RAS SError's ESR.
856bf0dcfdSJames Morse  *
866bf0dcfdSJames Morse  * It is implementation defined whether Uncategorized errors are containable.
876bf0dcfdSJames Morse  * We treat them as Uncontainable.
886bf0dcfdSJames Morse  * Non-RAS SError's are reported as Uncontained/Uncategorized.
896bf0dcfdSJames Morse  */
906bf0dcfdSJames Morse static inline u32 arm64_ras_serror_get_severity(u32 esr)
916bf0dcfdSJames Morse {
926bf0dcfdSJames Morse 	u32 aet = esr & ESR_ELx_AET;
936bf0dcfdSJames Morse 
946bf0dcfdSJames Morse 	if (!arm64_is_ras_serror(esr)) {
956bf0dcfdSJames Morse 		/* Not a RAS error, we can't interpret the ESR. */
966bf0dcfdSJames Morse 		return ESR_ELx_AET_UC;
976bf0dcfdSJames Morse 	}
986bf0dcfdSJames Morse 
996bf0dcfdSJames Morse 	/*
1006bf0dcfdSJames Morse 	 * AET is RES0 if 'the value returned in the DFSC field is not
1016bf0dcfdSJames Morse 	 * [ESR_ELx_FSC_SERROR]'
1026bf0dcfdSJames Morse 	 */
1036bf0dcfdSJames Morse 	if ((esr & ESR_ELx_FSC) != ESR_ELx_FSC_SERROR) {
1046bf0dcfdSJames Morse 		/* No severity information : Uncategorized */
1056bf0dcfdSJames Morse 		return ESR_ELx_AET_UC;
1066bf0dcfdSJames Morse 	}
1076bf0dcfdSJames Morse 
1086bf0dcfdSJames Morse 	return aet;
1096bf0dcfdSJames Morse }
1106bf0dcfdSJames Morse 
1116bf0dcfdSJames Morse bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr);
1126bf0dcfdSJames Morse void __noreturn arm64_serror_panic(struct pt_regs *regs, u32 esr);
11360ffc30dSCatalin Marinas #endif
114