blob: a91e8980a5908c37994db411015e55cbeeb257fd [file] [log] [blame]
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9/*
10 * This file contains the low-level entry-points into the kernel, that is,
11 * exception handlers, debug trap handlers, interrupt handlers and the
12 * system call handler.
13 */
14#include <linux/errno.h>
15
16#include <asm/asm.h>
17#include <asm/hardirq.h>
18#include <asm/irq.h>
19#include <asm/ocd.h>
20#include <asm/page.h>
21#include <asm/pgtable.h>
22#include <asm/ptrace.h>
23#include <asm/sysreg.h>
24#include <asm/thread_info.h>
25#include <asm/unistd.h>
26
27#ifdef CONFIG_PREEMPT
28# define preempt_stop mask_interrupts
29#else
30# define preempt_stop
31# define fault_resume_kernel fault_restore_all
32#endif
33
34#define __MASK(x) ((1 << (x)) - 1)
35#define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \
36 (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT))
37
38 .section .ex.text,"ax",@progbits
39 .align 2
40exception_vectors:
41 bral handle_critical
42 .align 2
43 bral handle_critical
44 .align 2
45 bral do_bus_error_write
46 .align 2
47 bral do_bus_error_read
48 .align 2
49 bral do_nmi_ll
50 .align 2
51 bral handle_address_fault
52 .align 2
53 bral handle_protection_fault
54 .align 2
55 bral handle_debug
56 .align 2
57 bral do_illegal_opcode_ll
58 .align 2
59 bral do_illegal_opcode_ll
60 .align 2
61 bral do_illegal_opcode_ll
62 .align 2
63 bral do_fpe_ll
64 .align 2
65 bral do_illegal_opcode_ll
66 .align 2
67 bral handle_address_fault
68 .align 2
69 bral handle_address_fault
70 .align 2
71 bral handle_protection_fault
72 .align 2
73 bral handle_protection_fault
74 .align 2
75 bral do_dtlb_modified
76
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070077#define tlbmiss_save pushm r0-r3
78#define tlbmiss_restore popm r0-r3
79
Haavard Skinnemoend704fb02008-01-14 21:42:56 +010080 .org 0x50
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070081 .global itlb_miss
82itlb_miss:
83 tlbmiss_save
84 rjmp tlb_miss_common
85
Haavard Skinnemoend704fb02008-01-14 21:42:56 +010086 .org 0x60
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070087dtlb_miss_read:
88 tlbmiss_save
89 rjmp tlb_miss_common
90
Haavard Skinnemoend704fb02008-01-14 21:42:56 +010091 .org 0x70
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070092dtlb_miss_write:
93 tlbmiss_save
94
95 .global tlb_miss_common
Haavard Skinnemoend704fb02008-01-14 21:42:56 +010096 .align 2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070097tlb_miss_common:
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +010098 mfsr r0, SYSREG_TLBEAR
99 mfsr r1, SYSREG_PTBR
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700100
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100101 /*
102 * First level lookup: The PGD contains virtual pointers to
103 * the second-level page tables, but they may be NULL if not
104 * present.
105 */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700106pgtbl_lookup:
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100107 lsr r2, r0, PGDIR_SHIFT
108 ld.w r3, r1[r2 << 2]
109 bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100110 cp.w r3, 0
111 breq page_table_not_present
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700112
113 /* Second level lookup */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100114 ld.w r2, r3[r1 << 2]
115 mfsr r0, SYSREG_TLBARLO
116 bld r2, _PAGE_BIT_PRESENT
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700117 brcc page_not_present
118
119 /* Mark the page as accessed */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100120 sbr r2, _PAGE_BIT_ACCESSED
121 st.w r3[r1 << 2], r2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700122
123 /* Drop software flags */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100124 andl r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
125 mtsr SYSREG_TLBELO, r2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700126
127 /* Figure out which entry we want to replace */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100128 mfsr r1, SYSREG_MMUCR
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700129 clz r2, r0
130 brcc 1f
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100131 mov r3, -1 /* All entries have been accessed, */
132 mov r2, 0 /* so start at 0 */
133 mtsr SYSREG_TLBARLO, r3 /* and reset TLBAR */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700134
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +01001351: bfins r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE
136 mtsr SYSREG_MMUCR, r1
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700137 tlbw
138
139 tlbmiss_restore
140 rete
141
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100142 /* The slow path of the TLB miss handler */
143 .align 2
144page_table_not_present:
Haavard Skinnemoena9a934f2008-01-14 23:11:26 +0100145 /* Do we need to synchronize with swapper_pg_dir? */
146 bld r0, 31
147 brcs sync_with_swapper_pg_dir
148
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100149page_not_present:
150 tlbmiss_restore
151 sub sp, 4
152 stmts --sp, r0-lr
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100153 call save_full_context_ex
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100154 mfsr r12, SYSREG_ECR
155 mov r11, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100156 call do_page_fault
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100157 rjmp ret_from_exception
158
Haavard Skinnemoena9a934f2008-01-14 23:11:26 +0100159 .align 2
160sync_with_swapper_pg_dir:
161 /*
162 * If swapper_pg_dir contains a non-NULL second-level page
163 * table pointer, copy it into the current PGD. If not, we
164 * must handle it as a full-blown page fault.
165 *
166 * Jumping back to pgtbl_lookup causes an unnecessary lookup,
167 * but it is guaranteed to be a cache hit, it won't happen
168 * very often, and we absolutely do not want to sacrifice any
169 * performance in the fast path in order to improve this.
170 */
171 mov r1, lo(swapper_pg_dir)
172 orh r1, hi(swapper_pg_dir)
173 ld.w r3, r1[r2 << 2]
174 cp.w r3, 0
175 breq page_not_present
176 mfsr r1, SYSREG_PTBR
177 st.w r1[r2 << 2], r3
178 rjmp pgtbl_lookup
179
180 /*
181 * We currently have two bytes left at this point until we
182 * crash into the system call handler...
183 *
184 * Don't worry, the assembler will let us know.
185 */
186
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700187
188 /* --- System Call --- */
189
Haavard Skinnemoend704fb02008-01-14 21:42:56 +0100190 .org 0x100
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700191system_call:
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400192#ifdef CONFIG_PREEMPT
193 mask_interrupts
194#endif
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700195 pushm r12 /* r12_orig */
196 stmts --sp, r0-lr
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400197
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700198 mfsr r0, SYSREG_RAR_SUP
199 mfsr r1, SYSREG_RSR_SUP
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400200#ifdef CONFIG_PREEMPT
201 unmask_interrupts
202#endif
203 zero_fp
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700204 stm --sp, r0-r1
205
206 /* check for syscall tracing */
207 get_thread_info r0
208 ld.w r1, r0[TI_flags]
209 bld r1, TIF_SYSCALL_TRACE
210 brcs syscall_trace_enter
211
212syscall_trace_cont:
213 cp.w r8, NR_syscalls
214 brhs syscall_badsys
215
216 lddpc lr, syscall_table_addr
217 ld.w lr, lr[r8 << 2]
218 mov r8, r5 /* 5th argument (6th is pushed by stub) */
219 icall lr
220
221 .global syscall_return
222syscall_return:
223 get_thread_info r0
224 mask_interrupts /* make sure we don't miss an interrupt
225 setting need_resched or sigpending
226 between sampling and the rets */
227
228 /* Store the return value so that the correct value is loaded below */
229 stdsp sp[REG_R12], r12
230
231 ld.w r1, r0[TI_flags]
232 andl r1, _TIF_ALLWORK_MASK, COH
233 brne syscall_exit_work
234
235syscall_exit_cont:
236 popm r8-r9
237 mtsr SYSREG_RAR_SUP, r8
238 mtsr SYSREG_RSR_SUP, r9
239 ldmts sp++, r0-lr
240 sub sp, -4 /* r12_orig */
241 rets
242
243 .align 2
244syscall_table_addr:
245 .long sys_call_table
246
247syscall_badsys:
248 mov r12, -ENOSYS
249 rjmp syscall_return
250
251 .global ret_from_fork
252ret_from_fork:
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100253 call schedule_tail
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700254
255 /* check for syscall tracing */
256 get_thread_info r0
257 ld.w r1, r0[TI_flags]
258 andl r1, _TIF_ALLWORK_MASK, COH
259 brne syscall_exit_work
260 rjmp syscall_exit_cont
261
262syscall_trace_enter:
263 pushm r8-r12
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100264 call syscall_trace
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700265 popm r8-r12
266 rjmp syscall_trace_cont
267
268syscall_exit_work:
269 bld r1, TIF_SYSCALL_TRACE
270 brcc 1f
271 unmask_interrupts
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100272 call syscall_trace
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700273 mask_interrupts
274 ld.w r1, r0[TI_flags]
275
2761: bld r1, TIF_NEED_RESCHED
277 brcc 2f
278 unmask_interrupts
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100279 call schedule
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700280 mask_interrupts
281 ld.w r1, r0[TI_flags]
282 rjmp 1b
283
David Howellsd0420c82009-09-02 09:14:16 +01002842: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700285 tst r1, r2
286 breq 3f
287 unmask_interrupts
288 mov r12, sp
289 mov r11, r0
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100290 call do_notify_resume
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700291 mask_interrupts
292 ld.w r1, r0[TI_flags]
293 rjmp 1b
294
2953: bld r1, TIF_BREAKPOINT
296 brcc syscall_exit_cont
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100297 rjmp enter_monitor_mode
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700298
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700299 /* This function expects to find offending PC in SYSREG_RAR_EX */
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100300 .type save_full_context_ex, @function
301 .align 2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700302save_full_context_ex:
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100303 mfsr r11, SYSREG_RAR_EX
304 sub r9, pc, . - debug_trampoline
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700305 mfsr r8, SYSREG_RSR_EX
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100306 cp.w r9, r11
307 breq 3f
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700308 mov r12, r8
309 andh r8, (MODE_MASK >> 16), COH
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700310 brne 2f
311
3121: pushm r11, r12 /* PC and SR */
313 unmask_exceptions
314 ret r12
315
3162: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
317 stdsp sp[4], r10 /* replace saved SP */
318 rjmp 1b
319
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100320 /*
321 * The debug handler set up a trampoline to make us
322 * automatically enter monitor mode upon return, but since
323 * we're saving the full context, we must assume that the
324 * exception handler might want to alter the return address
325 * and/or status register. So we need to restore the original
326 * context and enter monitor mode manually after the exception
327 * has been handled.
328 */
3293: get_thread_info r8
330 ld.w r11, r8[TI_rar_saved]
331 ld.w r12, r8[TI_rsr_saved]
332 rjmp 1b
333 .size save_full_context_ex, . - save_full_context_ex
334
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700335 /* Low-level exception handlers */
336handle_critical:
Haavard Skinnemoen9e3f5442008-08-20 15:46:24 +0200337 /*
338 * AT32AP700x errata:
339 *
340 * After a Java stack overflow or underflow trap, any CPU
341 * memory access may cause erratic behavior. This will happen
342 * when the four least significant bits of the JOSP system
343 * register contains any value between 9 and 15 (inclusive).
344 *
345 * Possible workarounds:
346 * - Don't use the Java Extension Module
347 * - Ensure that the stack overflow and underflow trap
348 * handlers do not do any memory access or trigger any
349 * exceptions before the overflow/underflow condition is
350 * cleared (by incrementing or decrementing the JOSP)
351 * - Make sure that JOSP does not contain any problematic
352 * value before doing any exception or interrupt
353 * processing.
354 * - Set up a critical exception handler which writes a
355 * known-to-be-safe value, e.g. 4, to JOSP before doing
356 * any further processing.
357 *
358 * We'll use the last workaround for now since we cannot
359 * guarantee that user space processes don't use Java mode.
360 * Non-well-behaving userland will be terminated with extreme
361 * prejudice.
362 */
363#ifdef CONFIG_CPU_AT32AP700X
364 /*
365 * There's a chance we can't touch memory, so temporarily
366 * borrow PTBR to save the stack pointer while we fix things
367 * up...
368 */
369 mtsr SYSREG_PTBR, sp
370 mov sp, 4
371 mtsr SYSREG_JOSP, sp
372 mfsr sp, SYSREG_PTBR
373 sub pc, -2
374
375 /* Push most of pt_regs on stack. We'll do the rest later */
Haavard Skinnemoen5998a3c2007-12-03 18:30:15 +0100376 sub sp, 4
Haavard Skinnemoen9e3f5442008-08-20 15:46:24 +0200377 pushm r0-r12
378
379 /* PTBR mirrors current_thread_info()->task->active_mm->pgd */
380 get_thread_info r0
381 ld.w r1, r0[TI_task]
382 ld.w r2, r1[TSK_active_mm]
383 ld.w r3, r2[MM_pgd]
384 mtsr SYSREG_PTBR, r3
385#else
386 sub sp, 4
387 pushm r0-r12
388#endif
389 sub r0, sp, -(14 * 4)
390 mov r1, lr
391 mfsr r2, SYSREG_RAR_EX
392 mfsr r3, SYSREG_RSR_EX
393 pushm r0-r3
394
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700395 mfsr r12, SYSREG_ECR
396 mov r11, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100397 call do_critical_exception
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700398
399 /* We should never get here... */
400bad_return:
401 sub r12, pc, (. - 1f)
Andreas Bießmannfb1601f2013-10-24 12:31:04 +0200402 lddpc pc, 2f
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700403 .align 2
4041: .asciz "Return from critical exception!"
Andreas Bießmannfb1601f2013-10-24 12:31:04 +02004052: .long panic
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700406
407 .align 1
408do_bus_error_write:
409 sub sp, 4
410 stmts --sp, r0-lr
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100411 call save_full_context_ex
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700412 mov r11, 1
413 rjmp 1f
414
415do_bus_error_read:
416 sub sp, 4
417 stmts --sp, r0-lr
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100418 call save_full_context_ex
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700419 mov r11, 0
4201: mfsr r12, SYSREG_BEAR
421 mov r10, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100422 call do_bus_error
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700423 rjmp ret_from_exception
424
425 .align 1
426do_nmi_ll:
427 sub sp, 4
428 stmts --sp, r0-lr
Haavard Skinnemoen92b728c2007-03-13 10:06:37 +0100429 mfsr r9, SYSREG_RSR_NMI
430 mfsr r8, SYSREG_RAR_NMI
431 bfextu r0, r9, MODE_SHIFT, 3
432 brne 2f
433
4341: pushm r8, r9 /* PC and SR */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700435 mfsr r12, SYSREG_ECR
436 mov r11, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100437 call do_nmi
Haavard Skinnemoen92b728c2007-03-13 10:06:37 +0100438 popm r8-r9
439 mtsr SYSREG_RAR_NMI, r8
440 tst r0, r0
441 mtsr SYSREG_RSR_NMI, r9
442 brne 3f
443
444 ldmts sp++, r0-lr
445 sub sp, -4 /* skip r12_orig */
446 rete
447
4482: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
449 stdsp sp[4], r10 /* replace saved SP */
450 rjmp 1b
451
4523: popm lr
453 sub sp, -4 /* skip sp */
454 popm r0-r12
455 sub sp, -4 /* skip r12_orig */
456 rete
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700457
458handle_address_fault:
459 sub sp, 4
460 stmts --sp, r0-lr
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100461 call save_full_context_ex
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700462 mfsr r12, SYSREG_ECR
463 mov r11, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100464 call do_address_exception
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700465 rjmp ret_from_exception
466
467handle_protection_fault:
468 sub sp, 4
469 stmts --sp, r0-lr
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100470 call save_full_context_ex
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700471 mfsr r12, SYSREG_ECR
472 mov r11, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100473 call do_page_fault
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700474 rjmp ret_from_exception
475
476 .align 1
477do_illegal_opcode_ll:
478 sub sp, 4
479 stmts --sp, r0-lr
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100480 call save_full_context_ex
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700481 mfsr r12, SYSREG_ECR
482 mov r11, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100483 call do_illegal_opcode
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700484 rjmp ret_from_exception
485
486do_dtlb_modified:
487 pushm r0-r3
488 mfsr r1, SYSREG_TLBEAR
489 mfsr r0, SYSREG_PTBR
490 lsr r2, r1, PGDIR_SHIFT
491 ld.w r0, r0[r2 << 2]
492 lsl r1, (32 - PGDIR_SHIFT)
493 lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
494
495 /* Translate to virtual address in P1 */
496 andl r0, 0xf000
497 sbr r0, 31
498 add r2, r0, r1 << 2
499 ld.w r3, r2[0]
500 sbr r3, _PAGE_BIT_DIRTY
501 mov r0, r3
502 st.w r2[0], r3
503
504 /* The page table is up-to-date. Update the TLB entry as well */
505 andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
506 mtsr SYSREG_TLBELO, r0
507
508 /* MMUCR[DRP] is updated automatically, so let's go... */
509 tlbw
510
511 popm r0-r3
512 rete
513
514do_fpe_ll:
515 sub sp, 4
516 stmts --sp, r0-lr
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100517 call save_full_context_ex
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700518 unmask_interrupts
519 mov r12, 26
520 mov r11, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100521 call do_fpe
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700522 rjmp ret_from_exception
523
524ret_from_exception:
525 mask_interrupts
526 lddsp r4, sp[REG_SR]
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100527
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700528 andh r4, (MODE_MASK >> 16), COH
529 brne fault_resume_kernel
530
531 get_thread_info r0
532 ld.w r1, r0[TI_flags]
533 andl r1, _TIF_WORK_MASK, COH
534 brne fault_exit_work
535
536fault_resume_user:
537 popm r8-r9
538 mask_exceptions
539 mtsr SYSREG_RAR_EX, r8
540 mtsr SYSREG_RSR_EX, r9
541 ldmts sp++, r0-lr
542 sub sp, -4
543 rete
544
545fault_resume_kernel:
546#ifdef CONFIG_PREEMPT
547 get_thread_info r0
548 ld.w r2, r0[TI_preempt_count]
549 cp.w r2, 0
550 brne 1f
551 ld.w r1, r0[TI_flags]
552 bld r1, TIF_NEED_RESCHED
553 brcc 1f
554 lddsp r4, sp[REG_SR]
555 bld r4, SYSREG_GM_OFFSET
556 brcs 1f
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100557 call preempt_schedule_irq
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07005581:
559#endif
560
561 popm r8-r9
562 mask_exceptions
563 mfsr r1, SYSREG_SR
564 mtsr SYSREG_RAR_EX, r8
565 mtsr SYSREG_RSR_EX, r9
566 popm lr
567 sub sp, -4 /* ignore SP */
568 popm r0-r12
569 sub sp, -4 /* ignore r12_orig */
570 rete
571
572irq_exit_work:
573 /* Switch to exception mode so that we can share the same code. */
574 mfsr r8, SYSREG_SR
575 cbr r8, SYSREG_M0_OFFSET
576 orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
577 mtsr SYSREG_SR, r8
578 sub pc, -2
579 get_thread_info r0
580 ld.w r1, r0[TI_flags]
581
582fault_exit_work:
583 bld r1, TIF_NEED_RESCHED
584 brcc 1f
585 unmask_interrupts
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100586 call schedule
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700587 mask_interrupts
588 ld.w r1, r0[TI_flags]
589 rjmp fault_exit_work
590
5911: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
592 tst r1, r2
593 breq 2f
594 unmask_interrupts
595 mov r12, sp
596 mov r11, r0
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100597 call do_notify_resume
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700598 mask_interrupts
599 ld.w r1, r0[TI_flags]
600 rjmp fault_exit_work
601
6022: bld r1, TIF_BREAKPOINT
603 brcc fault_resume_user
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100604 rjmp enter_monitor_mode
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700605
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100606 .section .kprobes.text, "ax", @progbits
607 .type handle_debug, @function
608handle_debug:
609 sub sp, 4 /* r12_orig */
610 stmts --sp, r0-lr
611 mfsr r8, SYSREG_RAR_DBG
612 mfsr r9, SYSREG_RSR_DBG
613 unmask_exceptions
614 pushm r8-r9
615 bfextu r9, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
616 brne debug_fixup_regs
617
618.Ldebug_fixup_cont:
619#ifdef CONFIG_TRACE_IRQFLAGS
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100620 call trace_hardirqs_off
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100621#endif
622 mov r12, sp
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100623 call do_debug
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100624 mov sp, r12
625
626 lddsp r2, sp[REG_SR]
627 bfextu r3, r2, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
628 brne debug_resume_kernel
629
630 get_thread_info r0
631 ld.w r1, r0[TI_flags]
632 mov r2, _TIF_DBGWORK_MASK
633 tst r1, r2
634 brne debug_exit_work
635
636 bld r1, TIF_SINGLE_STEP
637 brcc 1f
638 mfdr r4, OCD_DC
639 sbr r4, OCD_DC_SS_BIT
640 mtdr OCD_DC, r4
641
6421: popm r10,r11
643 mask_exceptions
644 mtsr SYSREG_RSR_DBG, r11
645 mtsr SYSREG_RAR_DBG, r10
646#ifdef CONFIG_TRACE_IRQFLAGS
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100647 call trace_hardirqs_on
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +01006481:
649#endif
650 ldmts sp++, r0-lr
651 sub sp, -4
652 retd
653 .size handle_debug, . - handle_debug
654
655 /* Mode of the trapped context is in r9 */
656 .type debug_fixup_regs, @function
657debug_fixup_regs:
658 mfsr r8, SYSREG_SR
659 mov r10, r8
660 bfins r8, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
661 mtsr SYSREG_SR, r8
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700662 sub pc, -2
663 stdsp sp[REG_LR], lr
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100664 mtsr SYSREG_SR, r10
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700665 sub pc, -2
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100666 sub r8, sp, -FRAME_SIZE_FULL
667 stdsp sp[REG_SP], r8
668 rjmp .Ldebug_fixup_cont
669 .size debug_fixup_regs, . - debug_fixup_regs
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700670
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100671 .type debug_resume_kernel, @function
672debug_resume_kernel:
673 mask_exceptions
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700674 popm r10, r11
675 mtsr SYSREG_RAR_DBG, r10
676 mtsr SYSREG_RSR_DBG, r11
Haavard Skinnemoen320516b2007-11-26 14:34:57 +0100677#ifdef CONFIG_TRACE_IRQFLAGS
678 bld r11, SYSREG_GM_OFFSET
679 brcc 1f
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100680 call trace_hardirqs_on
Haavard Skinnemoen320516b2007-11-26 14:34:57 +01006811:
682#endif
683 mfsr r2, SYSREG_SR
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100684 mov r1, r2
685 bfins r2, r3, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
Haavard Skinnemoen320516b2007-11-26 14:34:57 +0100686 mtsr SYSREG_SR, r2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700687 sub pc, -2
688 popm lr
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100689 mtsr SYSREG_SR, r1
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700690 sub pc, -2
691 sub sp, -4 /* skip SP */
692 popm r0-r12
693 sub sp, -4
694 retd
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100695 .size debug_resume_kernel, . - debug_resume_kernel
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700696
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100697 .type debug_exit_work, @function
698debug_exit_work:
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700699 /*
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100700 * We must return from Monitor Mode using a retd, and we must
701 * not schedule since that involves the D bit in SR getting
702 * cleared by something other than the debug hardware. This
703 * may cause undefined behaviour according to the Architecture
704 * manual.
705 *
706 * So we fix up the return address and status and return to a
707 * stub below in Exception mode. From there, we can follow the
708 * normal exception return path.
709 *
710 * The real return address and status registers are stored on
711 * the stack in the way the exception return path understands,
712 * so no need to fix anything up there.
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700713 */
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100714 sub r8, pc, . - fault_exit_work
715 mtsr SYSREG_RAR_DBG, r8
716 mov r9, 0
717 orh r9, hi(SR_EM | SR_GM | MODE_EXCEPTION)
718 mtsr SYSREG_RSR_DBG, r9
719 sub pc, -2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700720 retd
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100721 .size debug_exit_work, . - debug_exit_work
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700722
723 .set rsr_int0, SYSREG_RSR_INT0
724 .set rsr_int1, SYSREG_RSR_INT1
725 .set rsr_int2, SYSREG_RSR_INT2
726 .set rsr_int3, SYSREG_RSR_INT3
727 .set rar_int0, SYSREG_RAR_INT0
728 .set rar_int1, SYSREG_RAR_INT1
729 .set rar_int2, SYSREG_RAR_INT2
730 .set rar_int3, SYSREG_RAR_INT3
731
732 .macro IRQ_LEVEL level
733 .type irq_level\level, @function
734irq_level\level:
735 sub sp, 4 /* r12_orig */
736 stmts --sp,r0-lr
737 mfsr r8, rar_int\level
738 mfsr r9, rsr_int\level
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400739
740#ifdef CONFIG_PREEMPT
741 sub r11, pc, (. - system_call)
742 cp.w r11, r8
743 breq 4f
744#endif
745
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700746 pushm r8-r9
747
748 mov r11, sp
749 mov r12, \level
750
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100751 call do_IRQ
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700752
753 lddsp r4, sp[REG_SR]
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100754 bfextu r4, r4, SYSREG_M0_OFFSET, 3
755 cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET
756 breq 2f
757 cp.w r4, MODE_USER >> SYSREG_M0_OFFSET
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700758#ifdef CONFIG_PREEMPT
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100759 brne 3f
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700760#else
761 brne 1f
762#endif
763
764 get_thread_info r0
765 ld.w r1, r0[TI_flags]
766 andl r1, _TIF_WORK_MASK, COH
767 brne irq_exit_work
768
Haavard Skinnemoen320516b2007-11-26 14:34:57 +01007691:
770#ifdef CONFIG_TRACE_IRQFLAGS
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100771 call trace_hardirqs_on
Haavard Skinnemoen320516b2007-11-26 14:34:57 +0100772#endif
773 popm r8-r9
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700774 mtsr rar_int\level, r8
775 mtsr rsr_int\level, r9
776 ldmts sp++,r0-lr
777 sub sp, -4 /* ignore r12_orig */
778 rete
779
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400780#ifdef CONFIG_PREEMPT
7814: mask_interrupts
782 mfsr r8, rsr_int\level
783 sbr r8, 16
784 mtsr rsr_int\level, r8
785 ldmts sp++, r0-lr
786 sub sp, -4 /* ignore r12_orig */
787 rete
788#endif
789
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +01007902: get_thread_info r0
791 ld.w r1, r0[TI_flags]
792 bld r1, TIF_CPU_GOING_TO_SLEEP
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700793#ifdef CONFIG_PREEMPT
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100794 brcc 3f
795#else
796 brcc 1b
797#endif
798 sub r1, pc, . - cpu_idle_skip_sleep
799 stdsp sp[REG_PC], r1
800#ifdef CONFIG_PREEMPT
8013: get_thread_info r0
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700802 ld.w r2, r0[TI_preempt_count]
803 cp.w r2, 0
804 brne 1b
805 ld.w r1, r0[TI_flags]
806 bld r1, TIF_NEED_RESCHED
807 brcc 1b
808 lddsp r4, sp[REG_SR]
809 bld r4, SYSREG_GM_OFFSET
810 brcs 1b
Ben Nizette8d29b7b2009-01-14 09:32:19 +1100811 call preempt_schedule_irq
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700812#endif
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100813 rjmp 1b
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700814 .endm
815
816 .section .irq.text,"ax",@progbits
817
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700818 .global irq_level0
819 .global irq_level1
820 .global irq_level2
821 .global irq_level3
822 IRQ_LEVEL 0
823 IRQ_LEVEL 1
824 IRQ_LEVEL 2
825 IRQ_LEVEL 3
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100826
827 .section .kprobes.text, "ax", @progbits
828 .type enter_monitor_mode, @function
829enter_monitor_mode:
830 /*
831 * We need to enter monitor mode to do a single step. The
832 * monitor code will alter the return address so that we
833 * return directly to the user instead of returning here.
834 */
835 breakpoint
836 rjmp breakpoint_failed
837
838 .size enter_monitor_mode, . - enter_monitor_mode
839
840 .type debug_trampoline, @function
841 .global debug_trampoline
842debug_trampoline:
843 /*
844 * Save the registers on the stack so that the monitor code
845 * can find them easily.
846 */
847 sub sp, 4 /* r12_orig */
848 stmts --sp, r0-lr
849 get_thread_info r0
850 ld.w r8, r0[TI_rar_saved]
851 ld.w r9, r0[TI_rsr_saved]
852 pushm r8-r9
853
854 /*
855 * The monitor code will alter the return address so we don't
856 * return here.
857 */
858 breakpoint
859 rjmp breakpoint_failed
860 .size debug_trampoline, . - debug_trampoline
861
862 .type breakpoint_failed, @function
863breakpoint_failed:
864 /*
865 * Something went wrong. Perhaps the debug hardware isn't
866 * enabled?
867 */
868 lda.w r12, msg_breakpoint_failed
869 mov r11, sp
870 mov r10, 9 /* SIGKILL */
871 call die
8721: rjmp 1b
873
874msg_breakpoint_failed:
875 .asciz "Failed to enter Debug Mode"