ctxswap.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. ctxswap.S
  9. Abstract:
  10. This module implements context switching on the ARMv7 processor.
  11. Author:
  12. Evan Green 25-Aug-2012
  13. Environment:
  14. Kernel mode
  15. --*/
  16. //
  17. // ------------------------------------------------------------------ Includes
  18. //
  19. #include <minoca/kernel/arm.inc>
  20. //
  21. // --------------------------------------------------------------- Definitions
  22. //
  23. .equ CONTEXT_SWAP_MAGIC, 0x4A3A2A1A
  24. //
  25. // ---------------------------------------------------------------------- Code
  26. //
  27. ASSEMBLY_FILE_HEADER
  28. //
  29. // VOID
  30. // KepContextSwap (
  31. // PVOID *SavedStackLocation,
  32. // PVOID NewStack,
  33. // ULONGLONG NewThreadPointer,
  34. // BOOL FirstTime
  35. // )
  36. //
  37. /*++
  38. Routine Description:
  39. This routine switches context to the given thread.
  40. Arguments:
  41. SavedStackLocation - Supplies a pointer where the old stack pointer will
  42. be saved.
  43. NewStack - Supplies the new stack address.
  44. NewThreadPointer - Supplies the new thread pointer data.
  45. FirstTime - Supplies a boolean indicating whether the thread has never been
  46. run before.
  47. Return Value:
  48. None.
  49. --*/
  50. .equ FirstTime, 0x2C
  51. FUNCTION KepContextSwap
  52. //
  53. // Save state of the old thread, including flags and general registers.
  54. //
  55. mrs %r12, CPSR @ Get and save flags.
  56. stmdb %sp!, {%r4-%r12, %r14} @ Save registers.
  57. ldr %r12, =CONTEXT_SWAP_MAGIC @ Load the magic constant.
  58. stmdb %sp!, {%r12} @ Push it on the stack.
  59. ldr %r4, [%sp, #FirstTime] @ Get the FirstTime parameter.
  60. str %sp, [%r0] @ Save the old stack.
  61. DMB @ Ensure that save completed.
  62. //
  63. // Set up the new user mode thread pointer registers.
  64. //
  65. mcr p15, 0, %r2, c13, c0, 3 @ Set the TPIDRURO register.
  66. mcr p15, 0, %r3, c13, c0, 2 @ Set the TPIDRURW register.
  67. //
  68. // Switch to the new thread's kernel stack, effectively freezing the old
  69. // thread. Then perform any work that must be completed on the new stack.
  70. // Touch the stack before switching to it to trigger any top-level page
  71. // table updates needed to run the new stack on the old TTBR.
  72. //
  73. ldr %r0, [%r1] @ Touch the new stack to trigger faults.
  74. mov %sp, %r1 @ Switch to the new stack.
  75. .if THUMB
  76. mov %r7, #0 @ Zero out FP so the call stack stops here.
  77. .else
  78. mov %r11, #0 @ Zero out FP so the call stack stops here.
  79. .endif
  80. //
  81. // Perform any post-stack switch work needed on the old thread.
  82. //
  83. bl KepPostContextSwapWork @ Perform post stack switch work.
  84. //
  85. // Figure out if this is the new thread's first run, and jump over if not.
  86. //
  87. cmp %r4, #FALSE
  88. beq ContextSwapRestore
  89. ContextSwapFirstRun:
  90. mov %r0, %sp @ Set the trap frame parameter.
  91. bl KepPreThreadStartWork @ Perform any thread initialization.
  92. //
  93. // If this is the thread's first run, the stack is set up with a trap frame.
  94. // Restore it in the same manner as coming off an interrupt.
  95. //
  96. ARM_EXIT_INTERRUPT
  97. ContextSwapRestore:
  98. //
  99. // Restore the registers pushed during the context save, but first validate
  100. // that the magic constant is on the top of the stack. If it's not, there
  101. // are some serious problems, as in all likelihood garbage is about to be
  102. // popped out.
  103. //
  104. ldr %r12, =CONTEXT_SWAP_MAGIC @ Load the magic constant.
  105. ldmia %sp!, {%r11} @ Pop the value off the stack.
  106. cmp %r11, %r12 @ Compare values.
  107. beq ContextSwapRestoreValidStack @ Jump over break if valid.
  108. DEBUGGER_BREAK @ Breaking here is bad news.
  109. ContextSwapRestoreValidStack:
  110. //
  111. // Pop the registers and the flags.
  112. //
  113. ldmia %sp!, {%r4-%r12, %r14} @ Breaking here is *bad*. Look up!
  114. msr CPSR_cxsf, %r12
  115. //
  116. // Return back to the caller.
  117. //
  118. bx %lr
  119. END_FUNCTION KepContextSwap