fiq_glue.S 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * Copyright (C) 2008 Google, Inc.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/linkage.h>
  15. #include <asm/assembler.h>
  16. .text
  17. .global fiq_glue_end
  18. /* fiq stack: r0-r15,cpsr,spsr of interrupted mode */
  19. ENTRY(fiq_glue)
  20. /* store pc, cpsr from previous mode */
  21. mrs r12, spsr
  22. sub r11, lr, #4
  23. subs r10, #1
  24. bne nested_fiq
  25. stmfd sp!, {r11-r12, lr}
  26. /* store r8-r14 from previous mode */
  27. sub sp, sp, #(7 * 4)
  28. stmia sp, {r8-r14}^
  29. nop
  30. /* store r0-r7 from previous mode */
  31. stmfd sp!, {r0-r7}
  32. /* setup func(data,regs) arguments */
  33. mov r0, r9
  34. mov r1, sp
  35. mov r3, r8
  36. mov r7, sp
  37. /* Get sp and lr from non-user modes */
  38. and r4, r12, #MODE_MASK
  39. cmp r4, #USR_MODE
  40. beq fiq_from_usr_mode
  41. mov r7, sp
  42. orr r4, r4, #(PSR_I_BIT | PSR_F_BIT)
  43. msr cpsr_c, r4
  44. str sp, [r7, #(4 * 13)]
  45. str lr, [r7, #(4 * 14)]
  46. mrs r5, spsr
  47. str r5, [r7, #(4 * 17)]
  48. cmp r4, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
  49. /* use fiq stack if we reenter this mode */
  50. subne sp, r7, #(4 * 3)
  51. fiq_from_usr_mode:
  52. msr cpsr_c, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
  53. mov r2, sp
  54. sub sp, r7, #12
  55. stmfd sp!, {r2, ip, lr}
  56. /* call func(data,regs) */
  57. blx r3
  58. ldmfd sp, {r2, ip, lr}
  59. mov sp, r2
  60. /* restore/discard saved state */
  61. cmp r4, #USR_MODE
  62. beq fiq_from_usr_mode_exit
  63. msr cpsr_c, r4
  64. ldr sp, [r7, #(4 * 13)]
  65. ldr lr, [r7, #(4 * 14)]
  66. msr spsr_cxsf, r5
  67. fiq_from_usr_mode_exit:
  68. msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
  69. ldmfd sp!, {r0-r7}
  70. add sp, sp, #(7 * 4)
  71. ldmfd sp!, {r11-r12, lr}
  72. exit_fiq:
  73. msr spsr_cxsf, r12
  74. add r10, #1
  75. movs pc, r11
  76. nested_fiq:
  77. orr r12, r12, #(PSR_F_BIT)
  78. b exit_fiq
  79. fiq_glue_end:
  80. ENTRY(fiq_glue_setup) /* func, data, sp */
  81. mrs r3, cpsr
  82. msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
  83. movs r8, r0
  84. mov r9, r1
  85. mov sp, r2
  86. moveq r10, #0
  87. movne r10, #1
  88. msr cpsr_c, r3
  89. bx lr