ofwcall64.S 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*-
  2. * Copyright (C) 2009-2011 Nathan Whitehorn
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  18. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  20. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  21. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  22. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  23. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *
  25. * $FreeBSD$
  26. */
  27. #include <sys/syscall.h>
  28. #include <machine/trap.h>
  29. #include <machine/param.h>
  30. #include <machine/spr.h>
  31. #include <machine/asm.h>
  32. #include "opt_platform.h"
  33. #define OFWSTKSZ 4096 /* 4K Open Firmware stack */
  34. /*
  35. * Globals
  36. */
  37. .data
  38. .align 4
  39. ofwstk:
  40. .space OFWSTKSZ
  41. rtas_regsave:
  42. .space 32 /* 4 * sizeof(register_t) */
  43. GLOBAL(ofmsr)
  44. .llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
  45. GLOBAL(rtasmsr)
  46. .llong 0
  47. GLOBAL(openfirmware_entry)
  48. .llong 0 /* Open Firmware entry point */
  49. GLOBAL(rtas_entry)
  50. .llong 0 /* RTAS entry point */
  51. TOC_ENTRY(ofmsr)
  52. TOC_ENTRY(ofwstk)
  53. TOC_ENTRY(rtasmsr)
  54. TOC_ENTRY(openfirmware_entry)
  55. TOC_ENTRY(rtas_entry)
  56. TOC_ENTRY(rtas_regsave)
  57. /*
  58. * Open Firmware Real-mode Entry Point. This is a huge pain.
  59. */
  60. ASENTRY_NOPROF(ofwcall)
  61. mflr %r8
  62. std %r8,16(%r1)
  63. stdu %r1,-208(%r1)
  64. /*
  65. * We need to save the following, because OF's register save/
  66. * restore code assumes that the contents of registers are
  67. * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
  68. * get placed in that order in the stack.
  69. */
  70. mfcr %r4
  71. std %r4,48(%r1)
  72. std %r13,56(%r1)
  73. std %r14,64(%r1)
  74. std %r15,72(%r1)
  75. std %r16,80(%r1)
  76. std %r17,88(%r1)
  77. std %r18,96(%r1)
  78. std %r19,104(%r1)
  79. std %r20,112(%r1)
  80. std %r21,120(%r1)
  81. std %r22,128(%r1)
  82. std %r23,136(%r1)
  83. std %r24,144(%r1)
  84. std %r25,152(%r1)
  85. std %r26,160(%r1)
  86. std %r27,168(%r1)
  87. std %r28,176(%r1)
  88. std %r29,184(%r1)
  89. std %r30,192(%r1)
  90. std %r31,200(%r1)
  91. /* Record the old MSR */
  92. mfmsr %r6
  93. /* read client interface handler */
  94. addis %r4,%r2,TOC_REF(openfirmware_entry)@ha
  95. ld %r4,TOC_REF(openfirmware_entry)@l(%r4)
  96. ld %r4,0(%r4)
  97. /* Get OF stack pointer */
  98. addis %r7,%r2,TOC_REF(ofwstk)@ha
  99. ld %r7,TOC_REF(ofwstk)@l(%r7)
  100. addi %r7,%r7,OFWSTKSZ-40
  101. /*
  102. * Set the MSR to the OF value. This has the side effect of disabling
  103. * exceptions, which is important for the next few steps.
  104. * This does NOT, however, cause us to switch endianness.
  105. */
  106. addis %r5,%r2,TOC_REF(ofmsr)@ha
  107. ld %r5,TOC_REF(ofmsr)@l(%r5)
  108. ld %r5,0(%r5)
  109. #if defined(__LITTLE_ENDIAN__) && defined(QEMU)
  110. /* QEMU hack: qemu does not emulate mtmsrd correctly! */
  111. ori %r5,%r5,1 /* Leave PSR_LE set */
  112. #endif
  113. mtmsrd %r5
  114. isync
  115. /*
  116. * Set up OF stack. This needs to be accessible in real mode and
  117. * use the 32-bit ABI stack frame format. The pointer to the current
  118. * kernel stack is placed at the very top of the stack along with
  119. * the old MSR so we can get them back later.
  120. */
  121. mr %r5,%r1
  122. mr %r1,%r7
  123. std %r5,8(%r1) /* Save real stack pointer */
  124. std %r2,16(%r1) /* Save old TOC */
  125. std %r6,24(%r1) /* Save old MSR */
  126. std %r8,32(%r1) /* Save high 32-bits of the kernel's PC */
  127. li %r5,0
  128. stw %r5,4(%r1)
  129. stw %r5,0(%r1)
  130. #ifdef __LITTLE_ENDIAN__
  131. /* Atomic context switch w/ endian change */
  132. mtmsrd %r5, 1 /* Clear PSL_EE|PSL_RI */
  133. addis %r5,%r2,TOC_REF(ofmsr)@ha
  134. ld %r5,TOC_REF(ofmsr)@l(%r5)
  135. ld %r5,0(%r5)
  136. mtsrr0 %r4
  137. mtsrr1 %r5
  138. LOAD_LR_NIA
  139. 1:
  140. mflr %r5
  141. addi %r5, %r5, (2f-1b)
  142. mtlr %r5
  143. li %r5, 0
  144. rfid
  145. 2:
  146. RETURN_TO_NATIVE_ENDIAN
  147. #else
  148. /* Finally, branch to OF */
  149. mtctr %r4
  150. bctrl
  151. #endif
  152. /* Reload stack pointer, MSR, and reference PC from the OFW stack */
  153. ld %r7,32(%r1)
  154. ld %r6,24(%r1)
  155. ld %r2,16(%r1)
  156. ld %r1,8(%r1)
  157. /* Get back to the MSR/PC we want, using the cached high bits of PC */
  158. mtsrr1 %r6
  159. clrrdi %r7,%r7,32
  160. bl 1f
  161. 1: mflr %r8
  162. or %r8,%r8,%r7
  163. addi %r8,%r8,2f-1b
  164. mtsrr0 %r8
  165. rfid /* Turn on MMU, exceptions, and 64-bit mode */
  166. 2:
  167. /* Sign-extend the return value from OF */
  168. extsw %r3,%r3
  169. /* Restore all the non-volatile registers */
  170. ld %r5,48(%r1)
  171. mtcr %r5
  172. ld %r13,56(%r1)
  173. ld %r14,64(%r1)
  174. ld %r15,72(%r1)
  175. ld %r16,80(%r1)
  176. ld %r17,88(%r1)
  177. ld %r18,96(%r1)
  178. ld %r19,104(%r1)
  179. ld %r20,112(%r1)
  180. ld %r21,120(%r1)
  181. ld %r22,128(%r1)
  182. ld %r23,136(%r1)
  183. ld %r24,144(%r1)
  184. ld %r25,152(%r1)
  185. ld %r26,160(%r1)
  186. ld %r27,168(%r1)
  187. ld %r28,176(%r1)
  188. ld %r29,184(%r1)
  189. ld %r30,192(%r1)
  190. ld %r31,200(%r1)
  191. /* Restore the stack and link register */
  192. ld %r1,0(%r1)
  193. ld %r0,16(%r1)
  194. mtlr %r0
  195. blr
  196. ASEND(ofwcall)
  197. /*
  198. * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
  199. * stack)
  200. *
  201. * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
  202. */
  203. ASENTRY_NOPROF(rtascall)
  204. mflr %r9
  205. std %r9,16(%r1)
  206. stdu %r1,-208(%r1)
  207. /*
  208. * We need to save the following, because RTAS's register save/
  209. * restore code assumes that the contents of registers are
  210. * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
  211. * get placed in that order in the stack.
  212. */
  213. mfcr %r5
  214. std %r5,48(%r1)
  215. std %r13,56(%r1)
  216. std %r14,64(%r1)
  217. std %r15,72(%r1)
  218. std %r16,80(%r1)
  219. std %r17,88(%r1)
  220. std %r18,96(%r1)
  221. std %r19,104(%r1)
  222. std %r20,112(%r1)
  223. std %r21,120(%r1)
  224. std %r22,128(%r1)
  225. std %r23,136(%r1)
  226. std %r24,144(%r1)
  227. std %r25,152(%r1)
  228. std %r26,160(%r1)
  229. std %r27,168(%r1)
  230. std %r28,176(%r1)
  231. std %r29,184(%r1)
  232. std %r30,192(%r1)
  233. std %r31,200(%r1)
  234. /* Record the old MSR */
  235. mfmsr %r6
  236. /* Read RTAS entry and reg save area pointers */
  237. addis %r5,%r2,TOC_REF(rtas_entry)@ha
  238. ld %r5,TOC_REF(rtas_entry)@l(%r5)
  239. ld %r5,0(%r5)
  240. addis %r8,%r2,TOC_REF(rtas_regsave)@ha
  241. ld %r8,TOC_REF(rtas_regsave)@l(%r8)
  242. /*
  243. * Set the MSR to the RTAS value. This has the side effect of disabling
  244. * exceptions, which is important for the next few steps.
  245. */
  246. addis %r7,%r2,TOC_REF(rtasmsr)@ha
  247. ld %r7,TOC_REF(rtasmsr)@l(%r7)
  248. ld %r7,0(%r7)
  249. #ifdef __LITTLE_ENDIAN__
  250. /* QEMU hack: qemu does not emulate mtmsrd correctly! */
  251. ori %r7,%r7,1 /* Leave PSR_LE set */
  252. #endif
  253. mtmsrd %r7
  254. isync
  255. /*
  256. * Set up RTAS register save area, so that we can get back all of
  257. * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
  258. * Put this in r1, since RTAS is obliged to save it. Kernel globals
  259. * are below 4 GB, so this is safe.
  260. */
  261. mr %r7,%r1
  262. mr %r1,%r8
  263. std %r7,0(%r1) /* Save 64-bit stack pointer */
  264. std %r2,8(%r1) /* Save TOC */
  265. std %r6,16(%r1) /* Save MSR */
  266. std %r9,24(%r1) /* Save reference PC for high 32 bits */
  267. #ifdef __LITTLE_ENDIAN__
  268. /* Atomic context switch w/ endian change */
  269. li %r7, 0
  270. mtmsrd %r7, 1 /* Clear PSL_EE|PSL_RI */
  271. addis %r7,%r2,TOC_REF(rtasmsr)@ha
  272. ld %r7,TOC_REF(rtasmsr)@l(%r7)
  273. ld %r7,0(%r7)
  274. mtsrr0 %r5
  275. mtsrr1 %r7
  276. LOAD_LR_NIA
  277. 1:
  278. mflr %r5
  279. addi %r5, %r5, (2f-1b)
  280. mtlr %r5
  281. li %r5, 0
  282. rfid
  283. 2:
  284. RETURN_TO_NATIVE_ENDIAN
  285. #else
  286. /* Finally, branch to RTAS */
  287. mtctr %r5
  288. bctrl
  289. #endif
  290. /*
  291. * Reload stack pointer, MSR, reg PC from the reg save area in r1. We
  292. * are running in 32-bit mode at this point, so it doesn't matter if r1
  293. * has become sign-extended.
  294. */
  295. ld %r7,24(%r1)
  296. ld %r6,16(%r1)
  297. ld %r2,8(%r1)
  298. ld %r1,0(%r1)
  299. /*
  300. * Get back to the right PC. We need to atomically re-enable
  301. * exceptions, 64-bit mode, and the MMU. One thing that has likely
  302. * happened is that, if we were running in the high-memory direct
  303. * map, we no longer are as a result of LR truncation in RTAS.
  304. * Fix this by copying the high-order bits of the LR at function
  305. * entry onto the current PC and then jumping there while flipping
  306. * all the MSR bits.
  307. */
  308. mtsrr1 %r6
  309. clrrdi %r7,%r7,32
  310. bl 1f
  311. 1: mflr %r8
  312. or %r8,%r8,%r7
  313. addi %r8,%r8,2f-1b
  314. mtsrr0 %r8
  315. rfid /* Turn on MMU, exceptions, and 64-bit mode */
  316. 2:
  317. /* Sign-extend the return value from RTAS */
  318. extsw %r3,%r3
  319. /* Restore all the non-volatile registers */
  320. ld %r5,48(%r1)
  321. mtcr %r5
  322. ld %r13,56(%r1)
  323. ld %r14,64(%r1)
  324. ld %r15,72(%r1)
  325. ld %r16,80(%r1)
  326. ld %r17,88(%r1)
  327. ld %r18,96(%r1)
  328. ld %r19,104(%r1)
  329. ld %r20,112(%r1)
  330. ld %r21,120(%r1)
  331. ld %r22,128(%r1)
  332. ld %r23,136(%r1)
  333. ld %r24,144(%r1)
  334. ld %r25,152(%r1)
  335. ld %r26,160(%r1)
  336. ld %r27,168(%r1)
  337. ld %r28,176(%r1)
  338. ld %r29,184(%r1)
  339. ld %r30,192(%r1)
  340. ld %r31,200(%r1)
  341. /* Restore the stack and link register */
  342. ld %r1,0(%r1)
  343. ld %r0,16(%r1)
  344. mtlr %r0
  345. blr
  346. ASEND(rtascall)