Skip to content

Commit 2d685b7

Browse files
author
Fox Snowpatch
committed
1 parent 2dd0957 commit 2d685b7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+581
-1231
lines changed

MAINTAINERS

+1
Original file line numberDiff line numberDiff line change
@@ -9679,6 +9679,7 @@ F: include/asm-generic/vdso/vsyscall.h
96799679
F: include/vdso/
96809680
F: kernel/time/vsyscall.c
96819681
F: lib/vdso/
9682+
F: lib/vdso_kernel/
96829683

96839684
GENWQE (IBM Generic Workqueue Card)
96849685
M: Frank Haverkamp <[email protected]>

arch/Kconfig

+4
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,10 @@ config HAVE_SPARSE_SYSCALL_NR
15761576
entries at 4000, 5000 and 6000 locations. This option turns on syscall
15771577
related optimizations for a given architecture.
15781578

1579+
config ARCH_HAS_VDSO_ARCH_DATA
1580+
depends on HAVE_GENERIC_VDSO
1581+
bool
1582+
15791583
config ARCH_HAS_VDSO_TIME_DATA
15801584
bool
15811585

arch/arm/include/asm/vdso.h

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#ifdef __KERNEL__
66

7+
#define __VDSO_PAGES 4
8+
79
#ifndef __ASSEMBLY__
810

911
struct mm_struct;

arch/arm/include/asm/vdso/gettimeofday.h

+1-6
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ static inline bool arm_vdso_hres_capable(void)
112112
#define __arch_vdso_hres_capable arm_vdso_hres_capable
113113

114114
static __always_inline u64 __arch_get_hw_counter(int clock_mode,
115-
const struct vdso_data *vd)
115+
const struct vdso_time_data *vd)
116116
{
117117
#ifdef CONFIG_ARM_ARCH_TIMER
118118
u64 cycle_now;
@@ -135,11 +135,6 @@ static __always_inline u64 __arch_get_hw_counter(int clock_mode,
135135
#endif
136136
}
137137

138-
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
139-
{
140-
return _vdso_data;
141-
}
142-
143138
#endif /* !__ASSEMBLY__ */
144139

145140
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */

arch/arm/include/asm/vdso/vsyscall.h

+2-10
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,14 @@
77
#include <vdso/datapage.h>
88
#include <asm/cacheflush.h>
99

10-
extern struct vdso_data *vdso_data;
1110
extern bool cntvct_ok;
1211

1312
static __always_inline
14-
struct vdso_data *__arm_get_k_vdso_data(void)
15-
{
16-
return vdso_data;
17-
}
18-
#define __arch_get_k_vdso_data __arm_get_k_vdso_data
19-
20-
static __always_inline
21-
void __arm_sync_vdso_data(struct vdso_data *vdata)
13+
void __arm_sync_vdso_time_data(struct vdso_time_data *vdata)
2214
{
2315
flush_dcache_page(virt_to_page(vdata));
2416
}
25-
#define __arch_sync_vdso_data __arm_sync_vdso_data
17+
#define __arch_sync_vdso_time_data __arm_sync_vdso_time_data
2618

2719
/* The asm-generic header needs to be included after the definitions above */
2820
#include <asm-generic/vdso/vsyscall.h>

arch/arm/kernel/asm-offsets.c

-4
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,6 @@ int main(void)
153153
DEFINE(CACHE_WRITEBACK_ORDER, __CACHE_WRITEBACK_ORDER);
154154
DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE);
155155
BLANK();
156-
#ifdef CONFIG_VDSO
157-
DEFINE(VDSO_DATA_SIZE, sizeof(union vdso_data_store));
158-
#endif
159-
BLANK();
160156
#ifdef CONFIG_ARM_MPU
161157
DEFINE(MPU_RNG_INFO_RNGS, offsetof(struct mpu_rgn_info, rgns));
162158
DEFINE(MPU_RNG_INFO_USED, offsetof(struct mpu_rgn_info, used));

arch/arm/kernel/vdso.c

+7-27
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
#include <linux/cache.h>
10+
#include <linux/vdso_datastore.h>
1011
#include <linux/elf.h>
1112
#include <linux/err.h>
1213
#include <linux/kernel.h>
@@ -33,15 +34,6 @@ extern char vdso_start[], vdso_end[];
3334
/* Total number of pages needed for the data and text portions of the VDSO. */
3435
unsigned int vdso_total_pages __ro_after_init;
3536

