Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7e30b8d authored by Philippe Rétornaz's avatar Philippe Rétornaz Committed by Haavard Skinnemoen
Browse files

[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: default avatarPhilippe Rétornaz <philippe.retornaz@epfl.ch>
Signed-off-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
parent bb7aa6d4
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -159,11 +159,18 @@ handle_vmalloc_miss:

	.section .scall.text,"ax",@progbits
system_call:
#ifdef CONFIG_PREEMPT
	mask_interrupts
#endif
	pushm	r12		/* r12_orig */
	stmts	--sp, r0-lr
	zero_fp

	mfsr	r0, SYSREG_RAR_SUP
	mfsr	r1, SYSREG_RSR_SUP
#ifdef CONFIG_PREEMPT
	unmask_interrupts
#endif
	zero_fp
	stm	--sp, r0-r1

	/* check for syscall tracing */
@@ -638,6 +645,13 @@ irq_level\level:
	stmts	--sp,r0-lr
	mfsr	r8, rar_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

	mov	r11, sp
@@ -668,6 +682,16 @@ irq_level\level:
	sub	sp, -4		/* ignore r12_orig */
	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
	ld.w	r1, r0[TI_flags]
	bld	r1, TIF_CPU_GOING_TO_SLEEP