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
58#include <linux/linkage.h>
59#include <asm/irq.h>
60#include <asm/unistd.h>
61#include <asm/assembler.h>
62#include <asm/thread_info.h>
63#include <asm/errno.h>
64#include <asm/segment.h>
65#include <asm/smp.h>
66#include <asm/page.h>
67#include <asm/m32r.h>
68#include <asm/mmu_context.h>
69#include <asm/asm-offsets.h>
70
71
72#define sys_madvise sys_ni_syscall
73#define sys_readahead sys_ni_syscall
74#define sys_mprotect sys_ni_syscall
75#define sys_msync sys_ni_syscall
76#define sys_mlock sys_ni_syscall
77#define sys_munlock sys_ni_syscall
78#define sys_mlockall sys_ni_syscall
79#define sys_munlockall sys_ni_syscall
80#define sys_mremap sys_ni_syscall
81#define sys_mincore sys_ni_syscall
82#define sys_remap_file_pages sys_ni_syscall
83#endif
84
85#define R4(reg) @reg
86#define R5(reg) @(0x04,reg)
87#define R6(reg) @(0x08,reg)
88#define PTREGS(reg) @(0x0C,reg)
89#define R0(reg) @(0x10,reg)
90#define R1(reg) @(0x14,reg)
91#define R2(reg) @(0x18,reg)
92#define R3(reg) @(0x1C,reg)
93#define R7(reg) @(0x20,reg)
94#define R8(reg) @(0x24,reg)
95#define R9(reg) @(0x28,reg)
96#define R10(reg) @(0x2C,reg)
97#define R11(reg) @(0x30,reg)
98#define R12(reg) @(0x34,reg)
99#define SYSCALL_NR(reg) @(0x38,reg)
100#define ACC0H(reg) @(0x3C,reg)
101#define ACC0L(reg) @(0x40,reg)
102#define ACC1H(reg) @(0x44,reg)
103#define ACC1L(reg) @(0x48,reg)
104#define PSW(reg) @(0x4C,reg)
105#define BPC(reg) @(0x50,reg)
106#define BBPSW(reg) @(0x54,reg)
107#define BBPC(reg) @(0x58,reg)
108#define SPU(reg) @(0x5C,reg)
109#define FP(reg) @(0x60,reg)
110#define LR(reg) @(0x64,reg)
111#define SP(reg) @(0x68,reg)
112#define ORIG_R0(reg) @(0x6C,reg)
113
114#define nr_syscalls ((syscall_table_size)/4)
115
116#ifdef CONFIG_PREEMPT
117#define preempt_stop(x) DISABLE_INTERRUPTS(x)
118#else
119#define preempt_stop(x)
120#define resume_kernel restore_all
121#endif
122
123
124#define GET_THREAD_INFO(reg) GET_THREAD_INFO reg
125 .macro GET_THREAD_INFO reg
126 ldi \reg,
127 and \reg, sp
128 .endm
129
130ENTRY(ret_from_kernel_thread)
131 pop r0
132 bl schedule_tail
133 GET_THREAD_INFO(r8)
134 ld r0, R0(r8)
135 ld r1, R1(r8)
136 jl r1
137 bra syscall_exit
138
139ENTRY(ret_from_fork)
140 pop r0
141 bl schedule_tail
142 GET_THREAD_INFO(r8)
143 bra syscall_exit
144
145
146
147
148
149
150
151
152 ; userspace resumption stub bypassing syscall exit tracing
153 ALIGN
154ret_from_exception:
155 preempt_stop(r4)
156ret_from_intr:
157 ld r4, PSW(sp)
158#ifdef CONFIG_ISA_M32R2
159 and3 r4, r4,
160#else
161 and3 r4, r4,
162#endif
163 beqz r4, resume_kernel
164resume_userspace:
165 DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
166 ; setting need_resched or sigpending
167 ; between sampling and the iret
168 GET_THREAD_INFO(r8)
169 ld r9, @(TI_FLAGS, r8)
170 and3 r4, r9,
171 ; int/exception return?
172 bnez r4, work_pending
173 bra restore_all
174
175#ifdef CONFIG_PREEMPT
176ENTRY(resume_kernel)
177 GET_THREAD_INFO(r8)
178 ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
179 bnez r9, restore_all
180need_resched:
181 ld r9, @(TI_FLAGS, r8) ; need_resched set ?
182 and3 r4, r9,
183 beqz r4, restore_all
184 ld r4, PSW(sp) ; interrupts off (exception path) ?
185 and3 r4, r4,
186 beqz r4, restore_all
187 bl preempt_schedule_irq
188 bra need_resched
189#endif
190
191 ; system call handler stub
192ENTRY(system_call)
193 SWITCH_TO_KERNEL_STACK
194 SAVE_ALL
195 ENABLE_INTERRUPTS(r4) ; Enable interrupt
196 st sp, PTREGS(sp) ; implicit pt_regs parameter
197 cmpui r7,
198 bnc syscall_badsys
199 st r7, SYSCALL_NR(sp) ; syscall_nr
200 ; system call tracing in operation
201 GET_THREAD_INFO(r8)
202 ld r9, @(TI_FLAGS, r8)
203 and3 r4, r9,
204 bnez r4, syscall_trace_entry
205syscall_call:
206 slli r7,
207 LDIMM (r4, sys_call_table)
208 add r7, r4
209 ld r7, @r7
210 jl r7 ; execute system call
211 st r0, R0(sp) ; save the return value
212syscall_exit:
213 DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
214 ; setting need_resched or sigpending
215 ; between sampling and the iret
216 ld r9, @(TI_FLAGS, r8)
217 and3 r4, r9,
218 bnez r4, syscall_exit_work
219restore_all:
220 RESTORE_ALL
221
222
223
224 ALIGN
225work_pending:
226 and3 r4, r9,
227 beqz r4, work_notifysig
228work_resched:
229 bl schedule
230 DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
231 ; setting need_resched or sigpending
232 ; between sampling and the iret
233 ld r9, @(TI_FLAGS, r8)
234 and3 r4, r9,
235 ; than syscall tracing?
236 beqz r4, restore_all
237 and3 r4, r4,
238 bnez r4, work_resched
239
240work_notifysig: ; deal with pending signals and
241 ; notify-resume requests
242 mv r0, sp ; arg1 : struct pt_regs *regs
243 mv r1, r9 ; arg2 : __u32 thread_info_flags
244 bl do_notify_resume
245 bra resume_userspace
246
247 ; perform syscall exit tracing
248 ALIGN
249syscall_trace_entry:
250 ldi r4,
251 st r4, R0(sp)
252 bl do_syscall_trace
253 ld r0, ORIG_R0(sp)
254 ld r1, R1(sp)
255 ld r2, R2(sp)
256 ld r3, R3(sp)
257 ld r4, R4(sp)
258 ld r5, R5(sp)
259 ld r6, R6(sp)
260 ld r7, SYSCALL_NR(sp)
261 cmpui r7,
262 bc syscall_call
263 bra syscall_exit
264
265 ; perform syscall exit tracing
266 ALIGN
267syscall_exit_work:
268 ld r9, @(TI_FLAGS, r8)
269 and3 r4, r9,
270 beqz r4, work_pending
271 ENABLE_INTERRUPTS(r4) ; could let do_syscall_trace() call
272 ; schedule() instead
273 bl do_syscall_trace
274 bra resume_userspace
275
276 ALIGN
277syscall_fault:
278 SAVE_ALL
279 GET_THREAD_INFO(r8)
280 ldi r4,
281 st r4, R0(sp)
282 bra resume_userspace
283
284 ALIGN
285syscall_badsys:
286 ldi r4,
287 st r4, R0(sp)
288 bra resume_userspace
289
290 .global eit_vector
291
292 .equ ei_vec_table, eit_vector + 0x0200
293
294
295
296
297ENTRY(ei_handler)
298
299 ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
300 SWITCH_TO_KERNEL_STACK
301#endif
302 SAVE_ALL
303 mv r1, sp ; arg1(regs)
304 ; get ICU status
305 seth r0,
306 ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
307 push r0
308
309
310
311
312
313
314 slli r0,
315 srli r0,
316 ;; IRQ exist check
317
318
319 bnez r0, 0f
320 ld24 r14,
321 seth r0,
322 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
323 bra 1f
324 .fillinsn
3250:
326#endif
327 beqz r0, 1f ; if (!irq_num) goto exit
328 ;; IPI check
329 cmpi r0,
330 bc 2f
331 cmpi r0,
332 bnc 2f
333 LDIMM (r2, ei_vec_table)
334 add r2, r0
335 ld r2, @r2
336 beqz r2, 1f ; if (no IPI handler) goto exit
337 mv r0, r1 ; arg0(regs)
338 jl r2
339 .fillinsn
3401:
341 addi sp,
342 bra restore_all
343 .fillinsn
3442:
345 srli r0,
346#else
347 srli r0,
348#endif
349
350
351 add3 r2, r0,
352 bnez r2, 3f
353 seth r0,
354 lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN
355 slli r0,
356 srli r0,
357 addi r0,
358 bra check_end
359 .fillinsn
3603:
361#endif
362
363 add3 r2, r0,
364 bnez r2, 4f
365 seth r0,
366 lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN
367 slli r0,
368 srli r0,
369 add3 r0, r0,
370 bra check_end
371 .fillinsn
3724:
373#endif
374
375 add3 r2, r0,
376 bnez r2, 5f
377 seth r0,
378 lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN
379 slli r0,
380 srli r0,
381 add3 r0, r0,
382 ; bra check_end
383 .fillinsn
3845:
385#endif
386
387check_end:
388 bl do_IRQ
389 pop r14
390 seth r0,
391 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
392 bra ret_from_intr
393
394
395
396
397 ALIGN
398int_msg:
399 .asciz "Unknown interrupt\n"
400 .byte 0
401
402ENTRY(default_eit_handler)
403 push r0
404 mvfc r0, psw
405 push r1
406 push r2
407 push r3
408 push r0
409 LDIMM (r0, __KERNEL_DS)
410 mv r0, r1
411 mv r0, r2
412 LDIMM (r0, int_msg)
413 bl printk
414 pop r0
415 pop r3
416 pop r2
417 pop r1
418 mvtc r0, psw
419 pop r0
420infinit:
421 bra infinit
422
423#ifdef CONFIG_MMU
424
425
426
427ENTRY(ace_handler)
428 SWITCH_TO_KERNEL_STACK
429 SAVE_ALL
430
431 seth r2,
432 ld r4, @(low(MESTS_offset),r2)
433 st r4, @(low(MESTS_offset),r2)
434 srl3 r1, r4,
435#ifdef CONFIG_CHIP_M32700
436 and3 r1, r1,
437 ; WORKAROUND: ignore TME bit for the M32700(TS1).
438#endif
439 beqz r1, inst
440oprand:
441 ld r2, @(low(MDEVA_offset),r2) ; set address
442 srli r1,
443 bra 1f
444inst:
445 and3 r1, r4,
446 srli r1,
447 or3 r1, r1,
448 mvfc r2, bpc ; set address
449 .fillinsn
4501:
451 mvfc r3, psw
452 mv r0, sp
453 and3 r3, r3, 0x800
454 srli r3,
455 or r1, r3
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471 bl do_page_fault
472 bra ret_from_intr
473#endif
474
475
476ENTRY(alignment_check)
477
478 SWITCH_TO_KERNEL_STACK
479 SAVE_ALL
480 ldi r1,
481 mv r0, sp ; pt_regs
482 bl do_alignment_check
483error_code:
484 bra ret_from_exception
485
486ENTRY(rie_handler)
487
488 SWITCH_TO_KERNEL_STACK
489 SAVE_ALL
490 ldi r1,
491 mv r0, sp ; pt_regs
492 bl do_rie_handler
493 bra error_code
494
495ENTRY(pie_handler)
496
497 SWITCH_TO_KERNEL_STACK
498 SAVE_ALL
499 ldi r1,
500 mv r0, sp ; pt_regs
501 bl do_pie_handler
502 bra error_code
503
504ENTRY(debug_trap)
505
506 .global withdraw_debug_trap
507 SWITCH_TO_KERNEL_STACK
508 SAVE_ALL
509 mv r0, sp ; pt_regs
510 bl withdraw_debug_trap
511 ldi r1,
512 mv r0, sp ; pt_regs
513 bl do_debug_trap
514 bra error_code
515
516ENTRY(ill_trap)
517
518 SWITCH_TO_KERNEL_STACK
519 SAVE_ALL
520 ldi r1,
521 mv r0, sp ; pt_regs
522 bl do_ill_trap
523 bra error_code
524
525ENTRY(cache_flushing_handler)
526
527 .global _flush_cache_all
528 SWITCH_TO_KERNEL_STACK
529 push r0
530 push r1
531 push r2
532 push r3
533 push r4
534 push r5
535 push r6
536 push r7
537 push lr
538 bl _flush_cache_all
539 pop lr
540 pop r7
541 pop r6
542 pop r5
543 pop r4
544 pop r3
545 pop r2
546 pop r1
547 pop r0
548 rte
549
550 .section .rodata,"a"
551#include "syscall_table.S"
552
553syscall_table_size=(.-sys_call_table)
554