xref: /linux/arch/x86/um/os-Linux/tls.c (revision 1bbd5f21f426d99660ea8120b79595a282e5ff8a)
15c48b108SAl Viro #include <errno.h>
25c48b108SAl Viro #include <linux/unistd.h>
35c48b108SAl Viro 
4*1bbd5f21SAl Viro #include <sys/ptrace.h>
55c48b108SAl Viro #include <sys/syscall.h>
65c48b108SAl Viro #include <unistd.h>
75c48b108SAl Viro 
85c48b108SAl Viro #include "sysdep/tls.h"
95c48b108SAl Viro 
10*1bbd5f21SAl Viro #ifndef PTRACE_GET_THREAD_AREA
11*1bbd5f21SAl Viro #define PTRACE_GET_THREAD_AREA 25
12*1bbd5f21SAl Viro #endif
13*1bbd5f21SAl Viro 
14*1bbd5f21SAl Viro #ifndef PTRACE_SET_THREAD_AREA
15*1bbd5f21SAl Viro #define PTRACE_SET_THREAD_AREA 26
16*1bbd5f21SAl Viro #endif
17*1bbd5f21SAl Viro 
185c48b108SAl Viro /* Checks whether host supports TLS, and sets *tls_min according to the value
195c48b108SAl Viro  * valid on the host.
205c48b108SAl Viro  * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
21*1bbd5f21SAl Viro void check_host_supports_tls(int *supports_tls, int *tls_min)
22*1bbd5f21SAl Viro {
235c48b108SAl Viro 	/* Values for x86 and x86_64.*/
245c48b108SAl Viro 	int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
255c48b108SAl Viro 	int i;
265c48b108SAl Viro 
275c48b108SAl Viro 	for (i = 0; i < ARRAY_SIZE(val); i++) {
285c48b108SAl Viro 		user_desc_t info;
295c48b108SAl Viro 		info.entry_number = val[i];
305c48b108SAl Viro 
315c48b108SAl Viro 		if (syscall(__NR_get_thread_area, &info) == 0) {
325c48b108SAl Viro 			*tls_min = val[i];
335c48b108SAl Viro 			*supports_tls = 1;
345c48b108SAl Viro 			return;
355c48b108SAl Viro 		} else {
365c48b108SAl Viro 			if (errno == EINVAL)
375c48b108SAl Viro 				continue;
385c48b108SAl Viro 			else if (errno == ENOSYS)
395c48b108SAl Viro 				*supports_tls = 0;
405c48b108SAl Viro 				return;
415c48b108SAl Viro 		}
425c48b108SAl Viro 	}
435c48b108SAl Viro 
445c48b108SAl Viro 	*supports_tls = 0;
455c48b108SAl Viro }
46*1bbd5f21SAl Viro 
47*1bbd5f21SAl Viro int os_set_thread_area(user_desc_t *info, int pid)
48*1bbd5f21SAl Viro {
49*1bbd5f21SAl Viro 	int ret;
50*1bbd5f21SAl Viro 
51*1bbd5f21SAl Viro 	ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
52*1bbd5f21SAl Viro 		     (unsigned long) info);
53*1bbd5f21SAl Viro 	if (ret < 0)
54*1bbd5f21SAl Viro 		ret = -errno;
55*1bbd5f21SAl Viro 	return ret;
56*1bbd5f21SAl Viro }
57*1bbd5f21SAl Viro 
58*1bbd5f21SAl Viro int os_get_thread_area(user_desc_t *info, int pid)
59*1bbd5f21SAl Viro {
60*1bbd5f21SAl Viro 	int ret;
61*1bbd5f21SAl Viro 
62*1bbd5f21SAl Viro 	ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
63*1bbd5f21SAl Viro 		     (unsigned long) info);
64*1bbd5f21SAl Viro 	if (ret < 0)
65*1bbd5f21SAl Viro 		ret = -errno;
66*1bbd5f21SAl Viro 	return ret;
67*1bbd5f21SAl Viro }
68