Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/vdso/datapage.h
26285 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
#ifndef __VDSO_DATAPAGE_H
3
#define __VDSO_DATAPAGE_H
4
5
#ifndef __ASSEMBLY__
6
7
#include <linux/compiler.h>
8
#include <uapi/linux/bits.h>
9
#include <uapi/linux/time.h>
10
#include <uapi/linux/types.h>
11
#include <uapi/asm-generic/errno-base.h>
12
13
#include <vdso/align.h>
14
#include <vdso/bits.h>
15
#include <vdso/cache.h>
16
#include <vdso/clocksource.h>
17
#include <vdso/ktime.h>
18
#include <vdso/limits.h>
19
#include <vdso/math64.h>
20
#include <vdso/page.h>
21
#include <vdso/processor.h>
22
#include <vdso/time.h>
23
#include <vdso/time32.h>
24
#include <vdso/time64.h>
25
26
#ifdef CONFIG_ARCH_HAS_VDSO_TIME_DATA
27
#include <asm/vdso/time_data.h>
28
#else
29
struct arch_vdso_time_data {};
30
#endif
31
32
#if defined(CONFIG_ARCH_HAS_VDSO_ARCH_DATA)
33
#include <asm/vdso/arch_data.h>
34
#elif defined(CONFIG_GENERIC_VDSO_DATA_STORE)
35
struct vdso_arch_data {
36
/* Needed for the generic code, never actually used at runtime */
37
char __unused;
38
};
39
#endif
40
41
#define VDSO_BASES (CLOCK_TAI + 1)
42
#define VDSO_BASE_AUX 0
43
#define VDSO_HRES (BIT(CLOCK_REALTIME) | \
44
BIT(CLOCK_MONOTONIC) | \
45
BIT(CLOCK_BOOTTIME) | \
46
BIT(CLOCK_TAI))
47
#define VDSO_COARSE (BIT(CLOCK_REALTIME_COARSE) | \
48
BIT(CLOCK_MONOTONIC_COARSE))
49
#define VDSO_RAW (BIT(CLOCK_MONOTONIC_RAW))
50
#define VDSO_AUX __GENMASK(CLOCK_AUX_LAST, CLOCK_AUX)
51
52
#define CS_HRES_COARSE 0
53
#define CS_RAW 1
54
#define CS_BASES (CS_RAW + 1)
55
56
/**
57
* struct vdso_timestamp - basetime per clock_id
58
* @sec: seconds
59
* @nsec: nanoseconds
60
*
61
* There is one vdso_timestamp object in vvar for each vDSO-accelerated
62
* clock_id. For high-resolution clocks, this encodes the time
63
* corresponding to vdso_time_data.cycle_last. For coarse clocks this encodes
64
* the actual time.
65
*
66
* To be noticed that for highres clocks nsec is left-shifted by
67
* vdso_time_data[x].shift.
68
*/
69
struct vdso_timestamp {
70
u64 sec;
71
u64 nsec;
72
};
73
74
/**
75
* struct vdso_clock - vdso per clocksource datapage representation
76
* @seq: timebase sequence counter
77
* @clock_mode: clock mode
78
* @cycle_last: timebase at clocksource init
79
* @max_cycles: maximum cycles which won't overflow 64bit multiplication
80
* @mask: clocksource mask
81
* @mult: clocksource multiplier
82
* @shift: clocksource shift
83
* @basetime[clock_id]: basetime per clock_id
84
* @offset[clock_id]: time namespace offset per clock_id
85
*
86
* See also struct vdso_time_data for basic access and ordering information as
87
* struct vdso_clock is used there.
88
*
89
* @basetime is used to store the base time for the system wide time getter
90
* VVAR page.
91
*
92
* @offset is used by the special time namespace VVAR pages which are
93
* installed instead of the real VVAR page. These namespace pages must set
94
* @seq to 1 and @clock_mode to VDSO_CLOCKMODE_TIMENS to force the code into
95
* the time namespace slow path. The namespace aware functions retrieve the
96
* real system wide VVAR page, read host time and add the per clock offset.
97
* For clocks which are not affected by time namespace adjustment the
98
* offset must be zero.
99
*/
100
struct vdso_clock {
101
u32 seq;
102
103
s32 clock_mode;
104
u64 cycle_last;
105
#ifdef CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT
106
u64 max_cycles;
107
#endif
108
u64 mask;
109
u32 mult;
110
u32 shift;
111
112
union {
113
struct vdso_timestamp basetime[VDSO_BASES];
114
struct timens_offset offset[VDSO_BASES];
115
};
116
};
117
118
/**
119
* struct vdso_time_data - vdso datapage representation
120
* @arch_data: architecture specific data (optional, defaults
121
* to an empty struct)
122
* @clock_data: clocksource related data (array)
123
* @aux_clock_data: auxiliary clocksource related data (array)
124
* @tz_minuteswest: minutes west of Greenwich
125
* @tz_dsttime: type of DST correction
126
* @hrtimer_res: hrtimer resolution
127
* @__unused: unused
128
*
129
* vdso_time_data will be accessed by 64 bit and compat code at the same time
130
* so we should be careful before modifying this structure.
131
*
132
* The ordering of the struct members is optimized to have fast acces to the
133
* often required struct members which are related to CLOCK_REALTIME and
134
* CLOCK_MONOTONIC. This information is stored in the first cache lines.
135
*/
136
struct vdso_time_data {
137
struct arch_vdso_time_data arch_data;
138
139
struct vdso_clock clock_data[CS_BASES];
140
struct vdso_clock aux_clock_data[MAX_AUX_CLOCKS];
141
142
s32 tz_minuteswest;
143
s32 tz_dsttime;
144
u32 hrtimer_res;
145
u32 __unused;
146
} ____cacheline_aligned;
147
148
/**
149
* struct vdso_rng_data - vdso RNG state information
150
* @generation: counter representing the number of RNG reseeds
151
* @is_ready: boolean signaling whether the RNG is initialized
152
*/
153
struct vdso_rng_data {
154
u64 generation;
155
u8 is_ready;
156
};
157
158
/*
159
* We use the hidden visibility to prevent the compiler from generating a GOT
160
* relocation. Not only is going through a GOT useless (the entry couldn't and
161
* must not be overridden by another library), it does not even work: the linker
162
* cannot generate an absolute address to the data page.
163
*
164
* With the hidden visibility, the compiler simply generates a PC-relative
165
* relocation, and this is what we need.
166
*/
167
#ifdef CONFIG_GENERIC_VDSO_DATA_STORE
168
extern struct vdso_time_data vdso_u_time_data __attribute__((visibility("hidden")));
169
extern struct vdso_rng_data vdso_u_rng_data __attribute__((visibility("hidden")));
170
extern struct vdso_arch_data vdso_u_arch_data __attribute__((visibility("hidden")));
171
172
extern struct vdso_time_data *vdso_k_time_data;
173
extern struct vdso_rng_data *vdso_k_rng_data;
174
extern struct vdso_arch_data *vdso_k_arch_data;
175
176
#define VDSO_ARCH_DATA_SIZE ALIGN(sizeof(struct vdso_arch_data), PAGE_SIZE)
177
#define VDSO_ARCH_DATA_PAGES (VDSO_ARCH_DATA_SIZE >> PAGE_SHIFT)
178
179
enum vdso_pages {
180
VDSO_TIME_PAGE_OFFSET,
181
VDSO_TIMENS_PAGE_OFFSET,
182
VDSO_RNG_PAGE_OFFSET,
183
VDSO_ARCH_PAGES_START,
184
VDSO_ARCH_PAGES_END = VDSO_ARCH_PAGES_START + VDSO_ARCH_DATA_PAGES - 1,
185
VDSO_NR_PAGES
186
};
187
188
#endif /* CONFIG_GENERIC_VDSO_DATA_STORE */
189
190
/*
191
* The generic vDSO implementation requires that gettimeofday.h
192
* provides:
193
* - __arch_get_hw_counter(): to get the hw counter based on the
194
* clock_mode.
195
* - gettimeofday_fallback(): fallback for gettimeofday.
196
* - clock_gettime_fallback(): fallback for clock_gettime.
197
* - clock_getres_fallback(): fallback for clock_getres.
198
*/
199
#ifdef ENABLE_COMPAT_VDSO
200
#include <asm/vdso/compat_gettimeofday.h>
201
#else
202
#include <asm/vdso/gettimeofday.h>
203
#endif /* ENABLE_COMPAT_VDSO */
204
205
#else /* !__ASSEMBLY__ */
206
207
#ifdef CONFIG_VDSO_GETRANDOM
208
#define __vdso_u_rng_data PROVIDE(vdso_u_rng_data = vdso_u_data + 2 * PAGE_SIZE);
209
#else
210
#define __vdso_u_rng_data
211
#endif
212
213
#ifdef CONFIG_ARCH_HAS_VDSO_ARCH_DATA
214
#define __vdso_u_arch_data PROVIDE(vdso_u_arch_data = vdso_u_data + 3 * PAGE_SIZE);
215
#else
216
#define __vdso_u_arch_data
217
#endif
218
219
#define VDSO_VVAR_SYMS \
220
PROVIDE(vdso_u_data = . - __VDSO_PAGES * PAGE_SIZE); \
221
PROVIDE(vdso_u_time_data = vdso_u_data); \
222
__vdso_u_rng_data \
223
__vdso_u_arch_data \
224
225
226
#endif /* !__ASSEMBLY__ */
227
228
#endif /* __VDSO_DATAPAGE_H */
229
230