hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 */
 
#ifndef __ASM_ARC_ENTRY_H
#define __ASM_ARC_ENTRY_H
 
#include <asm/unistd.h>        /* For NR_syscalls defination */
#include <asm/arcregs.h>
#include <asm/ptrace.h>
#include <asm/processor.h>    /* For VMALLOC_START */
#include <asm/mmu.h>
 
#ifdef CONFIG_ISA_ARCOMPACT
#include <asm/entry-compact.h>    /* ISA specific bits */
#else
#include <asm/entry-arcv2.h>
#endif
 
/* Note on the LD/ST addr modes with addr reg wback
 *
 * LD.a same as LD.aw
 *
 * LD.a    reg1, [reg2, x]  => Pre Incr
 *      Eff Addr for load = [reg2 + x]
 *
 * LD.ab   reg1, [reg2, x]  => Post Incr
 *      Eff Addr for load = [reg2]
 */
 
.macro PUSH reg
   st.a    \reg, [sp, -4]
.endm
 
.macro PUSHAX aux
   lr    r9, [\aux]
   PUSH    r9
.endm
 
.macro POP reg
   ld.ab    \reg, [sp, 4]
.endm
 
.macro POPAX aux
   POP    r9
   sr    r9, [\aux]
.endm
 
/*--------------------------------------------------------------
 * Helpers to save/restore Scratch Regs:
 * used by Interrupt/Exception Prologue/Epilogue
 *-------------------------------------------------------------*/
.macro  SAVE_R0_TO_R12
   PUSH    r0
   PUSH    r1
   PUSH    r2
   PUSH    r3
   PUSH    r4
   PUSH    r5
   PUSH    r6
   PUSH    r7
   PUSH    r8
   PUSH    r9
   PUSH    r10
   PUSH    r11
   PUSH    r12
.endm
 
.macro RESTORE_R12_TO_R0
   POP    r12
   POP    r11
   POP    r10
   POP    r9
   POP    r8
   POP    r7
   POP    r6
   POP    r5
   POP    r4
   POP    r3
   POP    r2
   POP    r1
   POP    r0
 
.endm
 
/*--------------------------------------------------------------
 * Helpers to save/restore callee-saved regs:
 * used by several macros below
 *-------------------------------------------------------------*/
.macro SAVE_R13_TO_R24
   PUSH    r13
   PUSH    r14
   PUSH    r15
   PUSH    r16
   PUSH    r17
   PUSH    r18
   PUSH    r19
   PUSH    r20
   PUSH    r21
   PUSH    r22
   PUSH    r23
   PUSH    r24
.endm
 
.macro RESTORE_R24_TO_R13
   POP    r24
   POP    r23
   POP    r22
   POP    r21
   POP    r20
   POP    r19
   POP    r18
   POP    r17
   POP    r16
   POP    r15
   POP    r14
   POP    r13
.endm
 
/*--------------------------------------------------------------
 * Collect User Mode callee regs as struct callee_regs - needed by
 * fork/do_signal/unaligned-access-emulation.
 * (By default only scratch regs are saved on entry to kernel)
 *
 * Special handling for r25 if used for caching Task Pointer.
 * It would have been saved in task->thread.user_r25 already, but to keep
 * the interface same it is copied into regular r25 placeholder in
 * struct callee_regs.
 *-------------------------------------------------------------*/
.macro SAVE_CALLEE_SAVED_USER
 
   mov    r12, sp        ; save SP as ref to pt_regs
   SAVE_R13_TO_R24
 
#ifdef CONFIG_ARC_CURR_IN_REG
   ; Retrieve orig r25 and save it with rest of callee_regs
   ld    r12, [r12, PT_user_r25]
   PUSH    r12
#else
   PUSH    r25
#endif
 
.endm
 
/*--------------------------------------------------------------
 * Save kernel Mode callee regs at the time of Contect Switch.
 *
 * Special handling for r25 if used for caching Task Pointer.
 * Kernel simply skips saving it since it will be loaded with
 * incoming task pointer anyways
 *-------------------------------------------------------------*/
.macro SAVE_CALLEE_SAVED_KERNEL
 
   SAVE_R13_TO_R24
 
#ifdef CONFIG_ARC_CURR_IN_REG
   sub     sp, sp, 4
#else
   PUSH    r25
#endif
.endm
 
