• Sebastian Hesselbarth's avatar
    ARM: 8100/1: Fix preemption disable in iwmmxt_task_enable() · 8cf2389b
    Sebastian Hesselbarth authored
    commit 431a84b1
     ("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-gd92a333a-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-gd92a333a-dirty #5
    task: bb230b80 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: 431a84b1 ("ARM: 8034/1: Disable preemption in iwmmxt_task_enable()")
    Signed-off-by: default avatarSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
    Acked-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Reported-by: default avatarJean-Francois Moine <moinejf@free.fr>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    8cf2389b
iwmmxt.S 8.33 KB