Преглед на файлове

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.
Linus Torvalds преди 20 години
родител
ревизия
b339a18b81
променени са 1 файла, в които са добавени 12 реда и са изтрити 8 реда
  1. 12 8
      arch/i386/kernel/process.c

+ 12 - 8
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))