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