xref: /linux/arch/x86/um/os-Linux/tls.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
25c48b108SAl Viro #include <errno.h>
35c48b108SAl Viro #include <linux/unistd.h>
45c48b108SAl Viro 
51bbd5f21SAl Viro #include <sys/ptrace.h>
65c48b108SAl Viro #include <sys/syscall.h>
75c48b108SAl Viro #include <unistd.h>
85c48b108SAl Viro 
9*9ffc6724STiwei Bie #include <os.h>
1037185b33SAl Viro #include <sysdep/tls.h>
115c48b108SAl Viro 
121bbd5f21SAl Viro #ifndef PTRACE_GET_THREAD_AREA
131bbd5f21SAl Viro #define PTRACE_GET_THREAD_AREA 25
141bbd5f21SAl Viro #endif
151bbd5f21SAl Viro 
161bbd5f21SAl Viro #ifndef PTRACE_SET_THREAD_AREA
171bbd5f21SAl Viro #define PTRACE_SET_THREAD_AREA 26
181bbd5f21SAl Viro #endif
191bbd5f21SAl Viro 
205c48b108SAl Viro /* Checks whether host supports TLS, and sets *tls_min according to the value
215c48b108SAl Viro  * valid on the host.
225c48b108SAl Viro  * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */
231bbd5f21SAl Viro void check_host_supports_tls(int *supports_tls, int *tls_min)
241bbd5f21SAl Viro {
255c48b108SAl Viro 	/* Values for x86 and x86_64.*/
265c48b108SAl Viro 	int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64};
275c48b108SAl Viro 	int i;
285c48b108SAl Viro 
295c48b108SAl Viro 	for (i = 0; i < ARRAY_SIZE(val); i++) {
305c48b108SAl Viro 		user_desc_t info;
315c48b108SAl Viro 		info.entry_number = val[i];
325c48b108SAl Viro 
335c48b108SAl Viro 		if (syscall(__NR_get_thread_area, &info) == 0) {
345c48b108SAl Viro 			*tls_min = val[i];
355c48b108SAl Viro 			*supports_tls = 1;
365c48b108SAl Viro 			return;
375c48b108SAl Viro 		} else {
385c48b108SAl Viro 			if (errno == EINVAL)
395c48b108SAl Viro 				continue;
405c48b108SAl Viro 			else if (errno == ENOSYS)
415c48b108SAl Viro 				*supports_tls = 0;
425c48b108SAl Viro 			return;
435c48b108SAl Viro 		}
445c48b108SAl Viro 	}
455c48b108SAl Viro 
465c48b108SAl Viro 	*supports_tls = 0;
475c48b108SAl Viro }
481bbd5f21SAl Viro 
491bbd5f21SAl Viro int os_set_thread_area(user_desc_t *info, int pid)
501bbd5f21SAl Viro {
511bbd5f21SAl Viro 	int ret;
521bbd5f21SAl Viro 
531bbd5f21SAl Viro 	ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
541bbd5f21SAl Viro 		     (unsigned long) info);
551bbd5f21SAl Viro 	if (ret < 0)
561bbd5f21SAl Viro 		ret = -errno;
571bbd5f21SAl Viro 	return ret;
581bbd5f21SAl Viro }
591bbd5f21SAl Viro 
601bbd5f21SAl Viro int os_get_thread_area(user_desc_t *info, int pid)
611bbd5f21SAl Viro {
621bbd5f21SAl Viro 	int ret;
631bbd5f21SAl Viro 
641bbd5f21SAl Viro 	ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
651bbd5f21SAl Viro 		     (unsigned long) info);
661bbd5f21SAl Viro 	if (ret < 0)
671bbd5f21SAl Viro 		ret = -errno;
681bbd5f21SAl Viro 	return ret;
691bbd5f21SAl Viro }
70