summaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux/tls.c')
-rw-r--r--arch/um/os-Linux/tls.c77
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 00000000000..63dfcf70937
--- /dev/null
+++ b/arch/um/os-Linux/tls.c
@@ -0,0 +1,77 @@
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <asm/ldt.h>
+#include "uml-config.h"
+
+/* TLS support - we basically rely on the host's one.*/
+
+/* In TT mode, this should be called only by the tracing thread, and makes sense
+ * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally.
+ *
+ */
+
+#ifndef PTRACE_GET_THREAD_AREA
+#define PTRACE_GET_THREAD_AREA 25
+#endif
+
+#ifndef PTRACE_SET_THREAD_AREA
+#define PTRACE_SET_THREAD_AREA 26
+#endif
+
+int os_set_thread_area(void *data, int pid)
+{
+ struct user_desc *info = data;
+ int ret;
+
+ ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number,
+ (unsigned long) info);
+ if (ret < 0)
+ ret = -errno;
+ return ret;
+}
+
+#ifdef UML_CONFIG_MODE_SKAS
+
+int os_get_thread_area(void *data, int pid)
+{
+ struct user_desc *info = data;
+ int ret;
+
+ ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number,
+ (unsigned long) info);
+ if (ret < 0)
+ ret = -errno;
+ return ret;
+}
+
+#endif
+
+#ifdef UML_CONFIG_MODE_TT
+#include "linux/unistd.h"
+
+_syscall1(int, get_thread_area, struct user_desc *, u_info);
+_syscall1(int, set_thread_area, struct user_desc *, u_info);
+
+int do_set_thread_area_tt(struct user_desc *info)
+{
+ int ret;
+
+ ret = set_thread_area(info);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ return ret;
+}
+
+int do_get_thread_area_tt(struct user_desc *info)
+{
+ int ret;
+
+ ret = get_thread_area(info);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ return ret;
+}
+
+#endif /* UML_CONFIG_MODE_TT */