summaryrefslogtreecommitdiff
path: root/arch/i386/kernel/process.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@evo.osdl.org>2005-07-22 19:23:47 (GMT)
committerLinus Torvalds <torvalds@evo.osdl.org>2005-07-22 19:23:47 (GMT)
commitb339a18b81a1f6ca1455559594f5df872b9e59f4 (patch)
tree1c3a34047734e5923484353dbe710b167ad7c72b /arch/i386/kernel/process.c
parentf60f700876cd51de9de69f3a3c865d95e287a24d (diff)
downloadlinux-fsl-qoriq-b339a18b81a1f6ca1455559594f5df872b9e59f4.tar.xz
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.
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r--arch/i386/kernel/process.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index ba243a4..d949205 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -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))