Commit | Line | Data |
---|---|---|
ebb5e78c AS |
1 | /* |
2 | * Copyright (C) 2015 Imagination Technologies | |
3 | * Author: Alex Smith <alex.smith@imgtec.com> | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. | |
9 | */ | |
10 | ||
11 | #include <asm/sgidefs.h> | |
12 | ||
13 | #if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT) | |
14 | ||
15 | /* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */ | |
16 | #undef CONFIG_64BIT | |
17 | #define CONFIG_32BIT 1 | |
18 | #ifndef __ASSEMBLY__ | |
19 | #include <asm-generic/atomic64.h> | |
20 | #endif | |
21 | #endif | |
22 | ||
23 | #ifndef __ASSEMBLY__ | |
24 | ||
25 | #include <asm/asm.h> | |
26 | #include <asm/page.h> | |
27 | #include <asm/vdso.h> | |
28 | ||
29 | static inline unsigned long get_vdso_base(void) | |
30 | { | |
31 | unsigned long addr; | |
32 | ||
33 | /* | |
34 | * We can't use cpu_has_mips_r6 since it needs the cpu_data[] | |
35 | * kernel symbol. | |
36 | */ | |
37 | #ifdef CONFIG_CPU_MIPSR6 | |
38 | /* | |
39 | * lapc <symbol> is an alias to addiupc reg, <symbol> - . | |
40 | * | |
41 | * We can't use addiupc because there is no label-label | |
42 | * support for the addiupc reloc | |
43 | */ | |
44 | __asm__("lapc %0, _start \n" | |
45 | : "=r" (addr) : :); | |
46 | #else | |
47 | /* | |
48 | * Get the base load address of the VDSO. We have to avoid generating | |
49 | * relocations and references to the GOT because ld.so does not peform | |
50 | * relocations on the VDSO. We use the current offset from the VDSO base | |
51 | * and perform a PC-relative branch which gives the absolute address in | |
52 | * ra, and take the difference. The assembler chokes on | |
53 | * "li %0, _start - .", so embed the offset as a word and branch over | |
54 | * it. | |
55 | * | |
56 | */ | |
57 | ||
58 | __asm__( | |
59 | " .set push \n" | |
60 | " .set noreorder \n" | |
61 | " bal 1f \n" | |
62 | " nop \n" | |
63 | " .word _start - . \n" | |
64 | "1: lw %0, 0($31) \n" | |
65 | " " STR(PTR_ADDU) " %0, $31, %0 \n" | |
66 | " .set pop \n" | |
67 | : "=r" (addr) | |
68 | : | |
69 | : "$31"); | |
70 | #endif /* CONFIG_CPU_MIPSR6 */ | |
71 | ||
72 | return addr; | |
73 | } | |
74 | ||
75 | static inline const union mips_vdso_data *get_vdso_data(void) | |
76 | { | |
77 | return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE); | |
78 | } | |
79 | ||
a7f4df4e AS |
80 | #ifdef CONFIG_CLKSRC_MIPS_GIC |
81 | ||
82 | static inline void __iomem *get_gic(const union mips_vdso_data *data) | |
83 | { | |
84 | return (void __iomem *)data - PAGE_SIZE; | |
85 | } | |
86 | ||
87 | #endif /* CONFIG_CLKSRC_MIPS_GIC */ | |
88 | ||
ebb5e78c | 89 | #endif /* __ASSEMBLY__ */ |