36-
static union vdso_data_store vdso_data_store __page_aligned_data;
37-
struct vdso_data *vdso_data = vdso_data_store.data;
38-
39-
static struct page *vdso_data_page __ro_after_init;
40-
static const struct vm_special_mapping vdso_data_mapping = {
41-
.name = "[vvar]",
42-
.pages = &vdso_data_page,
43-
};
44-
4537
static int vdso_mremap(const struct vm_special_mapping *sm,
4638
struct vm_area_struct *new_vma)
4739
{
@@ -192,9 +184,6 @@ static int __init vdso_init(void)
192184
if (vdso_text_pagelist == NULL)
193185
return -ENOMEM;
194186

195-
/* Grab the VDSO data page. */
196-
vdso_data_page = virt_to_page(vdso_data);
197-
198187
/* Grab the VDSO text pages. */
199188
for (i = 0; i < text_pages; i++) {
200189
struct page *page;
@@ -205,7 +194,7 @@ static int __init vdso_init(void)
205194

206195
vdso_text_mapping.pages = vdso_text_pagelist;
207196

208-
vdso_total_pages = 1; /* for the data/vvar page */
197+
vdso_total_pages = VDSO_NR_PAGES; /* for the data/vvar pages */
209198
vdso_total_pages += text_pages;
210199

211200
cntvct_ok = cntvct_functional();
@@ -216,16 +205,7 @@ static int __init vdso_init(void)
216205
}
217206
arch_initcall(vdso_init);
218207

219-
static int install_vvar(struct mm_struct *mm, unsigned long addr)
220-
{
221-
struct vm_area_struct *vma;
222-
223-
vma = _install_special_mapping(mm, addr, PAGE_SIZE,
224-
VM_READ | VM_MAYREAD,
225-
&vdso_data_mapping);
226-
227-
return PTR_ERR_OR_ZERO(vma);
228-
}
208+
static_assert(__VDSO_PAGES == VDSO_NR_PAGES);
229209

230210
/* assumes mmap_lock is write-locked */
231211
void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
@@ -238,12 +218,12 @@ void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
238218
if (vdso_text_pagelist == NULL)
239219
return;
240220

241-
if (install_vvar(mm, addr))
221+
if (IS_ERR(vdso_install_vvar_mapping(mm, addr)))
242222
return;
243223

244-
/* Account for vvar page. */
245-
addr += PAGE_SIZE;
246-
len = (vdso_total_pages - 1) << PAGE_SHIFT;
224+
/* Account for vvar pages. */
225+
addr += VDSO_NR_PAGES * PAGE_SIZE;
226+
len = (vdso_total_pages - VDSO_NR_PAGES) << PAGE_SHIFT;
247227

248228
vma = _install_special_mapping(mm, addr, len,
249229
VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,

arch/arm/vdso/vdso.lds.S

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111
*/
1212

1313
#include <linux/const.h>
14-
#include <asm/asm-offsets.h>
1514
#include <asm/page.h>
1615
#include <asm/vdso.h>
16+
#include <vdso/datapage.h>
1717

1818
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
1919
OUTPUT_ARCH(arm)
2020

2121
SECTIONS
2222
{
23-
PROVIDE(_vdso_data = . - VDSO_DATA_SIZE);
23+
VDSO_VVAR_SYMS
2424

2525
. = SIZEOF_HEADERS;
2626

arch/arm64/include/asm/vdso.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#ifndef __ASM_VDSO_H
66
#define __ASM_VDSO_H
77

8-
#define __VVAR_PAGES 2
8+
#define __VDSO_PAGES 4
99

1010
#ifndef __ASSEMBLY__
1111

arch/arm64/include/asm/vdso/compat_gettimeofday.h

+17-15
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
104104
}
105105

106106
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
107-
const struct vdso_data *vd)
107+
const struct vdso_time_data *vd)
108108
{
109109
u64 res;
110110

@@ -131,43 +131,45 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
131131
return res;
132132
}
133133

134-
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
134+
static __always_inline const struct vdso_time_data *__aarch64_get_vdso_u_time_data(void)
135135
{
136-
const struct vdso_data *ret;
136+
const struct vdso_time_data *ret;
137137

138138
/*
139-
* This simply puts &_vdso_data into ret. The reason why we don't use
140-
* `ret = _vdso_data` is that the compiler tends to optimise this in a
141-
* very suboptimal way: instead of keeping &_vdso_data in a register,
142-
* it goes through a relocation almost every time _vdso_data must be
139+
* This simply puts &_vdso_time_data into ret. The reason why we don't use
140+
* `ret = _vdso_time_data` is that the compiler tends to optimise this in a
141+
* very suboptimal way: instead of keeping &_vdso_time_data in a register,
142+
* it goes through a relocation almost every time _vdso_time_data must be
143143
* accessed (even in subfunctions). This is both time and space
144144
* consuming: each relocation uses a word in the code section, and it
145145
* has to be loaded at runtime.
146146
*
147147
* This trick hides the assignment from the compiler. Since it cannot
148148
* track where the pointer comes from, it will only use one relocation
149-
* where __arch_get_vdso_data() is called, and then keep the result in
150-
* a register.
149+
* where __aarch64_get_vdso_u_time_data() is called, and then keep the
150+
* result in a register.
151151
*/
152-
asm volatile("mov %0, %1" : "=r"(ret) : "r"(_vdso_data));
152+
asm volatile("mov %0, %1" : "=r"(ret) : "r"(vdso_u_time_data));
153153

154154
return ret;
155155
}
156+
#define __arch_get_vdso_u_time_data __aarch64_get_vdso_u_time_data
156157

