0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <asm/memory.h>
0010 #include <asm/glue.h>
0011 #include <asm/thread_notify.h>
0012 #include <asm/v7m.h>
0013
0014 #include "entry-header.S"
0015
0016 #ifdef CONFIG_TRACE_IRQFLAGS
0017 #error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation"
0018 #endif
0019
0020 __invalid_entry:
0021 v7m_exception_entry
0022 #ifdef CONFIG_PRINTK
0023 adr r0, strerr
0024 mrs r1, ipsr
0025 mov r2, lr
0026 bl _printk
0027 #endif
0028 mov r0, sp
0029 bl show_regs
0030 1: b 1b
0031 ENDPROC(__invalid_entry)
0032
0033 strerr: .asciz "\nUnhandled exception: IPSR = %08lx LR = %08lx\n"
0034
0035 .align 2
0036 __irq_entry:
0037 v7m_exception_entry
0038
0039 @
0040 @ Invoke the IRQ handler
0041 @
0042 mov r0, sp
0043 ldr_this_cpu sp, irq_stack_ptr, r1, r2
0044
0045 @
0046 @ If we took the interrupt while running in the kernel, we may already
0047 @ be using the IRQ stack, so revert to the original value in that case.
0048 @
0049 subs r2, sp, r0 @ SP above bottom of IRQ stack?
0050 rsbscs r2, r2, #THREAD_SIZE @ ... and below the top?
0051 movcs sp, r0
0052
0053 push {r0, lr} @ preserve LR and original SP
0054
0055 @ routine called with r0 = struct pt_regs *
0056 bl generic_handle_arch_irq
0057
0058 pop {r0, lr}
0059 mov sp, r0
0060
0061 @
0062 @ Check for any pending work if returning to user
0063 @
0064 ldr r1, =BASEADDR_V7M_SCB
0065 ldr r0, [r1, V7M_SCB_ICSR]
0066 tst r0, V7M_SCB_ICSR_RETTOBASE
0067 beq 2f
0068
0069 get_thread_info tsk
0070 ldr r2, [tsk, #TI_FLAGS]
0071 movs r2, r2, lsl #16
0072 beq 2f @ no work pending
0073 mov r0, #V7M_SCB_ICSR_PENDSVSET
0074 str r0, [r1, V7M_SCB_ICSR] @ raise PendSV
0075
0076 2:
0077 @ registers r0-r3 and r12 are automatically restored on exception
0078 @ return. r4-r7 were not clobbered in v7m_exception_entry so for
0079 @ correctness they don't need to be restored. So only r8-r11 must be
0080 @ restored here. The easiest way to do so is to restore r0-r7, too.
0081 ldmia sp!, {r0-r11}
0082 add sp, #PT_REGS_SIZE-S_IP
0083 cpsie i
0084 bx lr
0085 ENDPROC(__irq_entry)
0086
0087 __pendsv_entry:
0088 v7m_exception_entry
0089
0090 ldr r1, =BASEADDR_V7M_SCB
0091 mov r0, #V7M_SCB_ICSR_PENDSVCLR
0092 str r0, [r1, V7M_SCB_ICSR] @ clear PendSV
0093
0094 @ execute the pending work, including reschedule
0095 get_thread_info tsk
0096 mov why, #0
0097 b ret_to_user_from_irq
0098 ENDPROC(__pendsv_entry)
0099
0100
0101
0102
0103
0104
0105 ENTRY(__switch_to)
0106 .fnstart
0107 .cantunwind
0108 add ip, r1, #TI_CPU_SAVE
0109 stmia ip!, {r4 - r11} @ Store most regs on stack
0110 str sp, [ip], #4
0111 str lr, [ip], #4
0112 mov r5, r0
0113 mov r6, r2 @ Preserve 'next'
0114 add r4, r2, #TI_CPU_SAVE
0115 ldr r0, =thread_notify_head
0116 mov r1, #THREAD_NOTIFY_SWITCH
0117 bl atomic_notifier_call_chain
0118 mov r0, r5
0119 mov r1, r6
0120 ldmia r4, {r4 - r12, lr} @ Load all regs saved previously
0121 set_current r1, r2
0122 mov sp, ip
0123 bx lr
0124 .fnend
0125 ENDPROC(__switch_to)
0126
0127 .data
0128 #if CONFIG_CPU_V7M_NUM_IRQ <= 112
0129 .align 9
0130 #else
0131 .align 10
0132 #endif
0133
0134
0135
0136
0137 ENTRY(vector_table)
0138 .long 0 @ 0 - Reset stack pointer
0139 .long __invalid_entry @ 1 - Reset
0140 .long __invalid_entry @ 2 - NMI
0141 .long __invalid_entry @ 3 - HardFault
0142 .long __invalid_entry @ 4 - MemManage
0143 .long __invalid_entry @ 5 - BusFault
0144 .long __invalid_entry @ 6 - UsageFault
0145 .long __invalid_entry @ 7 - Reserved
0146 .long __invalid_entry @ 8 - Reserved
0147 .long __invalid_entry @ 9 - Reserved
0148 .long __invalid_entry @ 10 - Reserved
0149 .long vector_swi @ 11 - SVCall
0150 .long __invalid_entry @ 12 - Debug Monitor
0151 .long __invalid_entry @ 13 - Reserved
0152 .long __pendsv_entry @ 14 - PendSV
0153 .long __invalid_entry @ 15 - SysTick
0154 .rept CONFIG_CPU_V7M_NUM_IRQ
0155 .long __irq_entry @ External Interrupts
0156 .endr
0157 .align 2
0158 .globl exc_ret
0159 exc_ret:
0160 .space 4