Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / m32r / kernel / entry.S
1 /*
2  *  linux/arch/m32r/kernel/entry.S
3  *
4  *  Copyright (c) 2001, 2002  Hirokazu Takata, Hitoshi Yamamoto, H. Kondo
5  *  Copyright (c) 2003  Hitoshi Yamamoto
6  *  Copyright (c) 2004  Hirokazu Takata <takata at linux-m32r.org>
7  *
8  *  Taken from i386 version.
9  *    Copyright (C) 1991, 1992  Linus Torvalds
10  */
11
12 /*
13  * entry.S contains the system-call and fault low-level handling routines.
14  * This also contains the timer-interrupt handler, as well as all interrupts
15  * and faults that can result in a task-switch.
16  *
17  * NOTE: This code handles signal-recognition, which happens every time
18  * after a timer-interrupt and after each system call.
19  *
20  * Stack layout in 'ret_from_system_call':
21  *      ptrace needs to have all regs on the stack.
22  *      if the order here is changed, it needs to be
23  *      updated in fork.c:copy_thread, signal.c:do_signal,
24  *      ptrace.c and ptrace.h
25  *
26  * M32R/M32Rx/M32R2
27  *       @(sp)      - r4
28  *       @(0x04,sp) - r5
29  *       @(0x08,sp) - r6
30  *       @(0x0c,sp) - *pt_regs
31  *       @(0x10,sp) - r0
32  *       @(0x14,sp) - r1
33  *       @(0x18,sp) - r2
34  *       @(0x1c,sp) - r3
35  *       @(0x20,sp) - r7
36  *       @(0x24,sp) - r8
37  *       @(0x28,sp) - r9
38  *       @(0x2c,sp) - r10
39  *       @(0x30,sp) - r11
40  *       @(0x34,sp) - r12
41  *       @(0x38,sp) - syscall_nr
42  *       @(0x3c,sp) - acc0h
43  *       @(0x40,sp) - acc0l
44  *       @(0x44,sp) - acc1h             ; ISA_DSP_LEVEL2 only
45  *       @(0x48,sp) - acc1l             ; ISA_DSP_LEVEL2 only
46  *       @(0x4c,sp) - psw
47  *       @(0x50,sp) - bpc
48  *       @(0x54,sp) - bbpsw
49  *       @(0x58,sp) - bbpc
50  *       @(0x5c,sp) - spu (cr3)
51  *       @(0x60,sp) - fp (r13)
52  *       @(0x64,sp) - lr (r14)
53  *       @(0x68,sp) - spi (cr2)
54  *       @(0x6c,sp) - orig_r0
55  */
56
57 #include <linux/linkage.h>
58 #include <asm/irq.h>
59 #include <asm/unistd.h>
60 #include <asm/assembler.h>
61 #include <asm/thread_info.h>
62 #include <asm/errno.h>
63 #include <asm/segment.h>
64 #include <asm/smp.h>
65 #include <asm/page.h>
66 #include <asm/m32r.h>
67 #include <asm/mmu_context.h>
68 #include <asm/asm-offsets.h>
69
70 #if !defined(CONFIG_MMU)
71 #define sys_madvise             sys_ni_syscall
72 #define sys_readahead           sys_ni_syscall
73 #define sys_mprotect            sys_ni_syscall
74 #define sys_msync               sys_ni_syscall
75 #define sys_mlock               sys_ni_syscall
76 #define sys_munlock             sys_ni_syscall
77 #define sys_mlockall            sys_ni_syscall
78 #define sys_munlockall          sys_ni_syscall
79 #define sys_mremap              sys_ni_syscall
80 #define sys_mincore             sys_ni_syscall
81 #define sys_remap_file_pages    sys_ni_syscall
82 #endif /* CONFIG_MMU */
83
84 #define R4(reg)                 @reg
85 #define R5(reg)                 @(0x04,reg)
86 #define R6(reg)                 @(0x08,reg)
87 #define PTREGS(reg)             @(0x0C,reg)
88 #define R0(reg)                 @(0x10,reg)
89 #define R1(reg)                 @(0x14,reg)
90 #define R2(reg)                 @(0x18,reg)
91 #define R3(reg)                 @(0x1C,reg)
92 #define R7(reg)                 @(0x20,reg)
93 #define R8(reg)                 @(0x24,reg)
94 #define R9(reg)                 @(0x28,reg)
95 #define R10(reg)                @(0x2C,reg)
96 #define R11(reg)                @(0x30,reg)
97 #define R12(reg)                @(0x34,reg)
98 #define SYSCALL_NR(reg)         @(0x38,reg)
99 #define ACC0H(reg)              @(0x3C,reg)
100 #define ACC0L(reg)              @(0x40,reg)
101 #define ACC1H(reg)              @(0x44,reg)
102 #define ACC1L(reg)              @(0x48,reg)
103 #define PSW(reg)                @(0x4C,reg)
104 #define BPC(reg)                @(0x50,reg)
105 #define BBPSW(reg)              @(0x54,reg)
106 #define BBPC(reg)               @(0x58,reg)
107 #define SPU(reg)                @(0x5C,reg)
108 #define FP(reg)                 @(0x60,reg)  /* FP = R13 */
109 #define LR(reg)                 @(0x64,reg)
110 #define SP(reg)                 @(0x68,reg)
111 #define ORIG_R0(reg)            @(0x6C,reg)
112
113 #define nr_syscalls ((syscall_table_size)/4)
114
115 #ifdef CONFIG_PREEMPT
116 #define preempt_stop(x)         DISABLE_INTERRUPTS(x)
117 #else
118 #define preempt_stop(x)
119 #define resume_kernel           restore_all
120 #endif
121
122 /* how to get the thread information struct from ASM */
123 #define GET_THREAD_INFO(reg)    GET_THREAD_INFO reg
124         .macro GET_THREAD_INFO reg
125         ldi     \reg, #-THREAD_SIZE
126         and     \reg, sp
127         .endm
128
129 ENTRY(ret_from_kernel_thread)
130         pop     r0
131         bl      schedule_tail
132         GET_THREAD_INFO(r8)
133         ld      r0, R0(r8)
134         ld      r1, R1(r8)
135         jl      r1
136         bra     syscall_exit
137
138 ENTRY(ret_from_fork)
139         pop     r0
140         bl      schedule_tail
141         GET_THREAD_INFO(r8)
142         bra     syscall_exit
143
144 /*
145  * Return to user mode is not as complex as all this looks,
146  * but we want the default path for a system call return to
147  * go as quickly as possible which is why some of this is
148  * less clear than it otherwise should be.
149  */
150
151         ; userspace resumption stub bypassing syscall exit tracing
152         ALIGN
153 ret_from_exception:
154         preempt_stop(r4)
155 ret_from_intr:
156         ld      r4, PSW(sp)
157 #ifdef CONFIG_ISA_M32R2
158         and3    r4, r4, #0x8800         ; check BSM and BPM bits
159 #else
160         and3    r4, r4, #0x8000         ; check BSM bit
161 #endif
162         beqz    r4, resume_kernel
163 resume_userspace:
164         DISABLE_INTERRUPTS(r4)          ; make sure we don't miss an interrupt
165                                         ; setting need_resched or sigpending
166                                         ; between sampling and the iret
167         GET_THREAD_INFO(r8)
168         ld      r9, @(TI_FLAGS, r8)
169         and3    r4, r9, #_TIF_WORK_MASK ; is there any work to be done on
170                                         ; int/exception return?
171         bnez    r4, work_pending
172         bra     restore_all
173
174 #ifdef CONFIG_PREEMPT
175 ENTRY(resume_kernel)
176         GET_THREAD_INFO(r8)
177         ld      r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
178         bnez    r9, restore_all
179 need_resched:
180         ld      r9, @(TI_FLAGS, r8)     ; need_resched set ?
181         and3    r4, r9, #_TIF_NEED_RESCHED
182         beqz    r4, restore_all
183         ld      r4, PSW(sp)             ; interrupts off (exception path) ?
184         and3    r4, r4, #0x4000
185         beqz    r4, restore_all
186         bl      preempt_schedule_irq
187         bra     need_resched
188 #endif
189
190         ; system call handler stub
191 ENTRY(system_call)
192         SWITCH_TO_KERNEL_STACK
193         SAVE_ALL
194         ENABLE_INTERRUPTS(r4)           ; Enable interrupt
195         st      sp, PTREGS(sp)          ; implicit pt_regs parameter
196         cmpui   r7, #NR_syscalls
197         bnc     syscall_badsys
198         st      r7, SYSCALL_NR(sp)      ; syscall_nr
199                                         ; system call tracing in operation
200         GET_THREAD_INFO(r8)
201         ld      r9, @(TI_FLAGS, r8)
202         and3    r4, r9, #_TIF_SYSCALL_TRACE
203         bnez    r4, syscall_trace_entry
204 syscall_call:
205         slli    r7, #2                  ; table jump for the system call
206         LDIMM   (r4, sys_call_table)
207         add     r7, r4
208         ld      r7, @r7
209         jl      r7                      ; execute system call
210         st      r0, R0(sp)              ; save the return value
211 syscall_exit:
212         DISABLE_INTERRUPTS(r4)          ; make sure we don't miss an interrupt
213                                         ; setting need_resched or sigpending
214                                         ; between sampling and the iret
215         ld      r9, @(TI_FLAGS, r8)
216         and3    r4, r9, #_TIF_ALLWORK_MASK      ; current->work
217         bnez    r4, syscall_exit_work
218 restore_all:
219         RESTORE_ALL
220
221         # perform work that needs to be done immediately before resumption
222         # r9 : flags
223         ALIGN
224 work_pending:
225         and3    r4, r9, #_TIF_NEED_RESCHED
226         beqz    r4, work_notifysig
227 work_resched:
228         bl      schedule
229         DISABLE_INTERRUPTS(r4)          ; make sure we don't miss an interrupt
230                                         ; setting need_resched or sigpending
231                                         ; between sampling and the iret
232         ld      r9, @(TI_FLAGS, r8)
233         and3    r4, r9, #_TIF_WORK_MASK ; is there any work to be done other
234                                         ; than syscall tracing?
235         beqz    r4, restore_all
236         and3    r4, r4, #_TIF_NEED_RESCHED
237         bnez    r4, work_resched
238
239 work_notifysig:                         ; deal with pending signals and
240                                         ; notify-resume requests
241         mv      r0, sp                  ; arg1 : struct pt_regs *regs
242         mv      r1, r9                  ; arg2 : __u32 thread_info_flags
243         bl      do_notify_resume
244         bra     resume_userspace
245
246         ; perform syscall exit tracing
247         ALIGN
248 syscall_trace_entry:
249         ldi     r4, #-ENOSYS
250         st      r4, R0(sp)
251         bl      do_syscall_trace
252         ld      r0, ORIG_R0(sp)
253         ld      r1, R1(sp)
254         ld      r2, R2(sp)
255         ld      r3, R3(sp)
256         ld      r4, R4(sp)
257         ld      r5, R5(sp)
258         ld      r6, R6(sp)
259         ld      r7, SYSCALL_NR(sp)
260         cmpui   r7, #NR_syscalls
261         bc      syscall_call
262         bra     syscall_exit
263
264         ; perform syscall exit tracing
265         ALIGN
266 syscall_exit_work:
267         ld      r9, @(TI_FLAGS, r8)
268         and3    r4, r9, #_TIF_SYSCALL_TRACE
269         beqz    r4, work_pending
270         ENABLE_INTERRUPTS(r4)           ; could let do_syscall_trace() call
271                                         ; schedule() instead
272         bl      do_syscall_trace
273         bra     resume_userspace
274
275         ALIGN
276 syscall_fault:
277         SAVE_ALL
278         GET_THREAD_INFO(r8)
279         ldi     r4, #-EFAULT
280         st      r4, R0(sp)
281         bra     resume_userspace
282
283         ALIGN
284 syscall_badsys:
285         ldi     r4, #-ENOSYS
286         st      r4, R0(sp)
287         bra     resume_userspace
288
289         .global eit_vector
290
291         .equ ei_vec_table, eit_vector + 0x0200
292
293 /*
294  * EI handler routine
295  */
296 ENTRY(ei_handler)
297 #if defined(CONFIG_CHIP_M32700)
298         ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
299         SWITCH_TO_KERNEL_STACK
300 #endif
301         SAVE_ALL
302         mv      r1, sp                  ; arg1(regs)
303         ; get ICU status
304         seth    r0, #shigh(M32R_ICU_ISTS_ADDR)
305         ld      r0, @(low(M32R_ICU_ISTS_ADDR),r0)
306         push    r0
307 #if defined(CONFIG_SMP)
308         /*
309          * If IRQ == 0      --> Nothing to do,  Not write IMASK
310          * If IRQ == IPI    --> Do IPI handler, Not write IMASK
311          * If IRQ != 0, IPI --> Do do_IRQ(),    Write IMASK
312          */
313         slli    r0, #4
314         srli    r0, #24                 ; r0(irq_num<<2)
315         ;; IRQ exist check
316 #if defined(CONFIG_CHIP_M32700)
317         /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
318         bnez    r0, 0f
319         ld24    r14, #0x00070000
320         seth    r0, #shigh(M32R_ICU_IMASK_ADDR)
321         st      r14, @(low(M32R_ICU_IMASK_ADDR),r0)
322         bra     1f
323         .fillinsn
324 0:
325 #endif /* CONFIG_CHIP_M32700 */
326         beqz    r0, 1f                  ; if (!irq_num) goto exit
327         ;; IPI check
328         cmpi    r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
329         bc      2f
330         cmpi    r0, #((M32R_IRQ_IPI7+1)<<2)     ; ISN > IPI7 check
331         bnc     2f
332         LDIMM   (r2, ei_vec_table)
333         add     r2, r0
334         ld      r2, @r2
335         beqz    r2, 1f                  ; if (no IPI handler) goto exit
336         mv      r0, r1                  ; arg0(regs)
337         jl      r2
338         .fillinsn
339 1:
340         addi    sp, #4
341         bra     restore_all
342         .fillinsn
343 2:
344         srli    r0, #2
345 #else /* not CONFIG_SMP */
346         srli    r0, #22                 ; r0(irq)
347 #endif /* not CONFIG_SMP */
348
349 #if defined(CONFIG_PLAT_HAS_INT1ICU)
350         add3    r2, r0, #-(M32R_IRQ_INT1)       ; INT1# interrupt
351         bnez    r2, 3f
352         seth    r0, #shigh(M32R_INT1ICU_ISTS)
353         lduh    r0, @(low(M32R_INT1ICU_ISTS),r0)        ; bit10-6 : ISN
354         slli    r0, #21
355         srli    r0, #27                         ; ISN
356         addi    r0, #(M32R_INT1ICU_IRQ_BASE)
357         bra     check_end
358         .fillinsn
359 3:
360 #endif /* CONFIG_PLAT_HAS_INT1ICU */
361 #if defined(CONFIG_PLAT_HAS_INT0ICU)
362         add3    r2, r0, #-(M32R_IRQ_INT0)       ; INT0# interrupt
363         bnez    r2, 4f
364         seth    r0, #shigh(M32R_INT0ICU_ISTS)
365         lduh    r0, @(low(M32R_INT0ICU_ISTS),r0)        ; bit10-6 : ISN
366         slli    r0, #21
367         srli    r0, #27                         ; ISN
368         add3    r0, r0, #(M32R_INT0ICU_IRQ_BASE)
369         bra     check_end
370         .fillinsn
371 4:
372 #endif /* CONFIG_PLAT_HAS_INT0ICU */
373 #if defined(CONFIG_PLAT_HAS_INT2ICU)
374         add3    r2, r0, #-(M32R_IRQ_INT2)       ; INT2# interrupt
375         bnez    r2, 5f
376         seth    r0, #shigh(M32R_INT2ICU_ISTS)
377         lduh    r0, @(low(M32R_INT2ICU_ISTS),r0)        ; bit10-6 : ISN
378         slli    r0, #21
379         srli    r0, #27                         ; ISN
380         add3    r0, r0, #(M32R_INT2ICU_IRQ_BASE)
381         ; bra   check_end
382         .fillinsn
383 5:
384 #endif /* CONFIG_PLAT_HAS_INT2ICU */
385
386 check_end:
387         bl      do_IRQ
388         pop     r14
389         seth    r0, #shigh(M32R_ICU_IMASK_ADDR)
390         st      r14, @(low(M32R_ICU_IMASK_ADDR),r0)
391         bra  ret_from_intr
392
393 /*
394  * Default EIT handler
395  */
396         ALIGN
397 int_msg:
398         .asciz  "Unknown interrupt\n"
399         .byte   0
400
401 ENTRY(default_eit_handler)
402         push    r0
403         mvfc    r0, psw
404         push    r1
405         push    r2
406         push    r3
407         push    r0
408         LDIMM   (r0, __KERNEL_DS)
409         mv      r0, r1
410         mv      r0, r2
411         LDIMM   (r0, int_msg)
412         bl      printk
413         pop     r0
414         pop     r3
415         pop     r2
416         pop     r1
417         mvtc    r0, psw
418         pop     r0
419 infinit:
420         bra     infinit
421
422 #ifdef CONFIG_MMU
423 /*
424  * Access Exception handler
425  */
426 ENTRY(ace_handler)
427         SWITCH_TO_KERNEL_STACK
428         SAVE_ALL
429
430         seth    r2, #shigh(MMU_REG_BASE)        /* Check status register */
431         ld      r4, @(low(MESTS_offset),r2)
432         st      r4, @(low(MESTS_offset),r2)
433         srl3    r1, r4, #4
434 #ifdef CONFIG_CHIP_M32700
435         and3    r1, r1, #0x0000ffff
436         ; WORKAROUND: ignore TME bit for the M32700(TS1).
437 #endif /* CONFIG_CHIP_M32700 */
438         beqz    r1, inst
439 oprand:
440         ld      r2, @(low(MDEVA_offset),r2)     ; set address
441         srli    r1, #1
442         bra     1f
443 inst:
444         and3    r1, r4, #2
445         srli    r1, #1
446         or3     r1, r1, #8
447         mvfc    r2, bpc                         ; set address
448         .fillinsn
449 1:
450         mvfc    r3, psw
451         mv      r0, sp
452         and3    r3, r3, 0x800
453         srli    r3, #9
454         or      r1, r3
455         /*
456          * do_page_fault():
457          *    r0 : struct pt_regs *regs
458          *    r1 : unsigned long error-code
459          *    r2 : unsigned long address
460          * error-code:
461          *    +------+------+------+------+
462          *    | bit3 | bit2 | bit1 | bit0 |
463          *    +------+------+------+------+
464          *    bit 3 == 0:means data,          1:means instruction
465          *    bit 2 == 0:means kernel,        1:means user-mode
466          *    bit 1 == 0:means read,          1:means write
467          *    bit 0 == 0:means no page found  1:means protection fault
468          *
469          */
470         bl      do_page_fault
471         bra     ret_from_intr
472 #endif  /* CONFIG_MMU */
473
474
475 ENTRY(alignment_check)
476         /* void alignment_check(int error_code) */
477         SWITCH_TO_KERNEL_STACK
478         SAVE_ALL
479         ldi     r1, #0x30                       ; error_code
480         mv      r0, sp                          ; pt_regs
481         bl      do_alignment_check
482 error_code:
483         bra     ret_from_exception
484
485 ENTRY(rie_handler)
486         /* void rie_handler(int error_code) */
487         SWITCH_TO_KERNEL_STACK
488         SAVE_ALL
489         ldi     r1, #0x20                       ; error_code
490         mv      r0, sp                          ; pt_regs
491         bl      do_rie_handler
492         bra     error_code
493
494 ENTRY(pie_handler)
495         /* void pie_handler(int error_code) */
496         SWITCH_TO_KERNEL_STACK
497         SAVE_ALL
498         ldi     r1, #0                          ; error_code ; FIXME
499         mv      r0, sp                          ; pt_regs
500         bl      do_pie_handler
501         bra     error_code
502
503 ENTRY(debug_trap)
504         /* void debug_trap(void) */
505         .global withdraw_debug_trap
506         SWITCH_TO_KERNEL_STACK
507         SAVE_ALL
508         mv      r0, sp                          ; pt_regs
509         bl      withdraw_debug_trap
510         ldi     r1, #0                          ; error_code
511         mv      r0, sp                          ; pt_regs
512         bl      do_debug_trap
513         bra     error_code
514
515 ENTRY(ill_trap)
516         /* void ill_trap(void) */
517         SWITCH_TO_KERNEL_STACK
518         SAVE_ALL
519         ldi     r1, #0                          ; error_code ; FIXME
520         mv      r0, sp                          ; pt_regs
521         bl      do_ill_trap
522         bra     error_code
523
524 ENTRY(cache_flushing_handler)
525         /* void _flush_cache_all(void); */
526         .global _flush_cache_all
527         SWITCH_TO_KERNEL_STACK
528         push    r0
529         push    r1
530         push    r2
531         push    r3
532         push    r4
533         push    r5
534         push    r6
535         push    r7
536         push    lr
537         bl      _flush_cache_all
538         pop     lr
539         pop     r7
540         pop     r6
541         pop     r5
542         pop     r4
543         pop     r3
544         pop     r2
545         pop     r1
546         pop     r0
547         rte
548
549         .section .rodata,"a"
550 #include "syscall_table.S"
551
552 syscall_table_size=(.-sys_call_table)