s390: fix race on TIF_MCCK_PENDING
There is a small race window in the __switch_to code in regard to the transfer of the TIF_MCCK_PENDING bit from the previous to the next task. The bit is transferred before the task struct pointer and the thread-info pointer for the next task has been stored to lowcore. If a machine check sets the TIF_MCCK_PENDING bit between the transfer code and the store of current/thread_info the bit is still set for the previous task. And if the previous task has terminated it can get lost. The effect is that a pending CRW is not retrieved until the next machine checks sets TIF_MCCK_PENDING. To fix this reorder __switch_to to first store the task struct and thread-info pointer and then do the transfer of the bit. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
e5b8d7553f
commit
eda0c6d6b0
2 changed files with 22 additions and 20 deletions
|
@ -145,22 +145,23 @@ STACK_SIZE = 1 << STACK_SHIFT
|
|||
* gpr2 = prev
|
||||
*/
|
||||
ENTRY(__switch_to)
|
||||
stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
|
||||
st %r15,__THREAD_ksp(%r2) # store kernel stack of prev
|
||||
l %r4,__THREAD_info(%r2) # get thread_info of prev
|
||||
l %r5,__THREAD_info(%r3) # get thread_info of next
|
||||
lr %r15,%r5
|
||||
ahi %r15,STACK_SIZE # end of kernel stack of next
|
||||
st %r3,__LC_CURRENT # store task struct of next
|
||||
st %r5,__LC_THREAD_INFO # store thread info of next
|
||||
st %r15,__LC_KERNEL_STACK # store end of kernel stack
|
||||
lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
|
||||
mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
|
||||
l %r15,__THREAD_ksp(%r3) # load kernel stack of next
|
||||
tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
|
||||
jz 0f
|
||||
ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
|
||||
oi __TI_flags+3(%r5),_TIF_MCCK_PENDING # set it in next
|
||||
0: stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
|
||||
st %r15,__THREAD_ksp(%r2) # store kernel stack of prev
|
||||
l %r15,__THREAD_ksp(%r3) # load kernel stack of next
|
||||
lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
|
||||
lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
|
||||
st %r3,__LC_CURRENT # store task struct of next
|
||||
mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
|
||||
st %r5,__LC_THREAD_INFO # store thread info of next
|
||||
ahi %r5,STACK_SIZE # end of kernel stack of next
|
||||
st %r5,__LC_KERNEL_STACK # store end of kernel stack
|
||||
0: lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
|
||||
br %r14
|
||||
|
||||
__critical_start:
|
||||
|
|
|
@ -164,22 +164,23 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
|
|||
* gpr2 = prev
|
||||
*/
|
||||
ENTRY(__switch_to)
|
||||
stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
|
||||
stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev
|
||||
lg %r4,__THREAD_info(%r2) # get thread_info of prev
|
||||
lg %r5,__THREAD_info(%r3) # get thread_info of next
|
||||
lgr %r15,%r5
|
||||
aghi %r15,STACK_SIZE # end of kernel stack of next
|
||||
stg %r3,__LC_CURRENT # store task struct of next
|
||||
stg %r5,__LC_THREAD_INFO # store thread info of next
|
||||
stg %r15,__LC_KERNEL_STACK # store end of kernel stack
|
||||
lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
|
||||
mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
|
||||
lg %r15,__THREAD_ksp(%r3) # load kernel stack of next
|
||||
tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
|
||||
jz 0f
|
||||
ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
|
||||
oi __TI_flags+7(%r5),_TIF_MCCK_PENDING # set it in next
|
||||
0: stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
|
||||
stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev
|
||||
lg %r15,__THREAD_ksp(%r3) # load kernel stack of next
|
||||
lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
|
||||
lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
|
||||
stg %r3,__LC_CURRENT # store task struct of next
|
||||
mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
|
||||
stg %r5,__LC_THREAD_INFO # store thread info of next
|
||||
aghi %r5,STACK_SIZE # end of kernel stack of next
|
||||
stg %r5,__LC_KERNEL_STACK # store end of kernel stack
|
||||
0: lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
|
||||
br %r14
|
||||
|
||||
__critical_start:
|
||||
|
|
Loading…
Reference in a new issue