157158
#ifdef CONFIG_TIME_NS
158159
static __always_inline
159-
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
160+
const struct vdso_time_data *__aarch64_get_vdso_u_timens_data(void)
160161
{
161-
const struct vdso_data *ret;
162+
const struct vdso_time_data *ret;
162163

163-
/* See __arch_get_vdso_data(). */
164-
asm volatile("mov %0, %1" : "=r"(ret) : "r"(_timens_data));
164+
/* See __aarch64_get_vdso_u_time_data(). */
165+
asm volatile("mov %0, %1" : "=r"(ret) : "r"(vdso_u_timens_data));
165166

166167
return ret;
167168
}
169+
#define __arch_get_vdso_u_timens_data __aarch64_get_vdso_u_timens_data
168170
#endif
169171

170-
static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
172+
static inline bool vdso_clocksource_ok(const struct vdso_time_data *vd)
171173
{
172174
return vd->clock_mode == VDSO_CLOCKMODE_ARCHTIMER;
173175
}

arch/arm64/include/asm/vdso/getrandom.h

-12
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,6 @@ static __always_inline ssize_t getrandom_syscall(void *_buffer, size_t _len, uns
3333
return ret;
3434
}
3535

36-
static __always_inline const struct vdso_rng_data *__arch_get_vdso_rng_data(void)
37-
{
38-
/*
39-
* The RNG data is in the real VVAR data page, but if a task belongs to a time namespace
40-
* then VVAR_DATA_PAGE_OFFSET points to the namespace-specific VVAR page and VVAR_TIMENS_
41-
* PAGE_OFFSET points to the real VVAR page.
42-
*/
43-
if (IS_ENABLED(CONFIG_TIME_NS) && _vdso_data->clock_mode == VDSO_CLOCKMODE_TIMENS)
44-
return (void *)&_vdso_rng_data + VVAR_TIMENS_PAGE_OFFSET * (1UL << CONFIG_PAGE_SHIFT);
45-
return &_vdso_rng_data;
46-
}
47-
4836
#endif /* !__ASSEMBLY__ */
4937

5038
#endif /* __ASM_VDSO_GETRANDOM_H */

arch/arm64/include/asm/vdso/gettimeofday.h

+1-15
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
6767
}
6868

6969
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
70-
const struct vdso_data *vd)
70+
const struct vdso_time_data *vd)
7171
{
7272
u64 res;
7373

@@ -99,20 +99,6 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
9999
return res;
100100
}
101101

102-
static __always_inline
103-
const struct vdso_data *__arch_get_vdso_data(void)
104-
{
105-
return _vdso_data;
106-
}
107-
108-
#ifdef CONFIG_TIME_NS
109-
static __always_inline
110-
const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
111-
{
112-
return _timens_data;
113-
}
114-
#endif
115-
116102
#endif /* !__ASSEMBLY__ */
117103

118104
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */

arch/arm64/include/asm/vdso/vsyscall.h

+1-24
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,18 @@
22
#ifndef __ASM_VDSO_VSYSCALL_H
33
#define __ASM_VDSO_VSYSCALL_H
44

5-
#define __VDSO_RND_DATA_OFFSET 480
6-
75
#ifndef __ASSEMBLY__
86

97
#include <vdso/datapage.h>
108

11-
enum vvar_pages {
12-
VVAR_DATA_PAGE_OFFSET,
13-
VVAR_TIMENS_PAGE_OFFSET,
14-
VVAR_NR_PAGES,
15-
};
16-
179
#define VDSO_PRECISION_MASK ~(0xFF00ULL<<48)
1810

19-
extern struct vdso_data *vdso_data;
2011

2112
/*
2213
* Update the vDSO data page to keep in sync with kernel timekeeping.
2314
*/
2415
static __always_inline
25-
struct vdso_data *__arm64_get_k_vdso_data(void)
26-
{
27-
return vdso_data;
28-
}
29-
#define __arch_get_k_vdso_data __arm64_get_k_vdso_data
30-
31-
static __always_inline
32-
struct vdso_rng_data *__arm64_get_k_vdso_rnd_data(void)
33-
{
34-
return (void *)vdso_data + __VDSO_RND_DATA_OFFSET;
35-
}
36-
#define __arch_get_k_vdso_rng_data __arm64_get_k_vdso_rnd_data
37-
38-
static __always_inline
39-
void __arm64_update_vsyscall(struct vdso_data *vdata)
16+
void __arm64_update_vsyscall(struct vdso_time_data *vdata)
4017
{
4118
vdata[CS_HRES_COARSE].mask = VDSO_PRECISION_MASK;
4219
vdata[CS_RAW].mask = VDSO_PRECISION_MASK;

0 commit comments

Comments
 (0)