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: 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 50#include "lib_types.h" 51#include "lib_string.h" 52#include "lib_printf.h" 53#include "lib_queue.h" 54#include "lib_malloc.h" 55#include <hndrte_armtrap.h> 56#include "exception.h" 57#include "cfe.h" 58#include "cfe_error.h" 59#include "cfe_iocb.h" 60#include "exchandler.h" 61#include "cpu_config.h" 62#include "bsp_config.h" 63 64/* ********************************************************************* 65 * Constants 66 ********************************************************************* */ 67 68/* ********************************************************************* 69 * Globals 70 ********************************************************************* */ 71 72exc_handler_t exc_handler; 73//extern void _exc_entry(void); 74//extern void _exc_setup_locore(long); 75extern void CPUCFG_TLBHANDLER(void); 76extern void cfe_flushcache(uint32_t,long,long); 77extern uint32_t _getstatus(void); 78extern void _setstatus(uint32_t); 79 80 81/* ********************************************************************* 82 * cfe_exception(code,info) 83 * 84 * Exception handler. This routine is called when any CPU 85 * exception that is handled by the assembly-language 86 * vectors is reached. The usual thing to do here is just to 87 * reboot. 88 * 89 * Input parameters: 90 * code - exception type 91 * info - exception stack frame 92 * 93 * Return value: 94 * usually reboots 95 ********************************************************************* */ 96void cfe_exception(trap_t *tr) 97{ 98 /* 99 * ARM7TDMI trap types: 100 * 0=RST, 1=UND, 2=SWI, 3=IAB, 4=DAB, 5=BAD, 6=IRQ, 7=FIQ 101 * 102 * ARM CM3 trap types: 103 * 1=RST, 2=NMI, 3=FAULT, 4=MM, 5=BUS, 6=USAGE, 11=SVC, 104 * 12=DMON, 14=PENDSV, 15=SYSTICK, 16+=ISR 105 * 106 * ARM CA9 trap types: 107 * 0=RST, 1=UND, 2=SWI, 3=IAB, 4=DAB, 5=BAD, 6=IRQ, 7=FIQ 108 */ 109 110 uint32 *stack = (uint32*)tr->r13; 111 char *tr_type_str[8] = {"RST", "UND", "SWI", "IAB", "DAB", "BAD", "IRQ", "FIQ"}; 112 char *type_str = "UKN"; 113 114 if (tr->type < 8) 115 type_str = tr_type_str[tr->type]; 116 117 /* Note that UTF parses the first line, so the format should not be changed. */ 118 printf("\nTRAP [%s](x)[%x]: pc[%x], lr[%x], sp[%x], cpsr[%x], spsr[%x]\n", 119 type_str, tr->type, (uint32)tr, tr->pc, tr->r14, tr->r13, tr->cpsr, tr->spsr); 120 printf(" r0[%x], r1[%x], r2[%x], r3[%x], r4[%x], r5[%x], r6[%x]\n", 121 tr->r0, tr->r1, tr->r2, tr->r3, tr->r4, tr->r5, tr->r6); 122 printf(" r7[%x], r8[%x], r9[%x], r10[%x], r11[%x], r12[%x]\n", 123 tr->r7, tr->r8, tr->r9, tr->r10, tr->r11, tr->r12); 124 125 /* 126 * stack content before trap occured 127 */ 128 printf("\n sp+0 %08x %08x %08x %08x\n", 129 stack[0], stack[1], stack[2], stack[3]); 130 printf(" sp+10 %08x %08x %08x %08x\n\n", 131 stack[4], stack[5], stack[6], stack[7]); 132 133 xprintf("\n"); 134 _exc_restart(); 135} 136 137/* ********************************************************************* 138 * cfe_setup_exceptions() 139 * 140 * Set up the exception handlers. 141 * 142 * Input parameters: 143 * nothing 144 * 145 * Return value: 146 * nothing 147 ********************************************************************* */ 148void cfe_setup_exceptions(void) 149{ 150 /* Set trap handler */ 151 hndrte_set_trap((uint32)cfe_exception); 152} 153 154 155/* ********************************************************************* 156 * exc_initialize_block() 157 * 158 * Set up the exception handler. Allow exceptions to be caught. 159 * Allocate memory for jmpbuf and store it away. 160 * 161 * Returns NULL if error in memory allocation. 162 * 163 * Input parameters: 164 * nothing 165 * 166 * Return value: 167 * jmpbuf_t structure, or NULL if no memory 168 ********************************************************************* */ 169jmpbuf_t *exc_initialize_block(void) 170{ 171 jmpbuf_t *jmpbuf_local; 172 173 exc_handler.catch_exc = 1; 174 175 /* Create the jmpbuf_t object */ 176 jmpbuf_local = (jmpbuf_t *) KMALLOC((sizeof(jmpbuf_t)),0); 177 178 if (jmpbuf_local == NULL) { 179 return NULL; 180 } 181 182 q_enqueue( &(exc_handler.jmpbuf_stack), &((*jmpbuf_local).stack)); 183 184 return jmpbuf_local; 185} 186 187/* ********************************************************************* 188 * exc_cleanup_block(dq_jmpbuf) 189 * 190 * Remove dq_jmpbuf from the exception handler stack and free 191 * the memory. 192 * 193 * Input parameters: 194 * dq_jmpbuf - block to deallocate 195 * 196 * Return value: 197 * nothing 198 ********************************************************************* */ 199 200void exc_cleanup_block(jmpbuf_t *dq_jmpbuf) 201{ 202 int count; 203 204 if (dq_jmpbuf == NULL) { 205 return; 206 } 207 208 count = q_count( &(exc_handler.jmpbuf_stack)); 209 210 if( count > 0 ) { 211 q_dequeue( &(*dq_jmpbuf).stack ); 212 KFREE(dq_jmpbuf); 213 } 214} 215 216/* ********************************************************************* 217 * exc_cleanup_handler(dq_jmpbuf,chain_exc) 218 * 219 * Clean a block, then chain to the next exception if required. 220 * 221 * Input parameters: 222 * dq_jmpbuf - current exception 223 * chain_exc - true if we should chain to the next handler 224 * 225 * Return value: 226 * nothing 227 ********************************************************************* */ 228 229void exc_cleanup_handler(jmpbuf_t *dq_jmpbuf, int chain_exc) 230{ 231 exc_cleanup_block(dq_jmpbuf); 232 233 if( chain_exc == EXC_CHAIN_EXC ) { 234 /*Go to next exception on stack */ 235 exc_longjmp_handler(); 236 } 237} 238 239 240 241/* ********************************************************************* 242 * exc_longjmp_handler() 243 * 244 * This routine long jumps to the exception handler on the top 245 * of the exception stack. 246 * 247 * Input parameters: 248 * nothing 249 * 250 * Return value: 251 * nothing 252 ********************************************************************* */ 253void exc_longjmp_handler(void) 254{ 255 int count; 256 jmpbuf_t *jmpbuf_local; 257 258 count = q_count( &(exc_handler.jmpbuf_stack)); 259 260 if( count > 0 ) { 261 jmpbuf_local = (jmpbuf_t *) q_getlast(&(exc_handler.jmpbuf_stack)); 262 263 SETLEDS("CFE "); 264 265 lib_longjmp( (*jmpbuf_local).jmpbuf, -1); 266 } 267} 268 269 270/* ********************************************************************* 271 * mem_peek(d,addr,type) 272 * 273 * Read memory of the specified type at the specified address. 274 * Exceptions are caught in the case of a bad memory reference. 275 * 276 * Input parameters: 277 * d - pointer to where data should be placed 278 * addr - address to read 279 * type - type of read to do (MEM_BYTE, etc.) 280 * 281 * Return value: 282 * 0 if ok 283 * else error code 284 ********************************************************************* */ 285 286int mem_peek(void *d, long addr, int type) 287{ 288 289 jmpbuf_t *jb; 290 291 jb = exc_initialize_block(); 292 if( jb == NULL ) { 293 return CFE_ERR_NOMEM; 294 } 295 296 if (exc_try(jb) == 0) { 297 298 switch (type) { 299 case MEM_BYTE: 300 *(uint8_t *)d = *((volatile uint8_t *) addr); 301 break; 302 case MEM_HALFWORD: 303 *(uint16_t *)d = *((volatile uint16_t *) addr); 304 break; 305 case MEM_WORD: 306 *(uint32_t *)d = *((volatile uint32_t *) addr); 307 break; 308 case MEM_QUADWORD: 309 *(uint64_t *)d = *((volatile uint64_t *) addr); 310 break; 311 default: 312 return CFE_ERR_INV_PARAM; 313 } 314 315 exc_cleanup_block(jb); 316 } 317 else { 318 /*Exception handler*/ 319 320 exc_cleanup_handler(jb, EXC_NORMAL_RETURN); 321 return CFE_ERR_GETMEM; 322 } 323 324 return 0; 325} 326 327/* ********************************************************************* 328 * Write memory of type at address addr with value val. 329 * Exceptions are caught, handled (error message) and function 330 * returns with 0. 331 * 332 * 1 success 333 * 0 failure 334 ********************************************************************* */ 335 336int mem_poke(long addr, uint64_t val, int type) 337{ 338 339 jmpbuf_t *jb; 340 341 jb = exc_initialize_block(); 342 if( jb == NULL ) { 343 return CFE_ERR_NOMEM; 344 } 345 346 if (exc_try(jb) == 0) { 347 348 switch (type) { 349 case MEM_BYTE: 350 *((volatile uint8_t *) addr) = (uint8_t) val; 351 break; 352 case MEM_HALFWORD: 353 *((volatile uint16_t *) addr) = (uint16_t) val; 354 break; 355 case MEM_WORD: 356 *((volatile uint32_t *) addr) = (uint32_t) val; 357 break; 358 case MEM_QUADWORD: 359 *((volatile uint64_t *) addr) = (uint64_t) val; 360 break; 361 default: 362 return CFE_ERR_INV_PARAM; 363 } 364 365 exc_cleanup_block(jb); 366 } 367 else { 368 /*Exception handler*/ 369 370 exc_cleanup_handler(jb, EXC_NORMAL_RETURN); 371 return CFE_ERR_SETMEM; 372 } 373 374 return 0; 375} 376