Linux-libre 4.14.68-gnu
[librecmc/linux-libre.git] / arch / h8300 / kernel / entry.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *
4  *  linux/arch/h8300/kernel/entry.S
5  *
6  *  Yoshinori Sato <ysato@users.sourceforge.jp>
7  *  David McCullough <davidm@snapgear.com>
8  *
9  */
10
11 /*
12  *  entry.S
13  *  include exception/interrupt gateway
14  *          system call entry
15  */
16
17 #include <linux/sys.h>
18 #include <asm/unistd.h>
19 #include <asm/setup.h>
20 #include <asm/segment.h>
21 #include <asm/linkage.h>
22 #include <asm/asm-offsets.h>
23 #include <asm/thread_info.h>
24 #include <asm/errno.h>
25
26 #if defined(CONFIG_CPU_H8300H)
27 #define USERRET 8
28 INTERRUPTS = 64
29         .h8300h
30         .macro  SHLL2 reg
31         shll.l  \reg
32         shll.l  \reg
33         .endm
34         .macro  SHLR2 reg
35         shlr.l  \reg
36         shlr.l  \reg
37         .endm
38         .macro  SAVEREGS
39         mov.l   er0,@-sp
40         mov.l   er1,@-sp
41         mov.l   er2,@-sp
42         mov.l   er3,@-sp
43         .endm
44         .macro  RESTOREREGS
45         mov.l   @sp+,er3
46         mov.l   @sp+,er2
47         .endm
48         .macro  SAVEEXR
49         .endm
50         .macro  RESTOREEXR
51         .endm
52 #endif
53 #if defined(CONFIG_CPU_H8S)
54 #define USERRET 10
55 #define USEREXR 8
56 INTERRUPTS = 128
57         .h8300s
58         .macro  SHLL2 reg
59         shll.l  #2,\reg
60         .endm
61         .macro  SHLR2 reg
62         shlr.l  #2,\reg
63         .endm
64         .macro  SAVEREGS
65         stm.l   er0-er3,@-sp
66         .endm
67         .macro  RESTOREREGS
68         ldm.l   @sp+,er2-er3
69         .endm
70         .macro  SAVEEXR
71         mov.w   @(USEREXR:16,er0),r1
72         mov.w   r1,@(LEXR-LER3:16,sp)           /* copy EXR */
73         .endm
74         .macro  RESTOREEXR
75         mov.w   @(LEXR-LER1:16,sp),r1           /* restore EXR */
76         mov.b   r1l,r1h
77         mov.w   r1,@(USEREXR:16,er0)
78         .endm
79 #endif
80
81
82 /* CPU context save/restore macros. */
83
84         .macro  SAVE_ALL
85         mov.l   er0,@-sp
86         stc     ccr,r0l                         /* check kernel mode */
87         btst    #4,r0l
88         bne     5f
89
90         /* user mode */
91         mov.l   sp,@_sw_usp
92         mov.l   @sp,er0                         /* restore saved er0 */
93         orc     #0x10,ccr                       /* switch kernel stack */
94         mov.l   @_sw_ksp,sp
95         sub.l   #(LRET-LORIG),sp                /* allocate LORIG - LRET */
96         SAVEREGS
97         mov.l   @_sw_usp,er0
98         mov.l   @(USERRET:16,er0),er1           /* copy the RET addr */
99         mov.l   er1,@(LRET-LER3:16,sp)
100         SAVEEXR
101
102         mov.l   @(LORIG-LER3:16,sp),er0
103         mov.l   er0,@(LER0-LER3:16,sp)          /* copy ER0 */
104         mov.w   e1,r1                           /* e1 highbyte = ccr */
105         and     #0xef,r1h                       /* mask mode? flag */
106         bra     6f
107 5:
108         /* kernel mode */
109         mov.l   @sp,er0                         /* restore saved er0 */
110         subs    #2,sp                           /* set dummy ccr */
111         subs    #4,sp                           /* set dummp sp */
112         SAVEREGS
113         mov.w   @(LRET-LER3:16,sp),r1           /* copy old ccr */
114 6:
115         mov.b   r1h,r1l
116         mov.b   #0,r1h
117         mov.w   r1,@(LCCR-LER3:16,sp)           /* set ccr */
118         mov.l   @_sw_usp,er2
119         mov.l   er2,@(LSP-LER3:16,sp)           /* set usp */
120         mov.l   er6,@-sp                        /* syscall arg #6 */
121         mov.l   er5,@-sp                        /* syscall arg #5 */
122         mov.l   er4,@-sp                        /* syscall arg #4 */
123         .endm                                   /* r1 = ccr */
124
125         .macro  RESTORE_ALL
126         mov.l   @sp+,er4
127         mov.l   @sp+,er5
128         mov.l   @sp+,er6
129         RESTOREREGS
130         mov.w   @(LCCR-LER1:16,sp),r0           /* check kernel mode */
131         btst    #4,r0l
132         bne     7f
133
134         orc     #0xc0,ccr
135         mov.l   @(LSP-LER1:16,sp),er0
136         mov.l   @(LER0-LER1:16,sp),er1          /* restore ER0 */
137         mov.l   er1,@er0
138         RESTOREEXR
139         mov.w   @(LCCR-LER1:16,sp),r1           /* restore the RET addr */
140         mov.b   r1l,r1h
141         mov.b   @(LRET+1-LER1:16,sp),r1l
142         mov.w   r1,e1
143         mov.w   @(LRET+2-LER1:16,sp),r1
144         mov.l   er1,@(USERRET:16,er0)
145
146         mov.l   @sp+,er1
147         add.l   #(LRET-LER1),sp                 /* remove LORIG - LRET */
148         mov.l   sp,@_sw_ksp
149         andc    #0xef,ccr                       /* switch to user mode */
150         mov.l   er0,sp
151         bra     8f
152 7:
153         mov.l   @sp+,er1
154         add.l   #10,sp
155 8:
156         mov.l   @sp+,er0
157         adds    #4,sp                           /* remove the sw created LVEC */
158         rte
159         .endm
160
161 .globl _system_call
162 .globl ret_from_exception
163 .globl ret_from_fork
164 .globl ret_from_kernel_thread
165 .globl ret_from_interrupt
166 .globl _interrupt_redirect_table
167 .globl _sw_ksp,_sw_usp
168 .globl _resume
169 .globl _interrupt_entry
170 .globl _trace_break
171 .globl _nmi
172
173 #if defined(CONFIG_ROMKERNEL)
174         .section .int_redirect,"ax"
175 _interrupt_redirect_table:
176 #if defined(CONFIG_CPU_H8300H)
177         .rept   7
178         .long   0
179         .endr
180 #endif
181 #if defined(CONFIG_CPU_H8S)
182         .rept   5
183         .long   0
184         .endr
185         jmp     @_trace_break
186         .long   0
187 #endif
188
189         jsr     @_interrupt_entry               /* NMI */
190         jmp     @_system_call                   /* TRAPA #0 (System call) */
191         .long   0
192 #if defined(CONFIG_KGDB)
193         jmp     @_kgdb_trap
194 #else
195         .long   0
196 #endif
197         jmp     @_trace_break                   /* TRAPA #3 (breakpoint) */
198         .rept   INTERRUPTS-12
199         jsr     @_interrupt_entry
200         .endr
201 #endif
202 #if defined(CONFIG_RAMKERNEL)
203 .globl _interrupt_redirect_table
204         .section .bss
205 _interrupt_redirect_table:
206         .space  4
207 #endif
208
209         .section .text
210         .align  2
211 _interrupt_entry:
212         SAVE_ALL
213 /* r1l is saved ccr */
214         mov.l   sp,er0
215         add.l   #LVEC,er0
216         btst    #4,r1l
217         bne     1f
218         /* user LVEC */
219         mov.l   @_sw_usp,er0
220         adds    #4,er0
221 1:
222         mov.l   @er0,er0                        /* LVEC address */
223 #if defined(CONFIG_ROMKERNEL)
224         sub.l   #_interrupt_redirect_table,er0
225 #endif
226 #if defined(CONFIG_RAMKERNEL)
227         mov.l   @_interrupt_redirect_table,er1
228         sub.l   er1,er0
229 #endif
230         SHLR2   er0
231         dec.l   #1,er0
232         mov.l   sp,er1
233         subs    #4,er1                          /* adjust ret_pc */
234 #if defined(CONFIG_CPU_H8S)
235         orc     #7,exr
236 #endif
237         jsr     @do_IRQ
238         jmp     @ret_from_interrupt
239
240 _system_call:
241         subs    #4,sp                           /* dummy LVEC */
242         SAVE_ALL
243         /* er0: syscall nr */
244         andc    #0xbf,ccr
245         mov.l   er0,er4
246
247         /* save top of frame */
248         mov.l   sp,er0
249         jsr     @set_esp0
250         andc    #0x3f,ccr
251         mov.l   sp,er2
252         and.w   #0xe000,r2
253         mov.l   @(TI_FLAGS:16,er2),er2
254         and.w   #_TIF_WORK_SYSCALL_MASK,r2
255         beq     1f
256         mov.l   sp,er0
257         jsr     @do_syscall_trace_enter
258 1:
259         cmp.l   #__NR_syscalls,er4
260         bcc     badsys
261         SHLL2   er4
262         mov.l   #_sys_call_table,er0
263         add.l   er4,er0
264         mov.l   @er0,er4
265         beq     ret_from_exception:16
266         mov.l   @(LER1:16,sp),er0
267         mov.l   @(LER2:16,sp),er1
268         mov.l   @(LER3:16,sp),er2
269         jsr     @er4
270         mov.l   er0,@(LER0:16,sp)               /* save the return value */
271         mov.l   sp,er2
272         and.w   #0xe000,r2
273         mov.l   @(TI_FLAGS:16,er2),er2
274         and.w   #_TIF_WORK_SYSCALL_MASK,r2
275         beq     2f
276         mov.l   sp,er0
277         jsr     @do_syscall_trace_leave
278 2:
279         orc     #0xc0,ccr
280         bra     resume_userspace
281
282 badsys:
283         mov.l   #-ENOSYS,er0
284         mov.l   er0,@(LER0:16,sp)
285         bra     resume_userspace
286
287 #if !defined(CONFIG_PREEMPT)
288 #define resume_kernel restore_all
289 #endif
290
291 ret_from_exception:
292 #if defined(CONFIG_PREEMPT)
293         orc     #0xc0,ccr
294 #endif
295 ret_from_interrupt:
296         mov.b   @(LCCR+1:16,sp),r0l
297         btst    #4,r0l
298         bne     resume_kernel:16        /* return from kernel */
299 resume_userspace:
300         andc    #0xbf,ccr
301         mov.l   sp,er4
302         and.w   #0xe000,r4              /* er4 <- current thread info */
303         mov.l   @(TI_FLAGS:16,er4),er1
304         and.l   #_TIF_WORK_MASK,er1
305         beq     restore_all:8
306 work_pending:
307         btst    #TIF_NEED_RESCHED,r1l
308         bne     work_resched:8
309         /* work notifysig */
310         mov.l   sp,er0
311         subs    #4,er0                  /* er0: pt_regs */
312         jsr     @do_notify_resume
313         bra     resume_userspace:8
314 work_resched:
315         mov.l   sp,er0
316         jsr     @set_esp0
317         jsr     @schedule
318         bra     resume_userspace:8
319 restore_all:
320         RESTORE_ALL                     /* Does RTE */
321
322 #if defined(CONFIG_PREEMPT)
323 resume_kernel:
324         mov.l   @(TI_PRE_COUNT:16,er4),er0
325         bne     restore_all:8
326 need_resched:
327         mov.l   @(TI_FLAGS:16,er4),er0
328         btst    #TIF_NEED_RESCHED,r0l
329         beq     restore_all:8
330         mov.b   @(LCCR+1:16,sp),r0l     /* Interrupt Enabled? */
331         bmi     restore_all:8
332         mov.l   sp,er0
333         jsr     @set_esp0
334         jsr     @preempt_schedule_irq
335         bra     need_resched:8
336 #endif
337
338 ret_from_fork:
339         mov.l   er2,er0
340         jsr     @schedule_tail
341         jmp     @ret_from_exception
342
343 ret_from_kernel_thread:
344         mov.l   er2,er0
345         jsr     @schedule_tail
346         mov.l   @(LER4:16,sp),er0
347         mov.l   @(LER5:16,sp),er1
348         jsr     @er1
349         jmp     @ret_from_exception
350
351 _resume:
352         /*
353          * Beware - when entering resume, offset of tss is in d1,
354          * prev (the current task) is in a0, next (the new task)
355          * is in a1 and d2.b is non-zero if the mm structure is
356          * shared between the tasks, so don't change these
357          * registers until their contents are no longer needed.
358          */
359
360         /* save sr */
361         sub.w   r3,r3
362         stc     ccr,r3l
363         mov.w   r3,@(THREAD_CCR+2:16,er0)
364
365         /* disable interrupts */
366         orc     #0xc0,ccr
367         mov.l   @_sw_usp,er3
368         mov.l   er3,@(THREAD_USP:16,er0)
369         mov.l   sp,@(THREAD_KSP:16,er0)
370
371         /* Skip address space switching if they are the same. */
372         /* FIXME: what did we hack out of here, this does nothing! */
373
374         mov.l   @(THREAD_USP:16,er1),er0
375         mov.l   er0,@_sw_usp
376         mov.l   @(THREAD_KSP:16,er1),sp
377
378         /* restore status register */
379         mov.w   @(THREAD_CCR+2:16,er1),r3
380
381         ldc     r3l,ccr
382         rts
383
384 _trace_break:
385         subs    #4,sp
386         SAVE_ALL
387         sub.l   er1,er1
388         dec.l   #1,er1
389         mov.l   er1,@(LORIG,sp)
390         mov.l   sp,er0
391         jsr     @set_esp0
392         mov.l   @_sw_usp,er0
393         mov.l   @er0,er1
394         mov.w   @(-2:16,er1),r2
395         cmp.w   #0x5730,r2
396         beq     1f
397         subs    #2,er1
398         mov.l   er1,@er0
399 1:
400         and.w   #0xff,e1
401         mov.l   er1,er0
402         jsr     @trace_trap
403         jmp     @ret_from_exception
404
405 _nmi:
406         subs    #4, sp
407         mov.l   er0, @-sp
408         mov.l   @_interrupt_redirect_table, er0
409         add.l   #8*4, er0
410         mov.l   er0, @(4,sp)
411         mov.l   @sp+, er0
412         jmp     @_interrupt_entry
413
414 #if defined(CONFIG_KGDB)
415 _kgdb_trap:
416         subs    #4,sp
417         SAVE_ALL
418         mov.l   sp,er0
419         add.l   #LRET,er0
420         mov.l   er0,@(LSP,sp)
421         jsr     @set_esp0
422         mov.l   sp,er0
423         subs    #4,er0
424         jsr     @h8300_kgdb_trap
425         jmp     @ret_from_exception
426 #endif
427
428         .section        .bss
429 _sw_ksp:
430         .space  4
431 _sw_usp:
432         .space  4
433
434         .end