diff options
author | Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> | 2006-03-31 05:30:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-31 15:18:52 -0500 |
commit | 3feb88562d149f078319e5a1b2f7acaa10251a5c (patch) | |
tree | 73fb00f0ecb9ed0c4cf8eec24c84253ce9620464 /arch/um/sys-i386 | |
parent | 54d8d3b5a0ce1cdbad1d3154c9ea9732d394e9c7 (diff) |
[PATCH] uml: check for differences in host support
If running on a host not supporting TLS (for instance 2.4) we should report
that cleanly to the user, instead of printing not comprehensible "error 5" for
that.
Additionally, i386 and x86_64 support different ranges for
user_desc->entry_number, and we must account for that; we couldn't pass
ourselves -1 because we need to override previously existing TLS descriptors
which glibc has possibly set, so test at startup the range to use.
x86 and x86_64 existing ranges are hardcoded.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Acked-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/sys-i386')
-rw-r--r-- | arch/um/sys-i386/tls.c | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c index 2251654c6b45..a3188e861cc7 100644 --- a/arch/um/sys-i386/tls.c +++ b/arch/um/sys-i386/tls.c | |||
@@ -24,6 +24,10 @@ | |||
24 | #include "skas.h" | 24 | #include "skas.h" |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | /* If needed we can detect when it's uninitialized. */ | ||
28 | static int host_supports_tls = -1; | ||
29 | int host_gdt_entry_tls_min = -1; | ||
30 | |||
27 | #ifdef CONFIG_MODE_SKAS | 31 | #ifdef CONFIG_MODE_SKAS |
28 | int do_set_thread_area_skas(struct user_desc *info) | 32 | int do_set_thread_area_skas(struct user_desc *info) |
29 | { | 33 | { |
@@ -157,11 +161,20 @@ void clear_flushed_tls(struct task_struct *task) | |||
157 | } | 161 | } |
158 | } | 162 | } |
159 | 163 | ||
160 | /* This in SKAS0 does not need to be used, since we have different host | 164 | /* In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a |
161 | * processes. Nor will this need to be used when we'll add support to the host | 165 | * common host process. So this is needed in SKAS0 too. |
166 | * | ||
167 | * However, if each thread had a different host process (and this was discussed | ||
168 | * for SMP support) this won't be needed. | ||
169 | * | ||
170 | * And this will not need be used when (and if) we'll add support to the host | ||
162 | * SKAS patch. */ | 171 | * SKAS patch. */ |
172 | |||
163 | int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to) | 173 | int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to) |
164 | { | 174 | { |
175 | if (!host_supports_tls) | ||
176 | return 0; | ||
177 | |||
165 | /* We have no need whatsoever to switch TLS for kernel threads; beyond | 178 | /* We have no need whatsoever to switch TLS for kernel threads; beyond |
166 | * that, that would also result in us calling os_set_thread_area with | 179 | * that, that would also result in us calling os_set_thread_area with |
167 | * userspace_pid[cpu] == 0, which gives an error. */ | 180 | * userspace_pid[cpu] == 0, which gives an error. */ |
@@ -173,6 +186,9 @@ int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to) | |||
173 | 186 | ||
174 | int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to) | 187 | int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to) |
175 | { | 188 | { |
189 | if (!host_supports_tls) | ||
190 | return 0; | ||
191 | |||
176 | if (needs_TLS_update(to)) | 192 | if (needs_TLS_update(to)) |
177 | return load_TLS(0, to); | 193 | return load_TLS(0, to); |
178 | 194 | ||
@@ -256,6 +272,9 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc) | |||
256 | struct user_desc info; | 272 | struct user_desc info; |
257 | int idx, ret; | 273 | int idx, ret; |
258 | 274 | ||
275 | if (!host_supports_tls) | ||
276 | return -ENOSYS; | ||
277 | |||
259 | if (copy_from_user(&info, user_desc, sizeof(info))) | 278 | if (copy_from_user(&info, user_desc, sizeof(info))) |
260 | return -EFAULT; | 279 | return -EFAULT; |
261 | 280 | ||
@@ -287,6 +306,9 @@ int ptrace_set_thread_area(struct task_struct *child, int idx, | |||
287 | { | 306 | { |
288 | struct user_desc info; | 307 | struct user_desc info; |
289 | 308 | ||
309 | if (!host_supports_tls) | ||
310 | return -EIO; | ||
311 | |||
290 | if (copy_from_user(&info, user_desc, sizeof(info))) | 312 | if (copy_from_user(&info, user_desc, sizeof(info))) |
291 | return -EFAULT; | 313 | return -EFAULT; |
292 | 314 | ||
@@ -298,6 +320,9 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc) | |||
298 | struct user_desc info; | 320 | struct user_desc info; |
299 | int idx, ret; | 321 | int idx, ret; |
300 | 322 | ||
323 | if (!host_supports_tls) | ||
324 | return -ENOSYS; | ||
325 | |||
301 | if (get_user(idx, &user_desc->entry_number)) | 326 | if (get_user(idx, &user_desc->entry_number)) |
302 | return -EFAULT; | 327 | return -EFAULT; |
303 | 328 | ||
@@ -321,6 +346,9 @@ int ptrace_get_thread_area(struct task_struct *child, int idx, | |||
321 | struct user_desc info; | 346 | struct user_desc info; |
322 | int ret; | 347 | int ret; |
323 | 348 | ||
349 | if (!host_supports_tls) | ||
350 | return -EIO; | ||
351 | |||
324 | ret = get_tls_entry(child, &info, idx); | 352 | ret = get_tls_entry(child, &info, idx); |
325 | if (ret < 0) | 353 | if (ret < 0) |
326 | goto out; | 354 | goto out; |
@@ -331,3 +359,26 @@ out: | |||
331 | return ret; | 359 | return ret; |
332 | } | 360 | } |
333 | 361 | ||
362 | |||
363 | /* XXX: This part is probably common to i386 and x86-64. Don't create a common | ||
364 | * file for now, do that when implementing x86-64 support.*/ | ||
365 | static int __init __setup_host_supports_tls(void) { | ||
366 | check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); | ||
367 | if (host_supports_tls) { | ||
368 | printk(KERN_INFO "Host TLS support detected\n"); | ||
369 | printk(KERN_INFO "Detected host type: "); | ||
370 | switch (host_gdt_entry_tls_min) { | ||
371 | case GDT_ENTRY_TLS_MIN_I386: | ||
372 | printk("i386\n"); | ||
373 | break; | ||
374 | case GDT_ENTRY_TLS_MIN_X86_64: | ||
375 | printk("x86_64\n"); | ||
376 | break; | ||
377 | } | ||
378 | } else | ||
379 | printk(KERN_ERR " Host TLS support NOT detected! " | ||
380 | "TLS support inside UML will not work\n"); | ||
381 | return 1; | ||
382 | } | ||
383 | |||
384 | __initcall(__setup_host_supports_tls); | ||