]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/m32r/kernel/entry.S
m32r: build fix of entry.S
[net-next-2.6.git] / arch / m32r / kernel / entry.S
CommitLineData
1da177e4
LT
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
8e8ff02c 23 * updated in fork.c:copy_thread, signal.c:do_signal,
1da177e4
LT
24 * ptrace.c and ptrace.h
25 *
8b03a632
HT
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
1da177e4
LT
55 */
56
1da177e4
LT
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
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 */
82
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)
1da177e4
LT
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)
1da177e4 111
9990b48a
HT
112#define nr_syscalls ((syscall_table_size)/4)
113
1da177e4
LT
114#ifdef CONFIG_PREEMPT
115#define preempt_stop(x) CLI(x)
116#else
117#define preempt_stop(x)
118#define resume_kernel restore_all
119#endif
120
121ENTRY(ret_from_fork)
4127272c 122 pop r0
1da177e4
LT
123 bl schedule_tail
124 GET_THREAD_INFO(r8)
125 bra syscall_exit
126
127/*
128 * Return to user mode is not as complex as all this looks,
129 * but we want the default path for a system call return to
130 * go as quickly as possible which is why some of this is
131 * less clear than it otherwise should be.
132 */
133
134 ; userspace resumption stub bypassing syscall exit tracing
135 ALIGN
136ret_from_exception:
137 preempt_stop(r4)
138ret_from_intr:
139 ld r4, PSW(sp)
140#ifdef CONFIG_ISA_M32R2
141 and3 r4, r4, #0x8800 ; check BSM and BPM bits
142#else
143 and3 r4, r4, #0x8000 ; check BSM bit
144#endif
145 beqz r4, resume_kernel
146ENTRY(resume_userspace)
147 CLI(r4) ; make sure we don't miss an interrupt
148 ; setting need_resched or sigpending
149 ; between sampling and the iret
150 GET_THREAD_INFO(r8)
151 ld r9, @(TI_FLAGS, r8)
152 and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done on
153 ; int/exception return?
154 bnez r4, work_pending
155 bra restore_all
156
157#ifdef CONFIG_PREEMPT
158ENTRY(resume_kernel)
159 GET_THREAD_INFO(r8)
160 ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
161 bnez r9, restore_all
162need_resched:
163 ld r9, @(TI_FLAGS, r8) ; need_resched set ?
164 and3 r4, r9, #_TIF_NEED_RESCHED
165 beqz r4, restore_all
166 ld r4, PSW(sp) ; interrupts off (exception path) ?
167 and3 r4, r4, #0x4000
168 beqz r4, restore_all
169 LDIMM (r4, PREEMPT_ACTIVE)
170 st r4, @(TI_PRE_COUNT, r8)
171 STI(r4)
172 bl schedule
173 ldi r4, #0
174 st r4, @(TI_PRE_COUNT, r8)
175 CLI(r4)
176 bra need_resched
177#endif
178
179 ; system call handler stub
180ENTRY(system_call)
181 SWITCH_TO_KERNEL_STACK
182 SAVE_ALL
183 STI(r4) ; Enable interrupt
184 st sp, PTREGS(sp) ; implicit pt_regs parameter
185 cmpui r7, #NR_syscalls
186 bnc syscall_badsys
187 st r7, SYSCALL_NR(sp) ; syscall_nr
188 ; system call tracing in operation
189 GET_THREAD_INFO(r8)
190 ld r9, @(TI_FLAGS, r8)
191 and3 r4, r9, #_TIF_SYSCALL_TRACE
192 bnez r4, syscall_trace_entry
193syscall_call:
194 slli r7, #2 ; table jump for the system call
195 LDIMM (r4, sys_call_table)
196 add r7, r4
197 ld r7, @r7
198 jl r7 ; execute system call
199 st r0, R0(sp) ; save the return value
200syscall_exit:
201 CLI(r4) ; make sure we don't miss an interrupt
202 ; setting need_resched or sigpending
203 ; between sampling and the iret
204 ld r9, @(TI_FLAGS, r8)
205 and3 r4, r9, #_TIF_ALLWORK_MASK ; current->work
206 bnez r4, syscall_exit_work
207restore_all:
208 RESTORE_ALL
209
210 # perform work that needs to be done immediately before resumption
8e8ff02c 211 # r9 : flags
1da177e4
LT
212 ALIGN
213work_pending:
214 and3 r4, r9, #_TIF_NEED_RESCHED
215 beqz r4, work_notifysig
216work_resched:
217 bl schedule
218 CLI(r4) ; make sure we don't miss an interrupt
219 ; setting need_resched or sigpending
220 ; between sampling and the iret
221 ld r9, @(TI_FLAGS, r8)
222 and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done other
223 ; than syscall tracing?
224 beqz r4, restore_all
225 and3 r4, r4, #_TIF_NEED_RESCHED
226 bnez r4, work_resched
227
228work_notifysig: ; deal with pending signals and
229 ; notify-resume requests
230 mv r0, sp ; arg1 : struct pt_regs *regs
231 ldi r1, #0 ; arg2 : sigset_t *oldset
232 mv r2, r9 ; arg3 : __u32 thread_info_flags
233 bl do_notify_resume
234 bra restore_all
235
236 ; perform syscall exit tracing
237 ALIGN
238syscall_trace_entry:
239 ldi r4, #-ENOSYS
240 st r4, R0(sp)
241 bl do_syscall_trace
242 ld r0, ORIG_R0(sp)
243 ld r1, R1(sp)
244 ld r2, R2(sp)
245 ld r3, R3(sp)
246 ld r4, R4(sp)
247 ld r5, R5(sp)
248 ld r6, R6(sp)
249 ld r7, SYSCALL_NR(sp)
250 cmpui r7, #NR_syscalls
251 bc syscall_call
252 bra syscall_exit
253
254 ; perform syscall exit tracing
255 ALIGN
256syscall_exit_work:
257 ld r9, @(TI_FLAGS, r8)
258 and3 r4, r9, #_TIF_SYSCALL_TRACE
259 beqz r4, work_pending
260 STI(r4) ; could let do_syscall_trace() call
261 ; schedule() instead
262 bl do_syscall_trace
263 bra resume_userspace
264
265 ALIGN
266syscall_fault:
267 SAVE_ALL
268 GET_THREAD_INFO(r8)
269 ldi r4, #-EFAULT
270 st r4, R0(sp)
271 bra resume_userspace
272
273 ALIGN
274syscall_badsys:
275 ldi r4, #-ENOSYS
276 st r4, R0(sp)
277 bra resume_userspace
278
279 .global eit_vector
280
281 .equ ei_vec_table, eit_vector + 0x0200
282
283/*
284 * EI handler routine
285 */
286ENTRY(ei_handler)
287#if defined(CONFIG_CHIP_M32700)
1da177e4 288 ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
5171b100 289 SWITCH_TO_KERNEL_STACK
1da177e4
LT
290#endif
291 SAVE_ALL
292 mv r1, sp ; arg1(regs)
de2232ed 293 ; get ICU status
1da177e4
LT
294 seth r0, #shigh(M32R_ICU_ISTS_ADDR)
295 ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
4127272c 296 push r0
1da177e4
LT
297#if defined(CONFIG_SMP)
298 /*
299 * If IRQ == 0 --> Nothing to do, Not write IMASK
300 * If IRQ == IPI --> Do IPI handler, Not write IMASK
301 * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK
302 */
303 slli r0, #4
304 srli r0, #24 ; r0(irq_num<<2)
305 ;; IRQ exist check
306#if defined(CONFIG_CHIP_M32700)
307 /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
5171b100
HT
308 bnez r0, 0f
309 ld24 r14, #0x00070000
310 seth r0, #shigh(M32R_ICU_IMASK_ADDR)
311 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
312 bra 1f
313 .fillinsn
3140:
315#endif /* CONFIG_CHIP_M32700 */
1da177e4 316 beqz r0, 1f ; if (!irq_num) goto exit
1da177e4
LT
317 ;; IPI check
318 cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
319 bc 2f
320 cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check
321 bnc 2f
322 LDIMM (r2, ei_vec_table)
323 add r2, r0
324 ld r2, @r2
325 beqz r2, 1f ; if (no IPI handler) goto exit
326 mv r0, r1 ; arg0(regs)
327 jl r2
328 .fillinsn
3291:
330 addi sp, #4
abd0a782 331 bra restore_all
1da177e4
LT
332 .fillinsn
3332:
334 srli r0, #2
5171b100 335#else /* not CONFIG_SMP */
1da177e4 336 srli r0, #22 ; r0(irq)
5171b100
HT
337#endif /* not CONFIG_SMP */
338
339#if defined(CONFIG_PLAT_HAS_INT1ICU)
1da177e4 340 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
5171b100
HT
341 bnez r2, 3f
342 seth r0, #shigh(M32R_INT1ICU_ISTS)
343 lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN
1da177e4
LT
344 slli r0, #21
345 srli r0, #27 ; ISN
5171b100 346 addi r0, #(M32R_INT1ICU_IRQ_BASE)
1da177e4
LT
347 bra check_end
348 .fillinsn
5171b100
HT
3493:
350#endif /* CONFIG_PLAT_HAS_INT1ICU */
351#if defined(CONFIG_PLAT_HAS_INT0ICU)
352 add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
353 bnez r2, 4f
354 seth r0, #shigh(M32R_INT0ICU_ISTS)
355 lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN
1da177e4 356 slli r0, #21
5171b100 357 srli r0, #27 ; ISN
33205613 358 add3 r0, r0, #(M32R_INT0ICU_IRQ_BASE)
1da177e4
LT
359 bra check_end
360 .fillinsn
5171b100
HT
3614:
362#endif /* CONFIG_PLAT_HAS_INT0ICU */
363#if defined(CONFIG_PLAT_HAS_INT2ICU)
364 add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
365 bnez r2, 5f
366 seth r0, #shigh(M32R_INT2ICU_ISTS)
367 lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN
9287d95e 368 slli r0, #21
5171b100 369 srli r0, #27 ; ISN
33205613 370 add3 r0, r0, #(M32R_INT2ICU_IRQ_BASE)
5171b100 371 ; bra check_end
9287d95e 372 .fillinsn
5171b100
HT
3735:
374#endif /* CONFIG_PLAT_HAS_INT2ICU */
de2232ed 375
9287d95e 376check_end:
1da177e4 377 bl do_IRQ
4127272c 378 pop r14
1da177e4
LT
379 seth r0, #shigh(M32R_ICU_IMASK_ADDR)
380 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
1da177e4
LT
381 bra ret_from_intr
382
383/*
384 * Default EIT handler
385 */
386 ALIGN
387int_msg:
388 .asciz "Unknown interrupt\n"
389 .byte 0
390
391ENTRY(default_eit_handler)
392 push r0
393 mvfc r0, psw
394 push r1
395 push r2
396 push r3
397 push r0
398 LDIMM (r0, __KERNEL_DS)
399 mv r0, r1
400 mv r0, r2
401 LDIMM (r0, int_msg)
402 bl printk
403 pop r0
404 pop r3
405 pop r2
406 pop r1
407 mvtc r0, psw
408 pop r0
409infinit:
410 bra infinit
411
412#ifdef CONFIG_MMU
413/*
414 * Access Exception handler
415 */
416ENTRY(ace_handler)
417 SWITCH_TO_KERNEL_STACK
418 SAVE_ALL
419
420 seth r2, #shigh(MMU_REG_BASE) /* Check status register */
421 ld r4, @(low(MESTS_offset),r2)
422 st r4, @(low(MESTS_offset),r2)
423 srl3 r1, r4, #4
424#ifdef CONFIG_CHIP_M32700
425 and3 r1, r1, #0x0000ffff
426 ; WORKAROUND: ignore TME bit for the M32700(TS1).
427#endif /* CONFIG_CHIP_M32700 */
428 beqz r1, inst
429oprand:
430 ld r2, @(low(MDEVA_offset),r2) ; set address
1da177e4
LT
431 srli r1, #1
432 bra 1f
433inst:
434 and3 r1, r4, #2
435 srli r1, #1
436 or3 r1, r1, #8
437 mvfc r2, bpc ; set address
438 .fillinsn
4391:
440 mvfc r3, psw
441 mv r0, sp
442 and3 r3, r3, 0x800
443 srli r3, #9
444 or r1, r3
445 /*
446 * do_page_fault():
447 * r0 : struct pt_regs *regs
448 * r1 : unsigned long error-code
449 * r2 : unsigned long address
450 * error-code:
451 * +------+------+------+------+
452 * | bit3 | bit2 | bit1 | bit0 |
453 * +------+------+------+------+
454 * bit 3 == 0:means data, 1:means instruction
455 * bit 2 == 0:means kernel, 1:means user-mode
456 * bit 1 == 0:means read, 1:means write
457 * bit 0 == 0:means no page found 1:means protection fault
458 *
459 */
460 bl do_page_fault
461 bra ret_from_intr
462#endif /* CONFIG_MMU */
463
464
465ENTRY(alignment_check)
de2232ed 466 /* void alignment_check(int error_code) */
1da177e4
LT
467 SWITCH_TO_KERNEL_STACK
468 SAVE_ALL
469 ldi r1, #0x30 ; error_code
470 mv r0, sp ; pt_regs
471 bl do_alignment_check
472error_code:
473 bra ret_from_exception
474
475ENTRY(rie_handler)
de2232ed 476 /* void rie_handler(int error_code) */
1da177e4
LT
477 SWITCH_TO_KERNEL_STACK
478 SAVE_ALL
1da177e4
LT
479 ldi r1, #0x20 ; error_code
480 mv r0, sp ; pt_regs
481 bl do_rie_handler
482 bra error_code
483
484ENTRY(pie_handler)
de2232ed 485 /* void pie_handler(int error_code) */
1da177e4
LT
486 SWITCH_TO_KERNEL_STACK
487 SAVE_ALL
488 ldi r1, #0 ; error_code ; FIXME
489 mv r0, sp ; pt_regs
490 bl do_pie_handler
491 bra error_code
492
493ENTRY(debug_trap)
1da177e4 494 /* void debug_trap(void) */
de2232ed 495 .global withdraw_debug_trap
1da177e4
LT
496 SWITCH_TO_KERNEL_STACK
497 SAVE_ALL
498 mv r0, sp ; pt_regs
499 bl withdraw_debug_trap
500 ldi r1, #0 ; error_code
501 mv r0, sp ; pt_regs
502 bl do_debug_trap
503 bra error_code
504
9de11aab
HT
505ENTRY(ill_trap)
506 /* void ill_trap(void) */
507 SWITCH_TO_KERNEL_STACK
508 SAVE_ALL
509 ldi r1, #0 ; error_code ; FIXME
510 mv r0, sp ; pt_regs
511 bl do_ill_trap
512 bra error_code
513
1da177e4 514ENTRY(cache_flushing_handler)
1da177e4 515 /* void _flush_cache_all(void); */
de2232ed 516 .global _flush_cache_all
1da177e4
LT
517 SWITCH_TO_KERNEL_STACK
518 push r0
519 push r1
520 push r2
521 push r3
522 push r4
523 push r5
524 push r6
525 push r7
526 push lr
527 bl _flush_cache_all
528 pop lr
529 pop r7
530 pop r6
531 pop r5
532 pop r4
533 pop r3
534 pop r2
535 pop r1
536 pop r0
537 rte
538
9990b48a
HT
539 .section .rodata,"a"
540#include "syscall_table.S"
1da177e4
LT
541
542syscall_table_size=(.-sys_call_table)