Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Call restore_sprs() before _switch()

commit 152d523e6307 ("powerpc: Create context switch helpers save_sprs()
and restore_sprs()") moved the restore of SPRs after the call to _switch().

There is an issue with this approach - new tasks do not return through
_switch(), they are set up by copy_thread() to directly return through
ret_from_fork() or ret_from_kernel_thread(). This means restore_sprs() is
not getting called for new tasks.

Fix this by moving restore_sprs() before _switch().

Fixes: 152d523e6307 ("powerpc: Create context switch helpers save_sprs() and restore_sprs()")
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Anton Blanchard and committed by
Michael Ellerman
20dbe670 d64d02ce

+9 -6
+9 -6
arch/powerpc/kernel/process.c
··· 971 971 972 972 tm_recheckpoint_new_task(new); 973 973 974 - last = _switch(old_thread, new_thread); 975 - 976 - /* Need to recalculate these after calling _switch() */ 977 - old_thread = &last->thread; 978 - new_thread = &current->thread; 979 - 974 + /* 975 + * Call restore_sprs() before calling _switch(). If we move it after 976 + * _switch() then we miss out on calling it for new tasks. The reason 977 + * for this is we manually create a stack frame for new tasks that 978 + * directly returns through ret_from_fork() or 979 + * ret_from_kernel_thread(). See copy_thread() for details. 980 + */ 980 981 restore_sprs(old_thread, new_thread); 982 + 983 + last = _switch(old_thread, new_thread); 981 984 982 985 #ifdef CONFIG_PPC_BOOK3S_64 983 986 if (current_thread_info()->local_flags & _TLF_LAZY_MMU) {