[CRIU] [PATCHv1 26/26] x86-32: restore TLS
Dmitry Safonov
dsafonov at virtuozzo.com
Thu Jun 16 03:53:43 PDT 2016
Put dumped TLS descriptors back to GDT.
Do it only if it was present.
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
criu/arch/x86/include/asm/restore.h | 23 +++++++++++++-
criu/arch/x86/include/asm/restorer.h | 5 +--
criu/arch/x86/restorer.c | 61 ++++++++++++++++++++++++++++++++++++
criu/pie/Makefile | 1 +
4 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/criu/arch/x86/include/asm/restore.h b/criu/arch/x86/include/asm/restore.h
index c00553dff24a..c5aa7cdebf03 100644
--- a/criu/arch/x86/include/asm/restore.h
+++ b/criu/arch/x86/include/asm/restore.h
@@ -28,7 +28,28 @@
;
#endif /* CONFIG_X86_64 */
-#define core_get_tls(pcore, ptls)
+static inline void core_get_tls(CoreEntry *pcore, tls_t *ptls)
+{
+ ThreadInfoX86 *ti = pcore->thread_info;
+ int i;
+
+ for (i = 0; i < GDT_ENTRY_TLS_NUM; i++) {
+ user_desc_t *to = &ptls->desc[i];
+ UserDescT *from = ti->tls[i];
+
+#define COPY_TLS(field) to->field = from->field
+ COPY_TLS(entry_number);
+ COPY_TLS(base_addr);
+ COPY_TLS(limit);
+ COPY_TLS(seg_32bit);
+ to->contents = ((u32)from->contents_h << 1) | from->contents_l;
+ COPY_TLS(read_exec_only);
+ COPY_TLS(limit_in_pages);
+ COPY_TLS(seg_not_present);
+ COPY_TLS(useable);
+#undef COPY_TLS
+ }
+}
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core);
diff --git a/criu/arch/x86/include/asm/restorer.h b/criu/arch/x86/include/asm/restorer.h
index f4ba22180a39..f5065d118ddb 100644
--- a/criu/arch/x86/include/asm/restorer.h
+++ b/criu/arch/x86/include/asm/restorer.h
@@ -334,10 +334,7 @@ int restore_nonsigframe_gpregs(UserX86RegsEntry *r);
int sigreturn_prep_fpu_frame(struct rt_sigframe *sigframe,
struct rt_sigframe *rsigframe);
-static inline void restore_tls(tls_t *ptls)
-{
- (void)ptls;
-}
+void restore_tls(tls_t *ptls);
int ptrace_set_breakpoint(pid_t pid, void *addr);
int ptrace_flush_breakpoints(pid_t pid);
diff --git a/criu/arch/x86/restorer.c b/criu/arch/x86/restorer.c
index 364b156be91e..db7254f26672 100644
--- a/criu/arch/x86/restorer.c
+++ b/criu/arch/x86/restorer.c
@@ -31,3 +31,64 @@ int restore_nonsigframe_gpregs(UserX86RegsEntry *r)
#endif
return 0;
}
+
+extern unsigned long call32_from_64(void *stack, void (*function)(void));
+
+asm ( ".pushsection .text \n"
+ "restore_set_thread_area: \n"
+ ".code32 \n"
+ "mov %edx, %ebx \n"
+ "movl $"__stringify(__NR32_set_thread_area)",%eax \n"
+ "int $0x80 \n"
+ "ret \n"
+ ".code64");
+extern void restore_set_thread_area(void);
+
+static void __restore_tls(tls_t *ptls)
+{
+ char *stack32 = (void*)sys_mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ int i;
+
+ if (stack32 == MAP_FAILED) {
+ pr_err("Failed to allocate stack for 32-bit TLS restore\n");
+ return;
+ }
+
+ for (i = 0; i < GDT_ENTRY_TLS_NUM; i++) {
+ user_desc_t *desc = &ptls->desc[i];
+ int ret;
+
+ if (desc->seg_not_present)
+ continue;
+
+ memcpy(stack32, desc, sizeof(user_desc_t));
+
+ /* user_desc parameter for set_thread_area syscall */
+ asm volatile ("\t movl %%edx,%%edx\n" : :"d"(stack32));
+ call32_from_64(stack32 + PAGE_SIZE, restore_set_thread_area);
+ asm volatile ("\t movl %%eax,%0\n" : "=r"(ret));
+ if (ret)
+ pr_err("Failed to restore TLS descriptor %d in GDT ret %d\n",
+ desc->entry_number, ret);
+ }
+
+ sys_munmap(stack32, PAGE_SIZE);
+}
+
+void restore_tls(tls_t *ptls)
+{
+ int i;
+
+ for (i = 0; i < GDT_ENTRY_TLS_NUM; i++) {
+ user_desc_t *desc = &ptls->desc[i];
+
+ if (!desc->seg_not_present)
+ goto need_restore;
+ }
+
+ return;
+
+need_restore:
+ __restore_tls(ptls);
+}
diff --git a/criu/pie/Makefile b/criu/pie/Makefile
index 4adec495fe74..fee5d3c6f911 100644
--- a/criu/pie/Makefile
+++ b/criu/pie/Makefile
@@ -14,6 +14,7 @@ restorer-obj-y += ./$(ARCH_DIR)/restorer.o
ifeq ($(ARCH),x86)
restorer-obj-e += ./$(ARCH_DIR)/syscalls-64.built-in.o
+ restorer-obj-y += ./$(ARCH_DIR)/call32.o
native-obj-y += ./$(ARCH_DIR)/parasite-head-64.o
native-obj-e += ./$(ARCH_DIR)/syscalls-64.built-in.o
--
2.8.3
More information about the CRIU
mailing list