[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>
This commit is contained in:
parent
bb7aa6d47f
commit
a7e30b8d91
|
@ -159,11 +159,18 @@ handle_vmalloc_miss:
|
||||||
|
|
||||||
.section .scall.text,"ax",@progbits
|
.section .scall.text,"ax",@progbits
|
||||||
system_call:
|
system_call:
|
||||||
|
#ifdef CONFIG_PREEMPT
|
||||||
|
mask_interrupts
|
||||||
|
#endif
|
||||||
pushm r12 /* r12_orig */
|
pushm r12 /* r12_orig */
|
||||||
stmts --sp, r0-lr
|
stmts --sp, r0-lr
|
||||||
zero_fp
|
|
||||||
mfsr r0, SYSREG_RAR_SUP
|
mfsr r0, SYSREG_RAR_SUP
|
||||||
mfsr r1, SYSREG_RSR_SUP
|
mfsr r1, SYSREG_RSR_SUP
|
||||||
|
#ifdef CONFIG_PREEMPT
|
||||||
|
unmask_interrupts
|
||||||
|
#endif
|
||||||
|
zero_fp
|
||||||
stm --sp, r0-r1
|
stm --sp, r0-r1
|
||||||
|
|
||||||
/* check for syscall tracing */
|
/* check for syscall tracing */
|
||||||
|
@ -638,6 +645,13 @@ irq_level\level:
|
||||||
stmts --sp,r0-lr
|
stmts --sp,r0-lr
|
||||||
mfsr r8, rar_int\level
|
mfsr r8, rar_int\level
|
||||||
mfsr r9, rsr_int\level
|
mfsr r9, rsr_int\level
|
||||||
|
|
||||||
|
#ifdef CONFIG_PREEMPT
|
||||||
|
sub r11, pc, (. - system_call)
|
||||||
|
cp.w r11, r8
|
||||||
|
breq 4f
|
||||||
|
#endif
|
||||||
|
|
||||||
pushm r8-r9
|
pushm r8-r9
|
||||||
|
|
||||||
mov r11, sp
|
mov r11, sp
|
||||||
|
@ -668,6 +682,16 @@ irq_level\level:
|
||||||
sub sp, -4 /* ignore r12_orig */
|
sub sp, -4 /* ignore r12_orig */
|
||||||
rete
|
rete
|
||||||
|
|
||||||
|
#ifdef CONFIG_PREEMPT
|
||||||
|
4: mask_interrupts
|
||||||
|
mfsr r8, rsr_int\level
|
||||||
|
sbr r8, 16
|
||||||
|
mtsr rsr_int\level, r8
|
||||||
|
ldmts sp++, r0-lr
|
||||||
|
sub sp, -4 /* ignore r12_orig */
|
||||||
|
rete
|
||||||
|
#endif
|
||||||
|
|
||||||
2: get_thread_info r0
|
2: get_thread_info r0
|
||||||
ld.w r1, r0[TI_flags]
|
ld.w r1, r0[TI_flags]
|
||||||
bld r1, TIF_CPU_GOING_TO_SLEEP
|
bld r1, TIF_CPU_GOING_TO_SLEEP
|
||||||
|
|
Loading…
Reference in a new issue