Home | History | Annotate | Line # | Download | only in arm32
exception.S revision 1.14.52.1
      1  1.14.52.1     matt /*	$NetBSD: exception.S,v 1.14.52.1 2007/08/28 18:51:57 matt Exp $	*/
      2        1.1    chris 
      3        1.1    chris /*
      4        1.1    chris  * Copyright (c) 1994-1997 Mark Brinicombe.
      5        1.1    chris  * Copyright (c) 1994 Brini.
      6        1.1    chris  * All rights reserved.
      7        1.1    chris  *
      8        1.1    chris  * This code is derived from software written for Brini by Mark Brinicombe
      9        1.1    chris  *
     10        1.1    chris  * Redistribution and use in source and binary forms, with or without
     11        1.1    chris  * modification, are permitted provided that the following conditions
     12        1.1    chris  * are met:
     13        1.1    chris  * 1. Redistributions of source code must retain the above copyright
     14        1.1    chris  *    notice, this list of conditions and the following disclaimer.
     15        1.1    chris  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1    chris  *    notice, this list of conditions and the following disclaimer in the
     17        1.1    chris  *    documentation and/or other materials provided with the distribution.
     18        1.1    chris  * 3. All advertising materials mentioning features or use of this software
     19        1.1    chris  *    must display the following acknowledgement:
     20        1.1    chris  *	This product includes software developed by Brini.
     21        1.1    chris  * 4. The name of the company nor the name of the author may be used to
     22        1.1    chris  *    endorse or promote products derived from this software without specific
     23        1.1    chris  *    prior written permission.
     24        1.1    chris  *
     25        1.1    chris  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
     26        1.1    chris  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     27        1.1    chris  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     28        1.1    chris  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     29        1.1    chris  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     30        1.1    chris  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     31        1.1    chris  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32        1.1    chris  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33        1.1    chris  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34        1.1    chris  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35        1.1    chris  * SUCH DAMAGE.
     36        1.1    chris  *
     37        1.1    chris  * RiscBSD kernel project
     38        1.1    chris  *
     39        1.1    chris  * exception.S
     40        1.1    chris  *
     41        1.1    chris  * Low level handlers for exception vectors
     42        1.1    chris  *
     43        1.1    chris  * Created      : 24/09/94
     44        1.1    chris  *
     45        1.1    chris  * Based on kate/display/abort.s
     46        1.1    chris  */
     47        1.1    chris 
     48  1.14.52.1     matt #include "opt_cpuoptions.h"
     49        1.1    chris #include "opt_ipkdb.h"
     50  1.14.52.1     matt #include "assym.h"
     51        1.1    chris #include <machine/asm.h>
     52        1.1    chris #include <machine/cpu.h>
     53        1.1    chris #include <machine/frame.h>
     54        1.1    chris 
     55        1.1    chris 	.text
     56        1.1    chris 	.align	0
     57        1.1    chris 
     58       1.12      scw AST_ALIGNMENT_FAULT_LOCALS
     59        1.1    chris 
     60        1.1    chris /*
     61        1.3  thorpej  * reset_entry:
     62        1.3  thorpej  *
     63        1.3  thorpej  *	Handler for Reset exception.
     64        1.3  thorpej  */
     65        1.3  thorpej ASENTRY_NP(reset_entry)
     66        1.3  thorpej 	adr	r0, Lreset_panicmsg
     67        1.3  thorpej 	mov	r1, lr
     68        1.3  thorpej 	bl	_C_LABEL(panic)
     69        1.3  thorpej 	/* NOTREACHED */
     70        1.3  thorpej Lreset_panicmsg:
     71        1.3  thorpej 	.asciz	"Reset vector called, LR = 0x%08x"
     72        1.3  thorpej 	.balign	4
     73        1.1    chris 
     74        1.3  thorpej /*
     75        1.3  thorpej  * swi_entry
     76        1.3  thorpej  *
     77        1.3  thorpej  *	Handler for the Software Interrupt exception.
     78        1.3  thorpej  */
     79        1.3  thorpej ASENTRY_NP(swi_entry)
     80        1.3  thorpej 	PUSHFRAME
     81        1.9      scw 	ENABLE_ALIGNMENT_FAULTS
     82        1.9      scw 
     83        1.3  thorpej 	mov	r0, sp			/* Pass the frame to any function */
     84        1.5    bjh21 	bl	_C_LABEL(swi_handler)	/* It's a SWI ! */
     85        1.1    chris 
     86       1.12      scw 	DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
     87        1.3  thorpej 	PULLFRAME
     88        1.3  thorpej 	movs	pc, lr			/* Exit */
     89        1.1    chris 
     90        1.3  thorpej /*
     91        1.3  thorpej  * prefetch_abort_entry:
     92        1.3  thorpej  *
     93        1.3  thorpej  *	Handler for the Prefetch Abort exception.
     94        1.3  thorpej  */
     95        1.1    chris ASENTRY_NP(prefetch_abort_entry)
     96       1.13      scw #ifdef __XSCALE__
     97       1.13      scw 	nop				/* Make absolutely sure any pending */
     98       1.13      scw 	nop				/* imprecise aborts have occurred. */
     99       1.13      scw #endif
    100        1.1    chris         sub     lr, lr, #0x00000004     /* Adjust the lr */
    101        1.1    chris 
    102        1.1    chris 	PUSHFRAMEINSVC
    103        1.9      scw 	ENABLE_ALIGNMENT_FAULTS
    104        1.9      scw 
    105       1.12      scw 	ldr	r1, Lprefetch_abort_handler_address
    106       1.12      scw 	adr	lr, exception_exit
    107        1.1    chris  	mov	r0, sp			/* pass the stack pointer as r0 */
    108       1.12      scw 	ldr	pc, [r1]
    109        1.1    chris 
    110        1.1    chris Lprefetch_abort_handler_address:
    111        1.1    chris 	.word	_C_LABEL(prefetch_abort_handler_address)
    112        1.1    chris 
    113        1.1    chris 	.data
    114        1.1    chris 	.global	_C_LABEL(prefetch_abort_handler_address)
    115        1.1    chris 
    116        1.1    chris _C_LABEL(prefetch_abort_handler_address):
    117        1.1    chris 	.word	abortprefetch
    118        1.1    chris 
    119        1.1    chris 	.text
    120        1.1    chris abortprefetch:
    121        1.7    bjh21         adr     r0, abortprefetchmsg
    122        1.1    chris 	b	_C_LABEL(panic)
    123        1.1    chris 
    124        1.1    chris abortprefetchmsg:
    125        1.1    chris         .asciz  "abortprefetch"
    126        1.1    chris         .align  0
    127        1.1    chris 
    128        1.1    chris /*
    129        1.3  thorpej  * data_abort_entry:
    130        1.1    chris  *
    131        1.3  thorpej  *	Handler for the Data Abort exception.
    132        1.1    chris  */
    133        1.3  thorpej ASENTRY_NP(data_abort_entry)
    134       1.13      scw #ifdef __XSCALE__
    135       1.13      scw 	nop				/* Make absolutely sure any pending */
    136       1.13      scw 	nop				/* imprecise aborts have occurred. */
    137       1.13      scw #endif
    138        1.3  thorpej         sub     lr, lr, #0x00000008     /* Adjust the lr */
    139        1.1    chris 
    140        1.3  thorpej 	PUSHFRAMEINSVC			/* Push trap frame and switch */
    141        1.3  thorpej 					/* to SVC32 mode */
    142        1.9      scw 	ENABLE_ALIGNMENT_FAULTS
    143        1.9      scw 
    144       1.12      scw 	ldr	r1, Ldata_abort_handler_address
    145       1.12      scw 	adr	lr, exception_exit
    146        1.3  thorpej 	mov	r0, sp			/* pass the stack pointer as r0 */
    147        1.3  thorpej 	ldr	pc, [r1]
    148        1.1    chris 
    149        1.3  thorpej Ldata_abort_handler_address:
    150        1.3  thorpej 	.word	_C_LABEL(data_abort_handler_address)
    151        1.1    chris 
    152        1.3  thorpej 	.data
    153        1.3  thorpej 	.global	_C_LABEL(data_abort_handler_address)
    154        1.3  thorpej _C_LABEL(data_abort_handler_address):
    155        1.3  thorpej 	.word	abortdata
    156        1.1    chris 
    157        1.3  thorpej 	.text
    158        1.3  thorpej abortdata:
    159        1.7    bjh21         adr     r0, abortdatamsg
    160        1.3  thorpej 	b	_C_LABEL(panic)
    161        1.1    chris 
    162        1.3  thorpej abortdatamsg:
    163        1.3  thorpej         .asciz  "abortdata"
    164        1.3  thorpej         .align  0
    165        1.1    chris 
    166        1.3  thorpej /*
    167        1.3  thorpej  * address_exception_entry:
    168        1.3  thorpej  *
    169        1.3  thorpej  *	Handler for the Address Exception exception.
    170        1.3  thorpej  *
    171        1.3  thorpej  *	NOTE: This exception isn't really used on arm32.  We
    172        1.3  thorpej  *	print a warning message to the console and then treat
    173        1.3  thorpej  *	it like a Data Abort.
    174        1.3  thorpej  */
    175        1.3  thorpej ASENTRY_NP(address_exception_entry)
    176        1.3  thorpej 	mrs	r1, cpsr_all
    177        1.3  thorpej 	mrs	r2, spsr_all
    178        1.3  thorpej 	mov	r3, lr
    179        1.3  thorpej 	adr	r0, Laddress_exception_msg
    180        1.3  thorpej 	bl	_C_LABEL(printf)	/* XXX CLOBBERS LR!! */
    181        1.3  thorpej 	b	data_abort_entry
    182        1.3  thorpej Laddress_exception_msg:
    183        1.3  thorpej 	.asciz	"Address Exception CPSR=0x%08x SPSR=0x%08x LR=0x%08x\n"
    184        1.3  thorpej 	.balign	4
    185       1.13      scw 
    186       1.13      scw /*
    187       1.13      scw  * General exception exit handler
    188       1.13      scw  * (Placed here to be within range of all the references to it)
    189       1.13      scw  *
    190       1.13      scw  * It exits straight away if not returning to USR mode.
    191       1.13      scw  * This loops around delivering any pending ASTs.
    192       1.13      scw  * Interrupts are disabled at suitable points to avoid ASTs
    193       1.13      scw  * being posted between testing and exit to user mode.
    194       1.13      scw  *
    195       1.13      scw  * This function uses PULLFRAMEFROMSVCANDEXIT and
    196       1.13      scw  * DO_AST_AND_RESTORE_ALIGNMENT_FAULTS thus should
    197       1.13      scw  * only be called if the exception handler used PUSHFRAMEINSVC
    198       1.13      scw  * followed by ENABLE_ALIGNMENT_FAULTS.
    199       1.13      scw  */
    200       1.13      scw 
    201       1.13      scw exception_exit:
    202       1.13      scw 	DO_AST_AND_RESTORE_ALIGNMENT_FAULTS
    203       1.13      scw 	PULLFRAMEFROMSVCANDEXIT
    204        1.1    chris 
    205        1.1    chris /*
    206        1.3  thorpej  * undefined_entry:
    207        1.3  thorpej  *
    208        1.3  thorpej  *	Handler for the Undefined Instruction exception.
    209        1.3  thorpej  *
    210        1.3  thorpej  *	We indirect the undefined vector via the handler address
    211        1.3  thorpej  *	in the data area.  Entry to the undefined handler must
    212        1.3  thorpej  *	look like direct entry from the vector.
    213        1.1    chris  */
    214        1.1    chris ASENTRY_NP(undefined_entry)
    215        1.1    chris #ifdef IPKDB
    216        1.1    chris /*
    217        1.1    chris  * IPKDB must be hooked in at the earliest possible entry point.
    218        1.1    chris  *
    219        1.1    chris  */
    220        1.1    chris /*
    221        1.1    chris  * Make room for all registers saving real r0-r7 and r15.
    222        1.1    chris  * The remaining registers are updated later.
    223        1.1    chris  */
    224        1.1    chris 	stmfd	sp!, {r0,r1}		/* psr & spsr */
    225        1.1    chris 	stmfd	sp!, {lr}		/* pc */
    226        1.1    chris 	stmfd	sp!, {r0-r14}		/* r0-r7, r8-r14 */
    227        1.1    chris /*
    228        1.1    chris  * Get previous psr.
    229        1.1    chris  */
    230        1.1    chris 	mrs	r7, cpsr_all
    231        1.1    chris 	mrs	r0, spsr_all
    232        1.1    chris 	str	r0, [sp, #(16*4)]
    233        1.1    chris /*
    234        1.1    chris  * Test for user mode.
    235        1.1    chris  */
    236        1.1    chris 	tst	r0, #0xf
    237        1.6   briggs 	bne	.Lprenotuser_push
    238        1.1    chris 	add	r1, sp, #(8*4)
    239        1.1    chris 	stmia	r1,{r8-r14}^		/* store user mode r8-r14*/
    240        1.6   briggs 	b	.Lgoipkdb
    241        1.1    chris /*
    242        1.1    chris  * Switch to previous mode to get r8-r13.
    243        1.1    chris  */
    244        1.6   briggs .Lprenotuser_push:
    245        1.1    chris 	orr	r0, r0, #(I32_bit) /* disable interrupts */
    246        1.1    chris 	msr	cpsr_all, r0
    247        1.1    chris 	mov	r1, r8
    248        1.1    chris 	mov	r2, r9
    249        1.1    chris 	mov	r3, r10
    250        1.1    chris 	mov	r4, r11
    251        1.1    chris 	mov	r5, r12
    252        1.1    chris 	mov	r6, r13
    253        1.1    chris 	msr	cpsr_all, r7		/* back to undefined mode */
    254        1.1    chris 	add	r8, sp, #(8*4)
    255        1.1    chris 	stmia	r8, {r1-r6}		/* r8-r13 */
    256        1.1    chris /*
    257        1.1    chris  * Now back to previous mode to get r14 and spsr.
    258        1.1    chris  */
    259        1.1    chris 	msr	cpsr_all, r0
    260        1.1    chris 	mov	r1, r14
    261        1.1    chris 	mrs	r2, spsr
    262        1.1    chris 	msr	cpsr_all, r7		/* back to undefined mode */
    263        1.1    chris 	str	r1, [sp, #(14*4)]	/* r14 */
    264        1.1    chris 	str	r2, [sp, #(17*4)]	/* spsr */
    265        1.1    chris /*
    266        1.1    chris  * Now to IPKDB.
    267        1.1    chris  */
    268        1.6   briggs .Lgoipkdb:
    269        1.1    chris 	mov	r0, sp
    270        1.1    chris 	bl	_C_LABEL(ipkdb_trap_glue)
    271        1.6   briggs 	ldr	r1, .Lipkdb_trap_return
    272        1.1    chris 	str	r0,[r1]
    273        1.9      scw 
    274        1.1    chris /*
    275        1.1    chris  * Have to load all registers from the stack.
    276        1.1    chris  *
    277        1.1    chris  * Start with spsr and pc.
    278        1.1    chris  */
    279        1.1    chris 	ldr	r0, [sp, #(16*4)]	/* spsr */
    280        1.1    chris 	ldr	r1, [sp, #(15*4)]	/* r15 */
    281        1.1    chris 	msr	spsr_all, r0
    282        1.1    chris 	mov	r14, r1
    283        1.1    chris /*
    284        1.1    chris  * Test for user mode.
    285        1.1    chris  */
    286        1.1    chris 	tst	r0, #0xf
    287        1.6   briggs 	bne	.Lprenotuser_pull
    288        1.1    chris 	add	r1, sp, #(8*4)
    289        1.1    chris 	ldmia	r1, {r8-r14}^		/* load user mode r8-r14 */
    290        1.6   briggs 	b	.Lpull_r0r7
    291        1.6   briggs .Lprenotuser_pull:
    292        1.1    chris /*
    293        1.1    chris  * Now previous mode spsr and r14.
    294        1.1    chris  */
    295        1.1    chris 	ldr	r1, [sp, #(17*4)]		/* spsr */
    296        1.1    chris 	ldr	r2, [sp, #(14*4)]		/* r14 */
    297        1.1    chris 	orr	r0, r0, #(I32_bit)
    298        1.1    chris 	msr	cpsr_all, r0			/* switch to previous mode */
    299        1.1    chris 	msr	spsr_all, r1
    300        1.1    chris 	mov	r14, r2
    301        1.1    chris 	msr	cpsr_all, r7			/* back to undefined mode */
    302        1.1    chris /*
    303        1.1    chris  * Now r8-r13.
    304        1.1    chris  */
    305        1.1    chris 	add	r8, sp, #(8*4)
    306        1.1    chris 	ldmia	r8, {r1-r6}		/* r8-r13 */
    307        1.1    chris 	msr	cpsr_all, r0
    308        1.1    chris 	mov	r8, r1
    309        1.1    chris 	mov	r9, r2
    310        1.1    chris 	mov	r10, r3
    311        1.1    chris 	mov	r11, r4
    312        1.1    chris 	mov	r12, r5
    313        1.1    chris 	mov	r13, r6
    314        1.1    chris 	msr	cpsr_all, r7
    315        1.6   briggs .Lpull_r0r7:
    316        1.1    chris /*
    317        1.1    chris  * Now the rest of the registers.
    318        1.1    chris  */
    319        1.1    chris 	ldr	r1,Lipkdb_trap_return
    320        1.1    chris 	ldr	r0,[r1]
    321        1.1    chris 	tst	r0,r0
    322        1.1    chris 	ldmfd	sp!, {r0-r7}		/* r0-r7 */
    323        1.1    chris 	add	sp, sp, #(10*4)		/* adjust sp */
    324        1.1    chris 
    325        1.1    chris /*
    326        1.1    chris  * Did IPKDB handle it?
    327        1.1    chris  */
    328        1.1    chris 	movnes	pc, lr			/* return */
    329        1.1    chris 
    330        1.1    chris #endif
    331        1.1    chris 	stmfd	sp!, {r0, r1}
    332        1.1    chris 	ldr	r0, Lundefined_handler_indirection
    333        1.1    chris 	ldr	r1, [sp], #0x0004
    334        1.1    chris 	str	r1, [r0, #0x0000]
    335        1.1    chris 	ldr	r1, [sp], #0x0004
    336        1.1    chris 	str	r1, [r0, #0x0004]
    337        1.1    chris 	ldmia	r0, {r0, r1, pc}
    338        1.1    chris 
    339        1.1    chris #ifdef IPKDB
    340        1.1    chris Lipkdb_trap_return:
    341        1.1    chris 	.word	Lipkdb_trap_return_data
    342        1.1    chris #endif
    343        1.1    chris 
    344        1.1    chris Lundefined_handler_indirection:
    345        1.1    chris 	.word	Lundefined_handler_indirection_data
    346        1.1    chris 
    347        1.1    chris /*
    348        1.1    chris  * assembly bounce code for calling the kernel
    349        1.1    chris  * undefined instruction handler. This uses
    350        1.1    chris  * a standard trap frame and is called in SVC mode.
    351        1.1    chris  */
    352        1.1    chris 
    353        1.1    chris ENTRY_NP(undefinedinstruction_bounce)
    354        1.1    chris 	PUSHFRAMEINSVC
    355        1.9      scw 	ENABLE_ALIGNMENT_FAULTS
    356       1.12      scw 
    357        1.1    chris 	mov	r0, sp
    358       1.12      scw 	adr	lr, exception_exit
    359       1.12      scw 	b	_C_LABEL(undefinedinstruction)
    360        1.1    chris 
    361        1.1    chris 	.data
    362        1.1    chris 	.align	0
    363        1.1    chris 
    364        1.1    chris #ifdef IPKDB
    365        1.1    chris Lipkdb_trap_return_data:
    366        1.1    chris 	.word	0
    367        1.1    chris #endif
    368        1.1    chris 
    369        1.1    chris /*
    370        1.1    chris  * Indirection data
    371        1.1    chris  * 2 words use for preserving r0 and r1
    372        1.1    chris  * 3rd word contains the undefined handler address.
    373        1.1    chris  */
    374        1.1    chris 
    375        1.1    chris Lundefined_handler_indirection_data:
    376        1.1    chris 	.word	0
    377        1.1    chris 	.word	0
    378        1.1    chris 
    379        1.1    chris 	.global	_C_LABEL(undefined_handler_address)
    380        1.1    chris _C_LABEL(undefined_handler_address):
    381        1.1    chris 	.word	_C_LABEL(undefinedinstruction_bounce)
    382