]> Git Repo - J-u-boot.git/blob - arch/arm/lib/interrupts_64.c
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / arch / arm / lib / interrupts_64.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2013
4  * David Feng <[email protected]>
5  */
6
7 #include <asm/esr.h>
8 #include <asm/global_data.h>
9 #include <asm/ptrace.h>
10 #include <irq_func.h>
11 #include <linux/compiler.h>
12 #include <efi_loader.h>
13 #include <semihosting.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 int interrupt_init(void)
18 {
19         enable_interrupts();
20
21         return 0;
22 }
23
24 void enable_interrupts(void)
25 {
26         return;
27 }
28
29 int disable_interrupts(void)
30 {
31         return 0;
32 }
33
34 static void show_efi_loaded_images(struct pt_regs *regs)
35 {
36         efi_print_image_infos((void *)regs->elr);
37 }
38
39 static void dump_far(unsigned long esr)
40 {
41         unsigned long el, far;
42
43         switch ((esr >> 26) & 0b111111) {
44         case 0x20:
45         case 0x21:
46         case 0x24:
47         case 0x25:
48         case 0x22:
49         case 0x34:
50         case 0x35:
51                 break;
52         default:
53                 return;
54         }
55
56         asm("mrs        %0, CurrentEl": "=r" (el));
57
58         switch (el >> 2) {
59         case 1:
60                 asm("mrs        %0, FAR_EL1": "=r" (far));
61                 break;
62         case 2:
63                 asm("mrs        %0, FAR_EL2": "=r" (far));
64                 break;
65         default:
66                 /* don't print anything to make output pretty */
67                 return;
68         }
69
70         printf(", far 0x%lx", far);
71 }
72
73 static void dump_instr(struct pt_regs *regs)
74 {
75         u32 *addr = (u32 *)(regs->elr & ~3UL);
76         int i;
77
78         printf("Code: ");
79         for (i = -4; i < 1; i++)
80                 printf(i == 0 ? "(%08x) " : "%08x ", addr[i]);
81         printf("\n");
82 }
83
84 void show_regs(struct pt_regs *regs)
85 {
86         int i;
87
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]);
93
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]);
97         printf("\n");
98         dump_instr(regs);
99 }
100
101 /*
102  * Try to "emulate" a semihosting call in the event that we don't have a
103  * debugger attached.
104  */
105 static bool smh_emulate_trap(struct pt_regs *regs)
106 {
107         int size;
108
109         if (ESR_ELx_EC(regs->esr) != ESR_ELx_EC_UNKNOWN)
110                 return false;
111
112         if (regs->spsr & PSR_MODE32_BIT) {
113                 if (regs->spsr & PSR_AA32_T_BIT) {
114                         u16 *insn = (u16 *)ALIGN_DOWN(regs->elr, 2);
115
116                         if (*insn != SMH_T32_SVC && *insn != SMH_T32_HLT)
117                                 return false;
118                         size = 2;
119                 } else {
120                         u32 *insn = (u32 *)ALIGN_DOWN(regs->elr, 4);
121
122                         if (*insn != SMH_A32_SVC && *insn != SMH_A32_HLT)
123                                 return false;
124                         size = 4;
125                 }
126         } else {
127                 u32 *insn = (u32 *)ALIGN_DOWN(regs->elr, 4);
128
129                 if (*insn != SMH_A64_HLT)
130                         return false;
131                 size = 4;
132         }
133
134         /* Avoid future semihosting calls */
135         disable_semihosting();
136
137         /* Just pretend the call failed */
138         regs->regs[0] = -1;
139         regs->elr += size;
140         return true;
141 }
142
143 /*
144  * do_bad_sync handles the impossible case in the Synchronous Abort vector.
145  */
146 void do_bad_sync(struct pt_regs *pt_regs)
147 {
148         efi_restore_gd();
149         printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08lx\n",
150                pt_regs->esr);
151         show_regs(pt_regs);
152         show_efi_loaded_images(pt_regs);
153         panic("Resetting CPU ...\n");
154 }
155
156 /*
157  * do_bad_irq handles the impossible case in the Irq vector.
158  */
159 void do_bad_irq(struct pt_regs *pt_regs)
160 {
161         efi_restore_gd();
162         printf("Bad mode in \"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
163         show_regs(pt_regs);
164         show_efi_loaded_images(pt_regs);
165         panic("Resetting CPU ...\n");
166 }
167
168 /*
169  * do_bad_fiq handles the impossible case in the Fiq vector.
170  */
171 void do_bad_fiq(struct pt_regs *pt_regs)
172 {
173         efi_restore_gd();
174         printf("Bad mode in \"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
175         show_regs(pt_regs);
176         show_efi_loaded_images(pt_regs);
177         panic("Resetting CPU ...\n");
178 }
179
180 /*
181  * do_bad_error handles the impossible case in the Error vector.
182  */
183 void do_bad_error(struct pt_regs *pt_regs)
184 {
185         efi_restore_gd();
186         printf("Bad mode in \"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
187         show_regs(pt_regs);
188         show_efi_loaded_images(pt_regs);
189         panic("Resetting CPU ...\n");
190 }
191
192 /*
193  * do_sync handles the Synchronous Abort exception.
194  */
195 void do_sync(struct pt_regs *pt_regs)
196 {
197         if (CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) &&
198             smh_emulate_trap(pt_regs))
199                 return;
200         efi_restore_gd();
201         printf("\"Synchronous Abort\" handler, esr 0x%08lx", pt_regs->esr);
202         dump_far(pt_regs->esr);
203         printf("\n");
204         show_regs(pt_regs);
205         show_efi_loaded_images(pt_regs);
206         panic("Resetting CPU ...\n");
207 }
208
209 /*
210  * do_irq handles the Irq exception.
211  */
212 void do_irq(struct pt_regs *pt_regs)
213 {
214         efi_restore_gd();
215         printf("\"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
216         show_regs(pt_regs);
217         show_efi_loaded_images(pt_regs);
218         panic("Resetting CPU ...\n");
219 }
220
221 /*
222  * do_fiq handles the Fiq exception.
223  */
224 void do_fiq(struct pt_regs *pt_regs)
225 {
226         efi_restore_gd();
227         printf("\"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
228         show_regs(pt_regs);
229         show_efi_loaded_images(pt_regs);
230         panic("Resetting CPU ...\n");
231 }
232
233 /*
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.
238  */
239 void __weak do_error(struct pt_regs *pt_regs)
240 {
241         efi_restore_gd();
242         printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
243         show_regs(pt_regs);
244         show_efi_loaded_images(pt_regs);
245         panic("Resetting CPU ...\n");
246 }
This page took 0.0349 seconds and 4 git commands to generate.