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