diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-12-07 14:00:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-12-07 14:00:31 -0500 |
commit | e17587b5b90da78f56c7a948e54dbac3dc791f31 (patch) | |
tree | 60228100507c7c6509188d9f3ee7bd43947c718d /arch | |
parent | 29ac0052ea454871273a1fc7ef09a97f3c214ee6 (diff) | |
parent | 5998a3cf327c90d0a7116eca72c0d2df2be8ecfd (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6:
[AVR32] Fix wrong pt_regs in critical exception handler
[AVR32] Fix copy_to_user_page() breakage
[AVR32] Follow the rules when dealing with the OCD system
[AVR32] Clean up OCD register usage
[AVR32] Implement irqflags trace and lockdep support
[AVR32] Implement stacktrace support
[AVR32] Kconfig: Use def_bool instead of bool + default
[AVR32] Fix invalid status register bit definitions in asm/ptrace.h
[AVR32] Add TIF_RESTORE_SIGMASK to the work masks
Diffstat (limited to 'arch')
-rw-r--r-- | arch/avr32/Kconfig | 65 | ||||
-rw-r--r-- | arch/avr32/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/avr32/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/avr32/kernel/entry-avr32b.S | 285 | ||||
-rw-r--r-- | arch/avr32/kernel/kprobes.c | 14 | ||||
-rw-r--r-- | arch/avr32/kernel/process.c | 9 | ||||
-rw-r--r-- | arch/avr32/kernel/ptrace.c | 273 | ||||
-rw-r--r-- | arch/avr32/kernel/stacktrace.c | 53 | ||||
-rw-r--r-- | arch/avr32/kernel/traps.c | 2 | ||||
-rw-r--r-- | arch/avr32/kernel/vmlinux.lds.S | 2 | ||||
-rw-r--r-- | arch/avr32/mm/cache.c | 20 |
11 files changed, 443 insertions, 283 deletions
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 4f402c924504..b77abce10c7a 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
@@ -6,8 +6,7 @@ | |||
6 | mainmenu "Linux Kernel Configuration" | 6 | mainmenu "Linux Kernel Configuration" |
7 | 7 | ||
8 | config AVR32 | 8 | config AVR32 |
9 | bool | 9 | def_bool y |
10 | default y | ||
11 | # With EMBEDDED=n, we get lots of stuff automatically selected | 10 | # With EMBEDDED=n, we get lots of stuff automatically selected |
12 | # that we usually don't need on AVR32. | 11 | # that we usually don't need on AVR32. |
13 | select EMBEDDED | 12 | select EMBEDDED |
@@ -20,51 +19,49 @@ config AVR32 | |||
20 | http://avr32linux.org/. | 19 | http://avr32linux.org/. |
21 | 20 | ||
22 | config GENERIC_GPIO | 21 | config GENERIC_GPIO |
23 | bool | 22 | def_bool y |
24 | default y | ||
25 | 23 | ||
26 | config GENERIC_HARDIRQS | 24 | config GENERIC_HARDIRQS |
27 | bool | 25 | def_bool y |
28 | default y | 26 | |
27 | config STACKTRACE_SUPPORT | ||
28 | def_bool y | ||
29 | |||
30 | config LOCKDEP_SUPPORT | ||
31 | def_bool y | ||
32 | |||
33 | config TRACE_IRQFLAGS_SUPPORT | ||
34 | def_bool y | ||
29 | 35 | ||
30 | config HARDIRQS_SW_RESEND | 36 | config HARDIRQS_SW_RESEND |
31 | bool | 37 | def_bool y |
32 | default y | ||
33 | 38 | ||
34 | config GENERIC_IRQ_PROBE | 39 | config GENERIC_IRQ_PROBE |
35 | bool | 40 | def_bool y |
36 | default y | ||
37 | 41 | ||
38 | config RWSEM_GENERIC_SPINLOCK | 42 | config RWSEM_GENERIC_SPINLOCK |
39 | bool | 43 | def_bool y |
40 | default y | ||
41 | 44 | ||
42 | config GENERIC_TIME | 45 | config GENERIC_TIME |
43 | bool | 46 | def_bool y |
44 | default y | ||
45 | 47 | ||
46 | config RWSEM_XCHGADD_ALGORITHM | 48 | config RWSEM_XCHGADD_ALGORITHM |
47 | bool | 49 | def_bool n |
48 | 50 | ||
49 | config ARCH_HAS_ILOG2_U32 | 51 | config ARCH_HAS_ILOG2_U32 |
50 | bool | 52 | def_bool n |
51 | default n | ||
52 | 53 | ||
53 | config ARCH_HAS_ILOG2_U64 | 54 | config ARCH_HAS_ILOG2_U64 |
54 | bool | 55 | def_bool n |
55 | default n | ||
56 | 56 | ||
57 | config GENERIC_HWEIGHT | 57 | config GENERIC_HWEIGHT |
58 | bool | 58 | def_bool y |
59 | default y | ||
60 | 59 | ||
61 | config GENERIC_CALIBRATE_DELAY | 60 | config GENERIC_CALIBRATE_DELAY |
62 | bool | 61 | def_bool y |
63 | default y | ||
64 | 62 | ||
65 | config GENERIC_BUG | 63 | config GENERIC_BUG |
66 | bool | 64 | def_bool y |
67 | default y | ||
68 | depends on BUG | 65 | depends on BUG |
69 | 66 | ||
70 | source "init/Kconfig" | 67 | source "init/Kconfig" |
@@ -139,28 +136,22 @@ config PHYS_OFFSET | |||
139 | source "kernel/Kconfig.preempt" | 136 | source "kernel/Kconfig.preempt" |
140 | 137 | ||
141 | config HAVE_ARCH_BOOTMEM_NODE | 138 | config HAVE_ARCH_BOOTMEM_NODE |
142 | bool | 139 | def_bool n |
143 | default n | ||
144 | 140 | ||
145 | config ARCH_HAVE_MEMORY_PRESENT | 141 | config ARCH_HAVE_MEMORY_PRESENT |
146 | bool | 142 | def_bool n |
147 | default n | ||
148 | 143 | ||
149 | config NEED_NODE_MEMMAP_SIZE | 144 | config NEED_NODE_MEMMAP_SIZE |
150 | bool | 145 | def_bool n |
151 | default n | ||
152 | 146 | ||
153 | config ARCH_FLATMEM_ENABLE | 147 | config ARCH_FLATMEM_ENABLE |
154 | bool | 148 | def_bool y |
155 | default y | ||
156 | 149 | ||
157 | config ARCH_DISCONTIGMEM_ENABLE | 150 | config ARCH_DISCONTIGMEM_ENABLE |
158 | bool | 151 | def_bool n |
159 | default n | ||
160 | 152 | ||
161 | config ARCH_SPARSEMEM_ENABLE | 153 | config ARCH_SPARSEMEM_ENABLE |
162 | bool | 154 | def_bool n |
163 | default n | ||
164 | 155 | ||
165 | source "mm/Kconfig" | 156 | source "mm/Kconfig" |
166 | 157 | ||
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile index 989fcd1fef7e..2d6d48f35f69 100644 --- a/arch/avr32/kernel/Makefile +++ b/arch/avr32/kernel/Makefile | |||
@@ -11,3 +11,4 @@ obj-y += signal.o sys_avr32.o process.o time.o | |||
11 | obj-y += init_task.o switch_to.o cpu.o | 11 | obj-y += init_task.o switch_to.o cpu.o |
12 | obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o | 12 | obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o |
13 | obj-$(CONFIG_KPROBES) += kprobes.o | 13 | obj-$(CONFIG_KPROBES) += kprobes.o |
14 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | ||
diff --git a/arch/avr32/kernel/asm-offsets.c b/arch/avr32/kernel/asm-offsets.c index 97d865865667..078cd33f467b 100644 --- a/arch/avr32/kernel/asm-offsets.c +++ b/arch/avr32/kernel/asm-offsets.c | |||
@@ -21,5 +21,7 @@ void foo(void) | |||
21 | OFFSET(TI_flags, thread_info, flags); | 21 | OFFSET(TI_flags, thread_info, flags); |
22 | OFFSET(TI_cpu, thread_info, cpu); | 22 | OFFSET(TI_cpu, thread_info, cpu); |
23 | OFFSET(TI_preempt_count, thread_info, preempt_count); | 23 | OFFSET(TI_preempt_count, thread_info, preempt_count); |
24 | OFFSET(TI_rar_saved, thread_info, rar_saved); | ||
25 | OFFSET(TI_rsr_saved, thread_info, rsr_saved); | ||
24 | OFFSET(TI_restart_block, thread_info, restart_block); | 26 | OFFSET(TI_restart_block, thread_info, restart_block); |
25 | } | 27 | } |
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index ccadfd9b438d..8cf16d7a7040 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S | |||
@@ -264,16 +264,7 @@ syscall_exit_work: | |||
264 | 264 | ||
265 | 3: bld r1, TIF_BREAKPOINT | 265 | 3: bld r1, TIF_BREAKPOINT |
266 | brcc syscall_exit_cont | 266 | brcc syscall_exit_cont |
267 | mfsr r3, SYSREG_TLBEHI | 267 | rjmp enter_monitor_mode |
268 | lddsp r2, sp[REG_PC] | ||
269 | andl r3, 0xff, COH | ||
270 | lsl r3, 1 | ||
271 | sbr r3, 30 | ||
272 | sbr r3, 0 | ||
273 | mtdr DBGREG_BWA2A, r2 | ||
274 | mtdr DBGREG_BWC2A, r3 | ||
275 | rjmp syscall_exit_cont | ||
276 | |||
277 | 268 | ||
278 | /* The slow path of the TLB miss handler */ | 269 | /* The slow path of the TLB miss handler */ |
279 | page_table_not_present: | 270 | page_table_not_present: |
@@ -288,11 +279,16 @@ page_not_present: | |||
288 | rjmp ret_from_exception | 279 | rjmp ret_from_exception |
289 | 280 | ||
290 | /* This function expects to find offending PC in SYSREG_RAR_EX */ | 281 | /* This function expects to find offending PC in SYSREG_RAR_EX */ |
282 | .type save_full_context_ex, @function | ||
283 | .align 2 | ||
291 | save_full_context_ex: | 284 | save_full_context_ex: |
285 | mfsr r11, SYSREG_RAR_EX | ||
286 | sub r9, pc, . - debug_trampoline | ||
292 | mfsr r8, SYSREG_RSR_EX | 287 | mfsr r8, SYSREG_RSR_EX |
288 | cp.w r9, r11 | ||
289 | breq 3f | ||
293 | mov r12, r8 | 290 | mov r12, r8 |
294 | andh r8, (MODE_MASK >> 16), COH | 291 | andh r8, (MODE_MASK >> 16), COH |
295 | mfsr r11, SYSREG_RAR_EX | ||
296 | brne 2f | 292 | brne 2f |
297 | 293 | ||
298 | 1: pushm r11, r12 /* PC and SR */ | 294 | 1: pushm r11, r12 /* PC and SR */ |
@@ -303,10 +299,25 @@ save_full_context_ex: | |||
303 | stdsp sp[4], r10 /* replace saved SP */ | 299 | stdsp sp[4], r10 /* replace saved SP */ |
304 | rjmp 1b | 300 | rjmp 1b |
305 | 301 | ||
302 | /* | ||
303 | * The debug handler set up a trampoline to make us | ||
304 | * automatically enter monitor mode upon return, but since | ||
305 | * we're saving the full context, we must assume that the | ||
306 | * exception handler might want to alter the return address | ||
307 | * and/or status register. So we need to restore the original | ||
308 | * context and enter monitor mode manually after the exception | ||
309 | * has been handled. | ||
310 | */ | ||
311 | 3: get_thread_info r8 | ||
312 | ld.w r11, r8[TI_rar_saved] | ||
313 | ld.w r12, r8[TI_rsr_saved] | ||
314 | rjmp 1b | ||
315 | .size save_full_context_ex, . - save_full_context_ex | ||
316 | |||
306 | /* Low-level exception handlers */ | 317 | /* Low-level exception handlers */ |
307 | handle_critical: | 318 | handle_critical: |
308 | pushm r12 | 319 | sub sp, 4 |
309 | pushm r0-r12 | 320 | stmts --sp, r0-lr |
310 | rcall save_full_context_ex | 321 | rcall save_full_context_ex |
311 | mfsr r12, SYSREG_ECR | 322 | mfsr r12, SYSREG_ECR |
312 | mov r11, sp | 323 | mov r11, sp |
@@ -439,6 +450,7 @@ do_fpe_ll: | |||
439 | ret_from_exception: | 450 | ret_from_exception: |
440 | mask_interrupts | 451 | mask_interrupts |
441 | lddsp r4, sp[REG_SR] | 452 | lddsp r4, sp[REG_SR] |
453 | |||
442 | andh r4, (MODE_MASK >> 16), COH | 454 | andh r4, (MODE_MASK >> 16), COH |
443 | brne fault_resume_kernel | 455 | brne fault_resume_kernel |
444 | 456 | ||
@@ -515,119 +527,124 @@ fault_exit_work: | |||
515 | 527 | ||
516 | 2: bld r1, TIF_BREAKPOINT | 528 | 2: bld r1, TIF_BREAKPOINT |
517 | brcc fault_resume_user | 529 | brcc fault_resume_user |
518 | mfsr r3, SYSREG_TLBEHI | 530 | rjmp enter_monitor_mode |
519 | lddsp r2, sp[REG_PC] | 531 | |
520 | andl r3, 0xff, COH | 532 | .section .kprobes.text, "ax", @progbits |
521 | lsl r3, 1 | 533 | .type handle_debug, @function |
522 | sbr r3, 30 | 534 | handle_debug: |
523 | sbr r3, 0 | 535 | sub sp, 4 /* r12_orig */ |
524 | mtdr DBGREG_BWA2A, r2 | 536 | stmts --sp, r0-lr |
525 | mtdr DBGREG_BWC2A, r3 | 537 | mfsr r8, SYSREG_RAR_DBG |
526 | rjmp fault_resume_user | 538 | mfsr r9, SYSREG_RSR_DBG |
527 | 539 | unmask_exceptions | |
528 | /* If we get a debug trap from privileged context we end up here */ | 540 | pushm r8-r9 |
529 | handle_debug_priv: | 541 | bfextu r9, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE |
530 | /* Fix up LR and SP in regs. r11 contains the mode we came from */ | 542 | brne debug_fixup_regs |
543 | |||
544 | .Ldebug_fixup_cont: | ||
545 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
546 | rcall trace_hardirqs_off | ||
547 | #endif | ||
548 | mov r12, sp | ||
549 | rcall do_debug | ||
550 | mov sp, r12 | ||
551 | |||
552 | lddsp r2, sp[REG_SR] | ||
553 | bfextu r3, r2, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE | ||
554 | brne debug_resume_kernel | ||
555 | |||
556 | get_thread_info r0 | ||
557 | ld.w r1, r0[TI_flags] | ||
558 | mov r2, _TIF_DBGWORK_MASK | ||
559 | tst r1, r2 | ||
560 | brne debug_exit_work | ||
561 | |||
562 | bld r1, TIF_SINGLE_STEP | ||
563 | brcc 1f | ||
564 | mfdr r4, OCD_DC | ||
565 | sbr r4, OCD_DC_SS_BIT | ||
566 | mtdr OCD_DC, r4 | ||
567 | |||
568 | 1: popm r10,r11 | ||
569 | mask_exceptions | ||
570 | mtsr SYSREG_RSR_DBG, r11 | ||
571 | mtsr SYSREG_RAR_DBG, r10 | ||
572 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
573 | rcall trace_hardirqs_on | ||
574 | 1: | ||
575 | #endif | ||
576 | ldmts sp++, r0-lr | ||
577 | sub sp, -4 | ||
578 | retd | ||
579 | .size handle_debug, . - handle_debug | ||
580 | |||
581 | /* Mode of the trapped context is in r9 */ | ||
582 | .type debug_fixup_regs, @function | ||
583 | debug_fixup_regs: | ||
531 | mfsr r8, SYSREG_SR | 584 | mfsr r8, SYSREG_SR |
532 | mov r9, r8 | 585 | mov r10, r8 |
533 | andh r8, hi(~MODE_MASK) | 586 | bfins r8, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE |
534 | or r8, r11 | ||
535 | mtsr SYSREG_SR, r8 | 587 | mtsr SYSREG_SR, r8 |
536 | sub pc, -2 | 588 | sub pc, -2 |
537 | stdsp sp[REG_LR], lr | 589 | stdsp sp[REG_LR], lr |
538 | mtsr SYSREG_SR, r9 | 590 | mtsr SYSREG_SR, r10 |
539 | sub pc, -2 | 591 | sub pc, -2 |
540 | sub r10, sp, -FRAME_SIZE_FULL | 592 | sub r8, sp, -FRAME_SIZE_FULL |
541 | stdsp sp[REG_SP], r10 | 593 | stdsp sp[REG_SP], r8 |
542 | mov r12, sp | 594 | rjmp .Ldebug_fixup_cont |
543 | rcall do_debug_priv | 595 | .size debug_fixup_regs, . - debug_fixup_regs |
544 | 596 | ||
545 | /* Now, put everything back */ | 597 | .type debug_resume_kernel, @function |
546 | ssrf SR_EM_BIT | 598 | debug_resume_kernel: |
599 | mask_exceptions | ||
547 | popm r10, r11 | 600 | popm r10, r11 |
548 | mtsr SYSREG_RAR_DBG, r10 | 601 | mtsr SYSREG_RAR_DBG, r10 |
549 | mtsr SYSREG_RSR_DBG, r11 | 602 | mtsr SYSREG_RSR_DBG, r11 |
550 | mfsr r8, SYSREG_SR | 603 | #ifdef CONFIG_TRACE_IRQFLAGS |
551 | mov r9, r8 | 604 | bld r11, SYSREG_GM_OFFSET |
552 | andh r8, hi(~MODE_MASK) | 605 | brcc 1f |
553 | andh r11, hi(MODE_MASK) | 606 | rcall trace_hardirqs_on |
554 | or r8, r11 | 607 | 1: |
555 | mtsr SYSREG_SR, r8 | 608 | #endif |
609 | mfsr r2, SYSREG_SR | ||
610 | mov r1, r2 | ||
611 | bfins r2, r3, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE | ||
612 | mtsr SYSREG_SR, r2 | ||
556 | sub pc, -2 | 613 | sub pc, -2 |
557 | popm lr | 614 | popm lr |
558 | mtsr SYSREG_SR, r9 | 615 | mtsr SYSREG_SR, r1 |
559 | sub pc, -2 | 616 | sub pc, -2 |
560 | sub sp, -4 /* skip SP */ | 617 | sub sp, -4 /* skip SP */ |
561 | popm r0-r12 | 618 | popm r0-r12 |
562 | sub sp, -4 | 619 | sub sp, -4 |
563 | retd | 620 | retd |
621 | .size debug_resume_kernel, . - debug_resume_kernel | ||
564 | 622 | ||
623 | .type debug_exit_work, @function | ||
624 | debug_exit_work: | ||
565 | /* | 625 | /* |
566 | * At this point, everything is masked, that is, interrupts, | 626 | * We must return from Monitor Mode using a retd, and we must |
567 | * exceptions and debugging traps. We might get called from | 627 | * not schedule since that involves the D bit in SR getting |
568 | * interrupt or exception context in some rare cases, but this | 628 | * cleared by something other than the debug hardware. This |
569 | * will be taken care of by do_debug(), so we're not going to | 629 | * may cause undefined behaviour according to the Architecture |
570 | * do a 100% correct context save here. | 630 | * manual. |
631 | * | ||
632 | * So we fix up the return address and status and return to a | ||
633 | * stub below in Exception mode. From there, we can follow the | ||
634 | * normal exception return path. | ||
635 | * | ||
636 | * The real return address and status registers are stored on | ||
637 | * the stack in the way the exception return path understands, | ||
638 | * so no need to fix anything up there. | ||
571 | */ | 639 | */ |
572 | handle_debug: | 640 | sub r8, pc, . - fault_exit_work |
573 | sub sp, 4 /* r12_orig */ | 641 | mtsr SYSREG_RAR_DBG, r8 |
574 | stmts --sp, r0-lr | 642 | mov r9, 0 |
575 | mfsr r10, SYSREG_RAR_DBG | 643 | orh r9, hi(SR_EM | SR_GM | MODE_EXCEPTION) |
576 | mfsr r11, SYSREG_RSR_DBG | 644 | mtsr SYSREG_RSR_DBG, r9 |
577 | unmask_exceptions | 645 | sub pc, -2 |
578 | pushm r10,r11 | ||
579 | andh r11, (MODE_MASK >> 16), COH | ||
580 | brne handle_debug_priv | ||
581 | |||
582 | mov r12, sp | ||
583 | rcall do_debug | ||
584 | |||
585 | lddsp r10, sp[REG_SR] | ||
586 | andh r10, (MODE_MASK >> 16), COH | ||
587 | breq debug_resume_user | ||
588 | |||
589 | debug_restore_all: | ||
590 | popm r10,r11 | ||
591 | mask_exceptions | ||
592 | mtsr SYSREG_RSR_DBG, r11 | ||
593 | mtsr SYSREG_RAR_DBG, r10 | ||
594 | ldmts sp++, r0-lr | ||
595 | sub sp, -4 | ||
596 | retd | 646 | retd |
597 | 647 | .size debug_exit_work, . - debug_exit_work | |
598 | debug_resume_user: | ||
599 | get_thread_info r0 | ||
600 | mask_interrupts | ||
601 | |||
602 | ld.w r1, r0[TI_flags] | ||
603 | andl r1, _TIF_DBGWORK_MASK, COH | ||
604 | breq debug_restore_all | ||
605 | |||
606 | 1: bld r1, TIF_NEED_RESCHED | ||
607 | brcc 2f | ||
608 | unmask_interrupts | ||
609 | rcall schedule | ||
610 | mask_interrupts | ||
611 | ld.w r1, r0[TI_flags] | ||
612 | rjmp 1b | ||
613 | |||
614 | 2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | ||
615 | tst r1, r2 | ||
616 | breq 3f | ||
617 | unmask_interrupts | ||
618 | mov r12, sp | ||
619 | mov r11, r0 | ||
620 | rcall do_notify_resume | ||
621 | mask_interrupts | ||
622 | ld.w r1, r0[TI_flags] | ||
623 | rjmp 1b | ||
624 | |||
625 | 3: bld r1, TIF_SINGLE_STEP | ||
626 | brcc debug_restore_all | ||
627 | mfdr r2, DBGREG_DC | ||
628 | sbr r2, DC_SS_BIT | ||
629 | mtdr DBGREG_DC, r2 | ||
630 | rjmp debug_restore_all | ||
631 | 648 | ||
632 | .set rsr_int0, SYSREG_RSR_INT0 | 649 | .set rsr_int0, SYSREG_RSR_INT0 |
633 | .set rsr_int1, SYSREG_RSR_INT1 | 650 | .set rsr_int1, SYSREG_RSR_INT1 |
@@ -675,7 +692,11 @@ irq_level\level: | |||
675 | andl r1, _TIF_WORK_MASK, COH | 692 | andl r1, _TIF_WORK_MASK, COH |
676 | brne irq_exit_work | 693 | brne irq_exit_work |
677 | 694 | ||
678 | 1: popm r8-r9 | 695 | 1: |
696 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
697 | rcall trace_hardirqs_on | ||
698 | #endif | ||
699 | popm r8-r9 | ||
679 | mtsr rar_int\level, r8 | 700 | mtsr rar_int\level, r8 |
680 | mtsr rsr_int\level, r9 | 701 | mtsr rsr_int\level, r9 |
681 | ldmts sp++,r0-lr | 702 | ldmts sp++,r0-lr |
@@ -748,3 +769,53 @@ cpu_idle_enable_int_and_exit: | |||
748 | IRQ_LEVEL 1 | 769 | IRQ_LEVEL 1 |
749 | IRQ_LEVEL 2 | 770 | IRQ_LEVEL 2 |
750 | IRQ_LEVEL 3 | 771 | IRQ_LEVEL 3 |
772 | |||
773 | .section .kprobes.text, "ax", @progbits | ||
774 | .type enter_monitor_mode, @function | ||
775 | enter_monitor_mode: | ||
776 | /* | ||
777 | * We need to enter monitor mode to do a single step. The | ||
778 | * monitor code will alter the return address so that we | ||
779 | * return directly to the user instead of returning here. | ||
780 | */ | ||
781 | breakpoint | ||
782 | rjmp breakpoint_failed | ||
783 | |||
784 | .size enter_monitor_mode, . - enter_monitor_mode | ||
785 | |||
786 | .type debug_trampoline, @function | ||
787 | .global debug_trampoline | ||
788 | debug_trampoline: | ||
789 | /* | ||
790 | * Save the registers on the stack so that the monitor code | ||
791 | * can find them easily. | ||
792 | */ | ||
793 | sub sp, 4 /* r12_orig */ | ||
794 | stmts --sp, r0-lr | ||
795 | get_thread_info r0 | ||
796 | ld.w r8, r0[TI_rar_saved] | ||
797 | ld.w r9, r0[TI_rsr_saved] | ||
798 | pushm r8-r9 | ||
799 | |||
800 | /* | ||
801 | * The monitor code will alter the return address so we don't | ||
802 | * return here. | ||
803 | */ | ||
804 | breakpoint | ||
805 | rjmp breakpoint_failed | ||
806 | .size debug_trampoline, . - debug_trampoline | ||
807 | |||
808 | .type breakpoint_failed, @function | ||
809 | breakpoint_failed: | ||
810 | /* | ||
811 | * Something went wrong. Perhaps the debug hardware isn't | ||
812 | * enabled? | ||
813 | */ | ||
814 | lda.w r12, msg_breakpoint_failed | ||
815 | mov r11, sp | ||
816 | mov r10, 9 /* SIGKILL */ | ||
817 | call die | ||
818 | 1: rjmp 1b | ||
819 | |||
820 | msg_breakpoint_failed: | ||
821 | .asciz "Failed to enter Debug Mode" | ||
diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c index 20b1c9d8f945..799ba89b07a8 100644 --- a/arch/avr32/kernel/kprobes.c +++ b/arch/avr32/kernel/kprobes.c | |||
@@ -70,9 +70,9 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
70 | 70 | ||
71 | BUG_ON(!(sysreg_read(SR) & SYSREG_BIT(SR_D))); | 71 | BUG_ON(!(sysreg_read(SR) & SYSREG_BIT(SR_D))); |
72 | 72 | ||
73 | dc = __mfdr(DBGREG_DC); | 73 | dc = ocd_read(DC); |
74 | dc |= DC_SS; | 74 | dc |= 1 << OCD_DC_SS_BIT; |
75 | __mtdr(DBGREG_DC, dc); | 75 | ocd_write(DC, dc); |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * We must run the instruction from its original location | 78 | * We must run the instruction from its original location |
@@ -91,9 +91,9 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) | |||
91 | 91 | ||
92 | pr_debug("resuming execution at PC=%08lx\n", regs->pc); | 92 | pr_debug("resuming execution at PC=%08lx\n", regs->pc); |
93 | 93 | ||
94 | dc = __mfdr(DBGREG_DC); | 94 | dc = ocd_read(DC); |
95 | dc &= ~DC_SS; | 95 | dc &= ~(1 << OCD_DC_SS_BIT); |
96 | __mtdr(DBGREG_DC, dc); | 96 | ocd_write(DC, dc); |
97 | 97 | ||
98 | *p->addr = BREAKPOINT_INSTRUCTION; | 98 | *p->addr = BREAKPOINT_INSTRUCTION; |
99 | flush_icache_range((unsigned long)p->addr, | 99 | flush_icache_range((unsigned long)p->addr, |
@@ -261,7 +261,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
261 | int __init arch_init_kprobes(void) | 261 | int __init arch_init_kprobes(void) |
262 | { | 262 | { |
263 | printk("KPROBES: Enabling monitor mode (MM|DBE)...\n"); | 263 | printk("KPROBES: Enabling monitor mode (MM|DBE)...\n"); |
264 | __mtdr(DBGREG_DC, DC_MM | DC_DBE); | 264 | ocd_write(DC, (1 << OCD_DC_MM_BIT) | (1 << OCD_DC_DBE_BIT)); |
265 | 265 | ||
266 | /* TODO: Register kretprobe trampoline */ | 266 | /* TODO: Register kretprobe trampoline */ |
267 | return 0; | 267 | return 0; |
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 13f988402613..9d6dac8af7a2 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c | |||
@@ -55,8 +55,8 @@ void machine_power_off(void) | |||
55 | 55 | ||
56 | void machine_restart(char *cmd) | 56 | void machine_restart(char *cmd) |
57 | { | 57 | { |
58 | __mtdr(DBGREG_DC, DC_DBE); | 58 | ocd_write(DC, (1 << OCD_DC_DBE_BIT)); |
59 | __mtdr(DBGREG_DC, DC_RES); | 59 | ocd_write(DC, (1 << OCD_DC_RES_BIT)); |
60 | while (1) ; | 60 | while (1) ; |
61 | } | 61 | } |
62 | 62 | ||
@@ -287,10 +287,11 @@ void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl) | |||
287 | regs->sr & SR_N ? 'N' : 'n', | 287 | regs->sr & SR_N ? 'N' : 'n', |
288 | regs->sr & SR_Z ? 'Z' : 'z', | 288 | regs->sr & SR_Z ? 'Z' : 'z', |
289 | regs->sr & SR_C ? 'C' : 'c'); | 289 | regs->sr & SR_C ? 'C' : 'c'); |
290 | printk("%sMode bits: %c%c%c%c%c%c%c%c%c\n", log_lvl, | 290 | printk("%sMode bits: %c%c%c%c%c%c%c%c%c%c\n", log_lvl, |
291 | regs->sr & SR_H ? 'H' : 'h', | 291 | regs->sr & SR_H ? 'H' : 'h', |
292 | regs->sr & SR_R ? 'R' : 'r', | ||
293 | regs->sr & SR_J ? 'J' : 'j', | 292 | regs->sr & SR_J ? 'J' : 'j', |
293 | regs->sr & SR_DM ? 'M' : 'm', | ||
294 | regs->sr & SR_D ? 'D' : 'd', | ||
294 | regs->sr & SR_EM ? 'E' : 'e', | 295 | regs->sr & SR_EM ? 'E' : 'e', |
295 | regs->sr & SR_I3M ? '3' : '.', | 296 | regs->sr & SR_I3M ? '3' : '.', |
296 | regs->sr & SR_I2M ? '2' : '.', | 297 | regs->sr & SR_I2M ? '2' : '.', |
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index 9e16b8a447f2..002369e44093 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c | |||
@@ -30,20 +30,22 @@ static struct pt_regs *get_user_regs(struct task_struct *tsk) | |||
30 | 30 | ||
31 | static void ptrace_single_step(struct task_struct *tsk) | 31 | static void ptrace_single_step(struct task_struct *tsk) |
32 | { | 32 | { |
33 | pr_debug("ptrace_single_step: pid=%u, SR=0x%08lx\n", | 33 | pr_debug("ptrace_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n", |
34 | tsk->pid, tsk->thread.cpu_context.sr); | 34 | tsk->pid, task_pt_regs(tsk)->pc, task_pt_regs(tsk)->sr); |
35 | if (!(tsk->thread.cpu_context.sr & SR_D)) { | ||
36 | /* | ||
37 | * Set a breakpoint at the current pc to force the | ||
38 | * process into debug mode. The syscall/exception | ||
39 | * exit code will set a breakpoint at the return | ||
40 | * address when this flag is set. | ||
41 | */ | ||
42 | pr_debug("ptrace_single_step: Setting TIF_BREAKPOINT\n"); | ||
43 | set_tsk_thread_flag(tsk, TIF_BREAKPOINT); | ||
44 | } | ||
45 | 35 | ||
46 | /* The monitor code will do the actual step for us */ | 36 | /* |
37 | * We can't schedule in Debug mode, so when TIF_BREAKPOINT is | ||
38 | * set, the system call or exception handler will do a | ||
39 | * breakpoint to enter monitor mode before returning to | ||
40 | * userspace. | ||
41 | * | ||
42 | * The monitor code will then notice that TIF_SINGLE_STEP is | ||
43 | * set and return to userspace with single stepping enabled. | ||
44 | * The CPU will then enter monitor mode again after exactly | ||
45 | * one instruction has been executed, and the monitor code | ||
46 | * will then send a SIGTRAP to the process. | ||
47 | */ | ||
48 | set_tsk_thread_flag(tsk, TIF_BREAKPOINT); | ||
47 | set_tsk_thread_flag(tsk, TIF_SINGLE_STEP); | 49 | set_tsk_thread_flag(tsk, TIF_SINGLE_STEP); |
48 | } | 50 | } |
49 | 51 | ||
@@ -55,23 +57,7 @@ static void ptrace_single_step(struct task_struct *tsk) | |||
55 | void ptrace_disable(struct task_struct *child) | 57 | void ptrace_disable(struct task_struct *child) |
56 | { | 58 | { |
57 | clear_tsk_thread_flag(child, TIF_SINGLE_STEP); | 59 | clear_tsk_thread_flag(child, TIF_SINGLE_STEP); |
58 | } | 60 | clear_tsk_thread_flag(child, TIF_BREAKPOINT); |
59 | |||
60 | /* | ||
61 | * Handle hitting a breakpoint | ||
62 | */ | ||
63 | static void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) | ||
64 | { | ||
65 | siginfo_t info; | ||
66 | |||
67 | info.si_signo = SIGTRAP; | ||
68 | info.si_errno = 0; | ||
69 | info.si_code = TRAP_BRKPT; | ||
70 | info.si_addr = (void __user *)instruction_pointer(regs); | ||
71 | |||
72 | pr_debug("ptrace_break: Sending SIGTRAP to PID %u (pc = 0x%p)\n", | ||
73 | tsk->pid, info.si_addr); | ||
74 | force_sig_info(SIGTRAP, &info, tsk); | ||
75 | } | 61 | } |
76 | 62 | ||
77 | /* | 63 | /* |
@@ -84,9 +70,6 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long offset, | |||
84 | unsigned long *regs; | 70 | unsigned long *regs; |
85 | unsigned long value; | 71 | unsigned long value; |
86 | 72 | ||
87 | pr_debug("ptrace_read_user(%p, %#lx, %p)\n", | ||
88 | tsk, offset, data); | ||
89 | |||
90 | if (offset & 3 || offset >= sizeof(struct user)) { | 73 | if (offset & 3 || offset >= sizeof(struct user)) { |
91 | printk("ptrace_read_user: invalid offset 0x%08lx\n", offset); | 74 | printk("ptrace_read_user: invalid offset 0x%08lx\n", offset); |
92 | return -EIO; | 75 | return -EIO; |
@@ -98,6 +81,9 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long offset, | |||
98 | if (offset < sizeof(struct pt_regs)) | 81 | if (offset < sizeof(struct pt_regs)) |
99 | value = regs[offset / sizeof(regs[0])]; | 82 | value = regs[offset / sizeof(regs[0])]; |
100 | 83 | ||
84 | pr_debug("ptrace_read_user(%s[%u], %#lx, %p) -> %#lx\n", | ||
85 | tsk->comm, tsk->pid, offset, data, value); | ||
86 | |||
101 | return put_user(value, data); | 87 | return put_user(value, data); |
102 | } | 88 | } |
103 | 89 | ||
@@ -111,8 +97,11 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long offset, | |||
111 | { | 97 | { |
112 | unsigned long *regs; | 98 | unsigned long *regs; |
113 | 99 | ||
100 | pr_debug("ptrace_write_user(%s[%u], %#lx, %#lx)\n", | ||
101 | tsk->comm, tsk->pid, offset, value); | ||
102 | |||
114 | if (offset & 3 || offset >= sizeof(struct user)) { | 103 | if (offset & 3 || offset >= sizeof(struct user)) { |
115 | printk("ptrace_write_user: invalid offset 0x%08lx\n", offset); | 104 | pr_debug(" invalid offset 0x%08lx\n", offset); |
116 | return -EIO; | 105 | return -EIO; |
117 | } | 106 | } |
118 | 107 | ||
@@ -155,11 +144,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
155 | { | 144 | { |
156 | int ret; | 145 | int ret; |
157 | 146 | ||
158 | pr_debug("arch_ptrace(%ld, %d, %#lx, %#lx)\n", | ||
159 | request, child->pid, addr, data); | ||
160 | |||
161 | pr_debug("ptrace: Enabling monitor mode...\n"); | 147 | pr_debug("ptrace: Enabling monitor mode...\n"); |
162 | __mtdr(DBGREG_DC, __mfdr(DBGREG_DC) | DC_MM | DC_DBE); | 148 | ocd_write(DC, ocd_read(DC) | (1 << OCD_DC_MM_BIT) |
149 | | (1 << OCD_DC_DBE_BIT)); | ||
163 | 150 | ||
164 | switch (request) { | 151 | switch (request) { |
165 | /* Read the word at location addr in the child process */ | 152 | /* Read the word at location addr in the child process */ |
@@ -240,19 +227,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
240 | break; | 227 | break; |
241 | } | 228 | } |
242 | 229 | ||
243 | pr_debug("sys_ptrace returning %d (DC = 0x%08lx)\n", ret, __mfdr(DBGREG_DC)); | ||
244 | return ret; | 230 | return ret; |
245 | } | 231 | } |
246 | 232 | ||
247 | asmlinkage void syscall_trace(void) | 233 | asmlinkage void syscall_trace(void) |
248 | { | 234 | { |
249 | pr_debug("syscall_trace called\n"); | ||
250 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | 235 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) |
251 | return; | 236 | return; |
252 | if (!(current->ptrace & PT_PTRACED)) | 237 | if (!(current->ptrace & PT_PTRACED)) |
253 | return; | 238 | return; |
254 | 239 | ||
255 | pr_debug("syscall_trace: notifying parent\n"); | ||
256 | /* The 0x80 provides a way for the tracing parent to | 240 | /* The 0x80 provides a way for the tracing parent to |
257 | * distinguish between a syscall stop and SIGTRAP delivery */ | 241 | * distinguish between a syscall stop and SIGTRAP delivery */ |
258 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | 242 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) |
@@ -271,86 +255,143 @@ asmlinkage void syscall_trace(void) | |||
271 | } | 255 | } |
272 | } | 256 | } |
273 | 257 | ||
274 | asmlinkage void do_debug_priv(struct pt_regs *regs) | ||
275 | { | ||
276 | unsigned long dc, ds; | ||
277 | unsigned long die_val; | ||
278 | |||
279 | ds = __mfdr(DBGREG_DS); | ||
280 | |||
281 | pr_debug("do_debug_priv: pc = %08lx, ds = %08lx\n", regs->pc, ds); | ||
282 | |||
283 | if (ds & DS_SSS) | ||
284 | die_val = DIE_SSTEP; | ||
285 | else | ||
286 | die_val = DIE_BREAKPOINT; | ||
287 | |||
288 | if (notify_die(die_val, "ptrace", regs, 0, 0, SIGTRAP) == NOTIFY_STOP) | ||
289 | return; | ||
290 | |||
291 | if (likely(ds & DS_SSS)) { | ||
292 | extern void itlb_miss(void); | ||
293 | extern void tlb_miss_common(void); | ||
294 | struct thread_info *ti; | ||
295 | |||
296 | dc = __mfdr(DBGREG_DC); | ||
297 | dc &= ~DC_SS; | ||
298 | __mtdr(DBGREG_DC, dc); | ||
299 | |||
300 | ti = current_thread_info(); | ||
301 | set_ti_thread_flag(ti, TIF_BREAKPOINT); | ||
302 | |||
303 | /* The TLB miss handlers don't check thread flags */ | ||
304 | if ((regs->pc >= (unsigned long)&itlb_miss) | ||
305 | && (regs->pc <= (unsigned long)&tlb_miss_common)) { | ||
306 | __mtdr(DBGREG_BWA2A, sysreg_read(RAR_EX)); | ||
307 | __mtdr(DBGREG_BWC2A, 0x40000001 | (get_asid() << 1)); | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * If we're running in supervisor mode, the breakpoint | ||
312 | * will take us where we want directly, no need to | ||
313 | * single step. | ||
314 | */ | ||
315 | if ((regs->sr & MODE_MASK) != MODE_SUPERVISOR) | ||
316 | set_ti_thread_flag(ti, TIF_SINGLE_STEP); | ||
317 | } else { | ||
318 | panic("Unable to handle debug trap at pc = %08lx\n", | ||
319 | regs->pc); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | /* | 258 | /* |
324 | * Handle breakpoints, single steps and other debuggy things. To keep | 259 | * debug_trampoline() is an assembly stub which will store all user |
325 | * things simple initially, we run with interrupts and exceptions | 260 | * registers on the stack and execute a breakpoint instruction. |
326 | * disabled all the time. | 261 | * |
262 | * If we single-step into an exception handler which runs with | ||
263 | * interrupts disabled the whole time so it doesn't have to check for | ||
264 | * pending work, its return address will be modified so that it ends | ||
265 | * up returning to debug_trampoline. | ||
266 | * | ||
267 | * If the exception handler decides to store the user context and | ||
268 | * enable interrupts after all, it will restore the original return | ||
269 | * address and status register value. Before it returns, it will | ||
270 | * notice that TIF_BREAKPOINT is set and execute a breakpoint | ||
271 | * instruction. | ||
327 | */ | 272 | */ |
328 | asmlinkage void do_debug(struct pt_regs *regs) | 273 | extern void debug_trampoline(void); |
329 | { | ||
330 | unsigned long dc, ds; | ||
331 | 274 | ||
332 | ds = __mfdr(DBGREG_DS); | 275 | asmlinkage struct pt_regs *do_debug(struct pt_regs *regs) |
333 | pr_debug("do_debug: pc = %08lx, ds = %08lx\n", regs->pc, ds); | 276 | { |
277 | struct thread_info *ti; | ||
278 | unsigned long trampoline_addr; | ||
279 | u32 status; | ||
280 | u32 ctrl; | ||
281 | int code; | ||
282 | |||
283 | status = ocd_read(DS); | ||
284 | ti = current_thread_info(); | ||
285 | code = TRAP_BRKPT; | ||
286 | |||
287 | pr_debug("do_debug: status=0x%08x PC=0x%08lx SR=0x%08lx tif=0x%08lx\n", | ||
288 | status, regs->pc, regs->sr, ti->flags); | ||
289 | |||
290 | if (!user_mode(regs)) { | ||
291 | unsigned long die_val = DIE_BREAKPOINT; | ||
292 | |||
293 | if (status & (1 << OCD_DS_SSS_BIT)) | ||
294 | die_val = DIE_SSTEP; | ||
295 | |||
296 | if (notify_die(die_val, "ptrace", regs, 0, 0, SIGTRAP) | ||
297 | == NOTIFY_STOP) | ||
298 | return regs; | ||
299 | |||
300 | if ((status & (1 << OCD_DS_SWB_BIT)) | ||
301 | && test_and_clear_ti_thread_flag( | ||
302 | ti, TIF_BREAKPOINT)) { | ||
303 | /* | ||
304 | * Explicit breakpoint from trampoline or | ||
305 | * exception/syscall/interrupt handler. | ||
306 | * | ||
307 | * The real saved regs are on the stack right | ||
308 | * after the ones we saved on entry. | ||
309 | */ | ||
310 | regs++; | ||
311 | pr_debug(" -> TIF_BREAKPOINT done, adjusted regs:" | ||
312 | "PC=0x%08lx SR=0x%08lx\n", | ||
313 | regs->pc, regs->sr); | ||
314 | BUG_ON(!user_mode(regs)); | ||
315 | |||
316 | if (test_thread_flag(TIF_SINGLE_STEP)) { | ||
317 | pr_debug("Going to do single step...\n"); | ||
318 | return regs; | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * No TIF_SINGLE_STEP means we're done | ||
323 | * stepping over a syscall. Do the trap now. | ||
324 | */ | ||
325 | code = TRAP_TRACE; | ||
326 | } else if ((status & (1 << OCD_DS_SSS_BIT)) | ||
327 | && test_ti_thread_flag(ti, TIF_SINGLE_STEP)) { | ||
328 | |||
329 | pr_debug("Stepped into something, " | ||
330 | "setting TIF_BREAKPOINT...\n"); | ||
331 | set_ti_thread_flag(ti, TIF_BREAKPOINT); | ||
332 | |||
333 | /* | ||
334 | * We stepped into an exception, interrupt or | ||
335 | * syscall handler. Some exception handlers | ||
336 | * don't check for pending work, so we need to | ||
337 | * set up a trampoline just in case. | ||
338 | * | ||
339 | * The exception entry code will undo the | ||
340 | * trampoline stuff if it does a full context | ||
341 | * save (which also means that it'll check for | ||
342 | * pending work later.) | ||
343 | */ | ||
344 | if ((regs->sr & MODE_MASK) == MODE_EXCEPTION) { | ||
345 | trampoline_addr | ||
346 | = (unsigned long)&debug_trampoline; | ||
347 | |||
348 | pr_debug("Setting up trampoline...\n"); | ||
349 | ti->rar_saved = sysreg_read(RAR_EX); | ||
350 | ti->rsr_saved = sysreg_read(RSR_EX); | ||
351 | sysreg_write(RAR_EX, trampoline_addr); | ||
352 | sysreg_write(RSR_EX, (MODE_EXCEPTION | ||
353 | | SR_EM | SR_GM)); | ||
354 | BUG_ON(ti->rsr_saved & MODE_MASK); | ||
355 | } | ||
356 | |||
357 | /* | ||
358 | * If we stepped into a system call, we | ||
359 | * shouldn't do a single step after we return | ||
360 | * since the return address is right after the | ||
361 | * "scall" instruction we were told to step | ||
362 | * over. | ||
363 | */ | ||
364 | if ((regs->sr & MODE_MASK) == MODE_SUPERVISOR) { | ||
365 | pr_debug("Supervisor; no single step\n"); | ||
366 | clear_ti_thread_flag(ti, TIF_SINGLE_STEP); | ||
367 | } | ||
368 | |||
369 | ctrl = ocd_read(DC); | ||
370 | ctrl &= ~(1 << OCD_DC_SS_BIT); | ||
371 | ocd_write(DC, ctrl); | ||
372 | |||
373 | return regs; | ||
374 | } else { | ||
375 | printk(KERN_ERR "Unexpected OCD_DS value: 0x%08x\n", | ||
376 | status); | ||
377 | printk(KERN_ERR "Thread flags: 0x%08lx\n", ti->flags); | ||
378 | die("Unhandled debug trap in kernel mode", | ||
379 | regs, SIGTRAP); | ||
380 | } | ||
381 | } else if (status & (1 << OCD_DS_SSS_BIT)) { | ||
382 | /* Single step in user mode */ | ||
383 | code = TRAP_TRACE; | ||
334 | 384 | ||
335 | if (test_thread_flag(TIF_BREAKPOINT)) { | 385 | ctrl = ocd_read(DC); |
336 | pr_debug("TIF_BREAKPOINT set\n"); | 386 | ctrl &= ~(1 << OCD_DC_SS_BIT); |
337 | /* We're taking care of it */ | 387 | ocd_write(DC, ctrl); |
338 | clear_thread_flag(TIF_BREAKPOINT); | ||
339 | __mtdr(DBGREG_BWC2A, 0); | ||
340 | } | 388 | } |
341 | 389 | ||
342 | if (test_thread_flag(TIF_SINGLE_STEP)) { | 390 | pr_debug("Sending SIGTRAP: code=%d PC=0x%08lx SR=0x%08lx\n", |
343 | pr_debug("TIF_SINGLE_STEP set, ds = 0x%08lx\n", ds); | 391 | code, regs->pc, regs->sr); |
344 | if (ds & DS_SSS) { | ||
345 | dc = __mfdr(DBGREG_DC); | ||
346 | dc &= ~DC_SS; | ||
347 | __mtdr(DBGREG_DC, dc); | ||
348 | 392 | ||
349 | clear_thread_flag(TIF_SINGLE_STEP); | 393 | clear_thread_flag(TIF_SINGLE_STEP); |
350 | ptrace_break(current, regs); | 394 | _exception(SIGTRAP, regs, code, instruction_pointer(regs)); |
351 | } | 395 | |
352 | } else { | 396 | return regs; |
353 | /* regular breakpoint */ | ||
354 | ptrace_break(current, regs); | ||
355 | } | ||
356 | } | 397 | } |
diff --git a/arch/avr32/kernel/stacktrace.c b/arch/avr32/kernel/stacktrace.c new file mode 100644 index 000000000000..9a68190bbffd --- /dev/null +++ b/arch/avr32/kernel/stacktrace.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Stack trace management functions | ||
3 | * | ||
4 | * Copyright (C) 2007 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/stacktrace.h> | ||
12 | #include <linux/thread_info.h> | ||
13 | |||
14 | register unsigned long current_frame_pointer asm("r7"); | ||
15 | |||
16 | struct stackframe { | ||
17 | unsigned long lr; | ||
18 | unsigned long fp; | ||
19 | }; | ||
20 | |||
21 | /* | ||
22 | * Save stack-backtrace addresses into a stack_trace buffer. | ||
23 | */ | ||
24 | void save_stack_trace(struct stack_trace *trace) | ||
25 | { | ||
26 | unsigned long low, high; | ||
27 | unsigned long fp; | ||
28 | struct stackframe *frame; | ||
29 | int skip = trace->skip; | ||
30 | |||
31 | low = (unsigned long)task_stack_page(current); | ||
32 | high = low + THREAD_SIZE; | ||
33 | fp = current_frame_pointer; | ||
34 | |||
35 | while (fp >= low && fp <= (high - 8)) { | ||
36 | frame = (struct stackframe *)fp; | ||
37 | |||
38 | if (skip) { | ||
39 | skip--; | ||
40 | } else { | ||
41 | trace->entries[trace->nr_entries++] = frame->lr; | ||
42 | if (trace->nr_entries >= trace->max_entries) | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * The next frame must be at a higher address than the | ||
48 | * current frame. | ||
49 | */ | ||
50 | low = fp + 8; | ||
51 | fp = frame->fp; | ||
52 | } | ||
53 | } | ||
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index 8a7caf8e7b45..870c075e6314 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c | |||
@@ -39,7 +39,7 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) | |||
39 | printk("FRAME_POINTER "); | 39 | printk("FRAME_POINTER "); |
40 | #endif | 40 | #endif |
41 | if (current_cpu_data.features & AVR32_FEATURE_OCD) { | 41 | if (current_cpu_data.features & AVR32_FEATURE_OCD) { |
42 | unsigned long did = __mfdr(DBGREG_DID); | 42 | unsigned long did = ocd_read(DID); |
43 | printk("chip: 0x%03lx:0x%04lx rev %lu\n", | 43 | printk("chip: 0x%03lx:0x%04lx rev %lu\n", |
44 | (did >> 1) & 0x7ff, | 44 | (did >> 1) & 0x7ff, |
45 | (did >> 12) & 0x7fff, | 45 | (did >> 12) & 0x7fff, |
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S index ce9ac9659883..11f08e35a2eb 100644 --- a/arch/avr32/kernel/vmlinux.lds.S +++ b/arch/avr32/kernel/vmlinux.lds.S | |||
@@ -77,10 +77,10 @@ SECTIONS | |||
77 | . = 0x100; | 77 | . = 0x100; |
78 | *(.scall.text) | 78 | *(.scall.text) |
79 | *(.irq.text) | 79 | *(.irq.text) |
80 | KPROBES_TEXT | ||
80 | TEXT_TEXT | 81 | TEXT_TEXT |
81 | SCHED_TEXT | 82 | SCHED_TEXT |
82 | LOCK_TEXT | 83 | LOCK_TEXT |
83 | KPROBES_TEXT | ||
84 | *(.fixup) | 84 | *(.fixup) |
85 | *(.gnu.warning) | 85 | *(.gnu.warning) |
86 | _etext = .; | 86 | _etext = .; |
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c index c1233c615e67..15a4e5e142c1 100644 --- a/arch/avr32/mm/cache.c +++ b/arch/avr32/mm/cache.c | |||
@@ -122,16 +122,6 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page) | |||
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 | ||
125 | /* | ||
126 | * This one is used by copy_to_user_page() | ||
127 | */ | ||
128 | void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, | ||
129 | unsigned long addr, int len) | ||
130 | { | ||
131 | if (vma->vm_flags & VM_EXEC) | ||
132 | flush_icache_range(addr, addr + len); | ||
133 | } | ||
134 | |||
135 | asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) | 125 | asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) |
136 | { | 126 | { |
137 | int ret; | 127 | int ret; |
@@ -159,3 +149,13 @@ asmlinkage int sys_cacheflush(int operation, void __user *addr, size_t len) | |||
159 | out: | 149 | out: |
160 | return ret; | 150 | return ret; |
161 | } | 151 | } |
152 | |||
153 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | ||
154 | unsigned long vaddr, void *dst, const void *src, | ||
155 | unsigned long len) | ||
156 | { | ||
157 | memcpy(dst, src, len); | ||
158 | if (vma->vm_flags & VM_EXEC) | ||
159 | flush_icache_range((unsigned long)dst, | ||
160 | (unsigned long)dst + len); | ||
161 | } | ||