Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/score/kernel/entry.S
10817 views
1
/*
2
* arch/score/kernel/entry.S
3
*
4
* Score Processor version.
5
*
6
* Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
7
* Chen Liqin <[email protected]>
8
* Lennox Wu <[email protected]>
9
*
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
14
*
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
19
*
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, see the file COPYING, or write
22
* to the Free Software Foundation, Inc.,
23
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
*/
25
26
#include <linux/err.h>
27
#include <linux/init.h>
28
#include <linux/linkage.h>
29
30
#include <asm/asmmacro.h>
31
#include <asm/thread_info.h>
32
#include <asm/unistd.h>
33
34
/*
35
* disable interrupts.
36
*/
37
.macro disable_irq
38
mfcr r8, cr0
39
srli r8, r8, 1
40
slli r8, r8, 1
41
mtcr r8, cr0
42
nop
43
nop
44
nop
45
nop
46
nop
47
.endm
48
49
/*
50
* enable interrupts.
51
*/
52
.macro enable_irq
53
mfcr r8, cr0
54
ori r8, 1
55
mtcr r8, cr0
56
nop
57
nop
58
nop
59
nop
60
nop
61
.endm
62
63
__INIT
64
ENTRY(debug_exception_vector)
65
nop!
66
nop!
67
nop!
68
nop!
69
nop!
70
nop!
71
nop!
72
nop!
73
74
ENTRY(general_exception_vector) # should move to addr 0x200
75
j general_exception
76
nop!
77
nop!
78
nop!
79
nop!
80
nop!
81
nop!
82
83
ENTRY(interrupt_exception_vector) # should move to addr 0x210
84
j interrupt_exception
85
nop!
86
nop!
87
nop!
88
nop!
89
nop!
90
nop!
91
92
.section ".text", "ax"
93
.align 2;
94
general_exception:
95
mfcr r31, cr2
96
nop
97
la r30, exception_handlers
98
andi r31, 0x1f # get ecr.exc_code
99
slli r31, r31, 2
100
add r30, r30, r31
101
lw r30, [r30]
102
br r30
103
104
interrupt_exception:
105
SAVE_ALL
106
mfcr r4, cr2
107
nop
108
lw r16, [r28, TI_REGS]
109
sw r0, [r28, TI_REGS]
110
la r3, ret_from_irq
111
srli r4, r4, 18 # get ecr.ip[7:2], interrupt No.
112
mv r5, r0
113
j do_IRQ
114
115
ENTRY(handle_nmi) # NMI #1
116
SAVE_ALL
117
mv r4, r0
118
la r8, nmi_exception_handler
119
brl r8
120
j restore_all
121
122
ENTRY(handle_adelinsn) # AdEL-instruction #2
123
SAVE_ALL
124
mfcr r8, cr6
125
nop
126
nop
127
sw r8, [r0, PT_EMA]
128
mv r4, r0
129
la r8, do_adelinsn
130
brl r8
131
mv r4, r0
132
j ret_from_exception
133
nop
134
135
ENTRY(handle_ibe) # BusEL-instruction #5
136
SAVE_ALL
137
mv r4, r0
138
la r8, do_be
139
brl r8
140
mv r4, r0
141
j ret_from_exception
142
nop
143
144
ENTRY(handle_pel) # P-EL #6
145
SAVE_ALL
146
mv r4, r0
147
la r8, do_pel
148
brl r8
149
mv r4, r0
150
j ret_from_exception
151
nop
152
153
ENTRY(handle_ccu) # CCU #8
154
SAVE_ALL
155
mv r4, r0
156
la r8, do_ccu
157
brl r8
158
mv r4, r0
159
j ret_from_exception
160
nop
161
162
ENTRY(handle_ri) # RI #9
163
SAVE_ALL
164
mv r4, r0
165
la r8, do_ri
166
brl r8
167
mv r4, r0
168
j ret_from_exception
169
nop
170
171
ENTRY(handle_tr) # Trap #10
172
SAVE_ALL
173
mv r4, r0
174
la r8, do_tr
175
brl r8
176
mv r4, r0
177
j ret_from_exception
178
nop
179
180
ENTRY(handle_adedata) # AdES-instruction #12
181
SAVE_ALL
182
mfcr r8, cr6
183
nop
184
nop
185
sw r8, [r0, PT_EMA]
186
mv r4, r0
187
la r8, do_adedata
188
brl r8
189
mv r4, r0
190
j ret_from_exception
191
nop
192
193
ENTRY(handle_cee) # CeE #16
194
SAVE_ALL
195
mv r4, r0
196
la r8, do_cee
197
brl r8
198
mv r4, r0
199
j ret_from_exception
200
nop
201
202
ENTRY(handle_cpe) # CpE #17
203
SAVE_ALL
204
mv r4, r0
205
la r8, do_cpe
206
brl r8
207
mv r4, r0
208
j ret_from_exception
209
nop
210
211
ENTRY(handle_dbe) # BusEL-data #18
212
SAVE_ALL
213
mv r4, r0
214
la r8, do_be
215
brl r8
216
mv r4, r0
217
j ret_from_exception
218
nop
219
220
ENTRY(handle_reserved) # others
221
SAVE_ALL
222
mv r4, r0
223
la r8, do_reserved
224
brl r8
225
mv r4, r0
226
j ret_from_exception
227
nop
228
229
#ifndef CONFIG_PREEMPT
230
#define resume_kernel restore_all
231
#else
232
#define __ret_from_irq ret_from_exception
233
#endif
234
235
.align 2
236
#ifndef CONFIG_PREEMPT
237
ENTRY(ret_from_exception)
238
disable_irq # preempt stop
239
nop
240
j __ret_from_irq
241
nop
242
#endif
243
244
ENTRY(ret_from_irq)
245
sw r16, [r28, TI_REGS]
246
247
ENTRY(__ret_from_irq)
248
lw r8, [r0, PT_PSR] # returning to kernel mode?
249
andri.c r8, r8, KU_USER
250
beq resume_kernel
251
252
resume_userspace:
253
disable_irq
254
lw r6, [r28, TI_FLAGS] # current->work
255
li r8, _TIF_WORK_MASK
256
and.c r8, r8, r6 # ignoring syscall_trace
257
bne work_pending
258
nop
259
j restore_all
260
nop
261
262
#ifdef CONFIG_PREEMPT
263
resume_kernel:
264
disable_irq
265
lw r8, [r28, TI_PRE_COUNT]
266
cmpz.c r8
267
bne r8, restore_all
268
need_resched:
269
lw r8, [r28, TI_FLAGS]
270
andri.c r9, r8, _TIF_NEED_RESCHED
271
beq restore_all
272
lw r8, [r28, PT_PSR] # Interrupts off?
273
andri.c r8, r8, 1
274
beq restore_all
275
bl preempt_schedule_irq
276
nop
277
j need_resched
278
nop
279
#endif
280
281
ENTRY(ret_from_fork)
282
bl schedule_tail # r4=struct task_struct *prev
283
284
ENTRY(syscall_exit)
285
nop
286
disable_irq
287
lw r6, [r28, TI_FLAGS] # current->work
288
li r8, _TIF_WORK_MASK
289
and.c r8, r6, r8
290
bne syscall_exit_work
291
292
ENTRY(restore_all) # restore full frame
293
RESTORE_ALL_AND_RET
294
295
work_pending:
296
andri.c r8, r6, _TIF_NEED_RESCHED # r6 is preloaded with TI_FLAGS
297
beq work_notifysig
298
work_resched:
299
bl schedule
300
nop
301
disable_irq
302
lw r6, [r28, TI_FLAGS]
303
li r8, _TIF_WORK_MASK
304
and.c r8, r6, r8 # is there any work to be done
305
# other than syscall tracing?
306
beq restore_all
307
andri.c r8, r6, _TIF_NEED_RESCHED
308
bne work_resched
309
310
work_notifysig:
311
mv r4, r0
312
li r5, 0
313
bl do_notify_resume # r6 already loaded
314
nop
315
j resume_userspace
316
nop
317
318
ENTRY(syscall_exit_work)
319
li r8, _TIF_SYSCALL_TRACE
320
and.c r8, r8, r6 # r6 is preloaded with TI_FLAGS
321
beq work_pending # trace bit set?
322
nop
323
enable_irq
324
mv r4, r0
325
li r5, 1
326
bl do_syscall_trace
327
nop
328
b resume_userspace
329
nop
330
331
.macro save_context reg
332
sw r12, [\reg, THREAD_REG12];
333
sw r13, [\reg, THREAD_REG13];
334
sw r14, [\reg, THREAD_REG14];
335
sw r15, [\reg, THREAD_REG15];
336
sw r16, [\reg, THREAD_REG16];
337
sw r17, [\reg, THREAD_REG17];
338
sw r18, [\reg, THREAD_REG18];
339
sw r19, [\reg, THREAD_REG19];
340
sw r20, [\reg, THREAD_REG20];
341
sw r21, [\reg, THREAD_REG21];
342
sw r29, [\reg, THREAD_REG29];
343
sw r2, [\reg, THREAD_REG2];
344
sw r0, [\reg, THREAD_REG0]
345
.endm
346
347
.macro restore_context reg
348
lw r12, [\reg, THREAD_REG12];
349
lw r13, [\reg, THREAD_REG13];
350
lw r14, [\reg, THREAD_REG14];
351
lw r15, [\reg, THREAD_REG15];
352
lw r16, [\reg, THREAD_REG16];
353
lw r17, [\reg, THREAD_REG17];
354
lw r18, [\reg, THREAD_REG18];
355
lw r19, [\reg, THREAD_REG19];
356
lw r20, [\reg, THREAD_REG20];
357
lw r21, [\reg, THREAD_REG21];
358
lw r29, [\reg, THREAD_REG29];
359
lw r0, [\reg, THREAD_REG0];
360
lw r2, [\reg, THREAD_REG2];
361
lw r3, [\reg, THREAD_REG3]
362
.endm
363
364
/*
365
* task_struct *resume(task_struct *prev, task_struct *next,
366
* struct thread_info *next_ti)
367
*/
368
ENTRY(resume)
369
mfcr r9, cr0
370
nop
371
nop
372
sw r9, [r4, THREAD_PSR]
373
save_context r4
374
sw r3, [r4, THREAD_REG3]
375
376
mv r28, r6
377
restore_context r5
378
mv r8, r6
379
addi r8, KERNEL_STACK_SIZE
380
subi r8, 32
381
la r9, kernelsp;
382
sw r8, [r9];
383
384
mfcr r9, cr0
385
ldis r7, 0x00ff
386
nop
387
and r9, r9, r7
388
lw r6, [r5, THREAD_PSR]
389
not r7, r7
390
and r6, r6, r7
391
or r6, r6, r9
392
mtcr r6, cr0
393
nop; nop; nop; nop; nop
394
br r3
395
396
ENTRY(handle_sys)
397
SAVE_ALL
398
sw r8, [r0, 16] # argument 5 from user r8
399
sw r9, [r0, 20] # argument 6 from user r9
400
enable_irq
401
402
sw r4, [r0, PT_ORIG_R4] #for restart syscall
403
sw r7, [r0, PT_ORIG_R7] #for restart syscall
404
sw r27, [r0, PT_IS_SYSCALL] # it from syscall
405
406
lw r9, [r0, PT_EPC] # skip syscall on return
407
addi r9, 4
408
sw r9, [r0, PT_EPC]
409
410
cmpi.c r27, __NR_syscalls # check syscall number
411
bgtu illegal_syscall
412
413
slli r8, r27, 2 # get syscall routine
414
la r11, sys_call_table
415
add r11, r11, r8
416
lw r10, [r11] # get syscall entry
417
418
cmpz.c r10
419
beq illegal_syscall
420
421
lw r8, [r28, TI_FLAGS]
422
li r9, _TIF_SYSCALL_TRACE
423
and.c r8, r8, r9
424
bne syscall_trace_entry
425
426
brl r10 # Do The Real system call
427
428
cmpi.c r4, 0
429
blt 1f
430
ldi r8, 0
431
sw r8, [r0, PT_R7]
432
b 2f
433
1:
434
cmpi.c r4, -MAX_ERRNO - 1
435
ble 2f
436
ldi r8, 0x1;
437
sw r8, [r0, PT_R7]
438
neg r4, r4
439
2:
440
sw r4, [r0, PT_R4] # save result
441
442
syscall_return:
443
disable_irq
444
lw r6, [r28, TI_FLAGS] # current->work
445
li r8, _TIF_WORK_MASK
446
and.c r8, r6, r8
447
bne syscall_return_work
448
j restore_all
449
450
syscall_return_work:
451
j syscall_exit_work
452
453
syscall_trace_entry:
454
mv r16, r10
455
mv r4, r0
456
li r5, 0
457
bl do_syscall_trace
458
459
mv r8, r16
460
lw r4, [r0, PT_R4] # Restore argument registers
461
lw r5, [r0, PT_R5]
462
lw r6, [r0, PT_R6]
463
lw r7, [r0, PT_R7]
464
brl r8
465
466
li r8, -MAX_ERRNO - 1
467
sw r8, [r0, PT_R7] # set error flag
468
469
neg r4, r4 # error
470
sw r4, [r0, PT_R0] # set flag for syscall
471
# restarting
472
1: sw r4, [r0, PT_R2] # result
473
j syscall_exit
474
475
illegal_syscall:
476
ldi r4, -ENOSYS # error
477
sw r4, [r0, PT_ORIG_R4]
478
sw r4, [r0, PT_R4]
479
ldi r9, 1 # set error flag
480
sw r9, [r0, PT_R7]
481
j syscall_return
482
483
ENTRY(sys_execve)
484
mv r4, r0
485
la r8, score_execve
486
br r8
487
488
ENTRY(sys_clone)
489
mv r4, r0
490
la r8, score_clone
491
br r8
492
493
ENTRY(sys_rt_sigreturn)
494
mv r4, r0
495
la r8, score_rt_sigreturn
496
br r8
497
498
ENTRY(sys_sigaltstack)
499
mv r4, r0
500
la r8, score_sigaltstack
501
br r8
502
503
#ifdef __ARCH_WANT_SYSCALL_DEPRECATED
504
ENTRY(sys_fork)
505
mv r4, r0
506
la r8, score_fork
507
br r8
508
509
ENTRY(sys_vfork)
510
mv r4, r0
511
la r8, score_vfork
512
br r8
513
#endif /* __ARCH_WANT_SYSCALL_DEPRECATED */
514
515
516