diff options
author | Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> | 2006-03-31 05:30:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-31 15:18:52 -0500 |
commit | aa6758d4867cd07bd76105ade6177fe6148e559a (patch) | |
tree | 0053f855c885a6dc322337468a2c45b6b2f8ddd0 /arch/um/os-Linux/tls.c | |
parent | 972410b0232e97609fcefc8e408fe3037fcd607b (diff) |
[PATCH] uml: implement {get,set}_thread_area for i386
Implement sys_[gs]et_thread_area and the corresponding ptrace operations for
UML. This is the main chunk, additional parts follow. This implementation is
now well tested and has run reliably for some time, and we've understood all
the previously existing problems.
Their implementation saves the new GDT content and then forwards the call to
the host when appropriate, i.e. immediately when the target process is
running or on context switch otherwise (i.e. on fork and on ptrace() calls).
In SKAS mode, we must switch registers on each context switch (because SKAS
does not switches tls_array together with current->mm).
Also, added get_cpu() locking; this has been done for SKAS mode, since TT does
not need it (it does not use smp_processor_id()).
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/os-Linux/tls.c')
-rw-r--r-- | arch/um/os-Linux/tls.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c new file mode 100644 index 000000000000..63dfcf709377 --- /dev/null +++ b/arch/um/os-Linux/tls.c | |||
@@ -0,0 +1,77 @@ | |||
1 | #include <errno.h> | ||
2 | #include <sys/ptrace.h> | ||
3 | #include <asm/ldt.h> | ||
4 | #include "uml-config.h" | ||
5 | |||
6 | /* TLS support - we basically rely on the host's one.*/ | ||
7 | |||
8 | /* In TT mode, this should be called only by the tracing thread, and makes sense | ||
9 | * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #ifndef PTRACE_GET_THREAD_AREA | ||
14 | #define PTRACE_GET_THREAD_AREA 25 | ||
15 | #endif | ||
16 | |||
17 | #ifndef PTRACE_SET_THREAD_AREA | ||
18 | #define PTRACE_SET_THREAD_AREA 26 | ||
19 | #endif | ||
20 | |||
21 | int os_set_thread_area(void *data, int pid) | ||
22 | { | ||
23 | struct user_desc *info = data; | ||
24 | int ret; | ||
25 | |||
26 | ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number, | ||
27 | (unsigned long) info); | ||
28 | if (ret < 0) | ||
29 | ret = -errno; | ||
30 | return ret; | ||
31 | } | ||
32 | |||
33 | #ifdef UML_CONFIG_MODE_SKAS | ||
34 | |||
35 | int os_get_thread_area(void *data, int pid) | ||
36 | { | ||
37 | struct user_desc *info = data; | ||
38 | int ret; | ||
39 | |||
40 | ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number, | ||
41 | (unsigned long) info); | ||
42 | if (ret < 0) | ||
43 | ret = -errno; | ||
44 | return ret; | ||
45 | } | ||
46 | |||
47 | #endif | ||
48 | |||
49 | #ifdef UML_CONFIG_MODE_TT | ||
50 | #include "linux/unistd.h" | ||
51 | |||
52 | _syscall1(int, get_thread_area, struct user_desc *, u_info); | ||
53 | _syscall1(int, set_thread_area, struct user_desc *, u_info); | ||
54 | |||
55 | int do_set_thread_area_tt(struct user_desc *info) | ||
56 | { | ||
57 | int ret; | ||
58 | |||
59 | ret = set_thread_area(info); | ||
60 | if (ret < 0) { | ||
61 | ret = -errno; | ||
62 | } | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | int do_get_thread_area_tt(struct user_desc *info) | ||
67 | { | ||
68 | int ret; | ||
69 | |||
70 | ret = get_thread_area(info); | ||
71 | if (ret < 0) { | ||
72 | ret = -errno; | ||
73 | } | ||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | #endif /* UML_CONFIG_MODE_TT */ | ||