Commit f9c8e3a2 authored by Pavel Emelyanov's avatar Pavel Emelyanov

pagemap: Factor out pfn retrieving for vdso and zero page

Acked-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent fe1d6d2b
......@@ -70,33 +70,10 @@ static int vdso_fill_self_symtable(struct vdso_symtable *s)
int vdso_init(void)
{
int ret = -1, fd;
off_t off;
if (vdso_fill_self_symtable(&vdso_sym_rt))
return -1;
fd = open_proc(getpid(), "pagemap");
if (fd < 0)
return -1;
off = (vdso_sym_rt.vma_start / PAGE_SIZE) * sizeof(u64);
if (lseek(fd, off, SEEK_SET) != off) {
pr_perror("Failed to seek address %lx\n", vdso_sym_rt.vma_start);
goto out;
}
ret = read(fd, &vdso_pfn, sizeof(vdso_pfn));
if (ret < 0 || ret != sizeof(vdso_pfn)) {
pr_perror("Can't read pme for pid %d", getpid());
ret = -1;
} else {
vdso_pfn = PME_PFRAME(vdso_pfn);
ret = 0;
}
out:
close(fd);
return ret;
return vaddr_to_pfn(vdso_sym_rt.vma_start, &vdso_pfn);
}
/*
......
......@@ -290,4 +290,6 @@ extern int read_fd_link(int lfd, char *buf, size_t size);
#define USEC_PER_SEC 1000000L
#define NSEC_PER_SEC 1000000000L
int vaddr_to_pfn(unsigned long vaddr, u64 *pfn);
#endif /* __CR_UTIL_H__ */
......@@ -159,9 +159,7 @@ unsigned long zero_page_pfn;
static int init_zero_page_pfn()
{
void *addr;
loff_t off;
u64 pfn;
int fd = -1;
int ret;
addr = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED) {
......@@ -171,37 +169,16 @@ static int init_zero_page_pfn()
if (*((int *) addr) != 0) {
BUG();
goto err;
}
fd = open("/proc/self/pagemap", O_RDONLY);
if (fd < 0) {
pr_perror("Unable to open /proc/self/pagemap");
goto err;
}
off = (unsigned long) addr / PAGE_SIZE * 8;
if (lseek(fd, off, SEEK_SET) != off) {
pr_perror("Can't open pagemap file");
goto err;
}
if (read(fd, &pfn, sizeof(pfn)) != sizeof(pfn)) {
pr_perror("Can't read pagemap file");
goto err;
return -1;
}
if (!(pfn & PME_PRESENT)) {
pr_err("The zero page isn't present");
goto err;
}
ret = vaddr_to_pfn((unsigned long)addr, &zero_page_pfn);
munmap(addr, PAGE_SIZE);
pfn &= PME_PFRAME_MASK;
if (zero_page_pfn == 0)
ret = -1;
zero_page_pfn = pfn;
err:
munmap(addr, PAGE_SIZE);
close_safe(&fd);
return zero_page_pfn ? 0 : -1;
return ret;
}
int kerndat_init(void)
......
......@@ -616,3 +616,29 @@ int is_root_user()
return 1;
}
int vaddr_to_pfn(unsigned long vaddr, u64 *pfn)
{
int fd, ret = -1;
off_t off;
fd = open_proc(getpid(), "pagemap");
if (fd < 0)
return -1;
off = (vaddr / PAGE_SIZE) * sizeof(u64);
if (lseek(fd, off, SEEK_SET) != off) {
pr_perror("Failed to seek address %lx\n", vaddr);
goto out;
}
ret = read(fd, pfn, sizeof(*pfn));
if (ret != sizeof(*pfn)) {
pr_perror("Can't read pme for pid %d", getpid());
ret = -1;
} else
ret = 0;
out:
close(fd);
return ret;
}
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