[CRIU] [PATCHv3 20/23] parasite/x86: always try to dump TLS

Dmitry Safonov dsafonov at virtuozzo.com
Fri Dec 9 10:19:46 PST 2016


As 64-bit parasite is now in 32-bit compat app and
64-bit applications can also have TLS in GDT - simplify and
just always dump TLS with 32-bit syscall get_thread_area,
it's 3 syscalls more - but that's a low cost for that.

Note that entry point for sys_get_thread_area() is only for 32-bits,
so we need to call raw int80 here with 32-bit syscall number.

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/arch/x86/include/asm/parasite.h | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/criu/arch/x86/include/asm/parasite.h b/criu/arch/x86/include/asm/parasite.h
index 7f9c16033067..302b412afa9c 100644
--- a/criu/arch/x86/include/asm/parasite.h
+++ b/criu/arch/x86/include/asm/parasite.h
@@ -2,21 +2,15 @@
 #define __ASM_PARASITE_H__
 
 #include "asm-generic/string.h"
+#include <compel/plugins/std/syscall-codes.h>
 
 #ifdef CONFIG_X86_32
 # define __parasite_entry __attribute__((regparm(3)))
 #endif
 
-#ifdef CONFIG_X86_32
-static void arch_get_user_desc(user_desc_t *desc)
-{
-	if (sys_get_thread_area(desc))
-		pr_err("Failed to dump TLS descriptor #%d\n",
-				desc->entry_number);
-}
-#else /* !X86_32 */
 static void arch_get_user_desc(user_desc_t *desc)
 {
+	int ret = __NR32_get_thread_area;
 	/*
 	 * For 64-bit applications, TLS (fs_base for Glibc) is
 	 * in MSR, which are dumped with the help of arch_prctl().
@@ -35,14 +29,24 @@ static void arch_get_user_desc(user_desc_t *desc)
 	 * #endif
 	 *	...
 	 * };
-	 *
-	 * For this mixed code we may want to call get_thread_area
-	 * 32-bit syscall. But as additional three calls to kernel
-	 * will slow dumping, I omit it here.
 	 */
-	desc->seg_not_present = 1;
+	asm volatile (
+	"       mov %0,%%eax                    \n"
+	"       mov %1,%%rbx                    \n"
+	"	int $0x80			\n"
+	"	mov %%eax,%0			\n"
+	: "+m"(ret)
+	: "m"(desc)
+	: "eax", "rbx", "memory");
+
+	/*
+	 * Fixup for Travis: on missing GDT entry get_thread_area()
+	 * retruns -EINTR then descriptor with seg_not_preset = 1
+	 */
+	if (ret)
+		pr_err("Failed to dump TLS descriptor #%d: %d\n",
+				desc->entry_number, ret);
 }
-#endif /* !X86_32 */
 
 static void arch_get_tls(tls_t *ptls)
 {
@@ -53,6 +57,7 @@ static void arch_get_tls(tls_t *ptls)
 		user_desc_t *d = &ptls->desc[i];
 
 		builtin_memset(d, 0, sizeof(user_desc_t));
+		d->seg_not_present = 1;
 		d->entry_number = GDT_ENTRY_TLS_MIN + i;
 		arch_get_user_desc(d);
 	}
-- 
2.10.2



More information about the CRIU mailing list