smtc-asm.S 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Assembly Language Functions for MIPS MT SMTC support
  3. */
  4. /*
  5. * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */
  6. #include <asm/regdef.h>
  7. #include <asm/asmmacro.h>
  8. #include <asm/stackframe.h>
  9. #include <asm/irqflags.h>
  10. /*
  11. * "Software Interrupt" linkage.
  12. *
  13. * This is invoked when an "Interrupt" is sent from one TC to another,
  14. * where the TC to be interrupted is halted, has it's Restart address
  15. * and Status values saved by the "remote control" thread, then modified
  16. * to cause execution to begin here, in kenel mode. This code then
  17. * disguises the TC state as that of an exception and transfers
  18. * control to the general exception or vectored interrupt handler.
  19. */
  20. .set noreorder
  21. /*
  22. The __smtc_ipi_vector would use k0 and k1 as temporaries and
  23. 1) Set EXL (this is per-VPE, so this can't be done by proxy!)
  24. 2) Restore the K/CU and IXMT bits to the pre "exception" state
  25. (EXL means no interrupts and access to the kernel map).
  26. 3) Set EPC to be the saved value of TCRestart.
  27. 4) Jump to the exception handler entry point passed by the sender.
  28. CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED??
  29. */
  30. /*
  31. * Reviled and slandered vision: Set EXL and restore K/CU/IXMT
  32. * state of pre-halt thread, then save everything and call
  33. * thought some function pointer to imaginary_exception, which
  34. * will parse a register value or memory message queue to
  35. * deliver things like interprocessor interrupts. On return
  36. * from that function, jump to the global ret_from_irq code
  37. * to invoke the scheduler and return as appropriate.
  38. */
  39. #define PT_PADSLOT4 (PT_R0-8)
  40. #define PT_PADSLOT5 (PT_R0-4)
  41. .text
  42. .align 5
  43. FEXPORT(__smtc_ipi_vector)
  44. #ifdef CONFIG_CPU_MICROMIPS
  45. nop
  46. #endif
  47. .set noat
  48. /* Disable thread scheduling to make Status update atomic */
  49. DMT 27 # dmt k1
  50. _ehb
  51. /* Set EXL */
  52. mfc0 k0,CP0_STATUS
  53. ori k0,k0,ST0_EXL
  54. mtc0 k0,CP0_STATUS
  55. _ehb
  56. /* Thread scheduling now inhibited by EXL. Restore TE state. */
  57. andi k1,k1,VPECONTROL_TE
  58. beqz k1,1f
  59. emt
  60. 1:
  61. /*
  62. * The IPI sender has put some information on the anticipated
  63. * kernel stack frame. If we were in user mode, this will be
  64. * built above the saved kernel SP. If we were already in the
  65. * kernel, it will be built above the current CPU SP.
  66. *
  67. * Were we in kernel mode, as indicated by CU0?
  68. */
  69. sll k1,k0,3
  70. .set noreorder
  71. bltz k1,2f
  72. move k1,sp
  73. .set reorder
  74. /*
  75. * If previously in user mode, set CU0 and use kernel stack.
  76. */
  77. li k1,ST0_CU0
  78. or k1,k1,k0
  79. mtc0 k1,CP0_STATUS
  80. _ehb
  81. get_saved_sp
  82. /* Interrupting TC will have pre-set values in slots in the new frame */
  83. 2: subu k1,k1,PT_SIZE
  84. /* Load TCStatus Value */
  85. lw k0,PT_TCSTATUS(k1)
  86. /* Write it to TCStatus to restore CU/KSU/IXMT state */
  87. mtc0 k0,$2,1
  88. _ehb
  89. lw k0,PT_EPC(k1)
  90. mtc0 k0,CP0_EPC
  91. /* Save all will redundantly recompute the SP, but use it for now */
  92. SAVE_ALL
  93. CLI
  94. TRACE_IRQS_OFF
  95. /* Function to be invoked passed stack pad slot 5 */
  96. lw t0,PT_PADSLOT5(sp)
  97. /* Argument from sender passed in stack pad slot 4 */
  98. lw a0,PT_PADSLOT4(sp)
  99. LONG_L s0, TI_REGS($28)
  100. LONG_S sp, TI_REGS($28)
  101. PTR_LA ra, ret_from_irq
  102. jr t0
  103. /*
  104. * Called from idle loop to provoke processing of queued IPIs
  105. * First IPI message in queue passed as argument.
  106. */
  107. LEAF(self_ipi)
  108. /* Before anything else, block interrupts */
  109. mfc0 t0,CP0_TCSTATUS
  110. ori t1,t0,TCSTATUS_IXMT
  111. mtc0 t1,CP0_TCSTATUS
  112. _ehb
  113. /* We know we're in kernel mode, so prepare stack frame */
  114. subu t1,sp,PT_SIZE
  115. sw ra,PT_EPC(t1)
  116. sw a0,PT_PADSLOT4(t1)
  117. la t2,ipi_decode
  118. sw t2,PT_PADSLOT5(t1)
  119. /* Save pre-disable value of TCStatus */
  120. sw t0,PT_TCSTATUS(t1)
  121. j __smtc_ipi_vector
  122. nop
  123. END(self_ipi)