hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
 * (C) Copyright 2013
 * David Feng <fenghua@phytium.com.cn>
 *
 * SPDX-License-Identifier:    GPL-2.0+
 */
 
#include <common.h>
#include <linux/compiler.h>
#include <efi_loader.h>
#include <iomem.h>
#include <stacktrace.h>
 
DECLARE_GLOBAL_DATA_PTR;
 
#if !CONFIG_IS_ENABLED(IRQ)
int interrupt_init(void)
{
   return 0;
}
 
void enable_interrupts(void)
{
   return;
}
 
int disable_interrupts(void)
{
   return 0;
}
#endif
 
#define REG_BITS(val, shift, mask)    (((val) >> (shift)) & (mask))
 
#ifndef CONFIG_SPL_BUILD
void show_regs(struct pt_regs *regs)
{
   int el = current_el();
   int i;
 
   const char *esr_bits_ec[] = {
       [0]  = "an unknown reason",
       [1]  = "a WFI or WFE instruction",
       [3]  = "an MCR or MRC access",
       [4]  = "an MCRR or MRRC access",
       [5]  = "an MCR or MRC access",
       [6]  = "an LDC or STC access to CP14",
       [7]  = "an access to an Advanced SIMD or floating-point register, resulting from CPACR_EL1.FPEN or CPTR_ELx.TFP",
       [8]  = "an MCR or MRC access",
       [12] = "an MCRR or MRRC access",
       [14] = "an Illegal execution state, or a PC or SP alignment fault",
       [10] = "HVC or SVC instruction execution",
       [18] = "HVC or SVC instruction execution",
       [19] = "SMC instruction execution in AArch32 state",
       [21] = "HVC or SVC instruction execution",
       [22] = "HVC or SVC instruction execution",
       [23] = "SMC instruction execution in AArch64 state",
       [24] = "MSR, MRS, or System instruction execution in AArch64 state",
       [31] = "IMPLEMENTATION DEFINED exception to EL3",
       [32] = "an Instruction abort",
       [33] = "an Instruction abort",
       [34] = "an Illegal execution state, or a PC or SP alignment fault",
       [36] = "a Data abort, from lower exception level",
       [37] = "a Data abort, from current exception level",
       [38] = "an Illegal execution state, or a PC or SP alignment fault",
       [40] = "a trapped Floating-point exception",
       [44] = "a trapped Floating-point exception",
       [47] = "SError interrupt",
       [48] = "a Breakpoint or Vector Catch debug event",
       [49] = "a Breakpoint or Vector Catch debug event",
       [50] = "a Software Step debug event",
       [51] = "a Software Step debug event",
       [52] = "a Watchpoint debug event",
       [53] = "a Watchpoint debug event",
       [56] = "execution of a Software Breakpoint instructio",
   };
 
   printf("\n");
 
   /* PC/LR/SP ... */
   printf("* Reason:        Exception from %s\n", esr_bits_ec[REG_BITS(regs->esr, 26, 0x3f)]);
   if (gd->flags & GD_FLG_RELOC) {
       printf("* PC         =   %016lx\n", regs->elr - gd->reloc_off);
       printf("* LR         =   %016lx\n", regs->regs[30] - gd->reloc_off);
   } else {
       printf("* ELR(PC)    =   %016lx\n", regs->elr);
       printf("* LR         =   %016lx\n", regs->regs[30]);
   }
   printf("* SP         =   %016lx\n", regs->sp);
   printf("* ESR_EL%d    =   %016lx\n", el, regs->esr);
   printf("* Reloc Off  =   %016lx\n\n", gd->reloc_off);
 
   /* CPU */
   for (i = 0; i < 29; i += 2)
       printf("x%-2d: %016lx x%-2d: %016lx\n",
              i, regs->regs[i], i+1, regs->regs[i+1]);
   printf("\n");
 
   /* SoC */
#ifdef CONFIG_ROCKCHIP_CRASH_DUMP
   iomem_show_by_compatible("-cru", 0, 0x400);
   iomem_show_by_compatible("-pmucru", 0, 0x400);
   iomem_show_by_compatible("-grf", 0, 0x400);
   iomem_show_by_compatible("-pmugrf", 0, 0x400);
#endif
   /* Call trace */
   dump_core_stack(regs);
}
 
#else
void show_regs(struct pt_regs *regs)
{
   int i;
 
   if (gd->flags & GD_FLG_RELOC) {
       printf("ELR:     %lx\n", regs->elr - gd->reloc_off);
       printf("LR:      %lx\n", regs->regs[30] - gd->reloc_off);
   } else {
       printf("ELR:     %lx\n", regs->elr);
       printf("LR:      %lx\n", regs->regs[30]);
   }
 
   printf("ESR:     %lx (ec=%ld)\n", regs->esr, REG_BITS(regs->esr, 26, 0x3f));
 
   for (i = 0; i < 29; i += 2)
       printf("x%-2d: %016lx x%-2d: %016lx\n",
              i, regs->regs[i], i+1, regs->regs[i+1]);
   printf("\n");
 
   dump_core_stack(regs);
}
#endif
 
/*
 * do_bad_sync handles the impossible case in the Synchronous Abort vector.
 */
void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
{
   efi_restore_gd();
   printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
   show_regs(pt_regs);
   panic("Resetting CPU ...\n");
}
 
/*
 * do_bad_irq handles the impossible case in the Irq vector.
 */
void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
{
   efi_restore_gd();
   printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
   show_regs(pt_regs);
   panic("Resetting CPU ...\n");
}
 
/*
 * do_bad_fiq handles the impossible case in the Fiq vector.
 */
void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
{
   efi_restore_gd();
   printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
   show_regs(pt_regs);
   panic("Resetting CPU ...\n");
}
 
/*
 * do_bad_error handles the impossible case in the Error vector.
 */
void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
{
   efi_restore_gd();
   printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
   show_regs(pt_regs);
   panic("Resetting CPU ...\n");
}
 
/*
 * do_sync handles the Synchronous Abort exception.
 */
void do_sync(struct pt_regs *pt_regs, unsigned int esr)
{
   efi_restore_gd();
   printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
   show_regs(pt_regs);
   panic("Resetting CPU ...\n");
}
 
#if !CONFIG_IS_ENABLED(IRQ)
/*
 * do_irq handles the Irq exception.
 */
void do_irq(struct pt_regs *pt_regs, unsigned int esr)
{
   efi_restore_gd();
   printf("\"Irq\" handler, esr 0x%08x\n", esr);
   show_regs(pt_regs);
   panic("Resetting CPU ...\n");
}
#endif
 
/*
 * do_fiq handles the Fiq exception.
 */
void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
{
   efi_restore_gd();
   printf("\"Fiq\" handler, esr 0x%08x\n", esr);
   show_regs(pt_regs);
   panic("Resetting CPU ...\n");
}
 
/*
 * do_error handles the Error exception.
 * Errors are more likely to be processor specific,
 * it is defined with weak attribute and can be redefined
 * in processor specific code.
 */
void __weak do_error(struct pt_regs *pt_regs, unsigned int esr)
{
   efi_restore_gd();
   printf("\"Error\" handler, esr 0x%08x\n", esr);
   show_regs(pt_regs);
   panic("Resetting CPU ...\n");
}