pal.S 7.7 KB

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