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