entry-v7m.S 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * linux/arch/arm/kernel/entry-v7m.S
  3. *
  4. * Copyright (C) 2008 ARM Ltd.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Low-level vector interface routines for the ARMv7-M architecture
  11. */
  12. #include <asm/memory.h>
  13. #include <asm/glue.h>
  14. #include <asm/thread_notify.h>
  15. #include <asm/v7m.h>
  16. #include <mach/entry-macro.S>
  17. #include "entry-header.S"
  18. #ifdef CONFIG_TRACE_IRQFLAGS
  19. #error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation"
  20. #endif
  21. __invalid_entry:
  22. v7m_exception_entry
  23. adr r0, strerr
  24. mrs r1, ipsr
  25. mov r2, lr
  26. bl printk
  27. mov r0, sp
  28. bl show_regs
  29. 1: b 1b
  30. ENDPROC(__invalid_entry)
  31. strerr: .asciz "\nUnhandled exception: IPSR = %08lx LR = %08lx\n"
  32. .align 2
  33. __irq_entry:
  34. v7m_exception_entry
  35. @
  36. @ Invoke the IRQ handler
  37. @
  38. mrs r0, ipsr
  39. ldr r1, =V7M_xPSR_EXCEPTIONNO
  40. and r0, r1
  41. sub r0, #16
  42. mov r1, sp
  43. stmdb sp!, {lr}
  44. @ routine called with r0 = irq number, r1 = struct pt_regs *
  45. bl nvic_handle_irq
  46. pop {lr}
  47. @
  48. @ Check for any pending work if returning to user
  49. @
  50. ldr r1, =BASEADDR_V7M_SCB
  51. ldr r0, [r1, V7M_SCB_ICSR]
  52. tst r0, V7M_SCB_ICSR_RETTOBASE
  53. beq 2f
  54. get_thread_info tsk
  55. ldr r2, [tsk, #TI_FLAGS]
  56. tst r2, #_TIF_WORK_MASK
  57. beq 2f @ no work pending
  58. mov r0, #V7M_SCB_ICSR_PENDSVSET
  59. str r0, [r1, V7M_SCB_ICSR] @ raise PendSV
  60. 2:
  61. @ registers r0-r3 and r12 are automatically restored on exception
  62. @ return. r4-r7 were not clobbered in v7m_exception_entry so for
  63. @ correctness they don't need to be restored. So only r8-r11 must be
  64. @ restored here. The easiest way to do so is to restore r0-r7, too.
  65. ldmia sp!, {r0-r11}
  66. add sp, #S_FRAME_SIZE-S_IP
  67. cpsie i
  68. bx lr
  69. ENDPROC(__irq_entry)
  70. __pendsv_entry:
  71. v7m_exception_entry
  72. ldr r1, =BASEADDR_V7M_SCB
  73. mov r0, #V7M_SCB_ICSR_PENDSVCLR
  74. str r0, [r1, V7M_SCB_ICSR] @ clear PendSV
  75. @ execute the pending work, including reschedule
  76. get_thread_info tsk
  77. mov why, #0
  78. b ret_to_user
  79. ENDPROC(__pendsv_entry)
  80. /*
  81. * Register switch for ARMv7-M processors.
  82. * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
  83. * previous and next are guaranteed not to be the same.
  84. */
  85. ENTRY(__switch_to)
  86. .fnstart
  87. .cantunwind
  88. add ip, r1, #TI_CPU_SAVE
  89. stmia ip!, {r4 - r11} @ Store most regs on stack
  90. str sp, [ip], #4
  91. str lr, [ip], #4
  92. mov r5, r0
  93. add r4, r2, #TI_CPU_SAVE
  94. ldr r0, =thread_notify_head
  95. mov r1, #THREAD_NOTIFY_SWITCH
  96. bl atomic_notifier_call_chain
  97. mov ip, r4
  98. mov r0, r5
  99. ldmia ip!, {r4 - r11} @ Load all regs saved previously
  100. ldr sp, [ip]
  101. ldr pc, [ip, #4]!
  102. .fnend
  103. ENDPROC(__switch_to)
  104. .data
  105. .align 8
  106. /*
  107. * Vector table (64 words => 256 bytes natural alignment)
  108. */
  109. ENTRY(vector_table)
  110. .long 0 @ 0 - Reset stack pointer
  111. .long __invalid_entry @ 1 - Reset
  112. .long __invalid_entry @ 2 - NMI
  113. .long __invalid_entry @ 3 - HardFault
  114. .long __invalid_entry @ 4 - MemManage
  115. .long __invalid_entry @ 5 - BusFault
  116. .long __invalid_entry @ 6 - UsageFault
  117. .long __invalid_entry @ 7 - Reserved
  118. .long __invalid_entry @ 8 - Reserved
  119. .long __invalid_entry @ 9 - Reserved
  120. .long __invalid_entry @ 10 - Reserved
  121. .long vector_swi @ 11 - SVCall
  122. .long __invalid_entry @ 12 - Debug Monitor
  123. .long __invalid_entry @ 13 - Reserved
  124. .long __pendsv_entry @ 14 - PendSV
  125. .long __invalid_entry @ 15 - SysTick
  126. .rept 64 - 16
  127. .long __irq_entry @ 16..64 - External Interrupts
  128. .endr