Merge tag 'kvm-s390-next-5.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / sh / kernel / entry-common.S
1 /* SPDX-License-Identifier: GPL-2.0
2  *
3  *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
4  *  Copyright (C) 2003 - 2008  Paul Mundt
5  */
6
7 ! NOTE:
8 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
9 ! to be jumped is too far, but it causes illegal slot exception.
10
11 /*      
12  * entry.S contains the system-call and fault low-level handling routines.
13  * This also contains the timer-interrupt handler, as well as all interrupts
14  * and faults that can result in a task-switch.
15  *
16  * NOTE: This code handles signal-recognition, which happens every time
17  * after a timer-interrupt and after each system call.
18  *
19  * NOTE: This code uses a convention that instructions in the delay slot
20  * of a transfer-control instruction are indented by an extra space, thus:
21  *
22  *    jmp       @k0         ! control-transfer instruction
23  *     ldc      k1, ssr     ! delay slot
24  *
25  * Stack layout in 'ret_from_syscall':
26  *      ptrace needs to have all regs on the stack.
27  *      if the order here is changed, it needs to be
28  *      updated in ptrace.c and ptrace.h
29  *
30  *      r0
31  *      ...
32  *      r15 = stack pointer
33  *      spc
34  *      pr
35  *      ssr
36  *      gbr
37  *      mach
38  *      macl
39  *      syscall #
40  *
41  */
42 #include <asm/dwarf.h>
43
44 #if defined(CONFIG_PREEMPTION)
45 #  define preempt_stop()        cli ; TRACE_IRQS_OFF
46 #else
47 #  define preempt_stop()
48 #  define resume_kernel         __restore_all
49 #endif
50
51
52         .align  2
53 ENTRY(exception_error)
54         !
55         TRACE_IRQS_ON
56         sti
57         mov.l   1f, r0
58         jmp     @r0
59          nop
60
61         .align  2
62 1:      .long   do_exception_error
63
64         .align  2
65 ret_from_exception:
66         CFI_STARTPROC simple
67         CFI_DEF_CFA r14, 0
68         CFI_REL_OFFSET 17, 64
69         CFI_REL_OFFSET 15, 60
70         CFI_REL_OFFSET 14, 56
71         CFI_REL_OFFSET 13, 52
72         CFI_REL_OFFSET 12, 48
73         CFI_REL_OFFSET 11, 44
74         CFI_REL_OFFSET 10, 40
75         CFI_REL_OFFSET 9, 36
76         CFI_REL_OFFSET 8, 32
77         preempt_stop()
78 ENTRY(ret_from_irq)
79         !
80         mov     #OFF_SR, r0
81         mov.l   @(r0,r15), r0   ! get status register
82         shll    r0
83         shll    r0              ! kernel space?
84         get_current_thread_info r8, r0
85         bt      resume_kernel   ! Yes, it's from kernel, go back soon
86
87 #ifdef CONFIG_PREEMPTION
88         bra     resume_userspace
89          nop
90 ENTRY(resume_kernel)
91         cli
92         TRACE_IRQS_OFF
93         mov.l   @(TI_PRE_COUNT,r8), r0  ! current_thread_info->preempt_count
94         tst     r0, r0
95         bf      noresched
96 need_resched:
97         mov.l   @(TI_FLAGS,r8), r0      ! current_thread_info->flags
98         tst     #_TIF_NEED_RESCHED, r0  ! need_resched set?
99         bt      noresched
100
101         mov     #OFF_SR, r0
102         mov.l   @(r0,r15), r0           ! get status register
103         shlr    r0
104         and     #(0xf0>>1), r0          ! interrupts off (exception path)?
105         cmp/eq  #(0xf0>>1), r0
106         bt      noresched
107         mov.l   1f, r0
108         jsr     @r0                     ! call preempt_schedule_irq
109          nop
110         bra     need_resched
111          nop
112
113 noresched:
114         bra     __restore_all
115          nop
116
117         .align 2
118 1:      .long   preempt_schedule_irq
119 #endif
120
121 ENTRY(resume_userspace)
122         ! r8: current_thread_info
123         cli
124         TRACE_IRQS_OFF
125         mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
126         tst     #(_TIF_WORK_MASK & 0xff), r0
127         bt/s    __restore_all
128          tst    #_TIF_NEED_RESCHED, r0
129
130         .align  2
131 work_pending:
132         ! r0: current_thread_info->flags
133         ! r8: current_thread_info
134         ! t:  result of "tst    #_TIF_NEED_RESCHED, r0"
135         bf/s    work_resched
136          tst    #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0
137 work_notifysig:
138         bt/s    __restore_all
139          mov    r15, r4
140         mov     r12, r5         ! set arg1(save_r0)
141         mov     r0, r6
142         sti
143         mov.l   2f, r1
144         mov.l   3f, r0
145         jmp     @r1
146          lds    r0, pr
147 work_resched:
148         mov.l   1f, r1
149         jsr     @r1                             ! schedule
150          nop
151         cli
152         TRACE_IRQS_OFF
153         !
154         mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
155         tst     #(_TIF_WORK_MASK & 0xff), r0
156         bt      __restore_all
157         bra     work_pending
158          tst    #_TIF_NEED_RESCHED, r0
159
160         .align  2
161 1:      .long   schedule
162 2:      .long   do_notify_resume
163 3:      .long   resume_userspace
164
165         .align  2
166 syscall_exit_work:
167         ! r0: current_thread_info->flags
168         ! r8: current_thread_info
169         tst     #(_TIF_WORK_SYSCALL_MASK & 0xff), r0
170         bt/s    work_pending
171          tst    #_TIF_NEED_RESCHED, r0
172         TRACE_IRQS_ON
173         sti
174         mov     r15, r4
175         mov.l   8f, r0                  ! do_syscall_trace_leave
176         jsr     @r0
177          nop
178         bra     resume_userspace
179          nop
180
181         .align  2
182 syscall_trace_entry:
183         !                       Yes it is traced.
184         mov     r15, r4
185         mov.l   7f, r11         ! Call do_syscall_trace_enter which notifies
186         jsr     @r11            ! superior (will chomp R[0-7])
187          nop
188         mov.l   r0, @(OFF_R0,r15)       ! Save return value
189         !                       Reload R0-R4 from kernel stack, where the
190         !                       parent may have modified them using
191         !                       ptrace(POKEUSR).  (Note that R0-R2 are
192         !                       reloaded from the kernel stack by syscall_call
193         !                       below, so don't need to be reloaded here.)
194         !                       This allows the parent to rewrite system calls
195         !                       and args on the fly.
196         mov.l   @(OFF_R4,r15), r4   ! arg0
197         mov.l   @(OFF_R5,r15), r5
198         mov.l   @(OFF_R6,r15), r6
199         mov.l   @(OFF_R7,r15), r7   ! arg3
200         mov.l   @(OFF_R3,r15), r3   ! syscall_nr
201         !
202         mov.l   2f, r10                 ! Number of syscalls
203         cmp/hs  r10, r3
204         bf      syscall_call
205         mov     #-ENOSYS, r0
206         bra     syscall_exit
207          mov.l  r0, @(OFF_R0,r15)       ! Return value
208
209 __restore_all:
210         mov     #OFF_SR, r0
211         mov.l   @(r0,r15), r0   ! get status register
212
213         shlr2   r0
214         and     #0x3c, r0
215         cmp/eq  #0x3c, r0
216         bt      1f
217         TRACE_IRQS_ON
218         bra     2f
219          nop
220 1:
221         TRACE_IRQS_OFF
222 2:
223         mov.l   3f, r0
224         jmp     @r0
225          nop
226
227         .align  2
228 3:      .long   restore_all
229
230         .align  2
231 syscall_badsys:                 ! Bad syscall number
232         get_current_thread_info r8, r0
233         mov     #-ENOSYS, r0
234         bra     resume_userspace
235          mov.l  r0, @(OFF_R0,r15)       ! Return value
236
237 /*
238  * The main debug trap handler.
239  *
240  * r8=TRA (not the trap number!)
241  *
242  * Note: This assumes that the trapa value is left in its original
243  * form (without the shlr2 shift) so the calculation for the jump
244  * call table offset remains a simple in place mask.
245  */
246 debug_trap:
247         mov     r8, r0
248         and     #(0xf << 2), r0
249         mov.l   1f, r8
250         add     r0, r8
251         mov.l   @r8, r8
252         jsr     @r8
253          nop
254         bra     ret_from_exception
255          nop
256         CFI_ENDPROC
257
258         .align  2
259 1:      .long   debug_trap_table
260
261 /*
262  * Syscall interface:
263  *
264  *      Syscall #: R3
265  *      Arguments #0 to #3: R4--R7
266  *      Arguments #4 to #6: R0, R1, R2
267  *      TRA: See following table.
268  *
269  * (TRA>>2)     Purpose
270  * --------     -------
271  * 0x00-0x0f    original SH-3/4 syscall ABI (not in general use).
272  * 0x10-0x1f    general SH-3/4 syscall ABI.
273  *      0x1f    unified SH-2/3/4 syscall ABI (preferred).
274  * 0x20-0x2f    original SH-2 syscall ABI.
275  * 0x30-0x3f    debug traps used by the kernel.
276  * 0x40-0xff    Not supported by all parts, so left unhandled.
277  *
278  * For making system calls, any trap number in the range for the
279  * given cpu model may be used, but the unified trap number 0x1f is
280  * preferred for compatibility with all models.
281  *
282  * The low bits of the trap number were once documented as matching
283  * the number of arguments, but they were never actually used as such
284  * by the kernel. SH-2 originally used its own separate trap range
285  * because several hardware exceptions fell in the range used for the
286  * SH-3/4 syscall ABI.
287  *
288  * This code also handles delegating other traps to the BIOS/gdb stub.
289  *
290  * Note: When we're first called, the TRA value must be shifted
291  * right 2 bits in order to get the value that was used as the "trapa"
292  * argument.
293  */
294
295         .align  2
296         .globl  ret_from_fork
297 ret_from_fork:
298         mov.l   1f, r8
299         jsr     @r8
300          mov    r0, r4
301         bra     syscall_exit
302          nop
303
304         .align  2
305         .globl  ret_from_kernel_thread
306 ret_from_kernel_thread:
307         mov.l   1f, r8
308         jsr     @r8
309          mov    r0, r4
310         mov.l   @(OFF_R5,r15), r5   ! fn
311         jsr     @r5
312          mov.l  @(OFF_R4,r15), r4   ! arg
313         bra     syscall_exit
314          nop
315
316         .align  2
317 1:      .long   schedule_tail
318
319 /*
320  * The poorly named main trapa decode and dispatch routine, for
321  * system calls and debug traps through their respective jump tables.
322  */
323 ENTRY(system_call)
324         setup_frame_reg
325 #if !defined(CONFIG_CPU_SH2)
326         mov.l   1f, r9
327         mov.l   @r9, r8         ! Read from TRA (Trap Address) Register
328 #endif
329
330         mov     #OFF_TRA, r10
331         add     r15, r10
332         mov.l   r8, @r10                ! set TRA value to tra
333
334         /*
335          * Check the trap type
336          */
337         mov     #((0x20 << 2) - 1), r9
338         cmp/hi  r9, r8
339         bt/s    debug_trap              ! it's a debug trap..
340          nop
341
342         TRACE_IRQS_ON
343         sti
344
345         !
346         get_current_thread_info r8, r10
347         mov.l   @(TI_FLAGS,r8), r8
348         mov     #(_TIF_WORK_SYSCALL_MASK & 0xff), r10
349         mov     #(_TIF_WORK_SYSCALL_MASK >> 8), r9
350         tst     r10, r8
351         shll8   r9
352         bf      syscall_trace_entry
353         tst     r9, r8
354         bf      syscall_trace_entry
355         !
356         mov.l   2f, r8                  ! Number of syscalls
357         cmp/hs  r8, r3
358         bt      syscall_badsys
359         !
360 syscall_call:
361         shll2   r3              ! x4
362         mov.l   3f, r8          ! Load the address of sys_call_table
363         add     r8, r3
364         mov.l   @r3, r8
365         mov.l   @(OFF_R2,r15), r2
366         mov.l   @(OFF_R1,r15), r1
367         mov.l   @(OFF_R0,r15), r0
368         mov.l   r2, @-r15
369         mov.l   r1, @-r15
370         mov.l   r0, @-r15
371         jsr     @r8             ! jump to specific syscall handler
372          nop
373         add     #12, r15
374         mov.l   @(OFF_R0,r15), r12              ! save r0
375         mov.l   r0, @(OFF_R0,r15)               ! save the return value
376         !
377 syscall_exit:
378         cli
379         TRACE_IRQS_OFF
380         !
381         get_current_thread_info r8, r0
382         mov.l   @(TI_FLAGS,r8), r0              ! current_thread_info->flags
383         tst     #(_TIF_ALLWORK_MASK & 0xff), r0
384         mov     #(_TIF_ALLWORK_MASK >> 8), r1
385         bf      syscall_exit_work
386         shlr8   r0
387         tst     r0, r1
388         bf      syscall_exit_work
389         bra     __restore_all
390          nop
391         .align  2
392 #if !defined(CONFIG_CPU_SH2)
393 1:      .long   TRA
394 #endif
395 2:      .long   NR_syscalls
396 3:      .long   sys_call_table
397 7:      .long   do_syscall_trace_enter
398 8:      .long   do_syscall_trace_leave