aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/kernel/entry-avr32b.S
diff options
context:
space:
mode:
authorPhilippe Rétornaz <philippe.retornaz@epfl.ch>2007-10-10 18:52:24 -0400
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2007-10-11 07:32:56 -0400
commita7e30b8d91d3291de4543d97849193ebc3ec4c1c (patch)
treeecf3548140022204214b20f6f69dfc67a6e026b9 /arch/avr32/kernel/entry-avr32b.S
parentbb7aa6d47fcd4f9ab18b4ade2ba078f7719f74ca (diff)
[AVR32] Fix random segfault with preemption
As explained on: http://www.avrfreaks.net/index.php?nameÿphpBB2&fileÿewtopic&tS307 If the current process is preempted before it can copy RAR_SUP and RSR_SUP both register are lost and the process will segfault as soon as it return from the syscall since the return adress will be corrupted. This patch disable IRQ as soon as we enter the syscall path and reenable them when the copy is done. In the interrupt handlers, check if we are interrupting the srrf instruction, if so disable interrupts and return. The interrupt handler will be re-called immediatly when the interrupts are reenabled. After some stressing workload: - find / > /dev/null in loop - top (in ssh) - ping -f avr32 The segfaults are not seen anymore. Signed-off-by: Philippe Rétornaz <philippe.retornaz@epfl.ch> Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32/kernel/entry-avr32b.S')
-rw-r--r--arch/avr32/kernel/entry-avr32b.S26
1 files changed, 25 insertions, 1 deletions
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 42657f1703b2..ccadfd9b438d 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -159,11 +159,18 @@ handle_vmalloc_miss:
159 159
160 .section .scall.text,"ax",@progbits 160 .section .scall.text,"ax",@progbits
161system_call: 161system_call:
162#ifdef CONFIG_PREEMPT
163 mask_interrupts
164#endif
162 pushm r12 /* r12_orig */ 165 pushm r12 /* r12_orig */
163 stmts --sp, r0-lr 166 stmts --sp, r0-lr
164 zero_fp 167
165 mfsr r0, SYSREG_RAR_SUP 168 mfsr r0, SYSREG_RAR_SUP
166 mfsr r1, SYSREG_RSR_SUP 169 mfsr r1, SYSREG_RSR_SUP
170#ifdef CONFIG_PREEMPT
171 unmask_interrupts
172#endif
173 zero_fp
167 stm --sp, r0-r1 174 stm --sp, r0-r1
168 175
169 /* check for syscall tracing */ 176 /* check for syscall tracing */
@@ -638,6 +645,13 @@ irq_level\level:
638 stmts --sp,r0-lr 645 stmts --sp,r0-lr
639 mfsr r8, rar_int\level 646 mfsr r8, rar_int\level
640 mfsr r9, rsr_int\level 647 mfsr r9, rsr_int\level
648
649#ifdef CONFIG_PREEMPT
650 sub r11, pc, (. - system_call)
651 cp.w r11, r8
652 breq 4f
653#endif
654
641 pushm r8-r9 655 pushm r8-r9
642 656
643 mov r11, sp 657 mov r11, sp
@@ -668,6 +682,16 @@ irq_level\level:
668 sub sp, -4 /* ignore r12_orig */ 682 sub sp, -4 /* ignore r12_orig */
669 rete 683 rete
670 684
685#ifdef CONFIG_PREEMPT
6864: mask_interrupts
687 mfsr r8, rsr_int\level
688 sbr r8, 16
689 mtsr rsr_int\level, r8
690 ldmts sp++, r0-lr
691 sub sp, -4 /* ignore r12_orig */
692 rete
693#endif
694
6712: get_thread_info r0 6952: get_thread_info r0
672 ld.w r1, r0[TI_flags] 696 ld.w r1, r0[TI_flags]
673 bld r1, TIF_CPU_GOING_TO_SLEEP 697 bld r1, TIF_CPU_GOING_TO_SLEEP