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