/*--------------------------------------------------------------
 * Opposite of SAVE_CALLEE_SAVED_KERNEL
 *-------------------------------------------------------------*/
.macro RESTORE_CALLEE_SAVED_KERNEL
 
#ifdef CONFIG_ARC_CURR_IN_REG
   add     sp, sp, 4  /* skip usual r25 placeholder */
#else
   POP    r25
#endif
   RESTORE_R24_TO_R13
.endm
 
/*--------------------------------------------------------------
 * Opposite of SAVE_CALLEE_SAVED_USER
 *
 * ptrace tracer or unaligned-access fixup might have changed a user mode
 * callee reg which is saved back to usual r25 storage location
 *-------------------------------------------------------------*/
.macro RESTORE_CALLEE_SAVED_USER
 
#ifdef CONFIG_ARC_CURR_IN_REG
   POP    r12
#else
   POP    r25
#endif
   RESTORE_R24_TO_R13
 
   ; SP is back to start of pt_regs
#ifdef CONFIG_ARC_CURR_IN_REG
   st    r12, [sp, PT_user_r25]
#endif
.endm
 
/*--------------------------------------------------------------
 * Super FAST Restore callee saved regs by simply re-adjusting SP
 *-------------------------------------------------------------*/
.macro DISCARD_CALLEE_SAVED_USER
   add     sp, sp, SZ_CALLEE_REGS
.endm
 
/*-------------------------------------------------------------
 * given a tsk struct, get to the base of it's kernel mode stack
 * tsk->thread_info is really a PAGE, whose bottom hoists stack
 * which grows upwards towards thread_info
 *------------------------------------------------------------*/
 
.macro GET_TSK_STACK_BASE tsk, out
 
   /* Get task->thread_info (this is essentially start of a PAGE) */
   ld  \out, [\tsk, TASK_THREAD_INFO]
 
   /* Go to end of page where stack begins (grows upwards) */
   add2 \out, \out, (THREAD_SIZE)/4
 
.endm
 
/*
 * @reg [OUT] thread_info->flags of "current"
 */
.macro GET_CURR_THR_INFO_FLAGS  reg
   GET_CURR_THR_INFO_FROM_SP  \reg
   ld  \reg, [\reg, THREAD_INFO_FLAGS]
.endm
 
#ifdef CONFIG_SMP
 
/*-------------------------------------------------
 * Retrieve the current running task on this CPU
 * 1. Determine curr CPU id.
 * 2. Use it to index into _current_task[ ]
 */
.macro  GET_CURR_TASK_ON_CPU   reg
   GET_CPU_ID  \reg
   ld.as  \reg, [@_current_task, \reg]
.endm
 
/*-------------------------------------------------
 * Save a new task as the "current" task on this CPU
 * 1. Determine curr CPU id.
 * 2. Use it to index into _current_task[ ]
 *
 * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS)
 * because ST r0, [r1, offset] can ONLY have s9 @offset
 * while   LD can take s9 (4 byte insn) or LIMM (8 byte insn)
 */
 
.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
   GET_CPU_ID  \tmp
   add2 \tmp, @_current_task, \tmp
   st   \tsk, [\tmp]
#ifdef CONFIG_ARC_CURR_IN_REG
   mov r25, \tsk
#endif
 
.endm
 
 
#else   /* Uniprocessor implementation of macros */
 
.macro  GET_CURR_TASK_ON_CPU    reg
   ld  \reg, [@_current_task]
.endm
 
.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
   st  \tsk, [@_current_task]
#ifdef CONFIG_ARC_CURR_IN_REG
   mov r25, \tsk
#endif
.endm
 
#endif /* SMP / UNI */
 
/* ------------------------------------------------------------------
 * Get the ptr to some field of Current Task at @off in task struct
 *  -Uses r25 for Current task ptr if that is enabled
 */
 
#ifdef CONFIG_ARC_CURR_IN_REG
 
.macro GET_CURR_TASK_FIELD_PTR  off,  reg
   add \reg, r25, \off
.endm
 
#else
 
.macro GET_CURR_TASK_FIELD_PTR  off,  reg
   GET_CURR_TASK_ON_CPU  \reg
   add \reg, \reg, \off
.endm
 
#endif    /* CONFIG_ARC_CURR_IN_REG */
 
#endif  /* __ASM_ARC_ENTRY_H */