vdso: Move parking into a separate routine

Since we might have a several vDSO zones lets hide
handling in arch-specific routines.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Cyrill Gorcunov 2014-07-18 18:44:52 +04:00 committed by Pavel Emelyanov
parent 6906e1a830
commit 6446fd2c1d
4 changed files with 32 additions and 11 deletions

View file

@ -146,7 +146,7 @@ extern struct vdso_symtable vdso_sym_rt;
extern u64 vdso_pfn;
extern int vdso_init(void);
extern int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size);
extern int vdso_do_park(struct vdso_symtable *sym_rt, unsigned long park_at, unsigned long park_size);
extern int vdso_fill_symtable(char *mem, size_t size, struct vdso_symtable *t);
extern int vdso_proxify(char *who, struct vdso_symtable *sym_rt,
VmaEntry *vdso_vma, VmaEntry *vvar_vma,

View file

@ -19,6 +19,7 @@
#include "vdso.h"
#include "vma.h"
#include "log.h"
#include "bug.h"
#ifdef LOG_PREFIX
# undef LOG_PREFIX
@ -246,7 +247,7 @@ err_oob:
return -EFAULT;
}
int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size)
static int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size)
{
unsigned long addr;
@ -262,6 +263,33 @@ int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size)
return 0;
}
/* Park runtime vDSO in some safe place where it can be accessible from restorer */
int vdso_do_park(struct vdso_symtable *sym_rt, unsigned long park_at, unsigned long park_size)
{
int ret;
BUG_ON((vdso_vma_size(sym_rt) + vvar_vma_size(sym_rt)) < park_size);
if (sym_rt->vvar_start != VDSO_BAD_ADDR) {
if (sym_rt->vma_start < sym_rt->vvar_start) {
ret = vdso_remap("rt-vdso", sym_rt->vma_start,
park_at, vdso_vma_size(sym_rt));
park_at += vdso_vma_size(sym_rt);
ret |= vdso_remap("rt-vvar", sym_rt->vvar_start,
park_at, vvar_vma_size(sym_rt));
} else {
ret = vdso_remap("rt-vvar", sym_rt->vvar_start,
park_at, vvar_vma_size(sym_rt));
park_at += vvar_vma_size(sym_rt);
ret |= vdso_remap("rt-vdso", sym_rt->vma_start,
park_at, vdso_vma_size(sym_rt));
}
} else
ret = vdso_remap("rt-vdso", sym_rt->vma_start,
park_at, vdso_vma_size(sym_rt));
return ret;
}
int vdso_proxify(char *who, struct vdso_symtable *sym_rt,
VmaEntry *vdso_vma, VmaEntry *vvar_vma,
unsigned long vdso_rt_parked_at)

View file

@ -15,6 +15,7 @@
#define vdso_init() (0)
#define parasite_fixup_vdso(ctl, pid, vma_area_list) (0)
#define vdso_vma_size(t) (0)
#define vdso_do_park(sym_rt, park_at, park_size) (0)
#define vdso_remap(who, from, to, size) (0)
#define vdso_proxify(who, sym_rt, vdso_vma, \
vvar_vma, vdso_rt_parked_at) (0)

View file

@ -701,16 +701,8 @@ long __export_restore_task(struct task_restore_args *args)
pr_info("Switched to the restorer %d\n", my_pid);
#ifdef CONFIG_VDSO
if (vdso_remap("rt-vdso", args->vdso_sym_rt.vma_start,
args->vdso_rt_parked_at,
vdso_vma_size(&args->vdso_sym_rt)))
if (vdso_do_park(&args->vdso_sym_rt, args->vdso_rt_parked_at, vdso_rt_size))
goto core_restore_end;
if (args->vdso_sym_rt.vvar_start != VVAR_BAD_ADDR) {
if (vdso_remap("rt-vvar", args->vdso_sym_rt.vvar_start,
args->vdso_rt_parked_at + vdso_vma_size(&args->vdso_sym_rt),
vvar_vma_size(&args->vdso_sym_rt)))
goto core_restore_end;
}
#endif
if (unmap_old_vmas((void *)args->premmapped_addr, args->premmapped_len,