1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
69
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
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)
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)
108#define LR(reg) @(0x64,reg)
109#define SP(reg) @(0x68,reg)
110#define ORIG_R0(reg) @(0x6C,reg)
111
112#define nr_syscalls ((syscall_table_size)/4)
113
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
120
121
122#define GET_THREAD_INFO(reg) GET_THREAD_INFO reg
123 .macro GET_THREAD_INFO reg
124 ldi \reg,
125 and \reg, sp
126 .endm
127
128ENTRY(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
136
137ENTRY(ret_from_fork)
138 pop r0
139 bl schedule_tail
140 GET_THREAD_INFO(r8)
141 bra syscall_exit
142
143
144
145
146
147
148
149
150 ; userspace resumption stub bypassing syscall exit tracing
151 ALIGN
152ret_from_exception:
153 preempt_stop(r4)
154ret_from_intr:
155 ld r4, PSW(sp)
156#ifdef CONFIG_ISA_M32R2
157 and3 r4, r4,
158#else
159 and3 r4, r4,
160#endif
161 beqz r4, resume_kernel
162resume_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,
169 ; int/exception return?
170 bnez r4, work_pending
171 bra restore_all
172
173#ifdef CONFIG_PREEMPT
174ENTRY(resume_kernel)
175 GET_THREAD_INFO(r8)
176 ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
177 bnez r9, restore_all
178need_resched:
179 ld r9, @(TI_FLAGS, r8) ; need_resched set ?
180 and3 r4, r9,
181 beqz r4, restore_all
182 ld r4, PSW(sp) ; interrupts off (exception path) ?
183 and3 r4, r4,
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,
190 st r4, @(TI_PRE_COUNT, r8)
191 DISABLE_INTERRUPTS(r4)
192 bra need_resched
193#endif
194
195 ; system call handler stub
196ENTRY(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,
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,
208 bnez r4, syscall_trace_entry
209syscall_call:
210 slli r7,
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
216syscall_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,
222 bnez r4, syscall_exit_work
223restore_all:
224 RESTORE_ALL
225
226
227
228 ALIGN
229work_pending:
230 and3 r4, r9,
231 beqz r4, work_notifysig
232work_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,
239 ; than syscall tracing?
240 beqz r4, restore_all
241 and3 r4, r4,
242 bnez r4, work_resched
243
244work_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
250
251 ; perform syscall exit tracing
252 ALIGN
253syscall_trace_entry:
254 ldi r4,
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,
266 bc syscall_call
267 bra syscall_exit
268
269 ; perform syscall exit tracing
270 ALIGN
271syscall_exit_work:
272 ld r9, @(TI_FLAGS, r8)
273 and3 r4, r9,
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
279
280 ALIGN
281syscall_fault:
282 SAVE_ALL
283 GET_THREAD_INFO(r8)
284 ldi r4,
285 st r4, R0(sp)
286 bra resume_userspace
287
288 ALIGN
289syscall_badsys:
290 ldi r4,
291 st r4, R0(sp)
292 bra resume_userspace
293
294 .global eit_vector
295
296 .equ ei_vec_table, eit_vector + 0x0200
297
298
299
300
301ENTRY(ei_handler)
302
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,
310 ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
311 push r0
312
313
314
315
316
317
318 slli r0,
319 srli r0,
320 ;; IRQ exist check
321
322
323 bnez r0, 0f
324 ld24 r14,
325 seth r0,
326 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
327 bra 1f
328 .fillinsn
3290:
330#endif
331 beqz r0, 1f ; if (!irq_num) goto exit
332 ;; IPI check
333 cmpi r0,
334 bc 2f
335 cmpi r0,
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
3441:
345 addi sp,
346 bra restore_all
347 .fillinsn
3482:
349 srli r0,
350#else
351 srli r0,
352#endif
353
354
355 add3 r2, r0,
356 bnez r2, 3f
357 seth r0,
358 lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN
359 slli r0,
360 srli r0,
361 addi r0,
362 bra check_end
363 .fillinsn
3643:
365#endif
366
367 add3 r2, r0,
368 bnez r2, 4f
369 seth r0,
370 lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN
371 slli r0,
372 srli r0,
373 add3 r0, r0,
374 bra check_end
375 .fillinsn
3764:
377#endif
378
379 add3 r2, r0,
380 bnez r2, 5f
381 seth r0,
382 lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN
383 slli r0,
384 srli r0,
385 add3 r0, r0,
386 ; bra check_end
387 .fillinsn
3885:
389#endif
390
391check_end:
392 bl do_IRQ
393 pop r14
394 seth r0,
395 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
396 bra ret_from_intr
397
398
399
400
401 ALIGN
402int_msg:
403 .asciz "Unknown interrupt\n"
404 .byte 0
405
406ENTRY(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
424infinit:
425 bra infinit
426
427#ifdef CONFIG_MMU
428
429
430
431ENTRY(ace_handler)
432 SWITCH_TO_KERNEL_STACK
433 SAVE_ALL
434
435 seth r2,
436 ld r4, @(low(MESTS_offset),r2)
437 st r4, @(low(MESTS_offset),r2)
438 srl3 r1, r4,
439#ifdef CONFIG_CHIP_M32700
440 and3 r1, r1,
441 ; WORKAROUND: ignore TME bit for the M32700(TS1).
442#endif
443 beqz r1, inst
444oprand:
445 ld r2, @(low(MDEVA_offset),r2) ; set address
446 srli r1,
447 bra 1f
448inst:
449 and3 r1, r4,
450 srli r1,
451 or3 r1, r1,
452 mvfc r2, bpc ; set address
453 .fillinsn
4541:
455 mvfc r3, psw
456 mv r0, sp
457 and3 r3, r3, 0x800
458 srli r3,
459 or r1, r3
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475 bl do_page_fault
476 bra ret_from_intr
477#endif
478
479
480ENTRY(alignment_check)
481
482 SWITCH_TO_KERNEL_STACK
483 SAVE_ALL
484 ldi r1,
485 mv r0, sp ; pt_regs
486 bl do_alignment_check
487error_code:
488 bra ret_from_exception
489
490ENTRY(rie_handler)
491
492 SWITCH_TO_KERNEL_STACK
493 SAVE_ALL
494 ldi r1,
495 mv r0, sp ; pt_regs
496 bl do_rie_handler
497 bra error_code
498
499ENTRY(pie_handler)
500
501 SWITCH_TO_KERNEL_STACK
502 SAVE_ALL
503 ldi r1,
504 mv r0, sp ; pt_regs
505 bl do_pie_handler
506 bra error_code
507
508ENTRY(debug_trap)
509
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,
516 mv r0, sp ; pt_regs
517 bl do_debug_trap
518 bra error_code
519
520ENTRY(ill_trap)
521
522 SWITCH_TO_KERNEL_STACK
523 SAVE_ALL
524 ldi r1,
525 mv r0, sp ; pt_regs
526 bl do_ill_trap
527 bra error_code
528
529ENTRY(cache_flushing_handler)
530
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
553
554 .section .rodata,"a"
555#include "syscall_table.S"
556
557syscall_table_size=(.-sys_call_table)
558