1/* 2 * PAL Firmware support 3 * IA-64 Processor Programmers Reference Vol 2 4 * 5 * Copyright (C) 1999 Don Dugger <don.dugger@intel.com> 6 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> 7 * Copyright (C) 1999-2001, 2003 Hewlett-Packard Co 8 * David Mosberger <davidm@hpl.hp.com> 9 * Stephane Eranian <eranian@hpl.hp.com> 10 * 11 * 05/22/2000 eranian Added support for stacked register calls 12 * 05/24/2000 eranian Added support for physical mode static calls 13 */ 14 15#include <asm/asmmacro.h> 16#include <asm/processor.h> 17 18 .data 19pal_entry_point: 20 data8 ia64_pal_default_handler 21 .text 22 23/* 24 * Set the PAL entry point address. This could be written in C code, but we do it here 25 * to keep it all in one module (besides, it's so trivial that it's 26 * not a big deal). 27 * 28 * in0 Address of the PAL entry point (text address, NOT a function descriptor). 29 */ 30GLOBAL_ENTRY(ia64_pal_handler_init) 31 alloc r3=ar.pfs,1,0,0,0 32 movl r2=pal_entry_point 33 ;; 34 st8 [r2]=in0 35 br.ret.sptk.many rp 36END(ia64_pal_handler_init) 37 38/* 39 * Default PAL call handler. This needs to be coded in assembly because it uses 40 * the static calling convention, i.e., the RSE may not be used and calls are 41 * done via "br.cond" (not "br.call"). 42 */ 43GLOBAL_ENTRY(ia64_pal_default_handler) 44 mov r8=-1 45 br.cond.sptk.many rp 46END(ia64_pal_default_handler) 47 48/* 49 * Make a PAL call using the static calling convention. 50 * 51 * in0 Index of PAL service 52 * in1 - in3 Remaining PAL arguments 53 * in4 1 ==> clear psr.ic, 0 ==> don't clear psr.ic 54 * 55 */ 56GLOBAL_ENTRY(ia64_pal_call_static) 57 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5) 58 alloc loc1 = ar.pfs,5,5,0,0 59 movl loc2 = pal_entry_point 601: { 61 mov r28 = in0 62 mov r29 = in1 63 mov r8 = ip 64 } 65 ;; 66 ld8 loc2 = [loc2] // loc2 <- entry point 67 tbit.nz p6,p7 = in4, 0 68 adds r8 = 1f-1b,r8 69 mov loc4=ar.rsc // save RSE configuration 70 ;; 71 mov ar.rsc=0 // put RSE in enforced lazy, LE mode 72 mov loc3 = psr 73 mov loc0 = rp 74 .body 75 mov r30 = in2 76 77(p6) rsm psr.i | psr.ic 78 mov r31 = in3 79 mov b7 = loc2 80 81(p7) rsm psr.i 82 ;; 83(p6) srlz.i 84 mov rp = r8 85 br.cond.sptk.many b7 861: mov psr.l = loc3 87 mov ar.rsc = loc4 // restore RSE configuration 88 mov ar.pfs = loc1 89 mov rp = loc0 90 ;; 91 srlz.d // seralize restoration of psr.l 92 br.ret.sptk.many b0 93END(ia64_pal_call_static) 94 95/* 96 * Make a PAL call using the stacked registers calling convention. 97 * 98 * Inputs: 99 * in0 Index of PAL service 100 * in2 - in3 Remaning PAL arguments 101 */ 102GLOBAL_ENTRY(ia64_pal_call_stacked) 103 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4) 104 alloc loc1 = ar.pfs,4,4,4,0 105 movl loc2 = pal_entry_point 106 107 mov r28 = in0 // Index MUST be copied to r28 108 mov out0 = in0 // AND in0 of PAL function 109 mov loc0 = rp 110 .body 111 ;; 112 ld8 loc2 = [loc2] // loc2 <- entry point 113 mov out1 = in1 114 mov out2 = in2 115 mov out3 = in3 116 mov loc3 = psr 117 ;; 118 rsm psr.i 119 mov b7 = loc2 120 ;; 121 br.call.sptk.many rp=b7 // now make the call 122.ret0: mov psr.l = loc3 123 mov ar.pfs = loc1 124 mov rp = loc0 125 ;; 126 srlz.d // serialize restoration of psr.l 127 br.ret.sptk.many b0 128END(ia64_pal_call_stacked) 129 130/* 131 * Make a physical mode PAL call using the static registers calling convention. 132 * 133 * Inputs: 134 * in0 Index of PAL service 135 * in2 - in3 Remaning PAL arguments 136 * 137 * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel. 138 * So we don't need to clear them. 139 */ 140#define PAL_PSR_BITS_TO_CLEAR \ 141 (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_DB | IA64_PSR_RT | \ 142 IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \ 143 IA64_PSR_DFL | IA64_PSR_DFH) 144 145#define PAL_PSR_BITS_TO_SET \ 146 (IA64_PSR_BN) 147 148 149GLOBAL_ENTRY(ia64_pal_call_phys_static) 150 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4) 151 alloc loc1 = ar.pfs,4,7,0,0 152 movl loc2 = pal_entry_point 1531: { 154 mov r28 = in0 // copy procedure index 155 mov r8 = ip // save ip to compute branch 156 mov loc0 = rp // save rp 157 } 158 .body 159 ;; 160 ld8 loc2 = [loc2] // loc2 <- entry point 161 mov r29 = in1 // first argument 162 mov r30 = in2 // copy arg2 163 mov r31 = in3 // copy arg3 164 ;; 165 mov loc3 = psr // save psr 166 adds r8 = 1f-1b,r8 // calculate return address for call 167 ;; 168 mov loc4=ar.rsc // save RSE configuration 169 dep.z loc2=loc2,0,61 // convert pal entry point to physical 170 tpa r8=r8 // convert rp to physical 171 ;; 172 mov b7 = loc2 // install target to branch reg 173 mov ar.rsc=0 // put RSE in enforced lazy, LE mode 174 movl r16=PAL_PSR_BITS_TO_CLEAR 175 movl r17=PAL_PSR_BITS_TO_SET 176 ;; 177 or loc3=loc3,r17 // add in psr the bits to set 178 ;; 179 andcm r16=loc3,r16 // removes bits to clear from psr 180 br.call.sptk.many rp=ia64_switch_mode_phys 181.ret1: mov rp = r8 // install return address (physical) 182 mov loc5 = r19 183 mov loc6 = r20 184 br.cond.sptk.many b7 1851: 186 mov ar.rsc=0 // put RSE in enforced lazy, LE mode 187 mov r16=loc3 // r16= original psr 188 mov r19=loc5 189 mov r20=loc6 190 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode 191.ret2: 192 mov psr.l = loc3 // restore init PSR 193 194 mov ar.pfs = loc1 195 mov rp = loc0 196 ;; 197 mov ar.rsc=loc4 // restore RSE configuration 198 srlz.d // seralize restoration of psr.l 199 br.ret.sptk.many b0 200END(ia64_pal_call_phys_static) 201 202/* 203 * Make a PAL call using the stacked registers in physical mode. 204 * 205 * Inputs: 206 * in0 Index of PAL service 207 * in2 - in3 Remaning PAL arguments 208 */ 209GLOBAL_ENTRY(ia64_pal_call_phys_stacked) 210 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5) 211 alloc loc1 = ar.pfs,5,7,4,0 212 movl loc2 = pal_entry_point 2131: { 214 mov r28 = in0 // copy procedure index 215 mov loc0 = rp // save rp 216 } 217 .body 218 ;; 219 ld8 loc2 = [loc2] // loc2 <- entry point 220 mov out0 = in0 // first argument 221 mov out1 = in1 // copy arg2 222 mov out2 = in2 // copy arg3 223 mov out3 = in3 // copy arg3 224 ;; 225 mov loc3 = psr // save psr 226 ;; 227 mov loc4=ar.rsc // save RSE configuration 228 dep.z loc2=loc2,0,61 // convert pal entry point to physical 229 ;; 230 mov ar.rsc=0 // put RSE in enforced lazy, LE mode 231 movl r16=PAL_PSR_BITS_TO_CLEAR 232 movl r17=PAL_PSR_BITS_TO_SET 233 ;; 234 or loc3=loc3,r17 // add in psr the bits to set 235 mov b7 = loc2 // install target to branch reg 236 ;; 237 andcm r16=loc3,r16 // removes bits to clear from psr 238 br.call.sptk.many rp=ia64_switch_mode_phys 239.ret6: 240 mov loc5 = r19 241 mov loc6 = r20 242 br.call.sptk.many rp=b7 // now make the call 243.ret7: 244 mov ar.rsc=0 // put RSE in enforced lazy, LE mode 245 mov r16=loc3 // r16= original psr 246 mov r19=loc5 247 mov r20=loc6 248 br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode 249 250.ret8: mov psr.l = loc3 // restore init PSR 251 mov ar.pfs = loc1 252 mov rp = loc0 253 ;; 254 mov ar.rsc=loc4 // restore RSE configuration 255 srlz.d // seralize restoration of psr.l 256 br.ret.sptk.many b0 257END(ia64_pal_call_phys_stacked) 258 259/* 260 * Save scratch fp scratch regs which aren't saved in pt_regs already (fp10-fp15). 261 * 262 * NOTE: We need to do this since firmware (SAL and PAL) may use any of the scratch 263 * regs fp-low partition. 264 * 265 * Inputs: 266 * in0 Address of stack storage for fp regs 267 */ 268GLOBAL_ENTRY(ia64_save_scratch_fpregs) 269 alloc r3=ar.pfs,1,0,0,0 270 add r2=16,in0 271 ;; 272 stf.spill [in0] = f10,32 273 stf.spill [r2] = f11,32 274 ;; 275 stf.spill [in0] = f12,32 276 stf.spill [r2] = f13,32 277 ;; 278 stf.spill [in0] = f14,32 279 stf.spill [r2] = f15,32 280 br.ret.sptk.many rp 281END(ia64_save_scratch_fpregs) 282 283/* 284 * Load scratch fp scratch regs (fp10-fp15) 285 * 286 * Inputs: 287 * in0 Address of stack storage for fp regs 288 */ 289GLOBAL_ENTRY(ia64_load_scratch_fpregs) 290 alloc r3=ar.pfs,1,0,0,0 291 add r2=16,in0 292 ;; 293 ldf.fill f10 = [in0],32 294 ldf.fill f11 = [r2],32 295 ;; 296 ldf.fill f12 = [in0],32 297 ldf.fill f13 = [r2],32 298 ;; 299 ldf.fill f14 = [in0],32 300 ldf.fill f15 = [r2],32 301 br.ret.sptk.many rp 302END(ia64_load_scratch_fpregs) 303