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
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
| /* SPDX-License-Identifier: GPL-2.0 */
| // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
|
| #include <linux/linkage.h>
| #include <abi/entry.h>
| #include <abi/pgtable-bits.h>
| #include <asm/errno.h>
| #include <asm/setup.h>
| #include <asm/unistd.h>
| #include <asm/asm-offsets.h>
| #include <linux/threads.h>
| #include <asm/setup.h>
| #include <asm/page.h>
| #include <asm/thread_info.h>
|
| #define PTE_INDX_MSK 0xffc
| #define PTE_INDX_SHIFT 10
| #define _PGDIR_SHIFT 22
|
| .macro zero_fp
| #ifdef CONFIG_STACKTRACE
| movi r8, 0
| #endif
| .endm
|
| .macro context_tracking
| #ifdef CONFIG_CONTEXT_TRACKING
| mfcr a0, epsr
| btsti a0, 31
| bt 1f
| jbsr context_tracking_user_exit
| ldw a0, (sp, LSAVE_A0)
| ldw a1, (sp, LSAVE_A1)
| ldw a2, (sp, LSAVE_A2)
| ldw a3, (sp, LSAVE_A3)
| #if defined(__CSKYABIV1__)
| ldw r6, (sp, LSAVE_A4)
| ldw r7, (sp, LSAVE_A5)
| #endif
| 1:
| #endif
| .endm
|
| .macro tlbop_begin name, val0, val1, val2
| ENTRY(csky_\name)
| mtcr a3, ss2
| mtcr r6, ss3
| mtcr a2, ss4
|
| RD_PGDR r6
| RD_MEH a3
| #ifdef CONFIG_CPU_HAS_TLBI
| tlbi.vaas a3
| sync.is
|
| btsti a3, 31
| bf 1f
| RD_PGDR_K r6
| 1:
| #else
| bgeni a2, 31
| WR_MCIR a2
| bgeni a2, 25
| WR_MCIR a2
| #endif
| bclri r6, 0
| lrw a2, va_pa_offset
| ld.w a2, (a2, 0)
| subu r6, a2
| bseti r6, 31
|
| mov a2, a3
| lsri a2, _PGDIR_SHIFT
| lsli a2, 2
| addu r6, a2
| ldw r6, (r6)
|
| lrw a2, va_pa_offset
| ld.w a2, (a2, 0)
| subu r6, a2
| bseti r6, 31
|
| lsri a3, PTE_INDX_SHIFT
| lrw a2, PTE_INDX_MSK
| and a3, a2
| addu r6, a3
| ldw a3, (r6)
|
| movi a2, (_PAGE_PRESENT | \val0)
| and a3, a2
| cmpne a3, a2
| bt \name
|
| /* First read/write the page, just update the flags */
| ldw a3, (r6)
| bgeni a2, PAGE_VALID_BIT
| bseti a2, PAGE_ACCESSED_BIT
| bseti a2, \val1
| bseti a2, \val2
| or a3, a2
| stw a3, (r6)
|
| /* Some cpu tlb-hardrefill bypass the cache */
| #ifdef CONFIG_CPU_NEED_TLBSYNC
| movi a2, 0x22
| bseti a2, 6
| mtcr r6, cr22
| mtcr a2, cr17
| sync
| #endif
|
| mfcr a3, ss2
| mfcr r6, ss3
| mfcr a2, ss4
| rte
| \name:
| mfcr a3, ss2
| mfcr r6, ss3
| mfcr a2, ss4
| SAVE_ALL 0
| .endm
| .macro tlbop_end is_write
| zero_fp
| context_tracking
| RD_MEH a2
| psrset ee, ie
| mov a0, sp
| movi a1, \is_write
| jbsr do_page_fault
| jmpi ret_from_exception
| .endm
|
| .text
|
| tlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT
| tlbop_end 0
|
| tlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
| tlbop_end 1
|
| tlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
| #ifndef CONFIG_CPU_HAS_LDSTEX
| jbsr csky_cmpxchg_fixup
| #endif
| tlbop_end 1
|
| ENTRY(csky_systemcall)
| SAVE_ALL TRAP0_SIZE
| zero_fp
| context_tracking
| psrset ee, ie
|
| lrw r9, __NR_syscalls
| cmphs syscallid, r9 /* Check nr of syscall */
| bt 1f
|
| lrw r9, sys_call_table
| ixw r9, syscallid
| ldw syscallid, (r9)
| cmpnei syscallid, 0
| bf ret_from_exception
|
| mov r9, sp
| bmaski r10, THREAD_SHIFT
| andn r9, r10
| ldw r10, (r9, TINFO_FLAGS)
| lrw r9, _TIF_SYSCALL_WORK
| and r10, r9
| cmpnei r10, 0
| bt csky_syscall_trace
| #if defined(__CSKYABIV2__)
| subi sp, 8
| stw r5, (sp, 0x4)
| stw r4, (sp, 0x0)
| jsr syscallid /* Do system call */
| addi sp, 8
| #else
| jsr syscallid
| #endif
| stw a0, (sp, LSAVE_A0) /* Save return value */
| 1:
| #ifdef CONFIG_DEBUG_RSEQ
| mov a0, sp
| jbsr rseq_syscall
| #endif
| jmpi ret_from_exception
|
| csky_syscall_trace:
| mov a0, sp /* sp = pt_regs pointer */
| jbsr syscall_trace_enter
| cmpnei a0, 0
| bt 1f
| /* Prepare args before do system call */
| ldw a0, (sp, LSAVE_A0)
| ldw a1, (sp, LSAVE_A1)
| ldw a2, (sp, LSAVE_A2)
| ldw a3, (sp, LSAVE_A3)
| #if defined(__CSKYABIV2__)
| subi sp, 8
| ldw r9, (sp, LSAVE_A4)
| stw r9, (sp, 0x0)
| ldw r9, (sp, LSAVE_A5)
| stw r9, (sp, 0x4)
| jsr syscallid /* Do system call */
| addi sp, 8
| #else
| ldw r6, (sp, LSAVE_A4)
| ldw r7, (sp, LSAVE_A5)
| jsr syscallid /* Do system call */
| #endif
| stw a0, (sp, LSAVE_A0) /* Save return value */
|
| 1:
| #ifdef CONFIG_DEBUG_RSEQ
| mov a0, sp
| jbsr rseq_syscall
| #endif
| mov a0, sp /* right now, sp --> pt_regs */
| jbsr syscall_trace_exit
| br ret_from_exception
|
| ENTRY(ret_from_kernel_thread)
| jbsr schedule_tail
| mov a0, r10
| jsr r9
| jbsr ret_from_exception
|
| ENTRY(ret_from_fork)
| jbsr schedule_tail
| mov r9, sp
| bmaski r10, THREAD_SHIFT
| andn r9, r10
| ldw r10, (r9, TINFO_FLAGS)
| lrw r9, _TIF_SYSCALL_WORK
| and r10, r9
| cmpnei r10, 0
| bf ret_from_exception
| mov a0, sp /* sp = pt_regs pointer */
| jbsr syscall_trace_exit
|
| ret_from_exception:
| psrclr ie
| ld r9, (sp, LSAVE_PSR)
| btsti r9, 31
|
| bt 1f
| /*
| * Load address of current->thread_info, Then get address of task_struct
| * Get task_needreshed in task_struct
| */
| mov r9, sp
| bmaski r10, THREAD_SHIFT
| andn r9, r10
|
| ldw r10, (r9, TINFO_FLAGS)
| lrw r9, _TIF_WORK_MASK
| and r10, r9
| cmpnei r10, 0
| bt exit_work
| #ifdef CONFIG_CONTEXT_TRACKING
| jbsr context_tracking_user_enter
| #endif
| 1:
| #ifdef CONFIG_PREEMPTION
| mov r9, sp
| bmaski r10, THREAD_SHIFT
| andn r9, r10
|
| ldw r10, (r9, TINFO_PREEMPT)
| cmpnei r10, 0
| bt 2f
| jbsr preempt_schedule_irq /* irq en/disable is done inside */
| 2:
| #endif
|
| #ifdef CONFIG_TRACE_IRQFLAGS
| ld r10, (sp, LSAVE_PSR)
| btsti r10, 6
| bf 2f
| jbsr trace_hardirqs_on
| 2:
| #endif
| RESTORE_ALL
|
| exit_work:
| lrw r9, ret_from_exception
| mov lr, r9
|
| btsti r10, TIF_NEED_RESCHED
| bt work_resched
|
| psrset ie
| mov a0, sp
| mov a1, r10
| jmpi do_notify_resume
|
| work_resched:
| jmpi schedule
|
| ENTRY(csky_trap)
| SAVE_ALL 0
| zero_fp
| context_tracking
| psrset ee
| mov a0, sp /* Push Stack pointer arg */
| jbsr trap_c /* Call C-level trap handler */
| jmpi ret_from_exception
|
| /*
| * Prototype from libc for abiv1:
| * register unsigned int __result asm("a0");
| * asm( "trap 3" :"=r"(__result)::);
| */
| ENTRY(csky_get_tls)
| USPTOKSP
|
| /* increase epc for continue */
| mfcr a0, epc
| addi a0, TRAP0_SIZE
| mtcr a0, epc
|
| /* get current task thread_info with kernel 8K stack */
| bmaski a0, THREAD_SHIFT
| not a0
| subi sp, 1
| and a0, sp
| addi sp, 1
|
| /* get tls */
| ldw a0, (a0, TINFO_TP_VALUE)
|
| KSPTOUSP
| rte
|
| ENTRY(csky_irq)
| SAVE_ALL 0
| zero_fp
| context_tracking
| psrset ee
|
| #ifdef CONFIG_TRACE_IRQFLAGS
| jbsr trace_hardirqs_off
| #endif
|
|
| mov a0, sp
| jbsr csky_do_IRQ
|
| jmpi ret_from_exception
|
| /*
| * a0 = prev task_struct *
| * a1 = next task_struct *
| * a0 = return next
| */
| ENTRY(__switch_to)
| lrw a3, TASK_THREAD
| addu a3, a0
|
| SAVE_SWITCH_STACK
|
| stw sp, (a3, THREAD_KSP)
|
| /* Set up next process to run */
| lrw a3, TASK_THREAD
| addu a3, a1
|
| ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */
|
| #if defined(__CSKYABIV2__)
| addi a3, a1, TASK_THREAD_INFO
| ldw tls, (a3, TINFO_TP_VALUE)
| #endif
|
| RESTORE_SWITCH_STACK
|
| rts
| ENDPROC(__switch_to)
|
|