1 /* $NetBSD: frame.h,v 1.6 2003/10/05 19:44:58 matt Exp $ */ 2 3 /* 4 * Copyright (c) 1994-1997 Mark Brinicombe. 5 * Copyright (c) 1994 Brini. 6 * All rights reserved. 7 * 8 * This code is derived from software written for Brini by Mark Brinicombe 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Brini. 21 * 4. The name of the company nor the name of the author may be used to 22 * endorse or promote products derived from this software without specific 23 * prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * $FreeBSD$ 38 */ 39 40 #ifndef _MACHINE_ASMACROS_H_ 41 #define _MACHINE_ASMACROS_H_ 42 43 #ifdef _KERNEL 44 45 #ifdef LOCORE 46 47 /* 48 * ASM macros for pushing and pulling trapframes from the stack 49 * 50 * These macros are used to handle the irqframe and trapframe structures 51 * defined above. 52 */ 53 54 /* 55 * PUSHFRAME - macro to push a trap frame on the stack in the current mode 56 * Since the current mode is used, the SVC lr field is not defined. 57 * 58 * NOTE: r13 and r14 are stored separately as a work around for the 59 * SA110 rev 2 STM^ bug 60 */ 61 62 #define PUSHFRAME \ 63 str lr, [sp, #-4]!; /* Push the return address */ \ 64 sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ 65 stmia sp, {r0-r12}; /* Push the user mode registers */ \ 66 add r0, sp, #(4*13); /* Adjust the stack pointer */ \ 67 stmia r0, {r13-r14}^; /* Push the user mode registers */ \ 68 mov r0, r0; /* NOP for previous instruction */ \ 69 mrs r0, spsr_all; /* Put the SPSR on the stack */ \ 70 str r0, [sp, #-4]!; 71 72 /* 73 * PULLFRAME - macro to pull a trap frame from the stack in the current mode 74 * Since the current mode is used, the SVC lr field is ignored. 75 */ 76 77 #define PULLFRAME \ 78 ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ 79 msr spsr_all, r0; \ 80 ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ 81 mov r0, r0; /* NOP for previous instruction */ \ 82 add sp, sp, #(4*17); /* Adjust the stack pointer */ \ 83 ldr lr, [sp], #0x0004; /* Pull the return address */ 84 85 /* 86 * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode 87 * This should only be used if the processor is not currently in SVC32 88 * mode. The processor mode is switched to SVC mode and the trap frame is 89 * stored. The SVC lr field is used to store the previous value of 90 * lr in SVC mode. 91 * 92 * NOTE: r13 and r14 are stored separately as a work around for the 93 * SA110 rev 2 STM^ bug 94 */ 95 96 #define PUSHFRAMEINSVC \ 97 stmdb sp, {r0-r3}; /* Save 4 registers */ \ 98 mov r0, lr; /* Save xxx32 r14 */ \ 99 mov r1, sp; /* Save xxx32 sp */ \ 100 mrs r3, spsr; /* Save xxx32 spsr */ \ 101 mrs r2, cpsr; /* Get the CPSR */ \ 102 bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ 103 orr r2, r2, #(PSR_SVC32_MODE); \ 104 msr cpsr_c, r2; /* Punch into SVC mode */ \ 105 mov r2, sp; /* Save SVC sp */ \ 106 str r0, [sp, #-4]!; /* Push return address */ \ 107 str lr, [sp, #-4]!; /* Push SVC lr */ \ 108 str r2, [sp, #-4]!; /* Push SVC sp */ \ 109 msr spsr_all, r3; /* Restore correct spsr */ \ 110 ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ 111 sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ 112 stmia sp, {r0-r12}; /* Push the user mode registers */ \ 113 add r0, sp, #(4*13); /* Adjust the stack pointer */ \ 114 stmia r0, {r13-r14}^; /* Push the user mode registers */ \ 115 mov r0, r0; /* NOP for previous instruction */ \ 116 mrs r0, spsr_all; /* Put the SPSR on the stack */ \ 117 str r0, [sp, #-4]! 118 119 /* 120 * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack 121 * in SVC32 mode and restore the saved processor mode and PC. 122 * This should be used when the SVC lr register needs to be restored on 123 * exit. 124 */ 125 126 #define PULLFRAMEFROMSVCANDEXIT \ 127 ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ 128 msr spsr_all, r0; /* restore SPSR */ \ 129 ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ 130 mov r0, r0; /* NOP for previous instruction */ \ 131 add sp, sp, #(4*15); /* Adjust the stack pointer */ \ 132 ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ 133 134 #define DATA(name) \ 135 .data ; \ 136 _ALIGN_DATA ; \ 137 .globl name ; \ 138 .type name, %object ; \ 139 name: 140 141 #define EMPTY 142 143 144 #define GET_CURPCB_ENTER \ 145 ldr r1, .Laflt_curpcb ;\ 146 ldr r1, [r1] 147 148 /* 149 * This macro must be invoked following PUSHFRAMEINSVC or PUSHFRAME at 150 * the top of interrupt/exception handlers. 151 * 152 * When invoked, r0 *must* contain the value of SPSR on the current 153 * trap/interrupt frame. This is always the case if ENABLE_ALIGNMENT_FAULTS 154 * is invoked immediately after PUSHFRAMEINSVC or PUSHFRAME. 155 */ 156 #define ENABLE_ALIGNMENT_FAULTS \ 157 and r0, r0, #(PSR_MODE) /* Test for USR32 mode */ ;\ 158 teq r0, #(PSR_USR32_MODE) ;\ 159 bne 1f /* Not USR mode skip AFLT */ ;\ 160 GET_CURPCB_ENTER /* r1 = curpcb */ ;\ 161 cmp r1, #0x00 /* curpcb NULL? */ ;\ 162 ldrne r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */ ;\ 163 tstne r1, #PCB_NOALIGNFLT ;\ 164 beq 1f /* AFLTs already enabled */ ;\ 165 ldr r2, .Laflt_cpufuncs ;\ 166 mov lr, pc ;\ 167 ldr pc, [r2, #CF_CONTROL] /* Enable alignment faults */ ;\ 168 1: 169 170 #define DO_AST_AND_RESTORE_ALIGNMENT_FAULTS \ 171 ldr r0, [sp] /* Get the SPSR from stack */ ;\ 172 mrs r4, cpsr /* save CPSR */ ;\ 173 and r0, r0, #(PSR_MODE) /* Returning to USR mode? */ ;\ 174 teq r0, #(PSR_USR32_MODE) ;\ 175 bne 2f /* Nope, get out now */ ;\ 176 bic r4, r4, #(I32_bit) ;\ 177 1: orr r0, r4, #(I32_bit) /* Disable IRQs */ ;\ 178 msr cpsr_c, r0 ;\ 179 ldr r5, .Laflt_curthread ;\ 180 ldr r5, [r5] ;\ 181 ldr r5, [r5, #(TD_FLAGS)] ;\ 182 and r5, r5, #(TDF_ASTPENDING) ;\ 183 teq r5, #0x00000000 ;\ 184 beq 2f /* Nope. Just bail */ ;\ 185 msr cpsr_c, r4 /* Restore interrupts */ ;\ 186 mov r0, sp ;\ 187 adr lr, 1b ;\ 188 b _C_LABEL(ast) /* ast(frame) */ ;\ 189 2: 190 191 #define AST_ALIGNMENT_FAULT_LOCALS ;\ 192 .Laflt_curpcb: ;\ 193 .word _C_LABEL(__pcpu) + PC_CURPCB ;\ 194 .Laflt_cpufuncs: ;\ 195 .word _C_LABEL(cpufuncs) ;\ 196 .Laflt_curthread: ;\ 197 .word _C_LABEL(__pcpu) + PC_CURTHREAD 198 199 200 #endif /* LOCORE */ 201 202 #endif /* _KERNEL */ 203 204 #endif /* !_MACHINE_ASMACROS_H_ */ 205