2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 09:58:09 +00:00

vdso: handle vvar_vclock vma-s

The vvar_vclock was introduced by [1]. Basically, the old vvar vma has
been splited on two parts. In term of C/R, these two vma-s can be still
treated as one.

[1] e93d2521b27f ("x86/vdso: Split virtual clock pages into dedicated mapping")

Signed-off-by: Andrei Vagin <avagin@google.com>
This commit is contained in:
Andrei Vagin 2024-12-05 22:17:38 +00:00 committed by Radostin Stoyanov
parent beff27eca1
commit 058572e91d
4 changed files with 59 additions and 12 deletions

View File

@ -30,6 +30,7 @@ struct vdso_symbol {
struct vdso_symtable { struct vdso_symtable {
unsigned long vdso_size; unsigned long vdso_size;
unsigned long vvar_size; unsigned long vvar_size;
unsigned long vvar_vclock_size;
struct vdso_symbol symbols[VDSO_SYMBOL_MAX]; struct vdso_symbol symbols[VDSO_SYMBOL_MAX];
bool vdso_before_vvar; /* order of vdso/vvar pair */ bool vdso_before_vvar; /* order of vdso/vvar pair */
}; };

View File

@ -45,6 +45,7 @@ static int remap_one(char *who, unsigned long *from, unsigned long to, size_t si
static int park_at(struct vdso_maps *rt, unsigned long vdso, unsigned long vvar) static int park_at(struct vdso_maps *rt, unsigned long vdso, unsigned long vvar)
{ {
unsigned long vvar_size = rt->sym.vvar_size; unsigned long vvar_size = rt->sym.vvar_size;
unsigned long vvar_vclock_size = rt->sym.vvar_vclock_size;
unsigned long vdso_size = rt->sym.vdso_size; unsigned long vdso_size = rt->sym.vdso_size;
int ret; int ret;
@ -54,8 +55,24 @@ static int park_at(struct vdso_maps *rt, unsigned long vdso, unsigned long vvar)
std_log_set_gettimeofday(NULL); /* stop using vdso for timings */ std_log_set_gettimeofday(NULL); /* stop using vdso for timings */
if (vvar) if (vvar) {
/*
* v6.13-rc1~172^2~9 splits the vvar vma in two parts vvar and
* vvar_clock. The last one is mapped right after the first
* one.
*/
if (vvar_vclock_size) {
unsigned long from;
vvar_size -= vvar_vclock_size;
from = rt->vvar_start + vvar_size;
ret = remap_one("rt-vvar", &from, vvar + vvar_size, vvar_vclock_size);
if (ret)
return ret;
}
ret = remap_one("rt-vvar", &rt->vvar_start, vvar, vvar_size); ret = remap_one("rt-vvar", &rt->vvar_start, vvar, vvar_size);
}
if (!ret) if (!ret)
vdso_update_gtod_addr(rt); vdso_update_gtod_addr(rt);

View File

@ -579,7 +579,8 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area, const char *file_pat
} else if (!strcmp(file_path, "[vdso]")) { } else if (!strcmp(file_path, "[vdso]")) {
if (handle_vdso_vma(vma_area)) if (handle_vdso_vma(vma_area))
goto err; goto err;
} else if (!strcmp(file_path, "[vvar]")) { } else if (!strcmp(file_path, "[vvar]") ||
!strcmp(file_path, "[vvar_vclock]")) {
if (handle_vvar_vma(vma_area)) if (handle_vvar_vma(vma_area))
goto err; goto err;
} else if (!strcmp(file_path, "[heap]")) { } else if (!strcmp(file_path, "[heap]")) {
@ -771,7 +772,7 @@ static int task_size_check(pid_t pid, VmaEntry *entry)
int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, dump_filemap_t dump_filemap) int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, dump_filemap_t dump_filemap)
{ {
struct vma_area *vma_area = NULL; struct vma_area *vma_area = NULL, *prev_vma_area = NULL;
unsigned long start, end, pgoff, prev_end = 0; unsigned long start, end, pgoff, prev_end = 0;
char r, w, x, s; char r, w, x, s;
int ret = -1, vm_file_fd = -1; int ret = -1, vm_file_fd = -1;
@ -813,8 +814,22 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, dump_filemap_t du
continue; continue;
} }
if (vma_area && vma_list_add(vma_area, vma_area_list, &prev_end, &vfi, &prev_vfi)) if (vma_area && vma_area_is(vma_area, VMA_AREA_VVAR) &&
goto err; prev_vma_area && vma_area_is(prev_vma_area, VMA_AREA_VVAR)) {
if (prev_vma_area->e->end != vma_area->e->start) {
pr_err("two nonconsecutive vvar vma-s: "
"%" PRIx64 "-%" PRIx64 " %" PRIx64 "-%" PRIx64 "\n",
prev_vma_area->e->start, prev_vma_area->e->end,
vma_area->e->start, vma_area->e->end);
goto err;
}
/* Merge all vvar vma-s into one. */
prev_vma_area->e->end = vma_area->e->end;
} else {
if (vma_area && vma_list_add(vma_area, vma_area_list, &prev_end, &vfi, &prev_vfi))
goto err;
prev_vma_area = vma_area;
}
if (eof) if (eof)
break; break;

View File

@ -310,7 +310,7 @@ static int vdso_parse_maps(pid_t pid, struct vdso_maps *s)
while (1) { while (1) {
unsigned long start, end; unsigned long start, end;
char *has_vdso, *has_vvar; char *has_vdso, *has_vvar, *has_vvar_vclock;
buf = breadline(&f); buf = breadline(&f);
if (buf == NULL) if (buf == NULL)
@ -318,13 +318,19 @@ static int vdso_parse_maps(pid_t pid, struct vdso_maps *s)
if (IS_ERR(buf)) if (IS_ERR(buf))
goto err; goto err;
has_vdso = strstr(buf, "[vdso]"); has_vvar = NULL;
if (!has_vdso) has_vvar_vclock = NULL;
do {
has_vdso = strstr(buf, "[vdso]");
if (has_vdso)
break;
has_vvar = strstr(buf, "[vvar]"); has_vvar = strstr(buf, "[vvar]");
else if (has_vvar)
has_vvar = NULL; break;
has_vvar_vclock = strstr(buf, "[vvar_vclock]");
} while (0);
if (!has_vdso && !has_vvar) if (!has_vdso && !has_vvar && !has_vvar_vclock)
continue; continue;
if (sscanf(buf, "%lx-%lx", &start, &end) != 2) { if (sscanf(buf, "%lx-%lx", &start, &end) != 2) {
@ -339,13 +345,21 @@ static int vdso_parse_maps(pid_t pid, struct vdso_maps *s)
} }
s->vdso_start = start; s->vdso_start = start;
s->sym.vdso_size = end - start; s->sym.vdso_size = end - start;
} else { } else if (has_vvar) {
if (s->vvar_start != VVAR_BAD_ADDR) { if (s->vvar_start != VVAR_BAD_ADDR) {
pr_err("Got second VVAR entry\n"); pr_err("Got second VVAR entry\n");
goto err; goto err;
} }
s->vvar_start = start; s->vvar_start = start;
s->sym.vvar_size = end - start; s->sym.vvar_size = end - start;
} else {
if (s->vvar_start == VDSO_BAD_ADDR ||
s->vvar_start + s->sym.vvar_size != start) {
pr_err("VVAR and VVAR_VCLOCK entries are not subsequent\n");
goto err;
}
s->sym.vvar_vclock_size = end - start;
s->sym.vvar_size += s->sym.vvar_vclock_size;
} }
} }