arm_nce.s 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /* SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project */
  2. /* SPDX-License-Identifier: GPL-2.0-or-later */
  3. #include "core/arm/nce/arm_nce_asm_definitions.h"
  4. #define LOAD_IMMEDIATE_32(reg, val) \
  5. mov reg, #(((val) >> 0x00) & 0xFFFF); \
  6. movk reg, #(((val) >> 0x10) & 0xFFFF), lsl #16
  7. /* static HaltReason Core::ARM_NCE::ReturnToRunCodeByTrampoline(void* tpidr, Core::GuestContext* ctx, u64 trampoline_addr) */
  8. .section .text._ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm, "ax", %progbits
  9. .global _ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm
  10. .type _ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm, %function
  11. _ZN4Core7ARM_NCE27ReturnToRunCodeByTrampolineEPvPNS_12GuestContextEm:
  12. /* Back up host sp to x3. */
  13. /* Back up host tpidr_el0 to x4. */
  14. mov x3, sp
  15. mrs x4, tpidr_el0
  16. /* Load guest sp. x5 is used as a scratch register. */
  17. ldr x5, [x1, #(GuestContextSp)]
  18. mov sp, x5
  19. /* Offset GuestContext pointer to the host member. */
  20. add x5, x1, #(GuestContextHostContext)
  21. /* Save original host sp and tpidr_el0 (x3, x4) to host context. */
  22. stp x3, x4, [x5, #(HostContextSpTpidrEl0)]
  23. /* Save all callee-saved host GPRs. */
  24. stp x19, x20, [x5, #(HostContextRegs+0x0)]
  25. stp x21, x22, [x5, #(HostContextRegs+0x10)]
  26. stp x23, x24, [x5, #(HostContextRegs+0x20)]
  27. stp x25, x26, [x5, #(HostContextRegs+0x30)]
  28. stp x27, x28, [x5, #(HostContextRegs+0x40)]
  29. stp x29, x30, [x5, #(HostContextRegs+0x50)]
  30. /* Save all callee-saved host FPRs. */
  31. stp q8, q9, [x5, #(HostContextVregs+0x0)]
  32. stp q10, q11, [x5, #(HostContextVregs+0x20)]
  33. stp q12, q13, [x5, #(HostContextVregs+0x40)]
  34. stp q14, q15, [x5, #(HostContextVregs+0x60)]
  35. /* Load guest tpidr_el0 from argument. */
  36. msr tpidr_el0, x0
  37. /* Tail call the trampoline to restore guest state. */
  38. br x2
  39. /* static HaltReason Core::ARM_NCE::ReturnToRunCodeByExceptionLevelChange(int tid, void* tpidr) */
  40. .section .text._ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv, "ax", %progbits
  41. .global _ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv
  42. .type _ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv, %function
  43. _ZN4Core7ARM_NCE37ReturnToRunCodeByExceptionLevelChangeEiPv:
  44. /* This jumps to the signal handler, which will restore the entire context. */
  45. /* On entry, x0 = thread id, which is already in the right place. */
  46. /* Move tpidr to x9 so it is not trampled. */
  47. mov x9, x1
  48. /* Set up arguments. */
  49. mov x8, #(__NR_tkill)
  50. mov x1, #(ReturnToRunCodeByExceptionLevelChangeSignal)
  51. /* Tail call the signal handler. */
  52. svc #0
  53. /* Block execution from flowing here. */
  54. brk #1000
  55. /* static void Core::ARM_NCE::ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void* info, void* raw_context) */
  56. .section .text._ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_, "ax", %progbits
  57. .global _ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_
  58. .type _ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_, %function
  59. _ZN4Core7ARM_NCE50ReturnToRunCodeByExceptionLevelChangeSignalHandlerEiPvS1_:
  60. stp x29, x30, [sp, #-0x10]!
  61. mov x29, sp
  62. /* Call the context restorer with the raw context. */
  63. mov x0, x2
  64. bl _ZN4Core7ARM_NCE19RestoreGuestContextEPv
  65. /* Save the old value of tpidr_el0. */
  66. mrs x8, tpidr_el0
  67. ldr x9, [x0, #(TpidrEl0NativeContext)]
  68. str x8, [x9, #(GuestContextHostContext + HostContextTpidrEl0)]
  69. /* Set our new tpidr_el0. */
  70. msr tpidr_el0, x0
  71. /* Unlock the context. */
  72. bl _ZN4Core7ARM_NCE22UnlockThreadParametersEPv
  73. /* Returning from here will enter the guest. */
  74. ldp x29, x30, [sp], #0x10
  75. ret
  76. /* static void Core::ARM_NCE::BreakFromRunCodeSignalHandler(int sig, void* info, void* raw_context) */
  77. .section .text._ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_, "ax", %progbits
  78. .global _ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_
  79. .type _ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_, %function
  80. _ZN4Core7ARM_NCE29BreakFromRunCodeSignalHandlerEiPvS1_:
  81. /* Check to see if we have the correct TLS magic. */
  82. mrs x8, tpidr_el0
  83. ldr w9, [x8, #(TpidrEl0TlsMagic)]
  84. LOAD_IMMEDIATE_32(w10, TlsMagic)
  85. cmp w9, w10
  86. b.ne 1f
  87. /* Correct TLS magic, so this is a guest interrupt. */
  88. /* Restore host tpidr_el0. */
  89. ldr x0, [x8, #(TpidrEl0NativeContext)]
  90. ldr x3, [x0, #(GuestContextHostContext + HostContextTpidrEl0)]
  91. msr tpidr_el0, x3
  92. /* Tail call the restorer. */
  93. mov x1, x2
  94. b _ZN4Core7ARM_NCE16SaveGuestContextEPNS_12GuestContextEPv
  95. /* Returning from here will enter host code. */
  96. 1:
  97. /* Incorrect TLS magic, so this is a spurious signal. */
  98. ret
  99. /* static void Core::ARM_NCE::GuestFaultSignalHandler(int sig, void* info, void* raw_context) */
  100. .section .text._ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_, "ax", %progbits
  101. .global _ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_
  102. .type _ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_, %function
  103. _ZN4Core7ARM_NCE23GuestFaultSignalHandlerEiPvS1_:
  104. /* Check to see if we have the correct TLS magic. */
  105. mrs x8, tpidr_el0
  106. ldr w9, [x8, #(TpidrEl0TlsMagic)]
  107. LOAD_IMMEDIATE_32(w10, TlsMagic)
  108. cmp w9, w10
  109. b.eq 1f
  110. /* Incorrect TLS magic, so this is a host fault. */
  111. /* Tail call the handler. */
  112. b _ZN4Core7ARM_NCE15HandleHostFaultEiPvS1_
  113. 1:
  114. /* Correct TLS magic, so this is a guest fault. */
  115. stp x29, x30, [sp, #-0x20]!
  116. str x19, [sp, #0x10]
  117. mov x29, sp
  118. /* Save the old tpidr_el0. */
  119. mov x19, x8
  120. /* Restore host tpidr_el0. */
  121. ldr x0, [x8, #(TpidrEl0NativeContext)]
  122. ldr x3, [x0, #(GuestContextHostContext + HostContextTpidrEl0)]
  123. msr tpidr_el0, x3
  124. /* Call the handler. */
  125. bl _ZN4Core7ARM_NCE16HandleGuestFaultEPNS_12GuestContextEPvS3_
  126. /* If the handler returned false, we want to preserve the host tpidr_el0. */
  127. cbz x0, 2f
  128. /* Otherwise, restore guest tpidr_el0. */
  129. msr tpidr_el0, x19
  130. 2:
  131. ldr x19, [sp, #0x10]
  132. ldp x29, x30, [sp], #0x20
  133. ret
  134. /* static void Core::ARM_NCE::LockThreadParameters(void* tpidr) */
  135. .section .text._ZN4Core7ARM_NCE20LockThreadParametersEPv, "ax", %progbits
  136. .global _ZN4Core7ARM_NCE20LockThreadParametersEPv
  137. .type _ZN4Core7ARM_NCE20LockThreadParametersEPv, %function
  138. _ZN4Core7ARM_NCE20LockThreadParametersEPv:
  139. /* Offset to lock member. */
  140. add x0, x0, #(TpidrEl0Lock)
  141. 1:
  142. /* Clear the monitor. */
  143. clrex
  144. 2:
  145. /* Load-linked with acquire ordering. */
  146. ldaxr w1, [x0]
  147. /* If the value was SpinLockLocked, clear monitor and retry. */
  148. cbz w1, 1b
  149. /* Store-conditional SpinLockLocked with relaxed ordering. */
  150. stxr w1, wzr, [x0]
  151. /* If we failed to store, retry. */
  152. cbnz w1, 2b
  153. ret
  154. /* static void Core::ARM_NCE::UnlockThreadParameters(void* tpidr) */
  155. .section .text._ZN4Core7ARM_NCE22UnlockThreadParametersEPv, "ax", %progbits
  156. .global _ZN4Core7ARM_NCE22UnlockThreadParametersEPv
  157. .type _ZN4Core7ARM_NCE22UnlockThreadParametersEPv, %function
  158. _ZN4Core7ARM_NCE22UnlockThreadParametersEPv:
  159. /* Offset to lock member. */
  160. add x0, x0, #(TpidrEl0Lock)
  161. /* Load SpinLockUnlocked. */
  162. mov w1, #(SpinLockUnlocked)
  163. /* Store value with release ordering. */
  164. stlr w1, [x0]
  165. ret