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