Skip to content

Commit 78a743c

Browse files
Tong Tiangenpalmer-dabbelt
authored andcommitted
riscv/vdso: Move vdso data page up front
As commit 601255a ("arm64: vdso: move data page before code pages"), the same issue exists on riscv, testcase is shown below, make sure that vdso.so is bigger than page size, struct timespec tp; clock_gettime(5, &tp); printf("tv_sec: %ld, tv_nsec: %ld\n", tp.tv_sec, tp.tv_nsec); without this patch, test result : tv_sec: 0, tv_nsec: 0 with this patch, test result : tv_sec: 1629271537, tv_nsec: 748000000 Move the vdso data page in front of the VDSO area to fix the issue. Fixes: ad5d112 ("riscv: use vDSO common flow to reduce the latency of the time-related functions") Signed-off-by: Tong Tiangen <[email protected]> Reviewed-by: Kefeng Wang <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent bb4a23c commit 78a743c

File tree

3 files changed

+30
-19
lines changed

3 files changed

+30
-19
lines changed

arch/riscv/include/asm/vdso.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
*/
2323
#ifdef CONFIG_MMU
2424

25+
#define __VVAR_PAGES 1
26+
2527
#ifndef __ASSEMBLY__
2628
#include <generated/vdso-offsets.h>
2729

arch/riscv/kernel/vdso.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ struct vdso_data {
2323

2424
extern char vdso_start[], vdso_end[];
2525

26+
enum vvar_pages {
27+
VVAR_DATA_PAGE_OFFSET,
28+
VVAR_NR_PAGES,
29+
};
30+
31+
#define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT)
32+
2633
static unsigned int vdso_pages __ro_after_init;
2734
static struct page **vdso_pagelist __ro_after_init;
2835

@@ -41,7 +48,7 @@ static int __init vdso_init(void)
4148

4249
vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
4350
vdso_pagelist =
44-
kcalloc(vdso_pages + 1, sizeof(struct page *), GFP_KERNEL);
51+
kcalloc(vdso_pages + VVAR_NR_PAGES, sizeof(struct page *), GFP_KERNEL);
4552
if (unlikely(vdso_pagelist == NULL)) {
4653
pr_err("vdso: pagelist allocation failed\n");
4754
return -ENOMEM;
@@ -66,7 +73,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
6673
unsigned long vdso_base, vdso_len;
6774
int ret;
6875

69-
vdso_len = (vdso_pages + 1) << PAGE_SHIFT;
76+
BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES);
77+
78+
vdso_len = (vdso_pages + VVAR_NR_PAGES) << PAGE_SHIFT;
7079

7180
mmap_write_lock(mm);
7281
vdso_base = get_unmapped_area(NULL, 0, vdso_len, 0, 0);
@@ -75,29 +84,28 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
7584
goto end;
7685
}
7786

78-
/*
79-
* Put vDSO base into mm struct. We need to do this before calling
80-
* install_special_mapping or the perf counter mmap tracking code
81-
* will fail to recognise it as a vDSO (since arch_vma_name fails).
82-
*/
83-
mm->context.vdso = (void *)vdso_base;
87+
mm->context.vdso = NULL;
88+
ret = install_special_mapping(mm, vdso_base, VVAR_SIZE,
89+
(VM_READ | VM_MAYREAD), &vdso_pagelist[vdso_pages]);
90+
if (unlikely(ret))
91+
goto end;
8492

8593
ret =
86-
install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT,
94+
install_special_mapping(mm, vdso_base + VVAR_SIZE,
95+
vdso_pages << PAGE_SHIFT,
8796
(VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC),
8897
vdso_pagelist);
8998

90-
if (unlikely(ret)) {
91-
mm->context.vdso = NULL;
99+
if (unlikely(ret))
92100
goto end;
93-
}
94101

95-
vdso_base += (vdso_pages << PAGE_SHIFT);
96-
ret = install_special_mapping(mm, vdso_base, PAGE_SIZE,
97-
(VM_READ | VM_MAYREAD), &vdso_pagelist[vdso_pages]);
102+
/*
103+
* Put vDSO base into mm struct. We need to do this before calling
104+
* install_special_mapping or the perf counter mmap tracking code
105+
* will fail to recognise it as a vDSO (since arch_vma_name fails).
106+
*/
107+
mm->context.vdso = (void *)vdso_base + VVAR_SIZE;
98108

99-
if (unlikely(ret))
100-
mm->context.vdso = NULL;
101109
end:
102110
mmap_write_unlock(mm);
103111
return ret;
@@ -108,7 +116,7 @@ const char *arch_vma_name(struct vm_area_struct *vma)
108116
if (vma->vm_mm && (vma->vm_start == (long)vma->vm_mm->context.vdso))
109117
return "[vdso]";
110118
if (vma->vm_mm && (vma->vm_start ==
111-
(long)vma->vm_mm->context.vdso + PAGE_SIZE))
119+
(long)vma->vm_mm->context.vdso - VVAR_SIZE))
112120
return "[vdso_data]";
113121
return NULL;
114122
}

arch/riscv/kernel/vdso/vdso.lds.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
* Copyright (C) 2012 Regents of the University of California
44
*/
55
#include <asm/page.h>
6+
#include <asm/vdso.h>
67

78
OUTPUT_ARCH(riscv)
89

910
SECTIONS
1011
{
11-
PROVIDE(_vdso_data = . + PAGE_SIZE);
12+
PROVIDE(_vdso_data = . - __VVAR_PAGES * PAGE_SIZE);
1213
. = SIZEOF_HEADERS;
1314

1415
.hash : { *(.hash) } :text

0 commit comments

Comments
 (0)