Commit 3feb88562d149f078319e5a1b2f7acaa10251a5c

Authored by Paolo 'Blaisorblade' Giarrusso
Committed by Linus Torvalds
1 parent 54d8d3b5a0

[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>

Showing 8 changed files with 102 additions and 6 deletions Inline Diff

arch/um/include/os.h
1 /* 1 /*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6 #ifndef __OS_H__ 6 #ifndef __OS_H__
7 #define __OS_H__ 7 #define __OS_H__
8 8
9 #include "uml-config.h" 9 #include "uml-config.h"
10 #include "asm/types.h" 10 #include "asm/types.h"
11 #include "../os/include/file.h" 11 #include "../os/include/file.h"
12 #include "sysdep/ptrace.h" 12 #include "sysdep/ptrace.h"
13 #include "kern_util.h" 13 #include "kern_util.h"
14 #include "skas/mm_id.h" 14 #include "skas/mm_id.h"
15 #include "irq_user.h" 15 #include "irq_user.h"
16 #include "sysdep/tls.h" 16 #include "sysdep/tls.h"
17 17
18 #define OS_TYPE_FILE 1 18 #define OS_TYPE_FILE 1
19 #define OS_TYPE_DIR 2 19 #define OS_TYPE_DIR 2
20 #define OS_TYPE_SYMLINK 3 20 #define OS_TYPE_SYMLINK 3
21 #define OS_TYPE_CHARDEV 4 21 #define OS_TYPE_CHARDEV 4
22 #define OS_TYPE_BLOCKDEV 5 22 #define OS_TYPE_BLOCKDEV 5
23 #define OS_TYPE_FIFO 6 23 #define OS_TYPE_FIFO 6
24 #define OS_TYPE_SOCK 7 24 #define OS_TYPE_SOCK 7
25 25
26 /* os_access() flags */ 26 /* os_access() flags */
27 #define OS_ACC_F_OK 0 /* Test for existence. */ 27 #define OS_ACC_F_OK 0 /* Test for existence. */
28 #define OS_ACC_X_OK 1 /* Test for execute permission. */ 28 #define OS_ACC_X_OK 1 /* Test for execute permission. */
29 #define OS_ACC_W_OK 2 /* Test for write permission. */ 29 #define OS_ACC_W_OK 2 /* Test for write permission. */
30 #define OS_ACC_R_OK 4 /* Test for read permission. */ 30 #define OS_ACC_R_OK 4 /* Test for read permission. */
31 #define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ 31 #define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */
32 32
33 /* 33 /*
34 * types taken from stat_file() in hostfs_user.c 34 * types taken from stat_file() in hostfs_user.c
35 * (if they are wrong here, they are wrong there...). 35 * (if they are wrong here, they are wrong there...).
36 */ 36 */
37 struct uml_stat { 37 struct uml_stat {
38 int ust_dev; /* device */ 38 int ust_dev; /* device */
39 unsigned long long ust_ino; /* inode */ 39 unsigned long long ust_ino; /* inode */
40 int ust_mode; /* protection */ 40 int ust_mode; /* protection */
41 int ust_nlink; /* number of hard links */ 41 int ust_nlink; /* number of hard links */
42 int ust_uid; /* user ID of owner */ 42 int ust_uid; /* user ID of owner */
43 int ust_gid; /* group ID of owner */ 43 int ust_gid; /* group ID of owner */
44 unsigned long long ust_size; /* total size, in bytes */ 44 unsigned long long ust_size; /* total size, in bytes */
45 int ust_blksize; /* blocksize for filesystem I/O */ 45 int ust_blksize; /* blocksize for filesystem I/O */
46 unsigned long long ust_blocks; /* number of blocks allocated */ 46 unsigned long long ust_blocks; /* number of blocks allocated */
47 unsigned long ust_atime; /* time of last access */ 47 unsigned long ust_atime; /* time of last access */
48 unsigned long ust_mtime; /* time of last modification */ 48 unsigned long ust_mtime; /* time of last modification */
49 unsigned long ust_ctime; /* time of last change */ 49 unsigned long ust_ctime; /* time of last change */
50 }; 50 };
51 51
52 struct openflags { 52 struct openflags {
53 unsigned int r : 1; 53 unsigned int r : 1;
54 unsigned int w : 1; 54 unsigned int w : 1;
55 unsigned int s : 1; /* O_SYNC */ 55 unsigned int s : 1; /* O_SYNC */
56 unsigned int c : 1; /* O_CREAT */ 56 unsigned int c : 1; /* O_CREAT */
57 unsigned int t : 1; /* O_TRUNC */ 57 unsigned int t : 1; /* O_TRUNC */
58 unsigned int a : 1; /* O_APPEND */ 58 unsigned int a : 1; /* O_APPEND */
59 unsigned int e : 1; /* O_EXCL */ 59 unsigned int e : 1; /* O_EXCL */
60 unsigned int cl : 1; /* FD_CLOEXEC */ 60 unsigned int cl : 1; /* FD_CLOEXEC */
61 }; 61 };
62 62
63 #define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \ 63 #define OPENFLAGS() ((struct openflags) { .r = 0, .w = 0, .s = 0, .c = 0, \
64 .t = 0, .a = 0, .e = 0, .cl = 0 }) 64 .t = 0, .a = 0, .e = 0, .cl = 0 })
65 65
66 static inline struct openflags of_read(struct openflags flags) 66 static inline struct openflags of_read(struct openflags flags)
67 { 67 {
68 flags.r = 1; 68 flags.r = 1;
69 return(flags); 69 return(flags);
70 } 70 }
71 71
72 static inline struct openflags of_write(struct openflags flags) 72 static inline struct openflags of_write(struct openflags flags)
73 { 73 {
74 flags.w = 1; 74 flags.w = 1;
75 return(flags); 75 return(flags);
76 } 76 }
77 77
78 static inline struct openflags of_rdwr(struct openflags flags) 78 static inline struct openflags of_rdwr(struct openflags flags)
79 { 79 {
80 return(of_read(of_write(flags))); 80 return(of_read(of_write(flags)));
81 } 81 }
82 82
83 static inline struct openflags of_set_rw(struct openflags flags, int r, int w) 83 static inline struct openflags of_set_rw(struct openflags flags, int r, int w)
84 { 84 {
85 flags.r = r; 85 flags.r = r;
86 flags.w = w; 86 flags.w = w;
87 return(flags); 87 return(flags);
88 } 88 }
89 89
90 static inline struct openflags of_sync(struct openflags flags) 90 static inline struct openflags of_sync(struct openflags flags)
91 { 91 {
92 flags.s = 1; 92 flags.s = 1;
93 return(flags); 93 return(flags);
94 } 94 }
95 95
96 static inline struct openflags of_create(struct openflags flags) 96 static inline struct openflags of_create(struct openflags flags)
97 { 97 {
98 flags.c = 1; 98 flags.c = 1;
99 return(flags); 99 return(flags);
100 } 100 }
101 101
102 static inline struct openflags of_trunc(struct openflags flags) 102 static inline struct openflags of_trunc(struct openflags flags)
103 { 103 {
104 flags.t = 1; 104 flags.t = 1;
105 return(flags); 105 return(flags);
106 } 106 }
107 107
108 static inline struct openflags of_append(struct openflags flags) 108 static inline struct openflags of_append(struct openflags flags)
109 { 109 {
110 flags.a = 1; 110 flags.a = 1;
111 return(flags); 111 return(flags);
112 } 112 }
113 113
114 static inline struct openflags of_excl(struct openflags flags) 114 static inline struct openflags of_excl(struct openflags flags)
115 { 115 {
116 flags.e = 1; 116 flags.e = 1;
117 return(flags); 117 return(flags);
118 } 118 }
119 119
120 static inline struct openflags of_cloexec(struct openflags flags) 120 static inline struct openflags of_cloexec(struct openflags flags)
121 { 121 {
122 flags.cl = 1; 122 flags.cl = 1;
123 return(flags); 123 return(flags);
124 } 124 }
125 125
126 /* file.c */ 126 /* file.c */
127 extern int os_stat_file(const char *file_name, struct uml_stat *buf); 127 extern int os_stat_file(const char *file_name, struct uml_stat *buf);
128 extern int os_stat_fd(const int fd, struct uml_stat *buf); 128 extern int os_stat_fd(const int fd, struct uml_stat *buf);
129 extern int os_access(const char *file, int mode); 129 extern int os_access(const char *file, int mode);
130 extern void os_print_error(int error, const char* str); 130 extern void os_print_error(int error, const char* str);
131 extern int os_get_exec_close(int fd, int *close_on_exec); 131 extern int os_get_exec_close(int fd, int *close_on_exec);
132 extern int os_set_exec_close(int fd, int close_on_exec); 132 extern int os_set_exec_close(int fd, int close_on_exec);
133 extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); 133 extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
134 extern int os_window_size(int fd, int *rows, int *cols); 134 extern int os_window_size(int fd, int *rows, int *cols);
135 extern int os_new_tty_pgrp(int fd, int pid); 135 extern int os_new_tty_pgrp(int fd, int pid);
136 extern int os_get_ifname(int fd, char *namebuf); 136 extern int os_get_ifname(int fd, char *namebuf);
137 extern int os_set_slip(int fd); 137 extern int os_set_slip(int fd);
138 extern int os_set_owner(int fd, int pid); 138 extern int os_set_owner(int fd, int pid);
139 extern int os_sigio_async(int master, int slave); 139 extern int os_sigio_async(int master, int slave);
140 extern int os_mode_fd(int fd, int mode); 140 extern int os_mode_fd(int fd, int mode);
141 141
142 extern int os_seek_file(int fd, __u64 offset); 142 extern int os_seek_file(int fd, __u64 offset);
143 extern int os_open_file(char *file, struct openflags flags, int mode); 143 extern int os_open_file(char *file, struct openflags flags, int mode);
144 extern int os_read_file(int fd, void *buf, int len); 144 extern int os_read_file(int fd, void *buf, int len);
145 extern int os_write_file(int fd, const void *buf, int count); 145 extern int os_write_file(int fd, const void *buf, int count);
146 extern int os_file_size(char *file, unsigned long long *size_out); 146 extern int os_file_size(char *file, unsigned long long *size_out);
147 extern int os_file_modtime(char *file, unsigned long *modtime); 147 extern int os_file_modtime(char *file, unsigned long *modtime);
148 extern int os_pipe(int *fd, int stream, int close_on_exec); 148 extern int os_pipe(int *fd, int stream, int close_on_exec);
149 extern int os_set_fd_async(int fd, int owner); 149 extern int os_set_fd_async(int fd, int owner);
150 extern int os_clear_fd_async(int fd); 150 extern int os_clear_fd_async(int fd);
151 extern int os_set_fd_block(int fd, int blocking); 151 extern int os_set_fd_block(int fd, int blocking);
152 extern int os_accept_connection(int fd); 152 extern int os_accept_connection(int fd);
153 extern int os_create_unix_socket(char *file, int len, int close_on_exec); 153 extern int os_create_unix_socket(char *file, int len, int close_on_exec);
154 extern int os_shutdown_socket(int fd, int r, int w); 154 extern int os_shutdown_socket(int fd, int r, int w);
155 extern void os_close_file(int fd); 155 extern void os_close_file(int fd);
156 extern int os_rcv_fd(int fd, int *helper_pid_out); 156 extern int os_rcv_fd(int fd, int *helper_pid_out);
157 extern int create_unix_socket(char *file, int len, int close_on_exec); 157 extern int create_unix_socket(char *file, int len, int close_on_exec);
158 extern int os_connect_socket(char *name); 158 extern int os_connect_socket(char *name);
159 extern int os_file_type(char *file); 159 extern int os_file_type(char *file);
160 extern int os_file_mode(char *file, struct openflags *mode_out); 160 extern int os_file_mode(char *file, struct openflags *mode_out);
161 extern int os_lock_file(int fd, int excl); 161 extern int os_lock_file(int fd, int excl);
162 extern void os_flush_stdout(void); 162 extern void os_flush_stdout(void);
163 extern int os_stat_filesystem(char *path, long *bsize_out, 163 extern int os_stat_filesystem(char *path, long *bsize_out,
164 long long *blocks_out, long long *bfree_out, 164 long long *blocks_out, long long *bfree_out,
165 long long *bavail_out, long long *files_out, 165 long long *bavail_out, long long *files_out,
166 long long *ffree_out, void *fsid_out, 166 long long *ffree_out, void *fsid_out,
167 int fsid_size, long *namelen_out, 167 int fsid_size, long *namelen_out,
168 long *spare_out); 168 long *spare_out);
169 extern int os_change_dir(char *dir); 169 extern int os_change_dir(char *dir);
170 extern int os_fchange_dir(int fd); 170 extern int os_fchange_dir(int fd);
171 171
172 /* start_up.c */ 172 /* start_up.c */
173 extern void os_early_checks(void); 173 extern void os_early_checks(void);
174 extern int can_do_skas(void); 174 extern int can_do_skas(void);
175 extern void os_check_bugs(void); 175 extern void os_check_bugs(void);
176 extern void check_host_supports_tls(int *supports_tls, int *tls_min);
176 177
177 /* Make sure they are clear when running in TT mode. Required by 178 /* Make sure they are clear when running in TT mode. Required by
178 * SEGV_MAYBE_FIXABLE */ 179 * SEGV_MAYBE_FIXABLE */
179 #ifdef UML_CONFIG_MODE_SKAS 180 #ifdef UML_CONFIG_MODE_SKAS
180 #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0) 181 #define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
181 #else 182 #else
182 #define clear_can_do_skas() do {} while (0) 183 #define clear_can_do_skas() do {} while (0)
183 #endif 184 #endif
184 185
185 /* mem.c */ 186 /* mem.c */
186 extern int create_mem_file(unsigned long long len); 187 extern int create_mem_file(unsigned long long len);
187 188
188 /* process.c */ 189 /* process.c */
189 extern unsigned long os_process_pc(int pid); 190 extern unsigned long os_process_pc(int pid);
190 extern int os_process_parent(int pid); 191 extern int os_process_parent(int pid);
191 extern void os_stop_process(int pid); 192 extern void os_stop_process(int pid);
192 extern void os_kill_process(int pid, int reap_child); 193 extern void os_kill_process(int pid, int reap_child);
193 extern void os_kill_ptraced_process(int pid, int reap_child); 194 extern void os_kill_ptraced_process(int pid, int reap_child);
194 extern void os_usr1_process(int pid); 195 extern void os_usr1_process(int pid);
195 extern long os_ptrace_ldt(long pid, long addr, long data); 196 extern long os_ptrace_ldt(long pid, long addr, long data);
196 197
197 extern int os_getpid(void); 198 extern int os_getpid(void);
198 extern int os_getpgrp(void); 199 extern int os_getpgrp(void);
199 200
200 extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)); 201 extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
201 extern void init_new_thread_signals(int altstack); 202 extern void init_new_thread_signals(int altstack);
202 extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); 203 extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
203 204
204 extern int os_map_memory(void *virt, int fd, unsigned long long off, 205 extern int os_map_memory(void *virt, int fd, unsigned long long off,
205 unsigned long len, int r, int w, int x); 206 unsigned long len, int r, int w, int x);
206 extern int os_protect_memory(void *addr, unsigned long len, 207 extern int os_protect_memory(void *addr, unsigned long len,
207 int r, int w, int x); 208 int r, int w, int x);
208 extern int os_unmap_memory(void *addr, int len); 209 extern int os_unmap_memory(void *addr, int len);
209 extern int os_drop_memory(void *addr, int length); 210 extern int os_drop_memory(void *addr, int length);
210 extern int can_drop_memory(void); 211 extern int can_drop_memory(void);
211 extern void os_flush_stdout(void); 212 extern void os_flush_stdout(void);
212 213
213 /* tt.c 214 /* tt.c
214 * for tt mode only (will be deleted in future...) 215 * for tt mode only (will be deleted in future...)
215 */ 216 */
216 extern void forward_ipi(int fd, int pid); 217 extern void forward_ipi(int fd, int pid);
217 extern void kill_child_dead(int pid); 218 extern void kill_child_dead(int pid);
218 extern void stop(void); 219 extern void stop(void);
219 extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); 220 extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
220 extern int protect_memory(unsigned long addr, unsigned long len, 221 extern int protect_memory(unsigned long addr, unsigned long len,
221 int r, int w, int x, int must_succeed); 222 int r, int w, int x, int must_succeed);
222 extern void forward_pending_sigio(int target); 223 extern void forward_pending_sigio(int target);
223 extern int start_fork_tramp(void *arg, unsigned long temp_stack, 224 extern int start_fork_tramp(void *arg, unsigned long temp_stack,
224 int clone_flags, int (*tramp)(void *)); 225 int clone_flags, int (*tramp)(void *));
225 226
226 /* uaccess.c */ 227 /* uaccess.c */
227 extern unsigned long __do_user_copy(void *to, const void *from, int n, 228 extern unsigned long __do_user_copy(void *to, const void *from, int n,
228 void **fault_addr, void **fault_catcher, 229 void **fault_addr, void **fault_catcher,
229 void (*op)(void *to, const void *from, 230 void (*op)(void *to, const void *from,
230 int n), int *faulted_out); 231 int n), int *faulted_out);
231 232
232 /* helper.c */ 233 /* helper.c */
233 extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, 234 extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
234 unsigned long *stack_out); 235 unsigned long *stack_out);
235 extern int run_helper_thread(int (*proc)(void *), void *arg, 236 extern int run_helper_thread(int (*proc)(void *), void *arg,
236 unsigned int flags, unsigned long *stack_out, 237 unsigned int flags, unsigned long *stack_out,
237 int stack_order); 238 int stack_order);
238 extern int helper_wait(int pid); 239 extern int helper_wait(int pid);
239 240
240 241
241 /* tls.c */ 242 /* tls.c */
242 extern int os_set_thread_area(user_desc_t *info, int pid); 243 extern int os_set_thread_area(user_desc_t *info, int pid);
243 extern int os_get_thread_area(user_desc_t *info, int pid); 244 extern int os_get_thread_area(user_desc_t *info, int pid);
244 245
245 /* umid.c */ 246 /* umid.c */
246 extern int umid_file_name(char *name, char *buf, int len); 247 extern int umid_file_name(char *name, char *buf, int len);
247 extern int set_umid(char *name); 248 extern int set_umid(char *name);
248 extern char *get_umid(void); 249 extern char *get_umid(void);
249 250
250 /* signal.c */ 251 /* signal.c */
251 extern void set_sigstack(void *sig_stack, int size); 252 extern void set_sigstack(void *sig_stack, int size);
252 extern void remove_sigstack(void); 253 extern void remove_sigstack(void);
253 extern void set_handler(int sig, void (*handler)(int), int flags, ...); 254 extern void set_handler(int sig, void (*handler)(int), int flags, ...);
254 extern int change_sig(int signal, int on); 255 extern int change_sig(int signal, int on);
255 extern void block_signals(void); 256 extern void block_signals(void);
256 extern void unblock_signals(void); 257 extern void unblock_signals(void);
257 extern int get_signals(void); 258 extern int get_signals(void);
258 extern int set_signals(int enable); 259 extern int set_signals(int enable);
259 extern void os_usr1_signal(int on); 260 extern void os_usr1_signal(int on);
260 261
261 /* trap.c */ 262 /* trap.c */
262 extern void os_fill_handlinfo(struct kern_handlers h); 263 extern void os_fill_handlinfo(struct kern_handlers h);
263 extern void do_longjmp(void *p, int val); 264 extern void do_longjmp(void *p, int val);
264 265
265 /* util.c */ 266 /* util.c */
266 extern void stack_protections(unsigned long address); 267 extern void stack_protections(unsigned long address);
267 extern void task_protections(unsigned long address); 268 extern void task_protections(unsigned long address);
268 extern int raw(int fd); 269 extern int raw(int fd);
269 extern void setup_machinename(char *machine_out); 270 extern void setup_machinename(char *machine_out);
270 extern void setup_hostinfo(void); 271 extern void setup_hostinfo(void);
271 extern int setjmp_wrapper(void (*proc)(void *, void *), ...); 272 extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
272 273
273 /* time.c */ 274 /* time.c */
274 #define BILLION (1000 * 1000 * 1000) 275 #define BILLION (1000 * 1000 * 1000)
275 276
276 extern void switch_timers(int to_real); 277 extern void switch_timers(int to_real);
277 extern void idle_sleep(int secs); 278 extern void idle_sleep(int secs);
278 extern void enable_timer(void); 279 extern void enable_timer(void);
279 extern void disable_timer(void); 280 extern void disable_timer(void);
280 extern void user_time_init(void); 281 extern void user_time_init(void);
281 extern void uml_idle_timer(void); 282 extern void uml_idle_timer(void);
282 extern unsigned long long os_nsecs(void); 283 extern unsigned long long os_nsecs(void);
283 284
284 /* skas/mem.c */ 285 /* skas/mem.c */
285 extern long run_syscall_stub(struct mm_id * mm_idp, 286 extern long run_syscall_stub(struct mm_id * mm_idp,
286 int syscall, unsigned long *args, long expected, 287 int syscall, unsigned long *args, long expected,
287 void **addr, int done); 288 void **addr, int done);
288 extern long syscall_stub_data(struct mm_id * mm_idp, 289 extern long syscall_stub_data(struct mm_id * mm_idp,
289 unsigned long *data, int data_count, 290 unsigned long *data, int data_count,
290 void **addr, void **stub_addr); 291 void **addr, void **stub_addr);
291 extern int map(struct mm_id * mm_idp, unsigned long virt, 292 extern int map(struct mm_id * mm_idp, unsigned long virt,
292 unsigned long len, int r, int w, int x, int phys_fd, 293 unsigned long len, int r, int w, int x, int phys_fd,
293 unsigned long long offset, int done, void **data); 294 unsigned long long offset, int done, void **data);
294 extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, 295 extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len,
295 int done, void **data); 296 int done, void **data);
296 extern int protect(struct mm_id * mm_idp, unsigned long addr, 297 extern int protect(struct mm_id * mm_idp, unsigned long addr,
297 unsigned long len, int r, int w, int x, int done, 298 unsigned long len, int r, int w, int x, int done,
298 void **data); 299 void **data);
299 300
300 /* skas/process.c */ 301 /* skas/process.c */
301 extern int is_skas_winch(int pid, int fd, void *data); 302 extern int is_skas_winch(int pid, int fd, void *data);
302 extern int start_userspace(unsigned long stub_stack); 303 extern int start_userspace(unsigned long stub_stack);
303 extern int copy_context_skas0(unsigned long stack, int pid); 304 extern int copy_context_skas0(unsigned long stack, int pid);
304 extern void userspace(union uml_pt_regs *regs); 305 extern void userspace(union uml_pt_regs *regs);
305 extern void map_stub_pages(int fd, unsigned long code, 306 extern void map_stub_pages(int fd, unsigned long code,
306 unsigned long data, unsigned long stack); 307 unsigned long data, unsigned long stack);
307 extern void new_thread(void *stack, void **switch_buf_ptr, 308 extern void new_thread(void *stack, void **switch_buf_ptr,
308 void **fork_buf_ptr, void (*handler)(int)); 309 void **fork_buf_ptr, void (*handler)(int));
309 extern void thread_wait(void *sw, void *fb); 310 extern void thread_wait(void *sw, void *fb);
310 extern void switch_threads(void *me, void *next); 311 extern void switch_threads(void *me, void *next);
311 extern int start_idle_thread(void *stack, void *switch_buf_ptr, 312 extern int start_idle_thread(void *stack, void *switch_buf_ptr,
312 void **fork_buf_ptr); 313 void **fork_buf_ptr);
313 extern void initial_thread_cb_skas(void (*proc)(void *), 314 extern void initial_thread_cb_skas(void (*proc)(void *),
314 void *arg); 315 void *arg);
315 extern void halt_skas(void); 316 extern void halt_skas(void);
316 extern void reboot_skas(void); 317 extern void reboot_skas(void);
317 318
318 /* irq.c */ 319 /* irq.c */
319 extern int os_waiting_for_events(struct irq_fd *active_fds); 320 extern int os_waiting_for_events(struct irq_fd *active_fds);
320 extern int os_isatty(int fd); 321 extern int os_isatty(int fd);
321 extern int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds); 322 extern int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds);
322 extern void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg, 323 extern void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
323 struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2); 324 struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2);
324 extern void os_free_irq_later(struct irq_fd *active_fds, 325 extern void os_free_irq_later(struct irq_fd *active_fds,
325 int irq, void *dev_id); 326 int irq, void *dev_id);
326 extern int os_get_pollfd(int i); 327 extern int os_get_pollfd(int i);
327 extern void os_set_pollfd(int i, int fd); 328 extern void os_set_pollfd(int i, int fd);
328 extern void os_set_ioignore(void); 329 extern void os_set_ioignore(void);
329 extern void init_irq_signals(int on_sigstack); 330 extern void init_irq_signals(int on_sigstack);
330 331
331 /* sigio.c */ 332 /* sigio.c */
332 extern void write_sigio_workaround(void); 333 extern void write_sigio_workaround(void);
333 extern int add_sigio_fd(int fd, int read); 334 extern int add_sigio_fd(int fd, int read);
334 extern int ignore_sigio_fd(int fd); 335 extern int ignore_sigio_fd(int fd);
335 336
336 /* skas/trap */ 337 /* skas/trap */
337 extern void sig_handler_common_skas(int sig, void *sc_ptr); 338 extern void sig_handler_common_skas(int sig, void *sc_ptr);
338 extern void user_signal(int sig, union uml_pt_regs *regs, int pid); 339 extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
339 340
340 #endif 341 #endif
341 342
arch/um/include/sysdep-i386/tls.h
1 #ifndef _SYSDEP_TLS_H 1 #ifndef _SYSDEP_TLS_H
2 #define _SYSDEP_TLS_H 2 #define _SYSDEP_TLS_H
3 3
4 # ifndef __KERNEL__ 4 # ifndef __KERNEL__
5 5
6 /* Change name to avoid conflicts with the original one from <asm/ldt.h>, which 6 /* Change name to avoid conflicts with the original one from <asm/ldt.h>, which
7 * may be named user_desc (but in 2.4 and in header matching its API was named 7 * may be named user_desc (but in 2.4 and in header matching its API was named
8 * modify_ldt_ldt_s). */ 8 * modify_ldt_ldt_s). */
9 9
10 typedef struct um_dup_user_desc { 10 typedef struct um_dup_user_desc {
11 unsigned int entry_number; 11 unsigned int entry_number;
12 unsigned int base_addr; 12 unsigned int base_addr;
13 unsigned int limit; 13 unsigned int limit;
14 unsigned int seg_32bit:1; 14 unsigned int seg_32bit:1;
15 unsigned int contents:2; 15 unsigned int contents:2;
16 unsigned int read_exec_only:1; 16 unsigned int read_exec_only:1;
17 unsigned int limit_in_pages:1; 17 unsigned int limit_in_pages:1;
18 unsigned int seg_not_present:1; 18 unsigned int seg_not_present:1;
19 unsigned int useable:1; 19 unsigned int useable:1;
20 } user_desc_t; 20 } user_desc_t;
21 21
22 # else /* __KERNEL__ */ 22 # else /* __KERNEL__ */
23 23
24 # include <asm/ldt.h> 24 # include <asm/ldt.h>
25 typedef struct user_desc user_desc_t; 25 typedef struct user_desc user_desc_t;
26 26
27 # endif /* __KERNEL__ */ 27 # endif /* __KERNEL__ */
28
29 #define GDT_ENTRY_TLS_MIN_I386 6
30 #define GDT_ENTRY_TLS_MIN_X86_64 12
31
28 #endif /* _SYSDEP_TLS_H */ 32 #endif /* _SYSDEP_TLS_H */
29 33
arch/um/include/user_util.h
1 /* 1 /*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6 #ifndef __USER_UTIL_H__ 6 #ifndef __USER_UTIL_H__
7 #define __USER_UTIL_H__ 7 #define __USER_UTIL_H__
8 8
9 #include "sysdep/ptrace.h" 9 #include "sysdep/ptrace.h"
10 10
11 /* Copied from kernel.h */
12 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
13
11 #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) 14 #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
12 15
13 extern int mode_tt; 16 extern int mode_tt;
14 17
15 extern int grantpt(int __fd); 18 extern int grantpt(int __fd);
16 extern int unlockpt(int __fd); 19 extern int unlockpt(int __fd);
17 extern char *ptsname(int __fd); 20 extern char *ptsname(int __fd);
18 21
19 struct cpu_task { 22 struct cpu_task {
20 int pid; 23 int pid;
21 void *task; 24 void *task;
22 }; 25 };
23 26
24 extern struct cpu_task cpu_tasks[]; 27 extern struct cpu_task cpu_tasks[];
25 28
26 extern void (*sig_info[])(int, union uml_pt_regs *); 29 extern void (*sig_info[])(int, union uml_pt_regs *);
27 30
28 extern unsigned long low_physmem; 31 extern unsigned long low_physmem;
29 extern unsigned long high_physmem; 32 extern unsigned long high_physmem;
30 extern unsigned long uml_physmem; 33 extern unsigned long uml_physmem;
31 extern unsigned long uml_reserved; 34 extern unsigned long uml_reserved;
32 extern unsigned long end_vm; 35 extern unsigned long end_vm;
33 extern unsigned long start_vm; 36 extern unsigned long start_vm;
34 extern unsigned long long highmem; 37 extern unsigned long long highmem;
35 38
36 extern char host_info[]; 39 extern char host_info[];
37 40
38 extern char saved_command_line[]; 41 extern char saved_command_line[];
39 42
40 extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; 43 extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
41 extern unsigned long _unprotected_end; 44 extern unsigned long _unprotected_end;
42 extern unsigned long brk_start; 45 extern unsigned long brk_start;
43 46
44 extern int pty_output_sigio; 47 extern int pty_output_sigio;
45 extern int pty_close_sigio; 48 extern int pty_close_sigio;
46 49
47 extern void *add_signal_handler(int sig, void (*handler)(int)); 50 extern void *add_signal_handler(int sig, void (*handler)(int));
48 extern int linux_main(int argc, char **argv); 51 extern int linux_main(int argc, char **argv);
49 extern void set_cmdline(char *cmd); 52 extern void set_cmdline(char *cmd);
50 extern void input_cb(void (*proc)(void *), void *arg, int arg_len); 53 extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
51 extern int get_pty(void); 54 extern int get_pty(void);
52 extern void *um_kmalloc(int size); 55 extern void *um_kmalloc(int size);
53 extern int switcheroo(int fd, int prot, void *from, void *to, int size); 56 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
54 extern void do_exec(int old_pid, int new_pid); 57 extern void do_exec(int old_pid, int new_pid);
55 extern void tracer_panic(char *msg, ...); 58 extern void tracer_panic(char *msg, ...);
56 extern int detach(int pid, int sig); 59 extern int detach(int pid, int sig);
57 extern int attach(int pid); 60 extern int attach(int pid);
58 extern void kill_child_dead(int pid); 61 extern void kill_child_dead(int pid);
59 extern int cont(int pid); 62 extern int cont(int pid);
60 extern void check_sigio(void); 63 extern void check_sigio(void);
61 extern void arch_check_bugs(void); 64 extern void arch_check_bugs(void);
62 extern int cpu_feature(char *what, char *buf, int len); 65 extern int cpu_feature(char *what, char *buf, int len);
63 extern int arch_handle_signal(int sig, union uml_pt_regs *regs); 66 extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
64 extern int arch_fixup(unsigned long address, void *sc_ptr); 67 extern int arch_fixup(unsigned long address, void *sc_ptr);
65 extern void arch_init_thread(void); 68 extern void arch_init_thread(void);
66 extern int raw(int fd); 69 extern int raw(int fd);
67 70
68 #endif 71 #endif
69 72
arch/um/os-Linux/sys-i386/Makefile
1 # 1 #
2 # Copyright (C) 2000 Jeff Dike (jdike@karaya.com) 2 # Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 # Licensed under the GPL 3 # Licensed under the GPL
4 # 4 #
5 5
6 obj-$(CONFIG_MODE_SKAS) = registers.o 6 obj-$(CONFIG_MODE_SKAS) = registers.o tls.o
7 7
8 USER_OBJS := $(obj-y) 8 USER_OBJS := $(obj-y)
9 9
10 include arch/um/scripts/Makefile.rules 10 include arch/um/scripts/Makefile.rules
11 11
arch/um/os-Linux/sys-i386/tls.c
File was created 1 #include <linux/unistd.h>
2 #include "sysdep/tls.h"
3 #include "user_util.h"
4
5 static _syscall1(int, get_thread_area, user_desc_t *, u_info);
6
7 /* Checks whether host supports TLS, and sets *tls_min according to the value
8 * valid on the host.
9 * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
10 void check_host_supports_tls(int *supports_tls, int *tls_min) {
11 /* Values for x86 and x86_64.*/
12 int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
13 int i;
14
15 for (i = 0; i < ARRAY_SIZE(val); i++) {
16 user_desc_t info;
17 info.entry_number = val[i];
18
19 if (get_thread_area(&info) == 0) {
20 *tls_min = val[i];
21 *supports_tls = 1;
22 return;
23 } else {
24 if (errno == EINVAL)
25 continue;
26 else if (errno == ENOSYS)
27 *supports_tls = 0;
28 return;
29 }
30 }
31
32 *supports_tls = 0;
33 }
34
arch/um/os-Linux/tls.c
1 #include <errno.h> 1 #include <errno.h>
2 #include <sys/ptrace.h> 2 #include <sys/ptrace.h>
3 #include <asm/ldt.h> 3 #include <asm/ldt.h>
4 #include "sysdep/tls.h" 4 #include "sysdep/tls.h"
5 #include "uml-config.h" 5 #include "uml-config.h"
6 6
7 /* TLS support - we basically rely on the host's one.*/ 7 /* TLS support - we basically rely on the host's one.*/
8 8
9 /* In TT mode, this should be called only by the tracing thread, and makes sense 9 /* In TT mode, this should be called only by the tracing thread, and makes sense
10 * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally. 10 * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally.
11 * 11 *
12 */ 12 */
13 13
14 #ifndef PTRACE_GET_THREAD_AREA 14 #ifndef PTRACE_GET_THREAD_AREA
15 #define PTRACE_GET_THREAD_AREA 25 15 #define PTRACE_GET_THREAD_AREA 25
16 #endif 16 #endif
17 17
18 #ifndef PTRACE_SET_THREAD_AREA 18 #ifndef PTRACE_SET_THREAD_AREA
19 #define PTRACE_SET_THREAD_AREA 26 19 #define PTRACE_SET_THREAD_AREA 26
20 #endif 20 #endif
21 21
22 int os_set_thread_area(user_desc_t *info, int pid) 22 int os_set_thread_area(user_desc_t *info, int pid)
23 { 23 {
24 int ret; 24 int ret;
25 25
26 ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number, 26 ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
27 (unsigned long) info); 27 (unsigned long) info);
28 if (ret < 0) 28 if (ret < 0)
29 ret = -errno; 29 ret = -errno;
30 return ret; 30 return ret;
31 } 31 }
32 32
33 #ifdef UML_CONFIG_MODE_SKAS 33 #ifdef UML_CONFIG_MODE_SKAS
34 34
35 int os_get_thread_area(user_desc_t *info, int pid) 35 int os_get_thread_area(user_desc_t *info, int pid)
36 { 36 {
37 int ret; 37 int ret;
38 38
39 ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number, 39 ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
40 (unsigned long) info); 40 (unsigned long) info);
41 if (ret < 0) 41 if (ret < 0)
42 ret = -errno; 42 ret = -errno;
43 return ret; 43 return ret;
44 } 44 }
45 45
46 #endif 46 #endif
47 47
48 #ifdef UML_CONFIG_MODE_TT 48 #ifdef UML_CONFIG_MODE_TT
49 #include "linux/unistd.h" 49 #include "linux/unistd.h"
50 50
51 _syscall1(int, get_thread_area, user_desc_t *, u_info); 51 static _syscall1(int, get_thread_area, user_desc_t *, u_info);
52 _syscall1(int, set_thread_area, user_desc_t *, u_info); 52 static _syscall1(int, set_thread_area, user_desc_t *, u_info);
53 53
54 int do_set_thread_area_tt(user_desc_t *info) 54 int do_set_thread_area_tt(user_desc_t *info)
55 { 55 {
56 int ret; 56 int ret;
57 57
58 ret = set_thread_area(info); 58 ret = set_thread_area(info);
59 if (ret < 0) { 59 if (ret < 0) {
60 ret = -errno; 60 ret = -errno;
61 } 61 }
62 return ret; 62 return ret;
63 } 63 }
64 64
65 int do_get_thread_area_tt(user_desc_t *info) 65 int do_get_thread_area_tt(user_desc_t *info)
66 { 66 {
67 int ret; 67 int ret;
68 68
69 ret = get_thread_area(info); 69 ret = get_thread_area(info);
70 if (ret < 0) { 70 if (ret < 0) {
71 ret = -errno; 71 ret = -errno;
72 } 72 }
73 return ret; 73 return ret;
74 } 74 }
75 75
76 #endif /* UML_CONFIG_MODE_TT */ 76 #endif /* UML_CONFIG_MODE_TT */
77 77
arch/um/sys-i386/tls.c
1 /* 1 /*
2 * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> 2 * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6 #include "linux/config.h" 6 #include "linux/config.h"
7 #include "linux/kernel.h" 7 #include "linux/kernel.h"
8 #include "linux/sched.h" 8 #include "linux/sched.h"
9 #include "linux/slab.h" 9 #include "linux/slab.h"
10 #include "linux/types.h" 10 #include "linux/types.h"
11 #include "asm/uaccess.h" 11 #include "asm/uaccess.h"
12 #include "asm/ptrace.h" 12 #include "asm/ptrace.h"
13 #include "asm/segment.h" 13 #include "asm/segment.h"
14 #include "asm/smp.h" 14 #include "asm/smp.h"
15 #include "asm/desc.h" 15 #include "asm/desc.h"
16 #include "choose-mode.h" 16 #include "choose-mode.h"
17 #include "kern.h" 17 #include "kern.h"
18 #include "kern_util.h" 18 #include "kern_util.h"
19 #include "mode_kern.h" 19 #include "mode_kern.h"
20 #include "os.h" 20 #include "os.h"
21 #include "mode.h" 21 #include "mode.h"
22 22
23 #ifdef CONFIG_MODE_SKAS 23 #ifdef CONFIG_MODE_SKAS
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 {
30 int ret; 34 int ret;
31 u32 cpu; 35 u32 cpu;
32 36
33 cpu = get_cpu(); 37 cpu = get_cpu();
34 ret = os_set_thread_area(info, userspace_pid[cpu]); 38 ret = os_set_thread_area(info, userspace_pid[cpu]);
35 put_cpu(); 39 put_cpu();
36 return ret; 40 return ret;
37 } 41 }
38 42
39 int do_get_thread_area_skas(struct user_desc *info) 43 int do_get_thread_area_skas(struct user_desc *info)
40 { 44 {
41 int ret; 45 int ret;
42 u32 cpu; 46 u32 cpu;
43 47
44 cpu = get_cpu(); 48 cpu = get_cpu();
45 ret = os_get_thread_area(info, userspace_pid[cpu]); 49 ret = os_get_thread_area(info, userspace_pid[cpu]);
46 put_cpu(); 50 put_cpu();
47 return ret; 51 return ret;
48 } 52 }
49 #endif 53 #endif
50 54
51 /* 55 /*
52 * sys_get_thread_area: get a yet unused TLS descriptor index. 56 * sys_get_thread_area: get a yet unused TLS descriptor index.
53 * XXX: Consider leaving one free slot for glibc usage at first place. This must 57 * XXX: Consider leaving one free slot for glibc usage at first place. This must
54 * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else. 58 * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else.
55 * 59 *
56 * Also, this must be tested when compiling in SKAS mode with dinamic linking 60 * Also, this must be tested when compiling in SKAS mode with dinamic linking
57 * and running against NPTL. 61 * and running against NPTL.
58 */ 62 */
59 static int get_free_idx(struct task_struct* task) 63 static int get_free_idx(struct task_struct* task)
60 { 64 {
61 struct thread_struct *t = &task->thread; 65 struct thread_struct *t = &task->thread;
62 int idx; 66 int idx;
63 67
64 if (!t->arch.tls_array) 68 if (!t->arch.tls_array)
65 return GDT_ENTRY_TLS_MIN; 69 return GDT_ENTRY_TLS_MIN;
66 70
67 for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) 71 for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
68 if (!t->arch.tls_array[idx].present) 72 if (!t->arch.tls_array[idx].present)
69 return idx + GDT_ENTRY_TLS_MIN; 73 return idx + GDT_ENTRY_TLS_MIN;
70 return -ESRCH; 74 return -ESRCH;
71 } 75 }
72 76
73 static inline void clear_user_desc(struct user_desc* info) 77 static inline void clear_user_desc(struct user_desc* info)
74 { 78 {
75 /* Postcondition: LDT_empty(info) returns true. */ 79 /* Postcondition: LDT_empty(info) returns true. */
76 memset(info, 0, sizeof(*info)); 80 memset(info, 0, sizeof(*info));
77 81
78 /* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain 82 /* Check the LDT_empty or the i386 sys_get_thread_area code - we obtain
79 * indeed an empty user_desc. 83 * indeed an empty user_desc.
80 */ 84 */
81 info->read_exec_only = 1; 85 info->read_exec_only = 1;
82 info->seg_not_present = 1; 86 info->seg_not_present = 1;
83 } 87 }
84 88
85 #define O_FORCE 1 89 #define O_FORCE 1
86 90
87 static int load_TLS(int flags, struct task_struct *to) 91 static int load_TLS(int flags, struct task_struct *to)
88 { 92 {
89 int ret = 0; 93 int ret = 0;
90 int idx; 94 int idx;
91 95
92 for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) { 96 for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) {
93 struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN]; 97 struct uml_tls_struct* curr = &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN];
94 98
95 /* Actually, now if it wasn't flushed it gets cleared and 99 /* Actually, now if it wasn't flushed it gets cleared and
96 * flushed to the host, which will clear it.*/ 100 * flushed to the host, which will clear it.*/
97 if (!curr->present) { 101 if (!curr->present) {
98 if (!curr->flushed) { 102 if (!curr->flushed) {
99 clear_user_desc(&curr->tls); 103 clear_user_desc(&curr->tls);
100 curr->tls.entry_number = idx; 104 curr->tls.entry_number = idx;
101 } else { 105 } else {
102 WARN_ON(!LDT_empty(&curr->tls)); 106 WARN_ON(!LDT_empty(&curr->tls));
103 continue; 107 continue;
104 } 108 }
105 } 109 }
106 110
107 if (!(flags & O_FORCE) && curr->flushed) 111 if (!(flags & O_FORCE) && curr->flushed)
108 continue; 112 continue;
109 113
110 ret = do_set_thread_area(&curr->tls); 114 ret = do_set_thread_area(&curr->tls);
111 if (ret) 115 if (ret)
112 goto out; 116 goto out;
113 117
114 curr->flushed = 1; 118 curr->flushed = 1;
115 } 119 }
116 out: 120 out:
117 return ret; 121 return ret;
118 } 122 }
119 123
120 /* Verify if we need to do a flush for the new process, i.e. if there are any 124 /* Verify if we need to do a flush for the new process, i.e. if there are any
121 * present desc's, only if they haven't been flushed. 125 * present desc's, only if they haven't been flushed.
122 */ 126 */
123 static inline int needs_TLS_update(struct task_struct *task) 127 static inline int needs_TLS_update(struct task_struct *task)
124 { 128 {
125 int i; 129 int i;
126 int ret = 0; 130 int ret = 0;
127 131
128 for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { 132 for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
129 struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; 133 struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
130 134
131 /* Can't test curr->present, we may need to clear a descriptor 135 /* Can't test curr->present, we may need to clear a descriptor
132 * which had a value. */ 136 * which had a value. */
133 if (curr->flushed) 137 if (curr->flushed)
134 continue; 138 continue;
135 ret = 1; 139 ret = 1;
136 break; 140 break;
137 } 141 }
138 return ret; 142 return ret;
139 } 143 }
140 144
141 /* On a newly forked process, the TLS descriptors haven't yet been flushed. So 145 /* On a newly forked process, the TLS descriptors haven't yet been flushed. So
142 * we mark them as such and the first switch_to will do the job. 146 * we mark them as such and the first switch_to will do the job.
143 */ 147 */
144 void clear_flushed_tls(struct task_struct *task) 148 void clear_flushed_tls(struct task_struct *task)
145 { 149 {
146 int i; 150 int i;
147 151
148 for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { 152 for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) {
149 struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; 153 struct uml_tls_struct* curr = &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN];
150 154
151 /* Still correct to do this, if it wasn't present on the host it 155 /* Still correct to do this, if it wasn't present on the host it
152 * will remain as flushed as it was. */ 156 * will remain as flushed as it was. */
153 if (!curr->present) 157 if (!curr->present)
154 continue; 158 continue;
155 159
156 curr->flushed = 0; 160 curr->flushed = 0;
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. */
168 if (likely(to->mm)) 181 if (likely(to->mm))
169 return load_TLS(O_FORCE, to); 182 return load_TLS(O_FORCE, to);
170 183
171 return 0; 184 return 0;
172 } 185 }
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
179 return 0; 195 return 0;
180 } 196 }
181 197
182 static int set_tls_entry(struct task_struct* task, struct user_desc *info, 198 static int set_tls_entry(struct task_struct* task, struct user_desc *info,
183 int idx, int flushed) 199 int idx, int flushed)
184 { 200 {
185 struct thread_struct *t = &task->thread; 201 struct thread_struct *t = &task->thread;
186 202
187 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) 203 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
188 return -EINVAL; 204 return -EINVAL;
189 205
190 t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info; 206 t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info;
191 t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1; 207 t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1;
192 t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed; 208 t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed;
193 209
194 return 0; 210 return 0;
195 } 211 }
196 212
197 int arch_copy_tls(struct task_struct *new) 213 int arch_copy_tls(struct task_struct *new)
198 { 214 {
199 struct user_desc info; 215 struct user_desc info;
200 int idx, ret = -EFAULT; 216 int idx, ret = -EFAULT;
201 217
202 if (copy_from_user(&info, 218 if (copy_from_user(&info,
203 (void __user *) UPT_ESI(&new->thread.regs.regs), 219 (void __user *) UPT_ESI(&new->thread.regs.regs),
204 sizeof(info))) 220 sizeof(info)))
205 goto out; 221 goto out;
206 222
207 ret = -EINVAL; 223 ret = -EINVAL;
208 if (LDT_empty(&info)) 224 if (LDT_empty(&info))
209 goto out; 225 goto out;
210 226
211 idx = info.entry_number; 227 idx = info.entry_number;
212 228
213 ret = set_tls_entry(new, &info, idx, 0); 229 ret = set_tls_entry(new, &info, idx, 0);
214 out: 230 out:
215 return ret; 231 return ret;
216 } 232 }
217 233
218 /* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */ 234 /* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
219 static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx) 235 static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx)
220 { 236 {
221 struct thread_struct *t = &task->thread; 237 struct thread_struct *t = &task->thread;
222 238
223 if (!t->arch.tls_array) 239 if (!t->arch.tls_array)
224 goto clear; 240 goto clear;
225 241
226 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) 242 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
227 return -EINVAL; 243 return -EINVAL;
228 244
229 if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present) 245 if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present)
230 goto clear; 246 goto clear;
231 247
232 *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls; 248 *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls;
233 249
234 out: 250 out:
235 /* Temporary debugging check, to make sure that things have been 251 /* Temporary debugging check, to make sure that things have been
236 * flushed. This could be triggered if load_TLS() failed. 252 * flushed. This could be triggered if load_TLS() failed.
237 */ 253 */
238 if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { 254 if (unlikely(task == current && !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) {
239 printk(KERN_ERR "get_tls_entry: task with pid %d got here " 255 printk(KERN_ERR "get_tls_entry: task with pid %d got here "
240 "without flushed TLS.", current->pid); 256 "without flushed TLS.", current->pid);
241 } 257 }
242 258
243 return 0; 259 return 0;
244 clear: 260 clear:
245 /* When the TLS entry has not been set, the values read to user in the 261 /* When the TLS entry has not been set, the values read to user in the
246 * tls_array are 0 (because it's cleared at boot, see 262 * tls_array are 0 (because it's cleared at boot, see
247 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that. 263 * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that.
248 */ 264 */
249 clear_user_desc(info); 265 clear_user_desc(info);
250 info->entry_number = idx; 266 info->entry_number = idx;
251 goto out; 267 goto out;
252 } 268 }
253 269
254 asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc) 270 asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
255 { 271 {
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
262 idx = info.entry_number; 281 idx = info.entry_number;
263 282
264 if (idx == -1) { 283 if (idx == -1) {
265 idx = get_free_idx(current); 284 idx = get_free_idx(current);
266 if (idx < 0) 285 if (idx < 0)
267 return idx; 286 return idx;
268 info.entry_number = idx; 287 info.entry_number = idx;
269 /* Tell the user which slot we chose for him.*/ 288 /* Tell the user which slot we chose for him.*/
270 if (put_user(idx, &user_desc->entry_number)) 289 if (put_user(idx, &user_desc->entry_number))
271 return -EFAULT; 290 return -EFAULT;
272 } 291 }
273 292
274 ret = CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, &info); 293 ret = CHOOSE_MODE_PROC(do_set_thread_area_tt, do_set_thread_area_skas, &info);
275 if (ret) 294 if (ret)
276 return ret; 295 return ret;
277 return set_tls_entry(current, &info, idx, 1); 296 return set_tls_entry(current, &info, idx, 1);
278 } 297 }
279 298
280 /* 299 /*
281 * Perform set_thread_area on behalf of the traced child. 300 * Perform set_thread_area on behalf of the traced child.
282 * Note: error handling is not done on the deferred load, and this differ from 301 * Note: error handling is not done on the deferred load, and this differ from
283 * i386. However the only possible error are caused by bugs. 302 * i386. However the only possible error are caused by bugs.
284 */ 303 */
285 int ptrace_set_thread_area(struct task_struct *child, int idx, 304 int ptrace_set_thread_area(struct task_struct *child, int idx,
286 struct user_desc __user *user_desc) 305 struct user_desc __user *user_desc)
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
293 return set_tls_entry(child, &info, idx, 0); 315 return set_tls_entry(child, &info, idx, 0);
294 } 316 }
295 317
296 asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc) 318 asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc)
297 { 319 {
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
304 ret = get_tls_entry(current, &info, idx); 329 ret = get_tls_entry(current, &info, idx);
305 if (ret < 0) 330 if (ret < 0)
306 goto out; 331 goto out;
307 332
308 if (copy_to_user(user_desc, &info, sizeof(info))) 333 if (copy_to_user(user_desc, &info, sizeof(info)))
309 ret = -EFAULT; 334 ret = -EFAULT;
310 335
311 out: 336 out:
312 return ret; 337 return ret;
313 } 338 }
314 339
315 /* 340 /*
316 * Perform get_thread_area on behalf of the traced child. 341 * Perform get_thread_area on behalf of the traced child.
317 */ 342 */
318 int ptrace_get_thread_area(struct task_struct *child, int idx, 343 int ptrace_get_thread_area(struct task_struct *child, int idx,
319 struct user_desc __user *user_desc) 344 struct user_desc __user *user_desc)
320 { 345 {
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;
327 355
328 if (copy_to_user(user_desc, &info, sizeof(info))) 356 if (copy_to_user(user_desc, &info, sizeof(info)))
329 ret = -EFAULT; 357 ret = -EFAULT;
330 out: 358 out:
331 return ret; 359 return ret;
332 } 360 }
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);
333 385
include/asm-um/segment.h
1 #ifndef __UM_SEGMENT_H 1 #ifndef __UM_SEGMENT_H
2 #define __UM_SEGMENT_H 2 #define __UM_SEGMENT_H
3 3
4 #include "asm/arch/segment.h" 4 extern int host_gdt_entry_tls_min;
5
6 #define GDT_ENTRY_TLS_ENTRIES 3
7 #define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min
8 #define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
5 9
6 #endif 10 #endif
7 11