Index: linux-2.6.16/arch/um/include/os.h
===================================================================
--- linux-2.6.16.orig/arch/um/include/os.h	2006-03-23 20:32:46.000000000 -0500
+++ linux-2.6.16/arch/um/include/os.h	2006-03-23 20:33:19.000000000 -0500
@@ -173,6 +173,7 @@ extern int os_fchange_dir(int fd);
 extern void os_early_checks(void);
 extern int can_do_skas(void);
 extern void os_check_bugs(void);
+extern int check_host_supports_tls(void);
 
 /* Make sure they are clear when running in TT mode. Required by
  * SEGV_MAYBE_FIXABLE */
Index: linux-2.6.16/arch/um/os-Linux/start_up.c
===================================================================
--- linux-2.6.16.orig/arch/um/os-Linux/start_up.c	2006-03-23 18:55:38.000000000 -0500
+++ linux-2.6.16/arch/um/os-Linux/start_up.c	2006-03-23 20:33:03.000000000 -0500
@@ -21,6 +21,7 @@
 #include <asm/unistd.h>
 #include <asm/page.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
@@ -647,3 +648,30 @@ void os_check_bugs(void)
 	check_sigio();
 }
 
+/* Returns true if host is supposed to support TLS, i.e. its 2.6 or upper */
+int check_host_supports_tls() {
+	struct utsname host;
+	int major, minor;
+
+	if (uname(&host) < 0) {
+		perror("uname");
+		return 0;
+	}
+
+	if (strlen(host.release) < 3)
+		goto out_invalid;
+	if (host.release[1] != '.')
+		goto out_invalid;
+
+	major = host.release[0];
+	minor = host.release[2];
+
+	return (major > 2) || (major == 2 && minor >= 6);
+
+out_invalid:
+	/* Why ever we are here? We can't say anything, suppose it could work. */
+	printk(UM_KERN_ERR "  TLS support detection: couldn't parse host release number from uname\n");
+	printk(UM_KERN_ERR "  TLS support detection: assuming TLS are supported and we are stupid\n");
+	printk(UM_KERN_ERR "  TLS support detection: please send a bug report to uml-devel mailing list\n");
+	return 1;
+}
Index: linux-2.6.16/arch/um/os-Linux/tls.c
===================================================================
--- linux-2.6.16.orig/arch/um/os-Linux/tls.c	2006-03-23 20:32:50.000000000 -0500
+++ linux-2.6.16/arch/um/os-Linux/tls.c	2006-03-23 20:33:03.000000000 -0500
@@ -73,4 +73,4 @@ int do_get_thread_area_tt(user_desc_t *i
 	return ret;
 }
 
-#endif
+#endif /* UML_CONFIG_MODE_TT */
Index: linux-2.6.16/arch/um/sys-i386/tls.c
===================================================================
--- linux-2.6.16.orig/arch/um/sys-i386/tls.c	2006-03-23 20:32:51.000000000 -0500
+++ linux-2.6.16/arch/um/sys-i386/tls.c	2006-03-23 20:33:03.000000000 -0500
@@ -24,6 +24,9 @@
 #include "skas.h"
 #endif
 
+/* If needed we can detect when it's uninitialized. */
+static int host_supports_tls = -1;
+
 #ifdef CONFIG_MODE_SKAS
 int do_set_thread_area_skas(struct user_desc *info)
 {
@@ -157,9 +160,15 @@ void clear_flushed_tls(struct task_struc
 	}
 }
 
-/* This in SKAS0 does not need to be used, since we have different host
- * processes. Nor will this need to be used when we'll add support to the host
+/* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a
+ * common host process. So this is needed in SKAS0 too.
+ *
+ * However, if each thread had a different host process (and this was discussed
+ * for SMP support) this won't be needed.
+ *
+ * And this will not need be used when (and if) we'll add support to the host
  * SKAS patch. */
+
 int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to)
 {
 	return load_TLS(O_FORCE, to);
@@ -250,6 +259,9 @@ asmlinkage int sys_set_thread_area(struc
 	struct user_desc info;
 	int idx, ret;
 
+	if (!host_supports_tls)
+		return -ENOSYS;
+
 	if (copy_from_user(&info, user_desc, sizeof(info)))
 		return -EFAULT;
 
@@ -281,6 +293,9 @@ int ptrace_set_thread_area(struct task_s
 {
 	struct user_desc info;
 
+	if (!host_supports_tls)
+		return -EIO;
+
 	if (copy_from_user(&info, user_desc, sizeof(info)))
 		return -EFAULT;
 
@@ -292,6 +307,9 @@ asmlinkage int sys_get_thread_area(struc
 	struct user_desc info;
 	int idx, ret;
 
+	if (!host_supports_tls)
+		return -ENOSYS;
+
 	if (get_user(idx, &user_desc->entry_number))
 		return -EFAULT;
 
@@ -315,6 +333,9 @@ int ptrace_get_thread_area(struct task_s
 	struct user_desc info;
 	int ret;
 
+	if (!host_supports_tls)
+		return -EIO;
+
 	ret = get_tls_entry(child, &info, idx);
 	if (ret < 0)
 		goto out;
@@ -327,8 +348,27 @@ out:
 
 void debug_arch_force_load_TLS(void)
 {
-	int err = load_TLS(O_FORCE, current);
+	int err;
+	if (!host_supports_tls)
+		return;
+
+	err = load_TLS(O_FORCE, current);
 	if (err && (err != -EINVAL))
 		printk("load_TLS(O_FORCE) in fork_handler failed, "
 			"errno %d, not EINVAL\n", -err);
 }
+
+/* XXX: This part is probably common to i386 and x86-64. Don't create a common
+ * file for now, do that when implementing x86-64 support.*/
+
+static int __init __setup_host_supports_tls(void) {
+	host_supports_tls = check_host_supports_tls();
+	if (host_supports_tls)
+		printk(KERN_INFO "Host TLS support detected\n");
+	else
+		printk(KERN_ERR "  Host TLS support NOT detected! "
+				"TLS support inside UML will not work\n");
+	return 1;
+}
+
+__initcall(__setup_host_supports_tls);
