blob: 2e091415a46e6d50d2f4c082970c12e9c96951a0 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
David Feng85fd5f12013-12-14 11:47:35 +08002/*
3 * (C) Copyright 2013
4 * David Feng <fenghua@phytium.com.cn>
David Feng85fd5f12013-12-14 11:47:35 +08005 */
6
7#include <common.h>
Sean Anderson064c8572022-03-22 16:59:31 -04008#include <asm/esr.h>
Simon Glass3ba929a2020-10-30 21:38:53 -06009#include <asm/global_data.h>
Simon Glass6b9f0102020-05-10 11:40:06 -060010#include <asm/ptrace.h>
Simon Glass9b61c7c2019-11-14 12:57:41 -070011#include <irq_func.h>
David Feng85fd5f12013-12-14 11:47:35 +080012#include <linux/compiler.h>
Alexander Graf58177862016-03-04 01:10:06 +010013#include <efi_loader.h>
Sean Anderson064c8572022-03-22 16:59:31 -040014#include <semihosting.h>
David Feng85fd5f12013-12-14 11:47:35 +080015
Peng Fanc3c9b332017-11-28 10:08:08 +080016DECLARE_GLOBAL_DATA_PTR;
David Feng85fd5f12013-12-14 11:47:35 +080017
18int interrupt_init(void)
19{
Ovidiu Panait8998e712020-04-20 10:31:44 +030020 enable_interrupts();
21
David Feng85fd5f12013-12-14 11:47:35 +080022 return 0;
23}
24
25void enable_interrupts(void)
26{
27 return;
28}
29
30int disable_interrupts(void)
31{
32 return 0;
33}
34
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +020035static void show_efi_loaded_images(struct pt_regs *regs)
36{
37 efi_print_image_infos((void *)regs->elr);
38}
39
Heinrich Schuchardt11efc1a2019-09-12 19:09:26 +020040static void dump_instr(struct pt_regs *regs)
41{
42 u32 *addr = (u32 *)(regs->elr & ~3UL);
43 int i;
44
45 printf("Code: ");
46 for (i = -4; i < 1; i++)
47 printf(i == 0 ? "(%08x) " : "%08x ", addr[i]);
48 printf("\n");
49}
50
David Feng85fd5f12013-12-14 11:47:35 +080051void show_regs(struct pt_regs *regs)
52{
53 int i;
54
Karl Beldanb33ccd12018-02-20 23:30:08 +000055 if (gd->flags & GD_FLG_RELOC)
56 printf("elr: %016lx lr : %016lx (reloc)\n",
57 regs->elr - gd->reloc_off,
58 regs->regs[30] - gd->reloc_off);
59 printf("elr: %016lx lr : %016lx\n", regs->elr, regs->regs[30]);
60
David Feng85fd5f12013-12-14 11:47:35 +080061 for (i = 0; i < 29; i += 2)
62 printf("x%-2d: %016lx x%-2d: %016lx\n",
63 i, regs->regs[i], i+1, regs->regs[i+1]);
64 printf("\n");
Heinrich Schuchardt11efc1a2019-09-12 19:09:26 +020065 dump_instr(regs);
David Feng85fd5f12013-12-14 11:47:35 +080066}
67
68/*
Sean Anderson064c8572022-03-22 16:59:31 -040069 * Try to "emulate" a semihosting call in the event that we don't have a
70 * debugger attached.
71 */
72static bool smh_emulate_trap(struct pt_regs *regs)
73{
74 int size;
75
76 if (ESR_ELx_EC(regs->esr) != ESR_ELx_EC_UNKNOWN)
77 return false;
78
79 if (regs->spsr & PSR_MODE32_BIT) {
80 if (regs->spsr & PSR_AA32_T_BIT) {
81 u16 *insn = (u16 *)ALIGN_DOWN(regs->elr, 2);
82
83 if (*insn != SMH_T32_SVC && *insn != SMH_T32_HLT)
84 return false;
85 size = 2;
86 } else {
87 u32 *insn = (u32 *)ALIGN_DOWN(regs->elr, 4);
88
89 if (*insn != SMH_A32_SVC && *insn != SMH_A32_HLT)
90 return false;
91 size = 4;
92 }
93 } else {
94 u32 *insn = (u32 *)ALIGN_DOWN(regs->elr, 4);
95
96 if (*insn != SMH_A64_HLT)
97 return false;
98 size = 4;
99 }
100
101 /* Avoid future semihosting calls */
102 disable_semihosting();
103
104 /* Just pretend the call failed */
105 regs->regs[0] = -1;
106 regs->elr += size;
107 return true;
108}
109
110/*
David Feng85fd5f12013-12-14 11:47:35 +0800111 * do_bad_sync handles the impossible case in the Synchronous Abort vector.
112 */
Sean Anderson2d755492022-03-22 17:17:35 -0400113void do_bad_sync(struct pt_regs *pt_regs)
David Feng85fd5f12013-12-14 11:47:35 +0800114{
Alexander Graf58177862016-03-04 01:10:06 +0100115 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -0400116 printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08lx\n",
117 pt_regs->esr);
David Feng85fd5f12013-12-14 11:47:35 +0800118 show_regs(pt_regs);
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +0200119 show_efi_loaded_images(pt_regs);
David Feng85fd5f12013-12-14 11:47:35 +0800120 panic("Resetting CPU ...\n");
121}
122
123/*
124 * do_bad_irq handles the impossible case in the Irq vector.
125 */
Sean Anderson2d755492022-03-22 17:17:35 -0400126void do_bad_irq(struct pt_regs *pt_regs)
David Feng85fd5f12013-12-14 11:47:35 +0800127{
Alexander Graf58177862016-03-04 01:10:06 +0100128 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -0400129 printf("Bad mode in \"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
David Feng85fd5f12013-12-14 11:47:35 +0800130 show_regs(pt_regs);
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +0200131 show_efi_loaded_images(pt_regs);
David Feng85fd5f12013-12-14 11:47:35 +0800132 panic("Resetting CPU ...\n");
133}
134
135/*
136 * do_bad_fiq handles the impossible case in the Fiq vector.
137 */
Sean Anderson2d755492022-03-22 17:17:35 -0400138void do_bad_fiq(struct pt_regs *pt_regs)
David Feng85fd5f12013-12-14 11:47:35 +0800139{
Alexander Graf58177862016-03-04 01:10:06 +0100140 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -0400141 printf("Bad mode in \"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
David Feng85fd5f12013-12-14 11:47:35 +0800142 show_regs(pt_regs);
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +0200143 show_efi_loaded_images(pt_regs);
David Feng85fd5f12013-12-14 11:47:35 +0800144 panic("Resetting CPU ...\n");
145}
146
147/*
148 * do_bad_error handles the impossible case in the Error vector.
149 */
Sean Anderson2d755492022-03-22 17:17:35 -0400150void do_bad_error(struct pt_regs *pt_regs)
David Feng85fd5f12013-12-14 11:47:35 +0800151{
Alexander Graf58177862016-03-04 01:10:06 +0100152 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -0400153 printf("Bad mode in \"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
David Feng85fd5f12013-12-14 11:47:35 +0800154 show_regs(pt_regs);
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +0200155 show_efi_loaded_images(pt_regs);
David Feng85fd5f12013-12-14 11:47:35 +0800156 panic("Resetting CPU ...\n");
157}
158
159/*
160 * do_sync handles the Synchronous Abort exception.
161 */
Sean Anderson2d755492022-03-22 17:17:35 -0400162void do_sync(struct pt_regs *pt_regs)
David Feng85fd5f12013-12-14 11:47:35 +0800163{
Sean Anderson064c8572022-03-22 16:59:31 -0400164 if (CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) &&
165 smh_emulate_trap(pt_regs))
166 return;
Alexander Graf58177862016-03-04 01:10:06 +0100167 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -0400168 printf("\"Synchronous Abort\" handler, esr 0x%08lx\n", pt_regs->esr);
David Feng85fd5f12013-12-14 11:47:35 +0800169 show_regs(pt_regs);
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +0200170 show_efi_loaded_images(pt_regs);
David Feng85fd5f12013-12-14 11:47:35 +0800171 panic("Resetting CPU ...\n");
172}
173
174/*
175 * do_irq handles the Irq exception.
176 */
Sean Anderson2d755492022-03-22 17:17:35 -0400177void do_irq(struct pt_regs *pt_regs)
David Feng85fd5f12013-12-14 11:47:35 +0800178{
Alexander Graf58177862016-03-04 01:10:06 +0100179 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -0400180 printf("\"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
David Feng85fd5f12013-12-14 11:47:35 +0800181 show_regs(pt_regs);
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +0200182 show_efi_loaded_images(pt_regs);
David Feng85fd5f12013-12-14 11:47:35 +0800183 panic("Resetting CPU ...\n");
184}
185
186/*
187 * do_fiq handles the Fiq exception.
188 */
Sean Anderson2d755492022-03-22 17:17:35 -0400189void do_fiq(struct pt_regs *pt_regs)
David Feng85fd5f12013-12-14 11:47:35 +0800190{
Alexander Graf58177862016-03-04 01:10:06 +0100191 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -0400192 printf("\"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
David Feng85fd5f12013-12-14 11:47:35 +0800193 show_regs(pt_regs);
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +0200194 show_efi_loaded_images(pt_regs);
David Feng85fd5f12013-12-14 11:47:35 +0800195 panic("Resetting CPU ...\n");
196}
197
198/*
199 * do_error handles the Error exception.
200 * Errors are more likely to be processor specific,
201 * it is defined with weak attribute and can be redefined
202 * in processor specific code.
203 */
Sean Anderson2d755492022-03-22 17:17:35 -0400204void __weak do_error(struct pt_regs *pt_regs)
David Feng85fd5f12013-12-14 11:47:35 +0800205{
Alexander Graf58177862016-03-04 01:10:06 +0100206 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -0400207 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
David Feng85fd5f12013-12-14 11:47:35 +0800208 show_regs(pt_regs);
Heinrich Schuchardtb7c0c382019-04-04 22:06:25 +0200209 show_efi_loaded_images(pt_regs);
David Feng85fd5f12013-12-14 11:47:35 +0800210 panic("Resetting CPU ...\n");
211}