Fix up incorrect "unlikely()" on %gs reload in x86 __switch_to
These days %gs is normally the TLS segment, so it's no longer zero. As a result, we shouldn't just assume that %fs/%gs tend to be zero together, but test them independently instead. Also, fix setting of debug registers to use the "next" pointer instead of "current". It so happens that the scheduler will have set the new current pointer before calling __switch_to(), but that's just an implementation detail.
This commit is contained in:
parent
f60f700876
commit
b339a18b81
|
@ -700,23 +700,27 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
|
|||
|
||||
/*
|
||||
* Restore %fs and %gs if needed.
|
||||
*
|
||||
* Glibc normally makes %fs be zero, and %gs is one of
|
||||
* the TLS segments.
|
||||
*/
|
||||
if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) {
|
||||
if (unlikely(prev->fs | next->fs))
|
||||
loadsegment(fs, next->fs);
|
||||
|
||||
if (prev->gs | next->gs)
|
||||
loadsegment(gs, next->gs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now maybe reload the debug registers
|
||||
*/
|
||||
if (unlikely(next->debugreg[7])) {
|
||||
set_debugreg(current->thread.debugreg[0], 0);
|
||||
set_debugreg(current->thread.debugreg[1], 1);
|
||||
set_debugreg(current->thread.debugreg[2], 2);
|
||||
set_debugreg(current->thread.debugreg[3], 3);
|
||||
set_debugreg(next->debugreg[0], 0);
|
||||
set_debugreg(next->debugreg[1], 1);
|
||||
set_debugreg(next->debugreg[2], 2);
|
||||
set_debugreg(next->debugreg[3], 3);
|
||||
/* no 4 and 5 */
|
||||
set_debugreg(current->thread.debugreg[6], 6);
|
||||
set_debugreg(current->thread.debugreg[7], 7);
|
||||
set_debugreg(next->debugreg[6], 6);
|
||||
set_debugreg(next->debugreg[7], 7);
|
||||
}
|
||||
|
||||
if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
|
||||
|
|
Loading…
Reference in New Issue