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