Linux 6.7-rc7
[linux-modified.git] / arch / mips / include / asm / vdso / vdso.h
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Copyright (C) 2015 Imagination Technologies
4  * Author: Alex Smith <alex.smith@imgtec.com>
5  */
6
7 #include <asm/sgidefs.h>
8
9 #ifndef __ASSEMBLY__
10
11 #include <asm/asm.h>
12 #include <asm/page.h>
13 #include <asm/vdso.h>
14
15 static inline unsigned long get_vdso_base(void)
16 {
17         unsigned long addr;
18
19         /*
20          * We can't use cpu_has_mips_r6 since it needs the cpu_data[]
21          * kernel symbol.
22          */
23 #ifdef CONFIG_CPU_MIPSR6
24         /*
25          * lapc <symbol> is an alias to addiupc reg, <symbol> - .
26          *
27          * We can't use addiupc because there is no label-label
28          * support for the addiupc reloc
29          */
30         __asm__("lapc   %0, _start                      \n"
31                 : "=r" (addr) : :);
32 #else
33         /*
34          * Get the base load address of the VDSO. We have to avoid generating
35          * relocations and references to the GOT because ld.so does not peform
36          * relocations on the VDSO. We use the current offset from the VDSO base
37          * and perform a PC-relative branch which gives the absolute address in
38          * ra, and take the difference. The assembler chokes on
39          * "li %0, _start - .", so embed the offset as a word and branch over
40          * it.
41          *
42          */
43
44         __asm__(
45         "       .set push                               \n"
46         "       .set noreorder                          \n"
47         "       bal     1f                              \n"
48         "        nop                                    \n"
49         "       .word   _start - .                      \n"
50         "1:     lw      %0, 0($31)                      \n"
51         "       " STR(PTR_ADDU) " %0, $31, %0           \n"
52         "       .set pop                                \n"
53         : "=r" (addr)
54         :
55         : "$31");
56 #endif /* CONFIG_CPU_MIPSR6 */
57
58         return addr;
59 }
60
61 static inline const struct vdso_data *get_vdso_data(void)
62 {
63         return (const struct vdso_data *)(get_vdso_base() - PAGE_SIZE);
64 }
65
66 #ifdef CONFIG_CLKSRC_MIPS_GIC
67
68 static inline void __iomem *get_gic(const struct vdso_data *data)
69 {
70         return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE;
71 }
72
73 #endif /* CONFIG_CLKSRC_MIPS_GIC */
74
75 #endif /* __ASSEMBLY__ */