diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/vdso | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/vdso')
-rw-r--r-- | arch/mips/vdso/.gitignore | 5 | ||||
-rw-r--r-- | arch/mips/vdso/Kconfig | 18 | ||||
-rw-r--r-- | arch/mips/vdso/Makefile | 208 | ||||
-rw-r--r-- | arch/mips/vdso/config-n32-o32-env.c | 19 | ||||
-rw-r--r-- | arch/mips/vdso/elf.S | 62 | ||||
-rw-r--r-- | arch/mips/vdso/genvdso.c | 312 | ||||
-rw-r--r-- | arch/mips/vdso/genvdso.h | 132 | ||||
-rw-r--r-- | arch/mips/vdso/sigreturn.S | 35 | ||||
-rw-r--r-- | arch/mips/vdso/vdso.lds.S | 105 | ||||
-rw-r--r-- | arch/mips/vdso/vgettimeofday.c | 78 |
10 files changed, 974 insertions, 0 deletions
diff --git a/arch/mips/vdso/.gitignore b/arch/mips/vdso/.gitignore new file mode 100644 index 000000000..1f43f6dd8 --- /dev/null +++ b/arch/mips/vdso/.gitignore | |||
@@ -0,0 +1,5 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | *.so* | ||
3 | vdso-*image.c | ||
4 | genvdso | ||
5 | vdso*.lds | ||
diff --git a/arch/mips/vdso/Kconfig b/arch/mips/vdso/Kconfig new file mode 100644 index 000000000..7aec72139 --- /dev/null +++ b/arch/mips/vdso/Kconfig | |||
@@ -0,0 +1,18 @@ | |||
1 | # For the pre-R6 code in arch/mips/vdso/vdso.h for locating | ||
2 | # the base address of VDSO, the linker will emit a R_MIPS_PC32 | ||
3 | # relocation in binutils > 2.25 but it will fail with older versions | ||
4 | # because that relocation is not supported for that symbol. As a result | ||
5 | # of which we are forced to disable the VDSO symbols when building | ||
6 | # with < 2.25 binutils on pre-R6 kernels. For more references on why we | ||
7 | # can't use other methods to get the base address of VDSO please refer to | ||
8 | # the comments on that file. | ||
9 | # | ||
10 | # GCC (at least up to version 9.2) appears to emit function calls that make use | ||
11 | # of the GOT when targeting microMIPS, which we can't use in the VDSO due to | ||
12 | # the lack of relocations. As such, we disable the VDSO for microMIPS builds. | ||
13 | |||
14 | config MIPS_LD_CAN_LINK_VDSO | ||
15 | def_bool LD_VERSION >= 225000000 || LD_IS_LLD | ||
16 | |||
17 | config MIPS_DISABLE_VDSO | ||
18 | def_bool CPU_MICROMIPS || (!CPU_MIPSR6 && !MIPS_LD_CAN_LINK_VDSO) | ||
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile new file mode 100644 index 000000000..2131d3fd7 --- /dev/null +++ b/arch/mips/vdso/Makefile | |||
@@ -0,0 +1,208 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | # Objects to go into the VDSO. | ||
3 | |||
4 | # Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before | ||
5 | # the inclusion of generic Makefile. | ||
6 | ARCH_REL_TYPE_ABS := R_MIPS_JUMP_SLOT|R_MIPS_GLOB_DAT | ||
7 | include $(srctree)/lib/vdso/Makefile | ||
8 | |||
9 | obj-vdso-y := elf.o vgettimeofday.o sigreturn.o | ||
10 | |||
11 | # Common compiler flags between ABIs. | ||
12 | ccflags-vdso := \ | ||
13 | $(filter -I%,$(KBUILD_CFLAGS)) \ | ||
14 | $(filter -E%,$(KBUILD_CFLAGS)) \ | ||
15 | $(filter -mmicromips,$(KBUILD_CFLAGS)) \ | ||
16 | $(filter -march=%,$(KBUILD_CFLAGS)) \ | ||
17 | $(filter -m%-float,$(KBUILD_CFLAGS)) \ | ||
18 | $(filter -mno-loongson-%,$(KBUILD_CFLAGS)) \ | ||
19 | $(CLANG_FLAGS) \ | ||
20 | -D__VDSO__ | ||
21 | |||
22 | ifndef CONFIG_64BIT | ||
23 | ccflags-vdso += -DBUILD_VDSO32 | ||
24 | endif | ||
25 | |||
26 | # | ||
27 | # The -fno-jump-tables flag only prevents the compiler from generating | ||
28 | # jump tables but does not prevent the compiler from emitting absolute | ||
29 | # offsets. | ||
30 | cflags-vdso := $(ccflags-vdso) \ | ||
31 | $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ | ||
32 | -O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \ | ||
33 | -mrelax-pic-calls $(call cc-option, -mexplicit-relocs) \ | ||
34 | -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \ | ||
35 | $(call cc-option, -fno-asynchronous-unwind-tables) | ||
36 | aflags-vdso := $(ccflags-vdso) \ | ||
37 | -D__ASSEMBLY__ -Wa,-gdwarf-2 | ||
38 | |||
39 | ifneq ($(c-gettimeofday-y),) | ||
40 | CFLAGS_vgettimeofday.o = -include $(c-gettimeofday-y) | ||
41 | |||
42 | # config-n32-o32-env.c prepares the environment to build a 32bit vDSO | ||
43 | # library on a 64bit kernel. | ||
44 | # Note: Needs to be included before than the generic library. | ||
45 | CFLAGS_vgettimeofday-o32.o = -include $(srctree)/$(src)/config-n32-o32-env.c -include $(c-gettimeofday-y) | ||
46 | CFLAGS_vgettimeofday-n32.o = -include $(srctree)/$(src)/config-n32-o32-env.c -include $(c-gettimeofday-y) | ||
47 | endif | ||
48 | |||
49 | CFLAGS_REMOVE_vgettimeofday.o = -pg | ||
50 | |||
51 | ifdef CONFIG_MIPS_DISABLE_VDSO | ||
52 | ifndef CONFIG_MIPS_LD_CAN_LINK_VDSO | ||
53 | $(warning MIPS VDSO requires binutils >= 2.25) | ||
54 | endif | ||
55 | obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y)) | ||
56 | endif | ||
57 | |||
58 | # VDSO linker flags. | ||
59 | ldflags-y := -Bsymbolic --no-undefined -soname=linux-vdso.so.1 \ | ||
60 | $(filter -E%,$(KBUILD_CFLAGS)) -nostdlib -shared \ | ||
61 | -G 0 --eh-frame-hdr --hash-style=sysv --build-id=sha1 -T | ||
62 | |||
63 | CFLAGS_REMOVE_vdso.o = -pg | ||
64 | |||
65 | GCOV_PROFILE := n | ||
66 | UBSAN_SANITIZE := n | ||
67 | KCOV_INSTRUMENT := n | ||
68 | |||
69 | # Check that we don't have PIC 'jalr t9' calls left | ||
70 | quiet_cmd_vdso_mips_check = VDSOCHK $@ | ||
71 | cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | egrep -h "jalr.*t9" > /dev/null; \ | ||
72 | then (echo >&2 "$@: PIC 'jalr t9' calls are not supported"; \ | ||
73 | rm -f $@; /bin/false); fi | ||
74 | |||
75 | # | ||
76 | # Shared build commands. | ||
77 | # | ||
78 | |||
79 | quiet_cmd_vdsold_and_vdso_check = LD $@ | ||
80 | cmd_vdsold_and_vdso_check = $(cmd_ld); $(cmd_vdso_check); $(cmd_vdso_mips_check) | ||
81 | |||
82 | quiet_cmd_vdsoas_o_S = AS $@ | ||
83 | cmd_vdsoas_o_S = $(CC) $(a_flags) -c -o $@ $< | ||
84 | |||
85 | # Strip rule for the raw .so files | ||
86 | $(obj)/%.so.raw: OBJCOPYFLAGS := -S | ||
87 | $(obj)/%.so.raw: $(obj)/%.so.dbg.raw FORCE | ||
88 | $(call if_changed,objcopy) | ||
89 | |||
90 | hostprogs := genvdso | ||
91 | |||
92 | quiet_cmd_genvdso = GENVDSO $@ | ||
93 | define cmd_genvdso | ||
94 | $(foreach file,$(filter %.raw,$^),cp $(file) $(file:%.raw=%) &&) \ | ||
95 | $(obj)/genvdso $(<:%.raw=%) $(<:%.dbg.raw=%) $@ $(VDSO_NAME) | ||
96 | endef | ||
97 | |||
98 | # | ||
99 | # Build native VDSO. | ||
100 | # | ||
101 | |||
102 | native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS)) | ||
103 | |||
104 | targets += $(obj-vdso-y) | ||
105 | targets += vdso.lds | ||
106 | targets += vdso.so.dbg.raw vdso.so.raw | ||
107 | targets += vdso.so.dbg vdso.so | ||
108 | targets += vdso-image.c | ||
109 | |||
110 | obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o) | ||
111 | |||
112 | $(obj-vdso): KBUILD_CFLAGS := $(cflags-vdso) $(native-abi) | ||
113 | $(obj-vdso): KBUILD_AFLAGS := $(aflags-vdso) $(native-abi) | ||
114 | |||
115 | $(obj)/vdso.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) $(native-abi) | ||
116 | |||
117 | $(obj)/vdso.so.dbg.raw: $(obj)/vdso.lds $(obj-vdso) FORCE | ||
118 | $(call if_changed,vdsold_and_vdso_check) | ||
119 | |||
120 | $(obj)/vdso-image.c: $(obj)/vdso.so.dbg.raw $(obj)/vdso.so.raw \ | ||
121 | $(obj)/genvdso FORCE | ||
122 | $(call if_changed,genvdso) | ||
123 | |||
124 | obj-y += vdso-image.o | ||
125 | |||
126 | # | ||
127 | # Build O32 VDSO. | ||
128 | # | ||
129 | |||
130 | # Define these outside the ifdef to ensure they are picked up by clean. | ||
131 | targets += $(obj-vdso-y:%.o=%-o32.o) | ||
132 | targets += vdso-o32.lds | ||
133 | targets += vdso-o32.so.dbg.raw vdso-o32.so.raw | ||
134 | targets += vdso-o32.so.dbg vdso-o32.so | ||
135 | targets += vdso-o32-image.c | ||
136 | |||
137 | ifdef CONFIG_MIPS32_O32 | ||
138 | |||
139 | obj-vdso-o32 := $(obj-vdso-y:%.o=$(obj)/%-o32.o) | ||
140 | |||
141 | $(obj-vdso-o32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=32 | ||
142 | $(obj-vdso-o32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=32 | ||
143 | |||
144 | $(obj)/%-o32.o: $(src)/%.S FORCE | ||
145 | $(call if_changed_dep,vdsoas_o_S) | ||
146 | |||
147 | $(obj)/%-o32.o: $(src)/%.c FORCE | ||
148 | $(call cmd,force_checksrc) | ||
149 | $(call if_changed_rule,cc_o_c) | ||
150 | |||
151 | $(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=32 | ||
152 | $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE | ||
153 | $(call if_changed_dep,cpp_lds_S) | ||
154 | |||
155 | $(obj)/vdso-o32.so.dbg.raw: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE | ||
156 | $(call if_changed,vdsold_and_vdso_check) | ||
157 | |||
158 | $(obj)/vdso-o32-image.c: VDSO_NAME := o32 | ||
159 | $(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg.raw $(obj)/vdso-o32.so.raw \ | ||
160 | $(obj)/genvdso FORCE | ||
161 | $(call if_changed,genvdso) | ||
162 | |||
163 | obj-y += vdso-o32-image.o | ||
164 | |||
165 | endif | ||
166 | |||
167 | # | ||
168 | # Build N32 VDSO. | ||
169 | # | ||
170 | |||
171 | targets += $(obj-vdso-y:%.o=%-n32.o) | ||
172 | targets += vdso-n32.lds | ||
173 | targets += vdso-n32.so.dbg.raw vdso-n32.so.raw | ||
174 | targets += vdso-n32.so.dbg vdso-n32.so | ||
175 | targets += vdso-n32-image.c | ||
176 | |||
177 | ifdef CONFIG_MIPS32_N32 | ||
178 | |||
179 | obj-vdso-n32 := $(obj-vdso-y:%.o=$(obj)/%-n32.o) | ||
180 | |||
181 | $(obj-vdso-n32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=n32 | ||
182 | $(obj-vdso-n32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=n32 | ||
183 | |||
184 | $(obj)/%-n32.o: $(src)/%.S FORCE | ||
185 | $(call if_changed_dep,vdsoas_o_S) | ||
186 | |||
187 | $(obj)/%-n32.o: $(src)/%.c FORCE | ||
188 | $(call cmd,force_checksrc) | ||
189 | $(call if_changed_rule,cc_o_c) | ||
190 | |||
191 | $(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=n32 | ||
192 | $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE | ||
193 | $(call if_changed_dep,cpp_lds_S) | ||
194 | |||
195 | $(obj)/vdso-n32.so.dbg.raw: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE | ||
196 | $(call if_changed,vdsold_and_vdso_check) | ||
197 | |||
198 | $(obj)/vdso-n32-image.c: VDSO_NAME := n32 | ||
199 | $(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg.raw $(obj)/vdso-n32.so.raw \ | ||
200 | $(obj)/genvdso FORCE | ||
201 | $(call if_changed,genvdso) | ||
202 | |||
203 | obj-y += vdso-n32-image.o | ||
204 | |||
205 | endif | ||
206 | |||
207 | # FIXME: Need install rule for debug. | ||
208 | # Needs to deal with dependency for generation of dbg by cmd_genvdso... | ||
diff --git a/arch/mips/vdso/config-n32-o32-env.c b/arch/mips/vdso/config-n32-o32-env.c new file mode 100644 index 000000000..0011a632a --- /dev/null +++ b/arch/mips/vdso/config-n32-o32-env.c | |||
@@ -0,0 +1,19 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Configuration file for O32 and N32 binaries. | ||
4 | * Note: To be included before lib/vdso/gettimeofday.c | ||
5 | */ | ||
6 | #if defined(CONFIG_MIPS32_O32) || defined(CONFIG_MIPS32_N32) | ||
7 | /* | ||
8 | * In case of a 32 bit VDSO for a 64 bit kernel fake a 32 bit kernel | ||
9 | * configuration. | ||
10 | */ | ||
11 | #undef CONFIG_64BIT | ||
12 | |||
13 | #define BUILD_VDSO32 | ||
14 | #define CONFIG_32BIT 1 | ||
15 | #define CONFIG_GENERIC_ATOMIC64 1 | ||
16 | #define BUILD_VDSO32_64 | ||
17 | |||
18 | #endif | ||
19 | |||
diff --git a/arch/mips/vdso/elf.S b/arch/mips/vdso/elf.S new file mode 100644 index 000000000..a25cb147f --- /dev/null +++ b/arch/mips/vdso/elf.S | |||
@@ -0,0 +1,62 @@ | |||
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/vdso/vdso.h> | ||
8 | |||
9 | #include <asm/isa-rev.h> | ||
10 | |||
11 | #include <linux/elfnote.h> | ||
12 | #include <linux/version.h> | ||
13 | |||
14 | ELFNOTE_START(Linux, 0, "a") | ||
15 | .long LINUX_VERSION_CODE | ||
16 | ELFNOTE_END | ||
17 | |||
18 | /* | ||
19 | * The .MIPS.abiflags section must be defined with the FP ABI flags set | ||
20 | * to 'any' to be able to link with both old and new libraries. | ||
21 | * Newer toolchains are capable of automatically generating this, but we want | ||
22 | * to work with older toolchains as well. Therefore, we define the contents of | ||
23 | * this section here (under different names), and then genvdso will patch | ||
24 | * it to have the correct name and type. | ||
25 | * | ||
26 | * We base the .MIPS.abiflags section on preprocessor definitions rather than | ||
27 | * CONFIG_* because we need to match the particular ABI we are building the | ||
28 | * VDSO for. | ||
29 | * | ||
30 | * See https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking | ||
31 | * for the .MIPS.abiflags section description. | ||
32 | */ | ||
33 | |||
34 | .section .mips_abiflags, "a" | ||
35 | .align 3 | ||
36 | __mips_abiflags: | ||
37 | .hword 0 /* version */ | ||
38 | .byte __mips /* isa_level */ | ||
39 | |||
40 | /* isa_rev */ | ||
41 | .byte MIPS_ISA_REV | ||
42 | |||
43 | /* gpr_size */ | ||
44 | #ifdef __mips64 | ||
45 | .byte 2 /* AFL_REG_64 */ | ||
46 | #else | ||
47 | .byte 1 /* AFL_REG_32 */ | ||
48 | #endif | ||
49 | |||
50 | /* cpr1_size */ | ||
51 | #if (MIPS_ISA_REV >= 6) || defined(__mips64) | ||
52 | .byte 2 /* AFL_REG_64 */ | ||
53 | #else | ||
54 | .byte 1 /* AFL_REG_32 */ | ||
55 | #endif | ||
56 | |||
57 | .byte 0 /* cpr2_size (AFL_REG_NONE) */ | ||
58 | .byte 0 /* fp_abi (Val_GNU_MIPS_ABI_FP_ANY) */ | ||
59 | .word 0 /* isa_ext */ | ||
60 | .word 0 /* ases */ | ||
61 | .word 0 /* flags1 */ | ||
62 | .word 0 /* flags2 */ | ||
diff --git a/arch/mips/vdso/genvdso.c b/arch/mips/vdso/genvdso.c new file mode 100644 index 000000000..abb06ae04 --- /dev/null +++ b/arch/mips/vdso/genvdso.c | |||
@@ -0,0 +1,312 @@ | |||
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 | /* | ||
8 | * This tool is used to generate the real VDSO images from the raw image. It | ||
9 | * first patches up the MIPS ABI flags and GNU attributes sections defined in | ||
10 | * elf.S to have the correct name and type. It then generates a C source file | ||
11 | * to be compiled into the kernel containing the VDSO image data and a | ||
12 | * mips_vdso_image struct for it, including symbol offsets extracted from the | ||
13 | * image. | ||
14 | * | ||
15 | * We need to be passed both a stripped and unstripped VDSO image. The stripped | ||
16 | * image is compiled into the kernel, but we must also patch up the unstripped | ||
17 | * image's ABI flags sections so that it can be installed and used for | ||
18 | * debugging. | ||
19 | */ | ||
20 | |||
21 | #include <sys/mman.h> | ||
22 | #include <sys/stat.h> | ||
23 | #include <sys/types.h> | ||
24 | |||
25 | #include <byteswap.h> | ||
26 | #include <elf.h> | ||
27 | #include <errno.h> | ||
28 | #include <fcntl.h> | ||
29 | #include <inttypes.h> | ||
30 | #include <stdarg.h> | ||
31 | #include <stdbool.h> | ||
32 | #include <stdio.h> | ||
33 | #include <stdlib.h> | ||
34 | #include <string.h> | ||
35 | #include <unistd.h> | ||
36 | |||
37 | /* Define these in case the system elf.h is not new enough to have them. */ | ||
38 | #ifndef SHT_GNU_ATTRIBUTES | ||
39 | # define SHT_GNU_ATTRIBUTES 0x6ffffff5 | ||
40 | #endif | ||
41 | #ifndef SHT_MIPS_ABIFLAGS | ||
42 | # define SHT_MIPS_ABIFLAGS 0x7000002a | ||
43 | #endif | ||
44 | |||
45 | enum { | ||
46 | ABI_O32 = (1 << 0), | ||
47 | ABI_N32 = (1 << 1), | ||
48 | ABI_N64 = (1 << 2), | ||
49 | |||
50 | ABI_ALL = ABI_O32 | ABI_N32 | ABI_N64, | ||
51 | }; | ||
52 | |||
53 | /* Symbols the kernel requires offsets for. */ | ||
54 | static struct { | ||
55 | const char *name; | ||
56 | const char *offset_name; | ||
57 | unsigned int abis; | ||
58 | } vdso_symbols[] = { | ||
59 | { "__vdso_sigreturn", "off_sigreturn", ABI_O32 }, | ||
60 | { "__vdso_rt_sigreturn", "off_rt_sigreturn", ABI_ALL }, | ||
61 | {} | ||
62 | }; | ||
63 | |||
64 | static const char *program_name; | ||
65 | static const char *vdso_name; | ||
66 | static unsigned char elf_class; | ||
67 | static unsigned int elf_abi; | ||
68 | static bool need_swap; | ||
69 | static FILE *out_file; | ||
70 | |||
71 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | ||
72 | # define HOST_ORDER ELFDATA2LSB | ||
73 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | ||
74 | # define HOST_ORDER ELFDATA2MSB | ||
75 | #endif | ||
76 | |||
77 | #define BUILD_SWAP(bits) \ | ||
78 | static uint##bits##_t swap_uint##bits(uint##bits##_t val) \ | ||
79 | { \ | ||
80 | return need_swap ? bswap_##bits(val) : val; \ | ||
81 | } | ||
82 | |||
83 | BUILD_SWAP(16) | ||
84 | BUILD_SWAP(32) | ||
85 | BUILD_SWAP(64) | ||
86 | |||
87 | #define __FUNC(name, bits) name##bits | ||
88 | #define _FUNC(name, bits) __FUNC(name, bits) | ||
89 | #define FUNC(name) _FUNC(name, ELF_BITS) | ||
90 | |||
91 | #define __ELF(x, bits) Elf##bits##_##x | ||
92 | #define _ELF(x, bits) __ELF(x, bits) | ||
93 | #define ELF(x) _ELF(x, ELF_BITS) | ||
94 | |||
95 | /* | ||
96 | * Include genvdso.h twice with ELF_BITS defined differently to get functions | ||
97 | * for both ELF32 and ELF64. | ||
98 | */ | ||
99 | |||
100 | #define ELF_BITS 64 | ||
101 | #include "genvdso.h" | ||
102 | #undef ELF_BITS | ||
103 | |||
104 | #define ELF_BITS 32 | ||
105 | #include "genvdso.h" | ||
106 | #undef ELF_BITS | ||
107 | |||
108 | static void *map_vdso(const char *path, size_t *_size) | ||
109 | { | ||
110 | int fd; | ||
111 | struct stat stat; | ||
112 | void *addr; | ||
113 | const Elf32_Ehdr *ehdr; | ||
114 | |||
115 | fd = open(path, O_RDWR); | ||
116 | if (fd < 0) { | ||
117 | fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name, | ||
118 | path, strerror(errno)); | ||
119 | return NULL; | ||
120 | } | ||
121 | |||
122 | if (fstat(fd, &stat) != 0) { | ||
123 | fprintf(stderr, "%s: Failed to stat '%s': %s\n", program_name, | ||
124 | path, strerror(errno)); | ||
125 | close(fd); | ||
126 | return NULL; | ||
127 | } | ||
128 | |||
129 | addr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, | ||
130 | 0); | ||
131 | if (addr == MAP_FAILED) { | ||
132 | fprintf(stderr, "%s: Failed to map '%s': %s\n", program_name, | ||
133 | path, strerror(errno)); | ||
134 | close(fd); | ||
135 | return NULL; | ||
136 | } | ||
137 | |||
138 | /* ELF32/64 header formats are the same for the bits we're checking. */ | ||
139 | ehdr = addr; | ||
140 | |||
141 | if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) { | ||
142 | fprintf(stderr, "%s: '%s' is not an ELF file\n", program_name, | ||
143 | path); | ||
144 | close(fd); | ||
145 | return NULL; | ||
146 | } | ||
147 | |||
148 | elf_class = ehdr->e_ident[EI_CLASS]; | ||
149 | switch (elf_class) { | ||
150 | case ELFCLASS32: | ||
151 | case ELFCLASS64: | ||
152 | break; | ||
153 | default: | ||
154 | fprintf(stderr, "%s: '%s' has invalid ELF class\n", | ||
155 | program_name, path); | ||
156 | close(fd); | ||
157 | return NULL; | ||
158 | } | ||
159 | |||
160 | switch (ehdr->e_ident[EI_DATA]) { | ||
161 | case ELFDATA2LSB: | ||
162 | case ELFDATA2MSB: | ||
163 | need_swap = ehdr->e_ident[EI_DATA] != HOST_ORDER; | ||
164 | break; | ||
165 | default: | ||
166 | fprintf(stderr, "%s: '%s' has invalid ELF data order\n", | ||
167 | program_name, path); | ||
168 | close(fd); | ||
169 | return NULL; | ||
170 | } | ||
171 | |||
172 | if (swap_uint16(ehdr->e_machine) != EM_MIPS) { | ||
173 | fprintf(stderr, | ||
174 | "%s: '%s' has invalid ELF machine (expected EM_MIPS)\n", | ||
175 | program_name, path); | ||
176 | close(fd); | ||
177 | return NULL; | ||
178 | } else if (swap_uint16(ehdr->e_type) != ET_DYN) { | ||
179 | fprintf(stderr, | ||
180 | "%s: '%s' has invalid ELF type (expected ET_DYN)\n", | ||
181 | program_name, path); | ||
182 | close(fd); | ||
183 | return NULL; | ||
184 | } | ||
185 | |||
186 | *_size = stat.st_size; | ||
187 | close(fd); | ||
188 | return addr; | ||
189 | } | ||
190 | |||
191 | static bool patch_vdso(const char *path, void *vdso) | ||
192 | { | ||
193 | if (elf_class == ELFCLASS64) | ||
194 | return patch_vdso64(path, vdso); | ||
195 | else | ||
196 | return patch_vdso32(path, vdso); | ||
197 | } | ||
198 | |||
199 | static bool get_symbols(const char *path, void *vdso) | ||
200 | { | ||
201 | if (elf_class == ELFCLASS64) | ||
202 | return get_symbols64(path, vdso); | ||
203 | else | ||
204 | return get_symbols32(path, vdso); | ||
205 | } | ||
206 | |||
207 | int main(int argc, char **argv) | ||
208 | { | ||
209 | const char *dbg_vdso_path, *vdso_path, *out_path; | ||
210 | void *dbg_vdso, *vdso; | ||
211 | size_t dbg_vdso_size, vdso_size, i; | ||
212 | |||
213 | program_name = argv[0]; | ||
214 | |||
215 | if (argc < 4 || argc > 5) { | ||
216 | fprintf(stderr, | ||
217 | "Usage: %s <debug VDSO> <stripped VDSO> <output file> [<name>]\n", | ||
218 | program_name); | ||
219 | return EXIT_FAILURE; | ||
220 | } | ||
221 | |||
222 | dbg_vdso_path = argv[1]; | ||
223 | vdso_path = argv[2]; | ||
224 | out_path = argv[3]; | ||
225 | vdso_name = (argc > 4) ? argv[4] : ""; | ||
226 | |||
227 | dbg_vdso = map_vdso(dbg_vdso_path, &dbg_vdso_size); | ||
228 | if (!dbg_vdso) | ||
229 | return EXIT_FAILURE; | ||
230 | |||
231 | vdso = map_vdso(vdso_path, &vdso_size); | ||
232 | if (!vdso) | ||
233 | return EXIT_FAILURE; | ||
234 | |||
235 | /* Patch both the VDSOs' ABI flags sections. */ | ||
236 | if (!patch_vdso(dbg_vdso_path, dbg_vdso)) | ||
237 | return EXIT_FAILURE; | ||
238 | if (!patch_vdso(vdso_path, vdso)) | ||
239 | return EXIT_FAILURE; | ||
240 | |||
241 | if (msync(dbg_vdso, dbg_vdso_size, MS_SYNC) != 0) { | ||
242 | fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name, | ||
243 | dbg_vdso_path, strerror(errno)); | ||
244 | return EXIT_FAILURE; | ||
245 | } else if (msync(vdso, vdso_size, MS_SYNC) != 0) { | ||
246 | fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name, | ||
247 | vdso_path, strerror(errno)); | ||
248 | return EXIT_FAILURE; | ||
249 | } | ||
250 | |||
251 | out_file = fopen(out_path, "w"); | ||
252 | if (!out_file) { | ||
253 | fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name, | ||
254 | out_path, strerror(errno)); | ||
255 | return EXIT_FAILURE; | ||
256 | } | ||
257 | |||
258 | fprintf(out_file, "/* Automatically generated - do not edit */\n"); | ||
259 | fprintf(out_file, "#include <linux/linkage.h>\n"); | ||
260 | fprintf(out_file, "#include <linux/mm.h>\n"); | ||
261 | fprintf(out_file, "#include <asm/vdso.h>\n"); | ||
262 | fprintf(out_file, "static int vdso_mremap(\n"); | ||
263 | fprintf(out_file, " const struct vm_special_mapping *sm,\n"); | ||
264 | fprintf(out_file, " struct vm_area_struct *new_vma)\n"); | ||
265 | fprintf(out_file, "{\n"); | ||
266 | fprintf(out_file, " unsigned long new_size =\n"); | ||
267 | fprintf(out_file, " new_vma->vm_end - new_vma->vm_start;\n"); | ||
268 | fprintf(out_file, " if (vdso_image.size != new_size)\n"); | ||
269 | fprintf(out_file, " return -EINVAL;\n"); | ||
270 | fprintf(out_file, " current->mm->context.vdso =\n"); | ||
271 | fprintf(out_file, " (void *)(new_vma->vm_start);\n"); | ||
272 | fprintf(out_file, " return 0;\n"); | ||
273 | fprintf(out_file, "}\n"); | ||
274 | |||
275 | /* Write out the stripped VDSO data. */ | ||
276 | fprintf(out_file, | ||
277 | "static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t", | ||
278 | vdso_size); | ||
279 | for (i = 0; i < vdso_size; i++) { | ||
280 | if (!(i % 10)) | ||
281 | fprintf(out_file, "\n\t"); | ||
282 | fprintf(out_file, "0x%02x, ", ((unsigned char *)vdso)[i]); | ||
283 | } | ||
284 | fprintf(out_file, "\n};\n"); | ||
285 | |||
286 | /* Preallocate a page array. */ | ||
287 | fprintf(out_file, | ||
288 | "static struct page *vdso_pages[PAGE_ALIGN(%zu) / PAGE_SIZE];\n", | ||
289 | vdso_size); | ||
290 | |||
291 | fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n", | ||
292 | (vdso_name[0]) ? "_" : "", vdso_name); | ||
293 | fprintf(out_file, "\t.data = vdso_data,\n"); | ||
294 | fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size); | ||
295 | fprintf(out_file, "\t.mapping = {\n"); | ||
296 | fprintf(out_file, "\t\t.name = \"[vdso]\",\n"); | ||
297 | fprintf(out_file, "\t\t.pages = vdso_pages,\n"); | ||
298 | fprintf(out_file, "\t\t.mremap = vdso_mremap,\n"); | ||
299 | fprintf(out_file, "\t},\n"); | ||
300 | |||
301 | /* Calculate and write symbol offsets to <output file> */ | ||
302 | if (!get_symbols(dbg_vdso_path, dbg_vdso)) { | ||
303 | unlink(out_path); | ||
304 | fclose(out_file); | ||
305 | return EXIT_FAILURE; | ||
306 | } | ||
307 | |||
308 | fprintf(out_file, "};\n"); | ||
309 | fclose(out_file); | ||
310 | |||
311 | return EXIT_SUCCESS; | ||
312 | } | ||
diff --git a/arch/mips/vdso/genvdso.h b/arch/mips/vdso/genvdso.h new file mode 100644 index 000000000..9bfb87403 --- /dev/null +++ b/arch/mips/vdso/genvdso.h | |||
@@ -0,0 +1,132 @@ | |||
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 | static inline bool FUNC(patch_vdso)(const char *path, void *vdso) | ||
8 | { | ||
9 | const ELF(Ehdr) *ehdr = vdso; | ||
10 | void *shdrs; | ||
11 | ELF(Shdr) *shdr; | ||
12 | char *shstrtab, *name; | ||
13 | uint16_t sh_count, sh_entsize, i; | ||
14 | |||
15 | shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff); | ||
16 | sh_count = swap_uint16(ehdr->e_shnum); | ||
17 | sh_entsize = swap_uint16(ehdr->e_shentsize); | ||
18 | |||
19 | shdr = shdrs + (sh_entsize * swap_uint16(ehdr->e_shstrndx)); | ||
20 | shstrtab = vdso + FUNC(swap_uint)(shdr->sh_offset); | ||
21 | |||
22 | for (i = 0; i < sh_count; i++) { | ||
23 | shdr = shdrs + (i * sh_entsize); | ||
24 | name = shstrtab + swap_uint32(shdr->sh_name); | ||
25 | |||
26 | /* | ||
27 | * Ensure there are no relocation sections - ld.so does not | ||
28 | * relocate the VDSO so if there are relocations things will | ||
29 | * break. | ||
30 | */ | ||
31 | switch (swap_uint32(shdr->sh_type)) { | ||
32 | case SHT_REL: | ||
33 | case SHT_RELA: | ||
34 | fprintf(stderr, | ||
35 | "%s: '%s' contains relocation sections\n", | ||
36 | program_name, path); | ||
37 | return false; | ||
38 | } | ||
39 | |||
40 | /* Check for existing sections. */ | ||
41 | if (strcmp(name, ".MIPS.abiflags") == 0) { | ||
42 | fprintf(stderr, | ||
43 | "%s: '%s' already contains a '.MIPS.abiflags' section\n", | ||
44 | program_name, path); | ||
45 | return false; | ||
46 | } | ||
47 | |||
48 | if (strcmp(name, ".mips_abiflags") == 0) { | ||
49 | strcpy(name, ".MIPS.abiflags"); | ||
50 | shdr->sh_type = swap_uint32(SHT_MIPS_ABIFLAGS); | ||
51 | shdr->sh_entsize = shdr->sh_size; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return true; | ||
56 | } | ||
57 | |||
58 | static inline bool FUNC(get_symbols)(const char *path, void *vdso) | ||
59 | { | ||
60 | const ELF(Ehdr) *ehdr = vdso; | ||
61 | void *shdrs, *symtab; | ||
62 | ELF(Shdr) *shdr; | ||
63 | const ELF(Sym) *sym; | ||
64 | char *strtab, *name; | ||
65 | uint16_t sh_count, sh_entsize, st_count, st_entsize, i, j; | ||
66 | uint64_t offset; | ||
67 | uint32_t flags; | ||
68 | |||
69 | shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff); | ||
70 | sh_count = swap_uint16(ehdr->e_shnum); | ||
71 | sh_entsize = swap_uint16(ehdr->e_shentsize); | ||
72 | |||
73 | for (i = 0; i < sh_count; i++) { | ||
74 | shdr = shdrs + (i * sh_entsize); | ||
75 | |||
76 | if (swap_uint32(shdr->sh_type) == SHT_SYMTAB) | ||
77 | break; | ||
78 | } | ||
79 | |||
80 | if (i == sh_count) { | ||
81 | fprintf(stderr, "%s: '%s' has no symbol table\n", program_name, | ||
82 | path); | ||
83 | return false; | ||
84 | } | ||
85 | |||
86 | /* Get flags */ | ||
87 | flags = swap_uint32(ehdr->e_flags); | ||
88 | if (elf_class == ELFCLASS64) | ||
89 | elf_abi = ABI_N64; | ||
90 | else if (flags & EF_MIPS_ABI2) | ||
91 | elf_abi = ABI_N32; | ||
92 | else | ||
93 | elf_abi = ABI_O32; | ||
94 | |||
95 | /* Get symbol table. */ | ||
96 | symtab = vdso + FUNC(swap_uint)(shdr->sh_offset); | ||
97 | st_entsize = FUNC(swap_uint)(shdr->sh_entsize); | ||
98 | st_count = FUNC(swap_uint)(shdr->sh_size) / st_entsize; | ||
99 | |||
100 | /* Get string table. */ | ||
101 | shdr = shdrs + (swap_uint32(shdr->sh_link) * sh_entsize); | ||
102 | strtab = vdso + FUNC(swap_uint)(shdr->sh_offset); | ||
103 | |||
104 | /* Write offsets for symbols needed by the kernel. */ | ||
105 | for (i = 0; vdso_symbols[i].name; i++) { | ||
106 | if (!(vdso_symbols[i].abis & elf_abi)) | ||
107 | continue; | ||
108 | |||
109 | for (j = 0; j < st_count; j++) { | ||
110 | sym = symtab + (j * st_entsize); | ||
111 | name = strtab + swap_uint32(sym->st_name); | ||
112 | |||
113 | if (!strcmp(name, vdso_symbols[i].name)) { | ||
114 | offset = FUNC(swap_uint)(sym->st_value); | ||
115 | |||
116 | fprintf(out_file, | ||
117 | "\t.%s = 0x%" PRIx64 ",\n", | ||
118 | vdso_symbols[i].offset_name, offset); | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | if (j == st_count) { | ||
124 | fprintf(stderr, | ||
125 | "%s: '%s' is missing required symbol '%s'\n", | ||
126 | program_name, path, vdso_symbols[i].name); | ||
127 | return false; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return true; | ||
132 | } | ||
diff --git a/arch/mips/vdso/sigreturn.S b/arch/mips/vdso/sigreturn.S new file mode 100644 index 000000000..e5c0ab98a --- /dev/null +++ b/arch/mips/vdso/sigreturn.S | |||
@@ -0,0 +1,35 @@ | |||
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/vdso/vdso.h> | ||
8 | |||
9 | #include <uapi/asm/unistd.h> | ||
10 | |||
11 | #include <asm/regdef.h> | ||
12 | #include <asm/asm.h> | ||
13 | |||
14 | .section .text | ||
15 | .cfi_sections .debug_frame | ||
16 | |||
17 | LEAF(__vdso_rt_sigreturn) | ||
18 | .cfi_signal_frame | ||
19 | |||
20 | li v0, __NR_rt_sigreturn | ||
21 | syscall | ||
22 | |||
23 | END(__vdso_rt_sigreturn) | ||
24 | |||
25 | #if _MIPS_SIM == _MIPS_SIM_ABI32 | ||
26 | |||
27 | LEAF(__vdso_sigreturn) | ||
28 | .cfi_signal_frame | ||
29 | |||
30 | li v0, __NR_sigreturn | ||
31 | syscall | ||
32 | |||
33 | END(__vdso_sigreturn) | ||
34 | |||
35 | #endif | ||
diff --git a/arch/mips/vdso/vdso.lds.S b/arch/mips/vdso/vdso.lds.S new file mode 100644 index 000000000..d90b65724 --- /dev/null +++ b/arch/mips/vdso/vdso.lds.S | |||
@@ -0,0 +1,105 @@ | |||
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 | #if _MIPS_SIM == _MIPS_SIM_ABI64 | ||
10 | OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips") | ||
11 | #elif _MIPS_SIM == _MIPS_SIM_NABI32 | ||
12 | OUTPUT_FORMAT("elf32-ntradlittlemips", "elf32-ntradbigmips", "elf32-ntradlittlemips") | ||
13 | #else | ||
14 | OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips") | ||
15 | #endif | ||
16 | |||
17 | OUTPUT_ARCH(mips) | ||
18 | |||
19 | SECTIONS | ||
20 | { | ||
21 | PROVIDE(_start = .); | ||
22 | . = SIZEOF_HEADERS; | ||
23 | |||
24 | /* | ||
25 | * In order to retain compatibility with older toolchains we provide the | ||
26 | * ABI flags section ourself. Newer assemblers will automatically | ||
27 | * generate .MIPS.abiflags sections so we discard such input sections, | ||
28 | * and then manually define our own section here. genvdso will patch | ||
29 | * this section to have the correct name/type. | ||
30 | */ | ||
31 | .mips_abiflags : { *(.mips_abiflags) } :text :abiflags | ||
32 | |||
33 | .reginfo : { *(.reginfo) } :text :reginfo | ||
34 | |||
35 | .hash : { *(.hash) } :text | ||
36 | .gnu.hash : { *(.gnu.hash) } | ||
37 | .dynsym : { *(.dynsym) } | ||
38 | .dynstr : { *(.dynstr) } | ||
39 | .gnu.version : { *(.gnu.version) } | ||
40 | .gnu.version_d : { *(.gnu.version_d) } | ||
41 | .gnu.version_r : { *(.gnu.version_r) } | ||
42 | |||
43 | .note : { *(.note.*) } :text :note | ||
44 | |||
45 | .text : { *(.text*) } :text | ||
46 | PROVIDE (__etext = .); | ||
47 | PROVIDE (_etext = .); | ||
48 | PROVIDE (etext = .); | ||
49 | |||
50 | .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr | ||
51 | .eh_frame : { KEEP (*(.eh_frame)) } :text | ||
52 | |||
53 | .dynamic : { *(.dynamic) } :text :dynamic | ||
54 | |||
55 | .rodata : { *(.rodata*) } :text | ||
56 | |||
57 | _end = .; | ||
58 | PROVIDE(end = .); | ||
59 | |||
60 | /DISCARD/ : { | ||
61 | *(.MIPS.abiflags) | ||
62 | *(.gnu.attributes) | ||
63 | *(.note.GNU-stack) | ||
64 | *(.data .data.* .gnu.linkonce.d.* .sdata*) | ||
65 | *(.bss .sbss .dynbss .dynsbss) | ||
66 | } | ||
67 | } | ||
68 | |||
69 | PHDRS | ||
70 | { | ||
71 | /* | ||
72 | * Provide a PT_MIPS_ABIFLAGS header to assign the ABI flags section | ||
73 | * to. We can specify the header type directly here so no modification | ||
74 | * is needed later on. | ||
75 | */ | ||
76 | abiflags 0x70000003; | ||
77 | |||
78 | /* | ||
79 | * The ABI flags header must exist directly after the PT_INTERP header, | ||
80 | * so we must explicitly place the PT_MIPS_REGINFO header after it to | ||
81 | * stop the linker putting one in at the start. | ||
82 | */ | ||
83 | reginfo 0x70000000; | ||
84 | |||
85 | text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */ | ||
86 | dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ | ||
87 | note PT_NOTE FLAGS(4); /* PF_R */ | ||
88 | eh_frame_hdr PT_GNU_EH_FRAME; | ||
89 | } | ||
90 | |||
91 | VERSION | ||
92 | { | ||
93 | LINUX_2.6 { | ||
94 | #ifndef CONFIG_MIPS_DISABLE_VDSO | ||
95 | global: | ||
96 | __vdso_clock_gettime; | ||
97 | __vdso_gettimeofday; | ||
98 | __vdso_clock_getres; | ||
99 | #if _MIPS_SIM != _MIPS_SIM_ABI64 | ||
100 | __vdso_clock_gettime64; | ||
101 | #endif | ||
102 | #endif | ||
103 | local: *; | ||
104 | }; | ||
105 | } | ||
diff --git a/arch/mips/vdso/vgettimeofday.c b/arch/mips/vdso/vgettimeofday.c new file mode 100644 index 000000000..6b83b6376 --- /dev/null +++ b/arch/mips/vdso/vgettimeofday.c | |||
@@ -0,0 +1,78 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
2 | /* | ||
3 | * MIPS64 and compat userspace implementations of gettimeofday() | ||
4 | * and similar. | ||
5 | * | ||
6 | * Copyright (C) 2015 Imagination Technologies | ||
7 | * Copyright (C) 2018 ARM Limited | ||
8 | * | ||
9 | */ | ||
10 | #include <linux/time.h> | ||
11 | #include <linux/types.h> | ||
12 | |||
13 | #if _MIPS_SIM != _MIPS_SIM_ABI64 | ||
14 | int __vdso_clock_gettime(clockid_t clock, | ||
15 | struct old_timespec32 *ts) | ||
16 | { | ||
17 | return __cvdso_clock_gettime32(clock, ts); | ||
18 | } | ||
19 | |||
20 | #ifdef CONFIG_MIPS_CLOCK_VSYSCALL | ||
21 | |||
22 | /* | ||
23 | * This is behind the ifdef so that we don't provide the symbol when there's no | ||
24 | * possibility of there being a usable clocksource, because there's nothing we | ||
25 | * can do without it. When libc fails the symbol lookup it should fall back on | ||
26 | * the standard syscall path. | ||
27 | */ | ||
28 | int __vdso_gettimeofday(struct __kernel_old_timeval *tv, | ||
29 | struct timezone *tz) | ||
30 | { | ||
31 | return __cvdso_gettimeofday(tv, tz); | ||
32 | } | ||
33 | |||
34 | #endif /* CONFIG_MIPS_CLOCK_VSYSCALL */ | ||
35 | |||
36 | int __vdso_clock_getres(clockid_t clock_id, | ||
37 | struct old_timespec32 *res) | ||
38 | { | ||
39 | return __cvdso_clock_getres_time32(clock_id, res); | ||
40 | } | ||
41 | |||
42 | int __vdso_clock_gettime64(clockid_t clock, | ||
43 | struct __kernel_timespec *ts) | ||
44 | { | ||
45 | return __cvdso_clock_gettime(clock, ts); | ||
46 | } | ||
47 | |||
48 | #else | ||
49 | |||
50 | int __vdso_clock_gettime(clockid_t clock, | ||
51 | struct __kernel_timespec *ts) | ||
52 | { | ||
53 | return __cvdso_clock_gettime(clock, ts); | ||
54 | } | ||
55 | |||
56 | #ifdef CONFIG_MIPS_CLOCK_VSYSCALL | ||
57 | |||
58 | /* | ||
59 | * This is behind the ifdef so that we don't provide the symbol when there's no | ||
60 | * possibility of there being a usable clocksource, because there's nothing we | ||
61 | * can do without it. When libc fails the symbol lookup it should fall back on | ||
62 | * the standard syscall path. | ||
63 | */ | ||
64 | int __vdso_gettimeofday(struct __kernel_old_timeval *tv, | ||
65 | struct timezone *tz) | ||
66 | { | ||
67 | return __cvdso_gettimeofday(tv, tz); | ||
68 | } | ||
69 | |||
70 | #endif /* CONFIG_MIPS_CLOCK_VSYSCALL */ | ||
71 | |||
72 | int __vdso_clock_getres(clockid_t clock_id, | ||
73 | struct __kernel_timespec *res) | ||
74 | { | ||
75 | return __cvdso_clock_getres(clock_id, res); | ||
76 | } | ||
77 | |||
78 | #endif | ||