# Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Index: linux-2.6.15/arch/um/sys-i386/tls.c
===================================================================
--- linux-2.6.15.orig/arch/um/sys-i386/tls.c	2005-12-22 18:57:11.000000000 -0500
+++ linux-2.6.15/arch/um/sys-i386/tls.c	2005-12-22 18:58:24.000000000 -0500
@@ -4,6 +4,7 @@
  */
 
 #include "linux/config.h"
+#include "linux/kernel.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/types.h"
@@ -11,6 +12,7 @@
 #include "asm/ptrace.h"
 #include "asm/segment.h"
 #include "asm/smp.h"
+#include "asm/desc.h"
 #include "choose-mode.h"
 #include "kern.h"
 #include "kern_util.h"
@@ -111,12 +113,23 @@ int load_TLS(int flags, struct task_stru
 	for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
 		struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
 
+#if 0
 		/* This check is a bit bogus. We won't clear the GDT entry at
 		 * task switch, which means that access through this segment
 		 * descriptor may not get the expected faults.
 		 */
-		if (!curr->present)
-			continue;
+#endif
+		/* Actually, now if it wasn't flushed it gets cleared and
+		 * flushed to the host, which will clear it.*/
+		if (!curr->present) {
+			if (!curr->flushed) {
+				clear_user_desc(&curr->tls);
+				curr->tls.entry_number = idx;
+			} else {
+				WARN_ON(!LDT_empty(&curr->tls));
+				continue;
+			}
+		}
 
 		if (!(flags & O_FORCE) && curr->flushed)
 			continue;
@@ -143,8 +156,9 @@ int needs_TLS_update(int force_presents,
 	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
 		struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
 
-		if (!curr->present)
-			continue;
+		/* Wrong since we may need anyway to flush it.*/
+		/*if (!curr->present)
+			continue;*/
 
 		if (!(curr->flushed || force_presents))
 			continue;
@@ -164,8 +178,13 @@ void clear_flushed_tls(struct task_struc
 	for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
 		struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
 
+		/* Still correct to do this, if it wasn't present on the host it
+		 * will remain as flushed as it was. But let's put it out for
+		 * now. */
+#if 0 /*OPTIM to reintroduce*/
 		if (!curr->present)
 			continue;
+#endif
 
 		curr->flushed = 0;
 	}
@@ -261,13 +280,8 @@ clear:
 	 * tls_array are 0 (because it's cleared at boot, see
 	 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
 	 */
-	memset(info, 0, sizeof(*info));
+	clear_user_desc(info);
 	info->entry_number = idx;
-	/* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
-	 * indeed an empty user_desc.
-	 */
-	info->read_exec_only = 1;
-	info->seg_not_present = 1;
 	goto out;
 }
 
