Skip to content

Commit 8cf2389

Browse files
shesselbaRussell King
authored andcommitted
ARM: 8100/1: Fix preemption disable in iwmmxt_task_enable()
commit 431a84b ("ARM: 8034/1: Disable preemption in iwmmxt_task_enable()") introduced macros {inc,dec}_preempt_count to iwmmxt_task_enable to make it run with preemption disabled. Unfortunately, other functions in iwmmxt.S also use concan_{save,dump,load} sections located in iwmmxt_task_enable() to deal with iWMMXt coprocessor. This causes an unbalanced preempt_count due to excessive dec_preempt_count and destroyed return addresses in callers of concan_ labels due to a register collision: Linux version 3.16.0-rc3-00062-gd92a333-dirty (jef@armhf) (gcc version 4.8.3 (Debian 4.8.3-4) ) #5 PREEMPT Thu Jul 3 19:46:39 CEST 2014 CPU: ARMv7 Processor [560f5815] revision 5 (ARMv7), cr=10c5387d CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache Machine model: SolidRun CuBox ... PJ4 iWMMXt v2 coprocessor enabled. ... Unable to handle kernel paging request at virtual address fffffffe pgd = bb25c000 [fffffffe] *pgd=3bfde821, *pte=00000000, *ppte=00000000 Internal error: Oops: 80000007 [#1] PREEMPT ARM Modules linked in: CPU: 0 PID: 62 Comm: startpar Not tainted 3.16.0-rc3-00062-gd92a333-dirty #5 task: bb230b8 ti: bb256000 task.ti: bb256000 PC is at 0xfffffffe LR is at iwmmxt_task_copy+0x44/0x4c pc : [<fffffffe>] lr : [<800130ac>] psr: 40000033 sp : bb257de8 ip : 00000013 fp : bb257ea4 r10: bb256000 r9 : fffffdfe r8 : 76e898e6 r7 : bb257ec8 r6 : bb256000 r5 : 7ea12760 r4 : 000000a0 r3 : ffffffff r2 : 00000003 r1 : bb257df8 r0 : 00000000 Flags: nZcv IRQs on FIQs on Mode SVC_32 ISA Thumb Segment user Control: 10c5387d Table: 3b25c019 DAC: 00000015 Process startpar (pid: 62, stack limit = 0xbb256248) This patch fixes the issue by moving concan_{save,dump,load} into separate code sections and make iwmmxt_task_enable() call them in the same way the other functions use concan_ symbols. The test for valid ownership is moved to concan_save and is safe for the other user of it, iwmmxt_task_disable(). The register collision is also resolved by moving concan_ symbols as {inc,dec}_preempt_count are now local to iwmmxt_task_enable(). Fixes: 431a84b ("ARM: 8034/1: Disable preemption in iwmmxt_task_enable()") Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Reported-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
1 parent 6b07699 commit 8cf2389

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

arch/arm/kernel/iwmmxt.S

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,19 @@ ENTRY(iwmmxt_task_enable)
9494

9595
mrc p15, 0, r2, c2, c0, 0
9696
mov r2, r2 @ cpwait
97+
bl concan_save
9798

98-
teq r1, #0 @ test for last ownership
99-
mov lr, r9 @ normal exit from exception
100-
beq concan_load @ no owner, skip save
99+
#ifdef CONFIG_PREEMPT_COUNT
100+
get_thread_info r10
101+
#endif
102+
4: dec_preempt_count r10, r3
103+
mov pc, r9 @ normal exit from exception
101104

102105
concan_save:
103106

107+
teq r1, #0 @ test for last ownership
108+
beq concan_load @ no owner, skip save
109+
104110
tmrc r2, wCon
105111

106112
@ CUP? wCx
@@ -138,7 +144,7 @@ concan_dump:
138144
wstrd wR15, [r1, #MMX_WR15]
139145

140146
2: teq r0, #0 @ anything to load?
141-
beq 3f
147+
moveq pc, lr @ if not, return
142148

143149
concan_load:
144150

@@ -171,14 +177,9 @@ concan_load:
171177
@ clear CUP/MUP (only if r1 != 0)
172178
teq r1, #0
173179
mov r2, #0
174-
beq 3f
175-
tmcr wCon, r2
180+
moveq pc, lr
176181

177-
3:
178-
#ifdef CONFIG_PREEMPT_COUNT
179-
get_thread_info r10
180-
#endif
181-
4: dec_preempt_count r10, r3
182+
tmcr wCon, r2
182183
mov pc, lr
183184

184185
/*

0 commit comments

Comments
 (0)