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