1 /** 2 * @file IA64minstate.h 3 * 4 * @remark Copy of source code from linux kernel 5 * @remark linux/arch/ia64/kernel/minstate.h 6 * 7 */ 8 9 #include <linux/config.h> 10 11 #include "IA64entry.h" 12 13 /* 14 * A couple of convenience macros that make writing and reading 15 * SAVE_MIN and SAVE_REST easier. 16 */ 17 #define rARPR r31 18 #define rCRIFS r30 19 #define rCRIPSR r29 20 #define rCRIIP r28 21 #define rARRSC r27 22 #define rARPFS r26 23 #define rARUNAT r25 24 #define rARRNAT r24 25 #define rARBSPSTORE r23 26 #define rKRBS r22 27 #define rB6 r21 28 #define rR1 r20 29 30 /* 31 * Here start the source dependent macros. 32 */ 33 34 /* 35 * For ivt.s we want to access the stack virtually so we dont have 36 * to disable translation on interrupts. 37 */ 38 #define MINSTATE_START_SAVE_MIN_VIRT \ 39 /* r1 = current (virtual) */ \ 40 dep r1=-1, r1, 61, 3; \ 41 /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ 42 (pUser) mov ar.rsc=0; \ 43 ;; \ 44 /* compute base of RBS */ \ 45 (pUser) addl rKRBS=IA64_RBS_OFFSET, r1; \ 46 (pUser) mov rARRNAT=ar.rnat; \ 47 /* get sp */ \ 48 (pKern) mov r1=sp; \ 49 ;; \ 50 /* compute base of memory stack */ \ 51 (pUser) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE, r1; \ 52 /* save ar.bspstore */ \ 53 (pUser) mov rARBSPSTORE=ar.bspstore; \ 54 ;; \ 55 /* if in kernel mode, use sp (r12) */ \ 56 (pKern) addl r1=-IA64_PT_REGS_SIZE, r1; \ 57 /* switch to kernel RBS */ \ 58 (pUser) mov ar.bspstore=rKRBS; \ 59 ;; \ 60 (pUser) mov r18=ar.bsp; \ 61 /* set eager mode, pl 0, little-endian, loadrs=0 */ \ 62 (pUser) mov ar.rsc=0x3; 63 64 #define MINSTATE_END_SAVE_MIN_VIRT \ 65 /* make `current' a kernel virtual address */ \ 66 or r13=r13, r14; \ 67 /* switch back to bank 1 (must be last in insn group) */ \ 68 bsw.1; \ 69 ;; 70 71 /* 72 * For mca_asm.S we want to access the stack physically since the state 73 * is saved before we go virtual and dont want to destroy the iip or ipsr. 74 */ 75 #define MINSTATE_START_SAVE_MIN_PHYS \ 76 (pKern) movl sp=ia64_init_stack+IA64_STK_OFFSET-IA64_PT_REGS_SIZE; \ 77 /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ 78 (pUser) mov ar.rsc=0; \ 79 /* compute base of register backing store */ \ 80 (pUser) addl rKRBS=IA64_RBS_OFFSET, r1; \ 81 ;; \ 82 (pUser) mov rARRNAT=ar.rnat; \ 83 /* compute physical addr of sp */ \ 84 (pKern) dep r1=0, sp, 61, 3; \ 85 /* compute base of memory stack */ \ 86 (pUser) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE, r1; \ 87 /* save ar.bspstore */ \ 88 (pUser) mov rARBSPSTORE=ar.bspstore; \ 89 /* compute kernel virtual addr of RBS */ \ 90 (pUser) dep rKRBS=-1, rKRBS, 61, 3; \ 91 ;; \ 92 /* if in kernel mode, use sp (r12) */ \ 93 (pKern) addl r1=-IA64_PT_REGS_SIZE, r1; \ 94 /* switch to kernel RBS */ \ 95 (pUser) mov ar.bspstore=rKRBS; \ 96 ;; \ 97 (pUser) mov r18=ar.bsp; \ 98 /* set eager mode, pl 0, little-endian, loadrs=0 */ \ 99 (pUser) mov ar.rsc=0x3; 100 101 #define MINSTATE_END_SAVE_MIN_PHYS \ 102 /* make sp a kernel virtual address */ \ 103 or r12=r12, r14; \ 104 /* make `current' a kernel virtual address */ \ 105 or r13=r13, r14; \ 106 ;; 107 108 #ifdef MINSTATE_VIRT 109 # define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_VIRT 110 # define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_VIRT 111 #endif 112 113 #ifdef MINSTATE_PHYS 114 # define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_PHYS 115 # define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_PHYS 116 #endif 117 118 /* 119 * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves 120 * the minimum state necessary that allows us to turn psr.ic back 121 * on. 122 * 123 * Assumed state upon entry: 124 * psr.ic: off 125 * psr.dt: off 126 * r31: contains saved predicates (pr) 127 * 128 * Upon exit, the state is as follows: 129 * psr.ic: off 130 * r2 = points to &pt_regs.r16 131 * r12 = kernel sp (kernel virtual address) 132 * r13 = points to current task_struct (kernel virtual address) 133 * p15 = TRUE if psr.i is set in cr.ipsr 134 * predicate registers (other than p2, p3, and p15), b6, r3, r8, r9, 135 * r10, r11, r14, r15: preserved 136 * 137 * Note that psr.ic is NOT turned on by this macro. This is so that 138 * we can pass interruption state as arguments to a handler. 139 */ 140 #define DO_SAVE_MIN(COVER, SAVE_IFS, EXTRA) \ 141 mov rARRSC=ar.rsc; \ 142 mov rARPFS=ar.pfs; \ 143 mov rR1=r1; \ 144 mov rARUNAT=ar.unat; \ 145 mov rCRIPSR=cr.ipsr; \ 146 /* rB6 = branch reg 6 */ \ 147 mov rB6=b6; \ 148 mov rCRIIP=cr.iip; \ 149 /* r1 = current (physical) */ \ 150 mov r1=IA64_KR(CURRENT); \ 151 COVER; \ 152 ;; \ 153 invala; \ 154 /* extract psr.cpl */ \ 155 extr.u r16=rCRIPSR, 32, 2; \ 156 ;; \ 157 /* are we in kernel mode already? (psr.cpl==0) */ \ 158 cmp.eq pKern, pUser=r0, r16; \ 159 /* switch from user to kernel RBS: */ \ 160 ;; \ 161 SAVE_IFS; \ 162 MINSTATE_START_SAVE_MIN \ 163 ;; \ 164 /* initialize first base pointer */ \ 165 mov r16=r1; \ 166 /* initialize second base pointer */ \ 167 adds r17=8, r1; \ 168 ;; \ 169 st8 [r16]=rCRIPSR, 16; /* save cr.ipsr */ \ 170 st8 [r17]=rCRIIP, 16; /* save cr.iip */ \ 171 (pKern) mov r18=r0; /* make sure r18 isn't NaT */ \ 172 ;; \ 173 st8 [r16]=rCRIFS, 16; /* save cr.ifs */ \ 174 st8 [r17]=rARUNAT, 16; /* save ar.unat */ \ 175 (pUser) sub r18=r18, rKRBS; /* r18=RSE.ndirty*8 */ \ 176 ;; \ 177 st8 [r16]=rARPFS, 16; /* save ar.pfs */ \ 178 st8 [r17]=rARRSC, 16; /* save ar.rsc */ \ 179 tbit.nz p15, p0=rCRIPSR, IA64_PSR_I_BIT \ 180 ;; /* avoid RAW on r16 & r17 */ \ 181 (pKern) adds r16=16, r16; /* skip over ar_rnat field */ \ 182 (pKern) adds r17=16, r17; /* skip over ar_bspstore field */ \ 183 (pUser) st8 [r16]=rARRNAT, 16; /* save ar.rnat */ \ 184 (pUser) st8 [r17]=rARBSPSTORE, 16; /* save ar.bspstore */ \ 185 ;; \ 186 st8 [r16]=rARPR, 16; /* save predicates */ \ 187 st8 [r17]=rB6, 16; /* save b6 */ \ 188 /* compute ar.rsc to be used for "loadrs" */ \ 189 shl r18=r18, 16; \ 190 ;; \ 191 st8 [r16]=r18, 16; /* save ar.rsc value for "loadrs" */ \ 192 st8.spill [r17]=rR1, 16; /* save original r1 */ \ 193 ;; \ 194 .mem.offset 0, 0; st8.spill [r16]=r2, 16; \ 195 .mem.offset 8, 0; st8.spill [r17]=r3, 16; \ 196 adds r2=IA64_PT_REGS_R16_OFFSET, r1; \ 197 ;; \ 198 .mem.offset 0, 0; st8.spill [r16]=r12, 16; \ 199 .mem.offset 8, 0; st8.spill [r17]=r13, 16; \ 200 /* initialize pSys=0, pNonSys=1 */ \ 201 cmp.eq pNonSys, pSys=r0, r0 \ 202 ;; \ 203 .mem.offset 0, 0; st8.spill [r16]=r14, 16; \ 204 .mem.offset 8, 0; st8.spill [r17]=r15, 16; \ 205 dep r14=-1, r0, 61, 3; \ 206 ;; \ 207 .mem.offset 0, 0; st8.spill [r16]=r8, 16; \ 208 .mem.offset 8, 0; st8.spill [r17]=r9, 16; \ 209 /* switch to kernel memory stack (with 16 bytes of scratch) */ \ 210 adds r12=-16, r1; \ 211 ;; \ 212 .mem.offset 0, 0; st8.spill [r16]=r10, 16; \ 213 .mem.offset 8, 0; st8.spill [r17]=r11, 16; \ 214 mov r13=IA64_KR(CURRENT); /* establish `current' */ \ 215 ;; \ 216 EXTRA; \ 217 movl r1=__gp; /* establish kernel global pointer */ \ 218 ;; \ 219 MINSTATE_END_SAVE_MIN 220 221 /* 222 * SAVE_REST saves the remainder of pt_regs (with psr.ic on). This 223 * macro guarantees to preserve all predicate registers, r8, r9, r10, 224 * r11, r14, and r15. 225 * 226 * Assumed state upon entry: 227 * psr.ic: on 228 * psr.dt: on 229 * r2: points to &pt_regs.r16 230 * r3: points to &pt_regs.r17 231 */ 232 #define SAVE_REST \ 233 .mem.offset 0, 0; st8.spill [r2]=r16, 16; \ 234 .mem.offset 8, 0; st8.spill [r3]=r17, 16; \ 235 ;; \ 236 .mem.offset 0, 0; st8.spill [r2]=r18, 16; \ 237 .mem.offset 8, 0; st8.spill [r3]=r19, 16; \ 238 ;; \ 239 mov r16=ar.ccv; /* M-unit */ \ 240 movl r18=FPSR_DEFAULT /* L-unit */ \ 241 ;; \ 242 mov r17=ar.fpsr; /* M-unit */ \ 243 mov ar.fpsr=r18; /* M-unit */ \ 244 ;; \ 245 .mem.offset 0, 0; st8.spill [r2]=r20, 16; \ 246 .mem.offset 8, 0; st8.spill [r3]=r21, 16; \ 247 mov r18=b0; \ 248 ;; \ 249 .mem.offset 0, 0; st8.spill [r2]=r22, 16; \ 250 .mem.offset 8, 0; st8.spill [r3]=r23, 16; \ 251 mov r19=b7; \ 252 ;; \ 253 .mem.offset 0, 0; st8.spill [r2]=r24, 16; \ 254 .mem.offset 8, 0; st8.spill [r3]=r25, 16; \ 255 ;; \ 256 .mem.offset 0, 0; st8.spill [r2]=r26, 16; \ 257 .mem.offset 8, 0; st8.spill [r3]=r27, 16; \ 258 ;; \ 259 .mem.offset 0, 0; st8.spill [r2]=r28, 16; \ 260 .mem.offset 8, 0; st8.spill [r3]=r29, 16; \ 261 ;; \ 262 .mem.offset 0, 0; st8.spill [r2]=r30, 16; \ 263 .mem.offset 8, 0; st8.spill [r3]=r31, 16; \ 264 ;; \ 265 st8 [r2]=r16, 16; /* ar.ccv */ \ 266 st8 [r3]=r17, 16; /* ar.fpsr */ \ 267 ;; \ 268 st8 [r2]=r18, 16; /* b0 */ \ 269 st8 [r3]=r19, 16+8; /* b7 */ \ 270 ;; \ 271 stf.spill [r2]=f6, 32; \ 272 stf.spill [r3]=f7, 32; \ 273 ;; \ 274 stf.spill [r2]=f8, 32; \ 275 stf.spill [r3]=f9, 32 276 277 #define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov rCRIFS=cr.ifs,) 278 #define SAVE_MIN_WITH_COVER_R19 \ 279 DO_SAVE_MIN(cover, mov rCRIFS=cr.ifs, mov r15=r19) 280 #define SAVE_MIN DO_SAVE_MIN(, mov rCRIFS=r0,) 281