Skip to content

Commit

Permalink
Fix up incorrect "unlikely()" on %gs reload in x86 __switch_to
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Linus Torvalds committed Jul 22, 2005
1 parent f60f700 commit b339a18
Showing 1 changed file with 12 additions and 8 deletions.
20 changes: 12 additions & 8 deletions arch/i386/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit b339a18

Please sign in to comment.