Merge tag 'fsl-qoriq-2022-10-18' of https://source.denx.de/u-boot/custodians/u-boot...
[platform/kernel/u-boot.git] / arch / arm / lib / interrupts_64.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2013
4  * David Feng <fenghua@phytium.com.cn>
5  */
6
7 #include <common.h>
8 #include <asm/esr.h>
9 #include <asm/global_data.h>
10 #include <asm/ptrace.h>
11 #include <irq_func.h>
12 #include <linux/compiler.h>
13 #include <efi_loader.h>
14 #include <semihosting.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 int interrupt_init(void)
19 {
20         enable_interrupts();
21
22         return 0;
23 }
24
25 void enable_interrupts(void)
26 {
27         return;
28 }
29
30 int disable_interrupts(void)
31 {
32         return 0;
33 }
34
35 static void show_efi_loaded_images(struct pt_regs *regs)
36 {
37         efi_print_image_infos((void *)regs->elr);
38 }
39
40 static 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
51 void show_regs(struct pt_regs *regs)
52 {
53         int i;
54
55         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
61         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");
65         dump_instr(regs);
66 }
67
68 /*
69  * Try to "emulate" a semihosting call in the event that we don't have a
70  * debugger attached.
71  */
72 static 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 /*
111  * do_bad_sync handles the impossible case in the Synchronous Abort vector.
112  */
113 void do_bad_sync(struct pt_regs *pt_regs)
114 {
115         efi_restore_gd();
116         printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08lx\n",
117                pt_regs->esr);
118         show_regs(pt_regs);
119         show_efi_loaded_images(pt_regs);
120         panic("Resetting CPU ...\n");
121 }
122
123 /*
124  * do_bad_irq handles the impossible case in the Irq vector.
125  */
126 void do_bad_irq(struct pt_regs *pt_regs)
127 {
128         efi_restore_gd();
129         printf("Bad mode in \"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
130         show_regs(pt_regs);
131         show_efi_loaded_images(pt_regs);
132         panic("Resetting CPU ...\n");
133 }
134
135 /*
136  * do_bad_fiq handles the impossible case in the Fiq vector.
137  */
138 void do_bad_fiq(struct pt_regs *pt_regs)
139 {
140         efi_restore_gd();
141         printf("Bad mode in \"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
142         show_regs(pt_regs);
143         show_efi_loaded_images(pt_regs);
144         panic("Resetting CPU ...\n");
145 }
146
147 /*
148  * do_bad_error handles the impossible case in the Error vector.
149  */
150 void do_bad_error(struct pt_regs *pt_regs)
151 {
152         efi_restore_gd();
153         printf("Bad mode in \"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
154         show_regs(pt_regs);
155         show_efi_loaded_images(pt_regs);
156         panic("Resetting CPU ...\n");
157 }
158
159 /*
160  * do_sync handles the Synchronous Abort exception.
161  */
162 void do_sync(struct pt_regs *pt_regs)
163 {
164         if (CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) &&
165             smh_emulate_trap(pt_regs))
166                 return;
167         efi_restore_gd();
168         printf("\"Synchronous Abort\" handler, esr 0x%08lx\n", pt_regs->esr);
169         show_regs(pt_regs);
170         show_efi_loaded_images(pt_regs);
171         panic("Resetting CPU ...\n");
172 }
173
174 /*
175  * do_irq handles the Irq exception.
176  */
177 void do_irq(struct pt_regs *pt_regs)
178 {
179         efi_restore_gd();
180         printf("\"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
181         show_regs(pt_regs);
182         show_efi_loaded_images(pt_regs);
183         panic("Resetting CPU ...\n");
184 }
185
186 /*
187  * do_fiq handles the Fiq exception.
188  */
189 void do_fiq(struct pt_regs *pt_regs)
190 {
191         efi_restore_gd();
192         printf("\"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
193         show_regs(pt_regs);
194         show_efi_loaded_images(pt_regs);
195         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  */
204 void __weak do_error(struct pt_regs *pt_regs)
205 {
206         efi_restore_gd();
207         printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
208         show_regs(pt_regs);
209         show_efi_loaded_images(pt_regs);
210         panic("Resetting CPU ...\n");
211 }