1 // SPDX-License-Identifier: GPL-2.0+
8 #include <asm/global_data.h>
9 #include <asm/ptrace.h>
11 #include <linux/compiler.h>
12 #include <efi_loader.h>
13 #include <semihosting.h>
15 DECLARE_GLOBAL_DATA_PTR;
17 int interrupt_init(void)
24 void enable_interrupts(void)
29 int disable_interrupts(void)
34 static void show_efi_loaded_images(struct pt_regs *regs)
36 efi_print_image_infos((void *)regs->elr);
39 static void dump_far(unsigned long esr)
41 unsigned long el, far;
43 switch ((esr >> 26) & 0b111111) {
56 asm("mrs %0, CurrentEl": "=r" (el));
60 asm("mrs %0, FAR_EL1": "=r" (far));
63 asm("mrs %0, FAR_EL2": "=r" (far));
66 /* don't print anything to make output pretty */
70 printf(", far 0x%lx", far);
73 static void dump_instr(struct pt_regs *regs)
75 u32 *addr = (u32 *)(regs->elr & ~3UL);
79 for (i = -4; i < 1; i++)
80 printf(i == 0 ? "(%08x) " : "%08x ", addr[i]);
84 void show_regs(struct pt_regs *regs)
88 if (gd->flags & GD_FLG_RELOC)
89 printf("elr: %016lx lr : %016lx (reloc)\n",
90 regs->elr - gd->reloc_off,
91 regs->regs[30] - gd->reloc_off);
92 printf("elr: %016lx lr : %016lx\n", regs->elr, regs->regs[30]);
94 for (i = 0; i < 29; i += 2)
95 printf("x%-2d: %016lx x%-2d: %016lx\n",
96 i, regs->regs[i], i+1, regs->regs[i+1]);
102 * Try to "emulate" a semihosting call in the event that we don't have a
105 static bool smh_emulate_trap(struct pt_regs *regs)
109 if (ESR_ELx_EC(regs->esr) != ESR_ELx_EC_UNKNOWN)
112 if (regs->spsr & PSR_MODE32_BIT) {
113 if (regs->spsr & PSR_AA32_T_BIT) {
114 u16 *insn = (u16 *)ALIGN_DOWN(regs->elr, 2);
116 if (*insn != SMH_T32_SVC && *insn != SMH_T32_HLT)
120 u32 *insn = (u32 *)ALIGN_DOWN(regs->elr, 4);
122 if (*insn != SMH_A32_SVC && *insn != SMH_A32_HLT)
127 u32 *insn = (u32 *)ALIGN_DOWN(regs->elr, 4);
129 if (*insn != SMH_A64_HLT)
134 /* Avoid future semihosting calls */
135 disable_semihosting();
137 /* Just pretend the call failed */
144 * do_bad_sync handles the impossible case in the Synchronous Abort vector.
146 void do_bad_sync(struct pt_regs *pt_regs)
149 printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08lx\n",
152 show_efi_loaded_images(pt_regs);
153 panic("Resetting CPU ...\n");
157 * do_bad_irq handles the impossible case in the Irq vector.
159 void do_bad_irq(struct pt_regs *pt_regs)
162 printf("Bad mode in \"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
164 show_efi_loaded_images(pt_regs);
165 panic("Resetting CPU ...\n");
169 * do_bad_fiq handles the impossible case in the Fiq vector.
171 void do_bad_fiq(struct pt_regs *pt_regs)
174 printf("Bad mode in \"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
176 show_efi_loaded_images(pt_regs);
177 panic("Resetting CPU ...\n");
181 * do_bad_error handles the impossible case in the Error vector.
183 void do_bad_error(struct pt_regs *pt_regs)
186 printf("Bad mode in \"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
188 show_efi_loaded_images(pt_regs);
189 panic("Resetting CPU ...\n");
193 * do_sync handles the Synchronous Abort exception.
195 void do_sync(struct pt_regs *pt_regs)
197 if (CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) &&
198 smh_emulate_trap(pt_regs))
201 printf("\"Synchronous Abort\" handler, esr 0x%08lx", pt_regs->esr);
202 dump_far(pt_regs->esr);
205 show_efi_loaded_images(pt_regs);
206 panic("Resetting CPU ...\n");
210 * do_irq handles the Irq exception.
212 void do_irq(struct pt_regs *pt_regs)
215 printf("\"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
217 show_efi_loaded_images(pt_regs);
218 panic("Resetting CPU ...\n");
222 * do_fiq handles the Fiq exception.
224 void do_fiq(struct pt_regs *pt_regs)
227 printf("\"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
229 show_efi_loaded_images(pt_regs);
230 panic("Resetting CPU ...\n");
234 * do_error handles the Error exception.
235 * Errors are more likely to be processor specific,
236 * it is defined with weak attribute and can be redefined
237 * in processor specific code.
239 void __weak do_error(struct pt_regs *pt_regs)
242 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
244 show_efi_loaded_images(pt_regs);
245 panic("Resetting CPU ...\n");