pal.S 7.5 KB

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