2 * Userspace implementations of __get_datapage
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef __VDSO_DATAPAGE_H
18 #define __VDSO_DATAPAGE_H
20 #include <linux/bitops.h>
21 #include <linux/types.h>
22 #include <asm/vdso_datapage.h>
25 * We use the hidden visibility to prevent the compiler from generating a GOT
26 * relocation. Not only is going through a GOT useless (the entry couldn't and
27 * mustn't be overridden by another library), it does not even work: the linker
28 * cannot generate an absolute address to the data page.
30 * With the hidden visibility, the compiler simply generates a PC-relative
31 * relocation (R_ARM_REL32), and this is what we need.
33 extern const struct vdso_data _vdso_data
__attribute__((visibility("hidden")));
35 static inline const struct vdso_data
*__get_datapage(void)
37 const struct vdso_data
*ret
;
39 * This simply puts &_vdso_data into ret. The reason why we don't use
40 * `ret = &_vdso_data` is that the compiler tends to optimise this in a
41 * very suboptimal way: instead of keeping &_vdso_data in a register,
42 * it goes through a relocation almost every time _vdso_data must be
43 * accessed (even in subfunctions). This is both time and space
44 * consuming: each relocation uses a word in the code section, and it
45 * has to be loaded at runtime.
47 * This trick hides the assignment from the compiler. Since it cannot
48 * track where the pointer comes from, it will only use one relocation
49 * where __get_datapage() is called, and then keep the result in a
52 asm("" : "=r"(ret
) : "0"(&_vdso_data
));
56 /* We can only guarantee 56 bits of precision. */
57 #define ARCH_CLOCK_FIXED_MASK GENMASK_ULL(55, 0)
59 #endif /* __VDSO_DATAPAGE_H */