Commit 154d1c6c authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

vdso: parasite -- Prepare new vdso mark structure.

Because of new vvar area we need to carry the
address of vvar proxy inside the mark. Thus
add members needed and update routines.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Acked-by: 's avatarAndrew Vagin <avagin@parallels.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 993205e3
......@@ -12,7 +12,9 @@ struct vm_area_list;
#define VDSO_PROT (PROT_READ | PROT_EXEC)
#define VDSO_BAD_ADDR (-1ul)
#define VVAR_BAD_ADDR VDSO_BAD_ADDR
#define VDSO_BAD_PFN (-1ull)
#define VVAR_BAD_PFN VDSO_BAD_PFN
struct vdso_symbol {
char name[32];
......@@ -43,6 +45,8 @@ enum {
struct vdso_symtable {
unsigned long vma_start;
unsigned long vma_end;
unsigned long vvar_start;
unsigned long vvar_end;
struct vdso_symbol symbols[VDSO_SYMBOL_MAX];
};
......@@ -50,6 +54,8 @@ struct vdso_symtable {
{ \
.vma_start = VDSO_BAD_ADDR, \
.vma_end = VDSO_BAD_ADDR, \
.vvar_start = VVAR_BAD_ADDR, \
.vvar_end = VVAR_BAD_ADDR, \
.symbols = { \
[0 ... VDSO_SYMBOL_MAX - 1] = \
(struct vdso_symbol)VDSO_SYMBOL_INIT, \
......@@ -78,26 +84,49 @@ static inline unsigned long vdso_vma_size(struct vdso_symtable *t)
*/
struct vdso_mark {
u64 signature;
unsigned long proxy_addr;
unsigned long proxy_vdso_addr;
unsigned long version;
/*
* In case of new vDSO format the VVAR area address
* neeed for easier discovering where it lives without
* relying on procfs output.
*/
unsigned long proxy_vvar_addr;
};
/* Magic number (criuvdso) */
#define VDSO_MARK_SIGNATURE (0x6f73647675697263ULL)
#define VDSO_MARK_SIGNATURE (0x6f73647675697263ULL) /* Magic number (criuvdso) */
#define VDSO_MARK_SIGNATURE_V2 (0x4f53447675697263ULL) /* Magic number (criuvDSO) */
static inline bool is_vdso_mark(void *addr)
static inline void vdso_put_mark(void *where, unsigned long proxy_vdso_addr, unsigned long proxy_vvar_addr)
{
struct vdso_mark *m = addr;
struct vdso_mark *m = where;
return m->signature == VDSO_MARK_SIGNATURE &&
m->proxy_addr != VDSO_BAD_ADDR;
m->signature = VDSO_MARK_SIGNATURE_V2;
m->proxy_vdso_addr = proxy_vdso_addr;
m->version = 2;
m->proxy_vvar_addr = proxy_vvar_addr;
}
static inline void vdso_put_mark(void *where, unsigned long proxy_addr)
static inline bool is_vdso_mark(void *addr)
{
struct vdso_mark *m = where;
struct vdso_mark *m = addr;
m->signature = VDSO_MARK_SIGNATURE;
m->proxy_addr = proxy_addr;
if (m->signature == VDSO_MARK_SIGNATURE_V2) {
/*
* New format
*/
return m->version == 2;
} else if (m->signature == VDSO_MARK_SIGNATURE) {
/*
* Old format -- simply extend the mark up
* to the version we support.
*/
vdso_put_mark(m, m->proxy_vdso_addr, VVAR_BAD_ADDR);
return true;
}
return false;
}
#define VDSO_SYMBOL_CLOCK_GETTIME_NAME "__vdso_clock_gettime"
......
......@@ -321,7 +321,7 @@ int vdso_proxify(char *who, struct vdso_symtable *sym_rt, VmaEntry *vma, unsigne
* it's auto-generated every new session if proxy required.
*/
sys_mprotect((void *)vdso_rt_parked_at, vdso_vma_size(sym_rt), PROT_WRITE);
vdso_put_mark((void *)vdso_rt_parked_at, vma->start);
vdso_put_mark((void *)vdso_rt_parked_at, vma->start, VVAR_BAD_ADDR);
sys_mprotect((void *)vdso_rt_parked_at, vdso_vma_size(sym_rt), VDSO_PROT);
return 0;
}
......@@ -84,10 +84,10 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
* Defer handling marked vdso.
*/
if (unlikely(args->is_marked)) {
BUG_ON(args->proxy_addr == VDSO_BAD_ADDR);
BUG_ON(args->proxy_vdso_addr == VDSO_BAD_ADDR);
BUG_ON(marked);
marked = vma;
proxy_addr = args->proxy_addr;
proxy_addr = args->proxy_vdso_addr;
continue;
}
......
......@@ -87,7 +87,8 @@ struct parasite_vma_entry
struct parasite_vdso_vma_entry {
unsigned long start;
unsigned long len;
unsigned long proxy_addr;
unsigned long proxy_vdso_addr;
unsigned long proxy_vvar_addr;
int is_marked;
};
......
......@@ -332,10 +332,12 @@ static int parasite_check_vdso_mark(struct parasite_vdso_vma_entry *args)
if (is_vdso_mark(m)) {
args->is_marked = 1;
args->proxy_addr = m->proxy_addr;
args->proxy_vdso_addr = m->proxy_vdso_addr;
args->proxy_vvar_addr = m->proxy_vvar_addr;
} else {
args->is_marked = 0;
args->proxy_addr = VDSO_BAD_ADDR;
args->proxy_vdso_addr = VDSO_BAD_ADDR;
args->proxy_vvar_addr = VVAR_BAD_ADDR;
}
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment