pal.S 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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. */
  49. GLOBAL_ENTRY(ia64_pal_call_static)
  50. .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
  51. alloc loc1 = ar.pfs,4,5,0,0
  52. movl loc2 = pal_entry_point
  53. 1: {
  54. mov r28 = in0
  55. mov r29 = in1
  56. mov r8 = ip
  57. }
  58. ;;
  59. ld8 loc2 = [loc2] // loc2 <- entry point
  60. adds r8 = 1f-1b,r8
  61. mov loc4=ar.rsc // save RSE configuration
  62. ;;
  63. mov ar.rsc=0 // put RSE in enforced lazy, LE mode
  64. mov loc3 = psr
  65. mov loc0 = rp
  66. .body
  67. mov r30 = in2
  68. mov r31 = in3
  69. mov b7 = loc2
  70. rsm psr.i
  71. ;;
  72. mov rp = r8
  73. br.cond.sptk.many b7
  74. 1: mov psr.l = loc3
  75. mov ar.rsc = loc4 // restore RSE configuration
  76. mov ar.pfs = loc1
  77. mov rp = loc0
  78. ;;
  79. srlz.d // seralize restoration of psr.l
  80. br.ret.sptk.many b0
  81. END(ia64_pal_call_static)
  82. /*
  83. * Make a PAL call using the stacked registers calling convention.
  84. *
  85. * Inputs:
  86. * in0 Index of PAL service
  87. * in2 - in3 Remaning PAL arguments
  88. */
  89. GLOBAL_ENTRY(ia64_pal_call_stacked)
  90. .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
  91. alloc loc1 = ar.pfs,4,4,4,0
  92. movl loc2 = pal_entry_point
  93. mov r28 = in0 // Index MUST be copied to r28
  94. mov out0 = in0 // AND in0 of PAL function
  95. mov loc0 = rp
  96. .body
  97. ;;
  98. ld8 loc2 = [loc2] // loc2 <- entry point
  99. mov out1 = in1
  100. mov out2 = in2
  101. mov out3 = in3
  102. mov loc3 = psr
  103. ;;
  104. rsm psr.i
  105. mov b7 = loc2
  106. ;;
  107. br.call.sptk.many rp=b7 // now make the call
  108. .ret0: mov psr.l = loc3
  109. mov ar.pfs = loc1
  110. mov rp = loc0
  111. ;;
  112. srlz.d // serialize restoration of psr.l
  113. br.ret.sptk.many b0
  114. END(ia64_pal_call_stacked)
  115. /*
  116. * Make a physical mode PAL call using the static registers calling convention.
  117. *
  118. * Inputs:
  119. * in0 Index of PAL service
  120. * in2 - in3 Remaning PAL arguments
  121. *
  122. * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel.
  123. * So we don't need to clear them.
  124. */
  125. #define PAL_PSR_BITS_TO_CLEAR \
  126. (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_DB | IA64_PSR_RT | \
  127. IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED | \
  128. IA64_PSR_DFL | IA64_PSR_DFH)
  129. #define PAL_PSR_BITS_TO_SET \
  130. (IA64_PSR_BN)
  131. GLOBAL_ENTRY(ia64_pal_call_phys_static)
  132. .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
  133. alloc loc1 = ar.pfs,4,7,0,0
  134. movl loc2 = pal_entry_point
  135. 1: {
  136. mov r28 = in0 // copy procedure index
  137. mov r8 = ip // save ip to compute branch
  138. mov loc0 = rp // save rp
  139. }
  140. .body
  141. ;;
  142. ld8 loc2 = [loc2] // loc2 <- entry point
  143. mov r29 = in1 // first argument
  144. mov r30 = in2 // copy arg2
  145. mov r31 = in3 // copy arg3
  146. ;;
  147. mov loc3 = psr // save psr
  148. adds r8 = 1f-1b,r8 // calculate return address for call
  149. ;;
  150. mov loc4=ar.rsc // save RSE configuration
  151. dep.z loc2=loc2,0,61 // convert pal entry point to physical
  152. tpa r8=r8 // convert rp to physical
  153. ;;
  154. mov b7 = loc2 // install target to branch reg
  155. mov ar.rsc=0 // put RSE in enforced lazy, LE mode
  156. movl r16=PAL_PSR_BITS_TO_CLEAR
  157. movl r17=PAL_PSR_BITS_TO_SET
  158. ;;
  159. or loc3=loc3,r17 // add in psr the bits to set
  160. ;;
  161. andcm r16=loc3,r16 // removes bits to clear from psr
  162. br.call.sptk.many rp=ia64_switch_mode_phys
  163. .ret1: mov rp = r8 // install return address (physical)
  164. mov loc5 = r19
  165. mov loc6 = r20
  166. br.cond.sptk.many b7
  167. 1:
  168. mov ar.rsc=0 // put RSE in enforced lazy, LE mode
  169. mov r16=loc3 // r16= original psr
  170. mov r19=loc5
  171. mov r20=loc6
  172. br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
  173. .ret2:
  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 Remaning 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 (fp10-fp15).
  236. *
  237. * NOTE: We need to do this since firmware (SAL and PAL) may use any of the scratch
  238. * regs fp-low partition.
  239. *
  240. * Inputs:
  241. * in0 Address of stack storage for fp regs
  242. */
  243. GLOBAL_ENTRY(ia64_save_scratch_fpregs)
  244. alloc r3=ar.pfs,1,0,0,0
  245. add r2=16,in0
  246. ;;
  247. stf.spill [in0] = f10,32
  248. stf.spill [r2] = f11,32
  249. ;;
  250. stf.spill [in0] = f12,32
  251. stf.spill [r2] = f13,32
  252. ;;
  253. stf.spill [in0] = f14,32
  254. stf.spill [r2] = f15,32
  255. br.ret.sptk.many rp
  256. END(ia64_save_scratch_fpregs)
  257. /*
  258. * Load scratch fp scratch regs (fp10-fp15)
  259. *
  260. * Inputs:
  261. * in0 Address of stack storage for fp regs
  262. */
  263. GLOBAL_ENTRY(ia64_load_scratch_fpregs)
  264. alloc r3=ar.pfs,1,0,0,0
  265. add r2=16,in0
  266. ;;
  267. ldf.fill f10 = [in0],32
  268. ldf.fill f11 = [r2],32
  269. ;;
  270. ldf.fill f12 = [in0],32
  271. ldf.fill f13 = [r2],32
  272. ;;
  273. ldf.fill f14 = [in0],32
  274. ldf.fill f15 = [r2],32
  275. br.ret.sptk.many rp
  276. END(ia64_load_scratch_fpregs)