1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Exception Handler			File: exchandler.c
5    *
6    *  This is the "C" part of the exception handler and the
7    *  associated setup routines.  We call these routines from
8    *  the assembly-language exception handler.
9    *
10    *  Author:  Mitch Lichtenberg
11    *
12    *********************************************************************
13    *
14    *  Copyright 2000,2001,2002,2003
15    *  Broadcom Corporation. All rights reserved.
16    *
17    *  This software is furnished under license and may be used and
18    *  copied only in accordance with the following terms and
19    *  conditions.  Subject to these conditions, you may download,
20    *  copy, install, use, modify and distribute modified or unmodified
21    *  copies of this software in source and/or binary form.  No title
22    *  or ownership is transferred hereby.
23    *
24    *  1) Any source code used, modified or distributed must reproduce
25    *     and retain this copyright notice and list of conditions
26    *     as they appear in the source file.
27    *
28    *  2) No right is granted to use any trade name, trademark, or
29    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
30    *     name may not be used to endorse or promote products derived
31    *     from this software without the prior written permission of
32    *     Broadcom Corporation.
33    *
34    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46    *     THE POSSIBILITY OF SUCH DAMAGE.
47    ********************************************************************* */
48
49#include "cfe.h"
50#include "lib_try.h"
51#include "exception.h"
52#include "ppcdefs.h"
53
54/*  *********************************************************************
55    *  Macros
56    ********************************************************************* */
57
58#define INSTALL_VECTOR(vec,hand) install_handler(vec,(uint32_t) hand);
59
60/*  *********************************************************************
61    *  Constants
62    ********************************************************************* */
63
64/*  *********************************************************************
65    *  Globals
66    ********************************************************************* */
67
68extern uint32_t _readmsr(void);
69extern void _writemsr(uint32_t);
70exc_handler_t exc_handler;
71extern void _exc_entry(void);
72extern uint32_t cfe_doxreq(void *);
73
74static const char *regnames = "r0  r1  r2  r3  r4  r5  r6  r7  "
75                              "r8  r9  r10 r11 r12 r13 r14 r15 "
76                              "r16 r17 r18 r19 r20 r21 r22 r23 "
77                              "r24 r25 r26 r27 r28 r29 r30 r31 ";
78static const char *excnames =
79    "Rsvd0   " /* 0 */
80    "Reset   "
81    "MCheck  "
82    "DSI     "
83    "ISI     "
84    "INTR    "
85    "Align   "
86    "Program "
87    "FPUnavl "
88    "DECR    "
89    "CINT    "
90    "RsvdB   "
91    "Syscall "
92    "Trace   "
93    "RsvdE   "
94    "RsvdF   "
95    "ITLBMiss"
96    "DTLBMisL"
97    "DTLBMisS"
98    "IBreak  "
99    "SMI     ";
100
101
102/*  *********************************************************************
103    *  cfe_exception(code,info)
104    *
105    *  Exception handler.  This routine is called when any CPU
106    *  exception that is handled by the assembly-language
107    *  vectors is reached.  The usual thing to do here is just to
108    *  reboot.
109    *
110    *  Input parameters:
111    *  	   code - exception type
112    *  	   info - exception stack frame
113    *
114    *  Return value:
115    *  	   usually reboots
116    ********************************************************************* */
117
118void cfe_exception(int code,uint32_t *info)
119{
120    int idx;
121
122    if (exc_handler.catch_exc == 1) {
123	/* XXX do something to MSR bits here? */
124
125	/* Unwind exception, return to CFE. */
126	exc_handler.catch_exc = 0;
127	exc_longjmp_handler();
128	}
129
130    xprintf("** Exception 0x%04X: SRR0=%08X SRR1=%08X [%8s]\n",
131	    code,info[XSPR_SRR0],info[XSPR_SRR1],
132	    excnames + ((code >> 8) * 8));
133    xprintf("        LR=%08X CTR=%08X XER=%08X DSISR=%08X\n",
134	    info[XGR_LR],info[XGR_CTR],info[XSPR_XER],info[XSPR_DSISR]);
135    xprintf("\n");
136    for (idx = 0;idx < 32; idx+= 2) {
137	xprintf("        %3s = %08X     %3s = %08X\n",
138		regnames+(idx*4),
139		info[XGR_R0+idx],
140		regnames+((idx+1)*4),
141		info[XGR_R0+idx+1]);
142	}
143
144    xprintf("\n");
145    _exc_restart();
146}
147
148
149#if CFG_RELOC
150/*  *********************************************************************
151    *  install_handler(vec,entry)
152    *
153    *  Create and install a vector in low memory that jumps
154    *  to wherever CFE is currently located
155    *
156    *  Input parameters:
157    *      vec - vector offset
158    *      entry - location of handler
159    *
160    *  Return value:
161    *      nothing
162    ********************************************************************* */
163
164static void install_handler(uint32_t vec,uint32_t entry)
165{
166    /*
167     * Vector code is as follows:
168     *
169     *        7c 11 43 a6     mtsprg  1,r0
170     *        7c 08 02 a6     mflr    r0
171     *        7c 10 43 a6     mtsprg  0,r0
172     *        3c 00 EH EH     lis     r0,EHEH
173     *        60 00 EL EL     ori     r0,r0,ELEL
174     *        7c 08 03 a6     mtlr    r0
175     *        38 00 VV VV     li      r0,VVVV
176     *        4e 80 00 20     blr
177     */
178
179    volatile uint32_t *v = (volatile uint32_t *) vec;
180
181    /*
182     * Construct exception vector code in memory
183     */
184
185    *v++ = 0x7c1143a6;
186    *v++ = 0x7c0802a6;
187    *v++ = 0x7c1043a6;
188    *v++ = 0x3c000000 | (entry >> 16);
189    *v++ = 0x60000000 | (entry & 0xFFFF);
190    *v++ = 0x7c0803a6;
191    *v++ = 0x38000000 | (vec);
192    *v++ = 0x4e800020;
193
194    /*
195     * Flush from cache into memory
196     */
197
198    __asm __volatile ("dcbf 0,%0" :: "r"(vec));
199    __asm __volatile ("icbi 0,%0" :: "r"(vec));
200    __asm __volatile ("dcbf 0,%0" :: "r"(vec+CPUCFG_CACHELINESIZE));
201    __asm __volatile ("icbi 0,%0" :: "r"(vec+CPUCFG_CACHELINESIZE));
202
203}
204
205static void install_apientry(uint32_t vec,uint32_t entry)
206{
207    /*
208     * API dispatch looks like this:
209     *
210     *        38 21 ff fc     addi    r1,r1,-4
211     *        7c 08 02 a6     mflr    r0
212     *        90 01 00 00     stw     r0,0(r1)
213     *        3c 00 EH EH     lis     r0,EHEH
214     *        60 00 EL EL     ori     r0,r0,ELEL
215     *        7c 08 03 a6     mtlr    r0
216     *        4e 80 00 21     blrl
217     *        80 01 00 00     lwz     r0,0(r1)
218     *        38 21 00 04     addi    r1,r1,4
219     *        7c 08 03 a6     mtlr    r0
220     *        4e 80 00 20     blr
221     */
222
223    volatile uint32_t *vp = (volatile uint32_t *) vec;
224
225    *vp++ = 0x3821fffc;
226    *vp++ = 0x7c0802a6;
227    *vp++ = 0x90010000;
228    *vp++ = 0x3c000000 | (entry >> 16);
229    *vp++ = 0x60000000 | (entry & 0xFFFF);
230    *vp++ = 0x7c0803a6;
231    *vp++ = 0x4e800021;
232    *vp++ = 0x80010000;
233    *vp++ = 0x38210004;
234    *vp++ = 0x7c0803a6;
235    *vp++ = 0x4e800020;
236
237    __asm __volatile ("dcbf 0,%0" :: "r"(vec));
238    __asm __volatile ("icbi 0,%0" :: "r"(vec));
239    __asm __volatile ("dcbf 0,%0" :: "r"(vec+CPUCFG_CACHELINESIZE));
240    __asm __volatile ("icbi 0,%0" :: "r"(vec+CPUCFG_CACHELINESIZE));
241
242}
243#endif
244
245/*  *********************************************************************
246    *  cfe_setup_exceptions()
247    *
248    *  Set up the exception handlers.
249    *
250    *  Input parameters:
251    *  	   nothing
252    *
253    *  Return value:
254    *  	   nothing
255    ********************************************************************* */
256void cfe_setup_exceptions(void)
257{
258#if CFG_RELOC
259    uint32_t msr;
260#endif
261
262    /*
263     * Set up the exception stack (queue of jmpbufs that we follow on exception)
264     */
265
266    exc_handler.catch_exc = 0;
267    q_init( &(exc_handler.jmpbuf_stack));
268
269#if CFG_RELOC
270    /*
271     * Install the low-level vectors
272     */
273
274    INSTALL_VECTOR(EXC_OFF_MCHECK,_exc_entry);
275    INSTALL_VECTOR(EXC_OFF_DSI,_exc_entry);
276    INSTALL_VECTOR(EXC_OFF_ISI,_exc_entry);
277    INSTALL_VECTOR(EXC_OFF_INT,_exc_entry);
278    INSTALL_VECTOR(EXC_OFF_ALIGN,_exc_entry);
279    INSTALL_VECTOR(EXC_OFF_PROGRAM,_exc_entry);
280    INSTALL_VECTOR(EXC_OFF_FPUNVL,_exc_entry);
281    INSTALL_VECTOR(EXC_OFF_DECR,_exc_entry);
282    INSTALL_VECTOR(EXC_OFF_CINT,_exc_entry);
283    INSTALL_VECTOR(EXC_OFF_SYSCALL,_exc_entry);
284    INSTALL_VECTOR(EXC_OFF_TRACE,_exc_entry);
285    INSTALL_VECTOR(EXC_OFF_RSVD,_exc_entry);
286    INSTALL_VECTOR(EXC_OFF_ITLBMISS,_exc_entry);
287    INSTALL_VECTOR(EXC_OFF_DTLBMISS_LD,_exc_entry);
288    INSTALL_VECTOR(EXC_OFF_DTLBMISS_ST,_exc_entry);
289    INSTALL_VECTOR(EXC_OFF_SMI,_exc_entry);
290
291    install_apientry(0x1500,(uint32_t) cfe_doxreq);
292
293    /*
294     * Switch the CPU to using the RAM vectors.
295     */
296
297    msr = _readmsr();
298    msr &= ~M_MSR_IP;	/* turn off instruction prefix */
299    _writemsr(msr);
300#endif
301}
302
303
304
305
306
307
308
309
310
311
312
313
314