From b8f3fca4891b4844407caad8e9a1239ca88c7a5c Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Mon, 17 Jul 2017 15:40:00 +0300 Subject: [PATCH] vdso: Don't parse self-maps if kdat.can_map_vdso Just map vdso at restorer's parking zone, no need for searching it in CRIU and remap it to park zone. That will save some open()/read()/close() syscalls for parsing maps file. Signed-off-by: Dmitry Safonov Signed-off-by: Andrei Vagin --- criu/arch/aarch64/include/asm/restorer.h | 1 + criu/arch/arm/include/asm/restorer.h | 1 + criu/arch/ppc64/include/asm/restorer.h | 1 + criu/arch/x86/include/asm/restorer.h | 5 +++++ criu/arch/x86/restorer.c | 10 ++++++++++ criu/cr-restore.c | 1 + criu/include/restorer.h | 1 + criu/pie/parasite-vdso.c | 19 +------------------ criu/pie/restorer.c | 11 ++++++++--- criu/vdso.c | 22 +++++++++++++++------- 10 files changed, 44 insertions(+), 28 deletions(-) diff --git a/criu/arch/aarch64/include/asm/restorer.h b/criu/arch/aarch64/include/asm/restorer.h index 000d3f8ba..bef85f3a3 100644 --- a/criu/arch/aarch64/include/asm/restorer.h +++ b/criu/arch/aarch64/include/asm/restorer.h @@ -54,6 +54,7 @@ #define kdat_compatible_cr() 0 #define kdat_can_map_vdso() 0 +#define arch_map_vdso(map, compat) -1 int restore_gpregs(struct rt_sigframe *f, UserAarch64RegsEntry *r); int restore_nonsigframe_gpregs(UserAarch64RegsEntry *r); diff --git a/criu/arch/arm/include/asm/restorer.h b/criu/arch/arm/include/asm/restorer.h index 3da166a44..d9208185f 100644 --- a/criu/arch/arm/include/asm/restorer.h +++ b/criu/arch/arm/include/asm/restorer.h @@ -55,6 +55,7 @@ #define kdat_compatible_cr() 0 #define kdat_can_map_vdso() 0 +#define arch_map_vdso(map, compat) -1 int restore_gpregs(struct rt_sigframe *f, UserArmRegsEntry *r); int restore_nonsigframe_gpregs(UserArmRegsEntry *r); diff --git a/criu/arch/ppc64/include/asm/restorer.h b/criu/arch/ppc64/include/asm/restorer.h index ad9c39a78..3fffa833c 100644 --- a/criu/arch/ppc64/include/asm/restorer.h +++ b/criu/arch/ppc64/include/asm/restorer.h @@ -50,6 +50,7 @@ #define kdat_compatible_cr() 0 #define kdat_can_map_vdso() 0 +#define arch_map_vdso(map, compat) -1 int restore_gpregs(struct rt_sigframe *f, UserPpc64RegsEntry *r); int restore_nonsigframe_gpregs(UserPpc64RegsEntry *r); diff --git a/criu/arch/x86/include/asm/restorer.h b/criu/arch/x86/include/asm/restorer.h index 04509ff2f..e39675d95 100644 --- a/criu/arch/x86/include/asm/restorer.h +++ b/criu/arch/x86/include/asm/restorer.h @@ -76,6 +76,10 @@ static inline int set_compat_robust_list(uint32_t head_ptr, uint32_t len) # define ARCH_MAP_VDSO_32 0x2002 #endif +#ifndef ARCH_MAP_VDSO_64 +# define ARCH_MAP_VDSO_64 0x2003 +#endif + extern int kdat_compatible_cr(void); extern int kdat_can_map_vdso(void); @@ -114,5 +118,6 @@ int restore_nonsigframe_gpregs(UserX86RegsEntry *r); int ptrace_set_breakpoint(pid_t pid, void *addr); int ptrace_flush_breakpoints(pid_t pid); +extern int arch_map_vdso(unsigned long map_at, bool compatible); #endif diff --git a/criu/arch/x86/restorer.c b/criu/arch/x86/restorer.c index d6da030b2..2d335d5e1 100644 --- a/criu/arch/x86/restorer.c +++ b/criu/arch/x86/restorer.c @@ -13,6 +13,16 @@ #include "log.h" #include "cpu.h" +int arch_map_vdso(unsigned long map_at, bool compatible) +{ + int vdso_type = compatible ? ARCH_MAP_VDSO_32 : ARCH_MAP_VDSO_64; + + pr_debug("Mapping %s vDSO at %lx\n", + compatible ? "compatible" : "native", map_at); + + return sys_arch_prctl(vdso_type, map_at); +} + int restore_nonsigframe_gpregs(UserX86RegsEntry *r) { long ret; diff --git a/criu/cr-restore.c b/criu/cr-restore.c index d1d2b3e63..83e9de1bb 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -3310,6 +3310,7 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns task_args->vdso_rt_parked_at = (unsigned long)mem; task_args->vdso_maps_rt = vdso_maps_rt; task_args->vdso_rt_size = vdso_rt_size; + task_args->can_map_vdso = kdat.can_map_vdso; #endif new_sp = restorer_stack(task_args->t->mz); diff --git a/criu/include/restorer.h b/criu/include/restorer.h index 789064ee1..6e1c78579 100644 --- a/criu/include/restorer.h +++ b/criu/include/restorer.h @@ -191,6 +191,7 @@ struct task_restore_args { bool compatible_mode; + bool can_map_vdso; #ifdef CONFIG_VDSO unsigned long vdso_rt_size; struct vdso_maps vdso_maps_rt; /* runtime vdso symbols */ diff --git a/criu/pie/parasite-vdso.c b/criu/pie/parasite-vdso.c index a31363352..8072c11f7 100644 --- a/criu/pie/parasite-vdso.c +++ b/criu/pie/parasite-vdso.c @@ -74,19 +74,8 @@ int vdso_do_park(struct vdso_maps *rt, unsigned long park_at, return ret; } +/* XXX: move in arch/ */ #if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT) -int vdso_map_compat(unsigned long map_at) -{ - int ret; - - pr_debug("Mapping compatible vDSO at %lx\n", map_at); - - ret = sys_arch_prctl(ARCH_MAP_VDSO_32, map_at); - if (ret < 0) - return ret; - return 0; -} - int __vdso_fill_symtable(uintptr_t mem, size_t size, struct vdso_symtable *t, bool compat_vdso) { @@ -96,12 +85,6 @@ int __vdso_fill_symtable(uintptr_t mem, size_t size, return vdso_fill_symtable(mem, size, t); } #else -int vdso_map_compat(unsigned long __always_unused map_at) -{ - /* shouldn't be called on !CONFIG_COMPAT */ - BUG(); - return 0; -} int __vdso_fill_symtable(uintptr_t mem, size_t size, struct vdso_symtable *t, bool __always_unused compat_vdso) { diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c index b26cc2be3..48b064d95 100644 --- a/criu/pie/restorer.c +++ b/criu/pie/restorer.c @@ -1156,6 +1156,9 @@ static bool vdso_needs_parking(struct task_restore_args *args) if (args->compatible_mode) return false; + if (args->can_map_vdso) + return false; + return !vdso_unmapped(args); } @@ -1226,10 +1229,12 @@ long __export_restore_task(struct task_restore_args *args) bootstrap_start, bootstrap_len, args->task_size)) goto core_restore_end; - /* Map compatible vdso */ - if (!vdso_unmapped(args) && args->compatible_mode) { - if (vdso_map_compat(args->vdso_rt_parked_at)) + /* Map vdso that wasn't parked */ + if (!vdso_unmapped(args) && args->can_map_vdso) { + if (arch_map_vdso(args->vdso_rt_parked_at, + args->compatible_mode) < 0) { goto core_restore_end; + } } /* Shift private vma-s to the left */ diff --git a/criu/vdso.c b/criu/vdso.c index ce62996fb..64046bc16 100644 --- a/criu/vdso.c +++ b/criu/vdso.c @@ -572,14 +572,22 @@ int vdso_init_restore(void) if (vdso_maps.vdso_start != VDSO_BAD_ADDR) return 0; - if (vdso_parse_maps(PROC_SELF, &vdso_maps)) { - pr_err("Failed reading self/maps for filling vdso/vvar bounds\n"); - return -1; - } + /* + * Parsing self-maps here only to find vvar/vdso vmas in + * criu's address space, for further remapping to restorer's + * parking zone. Don't need to do this if map-vdso API + * is present. + */ + if (!kdat.can_map_vdso) { + if (vdso_parse_maps(PROC_SELF, &vdso_maps)) { + pr_err("Failed reading self/maps for filling vdso/vvar bounds\n"); + return -1; + } - if (!is_kdat_vdso_sym_valid()) { - pr_err("Kdat sizes of vdso/vvar differ to maps file \n"); - return -1; + if (!is_kdat_vdso_sym_valid()) { + pr_err("Kdat sizes of vdso/vvar differ to maps file \n"); + return -1; + } } vdso_maps.sym = kdat.vdso_sym;