提交 07500b0d 编写于 作者: R Ralf Baechle

[MIPS] Fix context DSP context / TLS pointer switching bug for new threads.

A new born thread starts execution not in schedule but rather in
ret_from_fork which results in it bypassing the part of the code to
load a new context written in C which are the DSP context and the
userlocal register which Linux uses for the TLS pointer.  Frequently
we were just getting away with this bug for a number of reasons:

 o Real world application scenarios are very unlikely to use clone or fork
   in blocks of DSP code.
 o Linux by default runs the child process right after the fork, so the
   child by luck will find all the right context in the DSP and userlocal
   registers.
 o So far the rdhwr instruction was emulated on all hardware so userlocal
   wasn't getting referenced at all and the emulation wasn't suffering
   from the issue since it gets it's value straight from the thread's
   thread_info.

Fixed by moving the code to load the context from switch_to() to
finish_arch_switch which will be called by newborn and old threads.
Signed-off-by: NRalf Baechle <ralf@linux-mips.org>
上级 98ce4721
...@@ -68,11 +68,15 @@ do { \ ...@@ -68,11 +68,15 @@ do { \
if (cpu_has_dsp) \ if (cpu_has_dsp) \
__save_dsp(prev); \ __save_dsp(prev); \
(last) = resume(prev, next, task_thread_info(next)); \ (last) = resume(prev, next, task_thread_info(next)); \
} while (0)
#define finish_arch_switch(prev) \
do { \
if (cpu_has_dsp) \ if (cpu_has_dsp) \
__restore_dsp(current); \ __restore_dsp(current); \
if (cpu_has_userlocal) \ if (cpu_has_userlocal) \
write_c0_userlocal(task_thread_info(current)->tp_value);\ write_c0_userlocal(current_thread_info()->tp_value); \
} while(0) } while (0)
static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册