pal.S 7.4 KB

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