diff options
author | Vincenzo Frascino <vincenzo.frascino@arm.com> | 2019-06-21 05:52:46 -0400 |
---|---|---|
committer | Paul Burton <paul.burton@mips.com> | 2019-07-26 00:45:05 -0400 |
commit | 24640f233b466051ad3a5d2786d2951e43026c9d (patch) | |
tree | ca9acaf821110f4d249dd4a250d7a9b740675261 | |
parent | c2aeaaea175652af6610f97a0de6d7cd07311e18 (diff) |
mips: Add support for generic vDSO
The mips vDSO library requires some adaptations to take advantage of the
newly introduced generic vDSO library.
Introduce the following changes:
- Modification of vdso.c to be compliant with the common vdso datapage
- Use of lib/vdso for gettimeofday
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Paul Burton <paul.burton@mips.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
[paul.burton@mips.com: Prepend $(src) to config-n32-o32-env.c path.]
Signed-off-by: Paul Burton <paul.burton@mips.com>
-rw-r--r-- | arch/mips/Kconfig | 2 | ||||
-rw-r--r-- | arch/mips/include/asm/vdso.h | 78 | ||||
-rw-r--r-- | arch/mips/include/asm/vdso/gettimeofday.h | 151 | ||||
-rw-r--r-- | arch/mips/include/asm/vdso/vdso.h (renamed from arch/mips/vdso/vdso.h) | 6 | ||||
-rw-r--r-- | arch/mips/include/asm/vdso/vsyscall.h | 43 | ||||
-rw-r--r-- | arch/mips/kernel/vdso.c | 37 | ||||
-rw-r--r-- | arch/mips/vdso/Makefile | 33 | ||||
-rw-r--r-- | arch/mips/vdso/config-n32-o32-env.c | 17 | ||||
-rw-r--r-- | arch/mips/vdso/elf.S | 2 | ||||
-rw-r--r-- | arch/mips/vdso/sigreturn.S | 2 | ||||
-rw-r--r-- | arch/mips/vdso/vgettimeofday.c | 40 |
11 files changed, 296 insertions, 115 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 947c75684897..99078c1b5273 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -22,6 +22,7 @@ config MIPS | |||
22 | select GENERIC_CLOCKEVENTS | 22 | select GENERIC_CLOCKEVENTS |
23 | select GENERIC_CMOS_UPDATE | 23 | select GENERIC_CMOS_UPDATE |
24 | select GENERIC_CPU_AUTOPROBE | 24 | select GENERIC_CPU_AUTOPROBE |
25 | select GENERIC_GETTIMEOFDAY | ||
25 | select GENERIC_IOMAP | 26 | select GENERIC_IOMAP |
26 | select GENERIC_IRQ_PROBE | 27 | select GENERIC_IRQ_PROBE |
27 | select GENERIC_IRQ_SHOW | 28 | select GENERIC_IRQ_SHOW |
@@ -74,6 +75,7 @@ config MIPS | |||
74 | select HAVE_STACKPROTECTOR | 75 | select HAVE_STACKPROTECTOR |
75 | select HAVE_SYSCALL_TRACEPOINTS | 76 | select HAVE_SYSCALL_TRACEPOINTS |
76 | select HAVE_VIRT_CPU_ACCOUNTING_GEN if 64BIT || !SMP | 77 | select HAVE_VIRT_CPU_ACCOUNTING_GEN if 64BIT || !SMP |
78 | select HAVE_GENERIC_VDSO | ||
77 | select IRQ_FORCED_THREADING | 79 | select IRQ_FORCED_THREADING |
78 | select ISA if EISA | 80 | select ISA if EISA |
79 | select MODULES_USE_ELF_RELA if MODULES && 64BIT | 81 | select MODULES_USE_ELF_RELA if MODULES && 64BIT |
diff --git a/arch/mips/include/asm/vdso.h b/arch/mips/include/asm/vdso.h index a013fa4a3682..cc7b516129a8 100644 --- a/arch/mips/include/asm/vdso.h +++ b/arch/mips/include/asm/vdso.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #define __ASM_VDSO_H | 8 | #define __ASM_VDSO_H |
9 | 9 | ||
10 | #include <linux/mm_types.h> | 10 | #include <linux/mm_types.h> |
11 | #include <vdso/datapage.h> | ||
11 | 12 | ||
12 | #include <asm/barrier.h> | 13 | #include <asm/barrier.h> |
13 | 14 | ||
@@ -49,84 +50,9 @@ extern struct mips_vdso_image vdso_image_o32; | |||
49 | extern struct mips_vdso_image vdso_image_n32; | 50 | extern struct mips_vdso_image vdso_image_n32; |
50 | #endif | 51 | #endif |
51 | 52 | ||
52 | /** | ||
53 | * union mips_vdso_data - Data provided by the kernel for the VDSO. | ||
54 | * @xtime_sec: Current real time (seconds part). | ||
55 | * @xtime_nsec: Current real time (nanoseconds part, shifted). | ||
56 | * @wall_to_mono_sec: Wall-to-monotonic offset (seconds part). | ||
57 | * @wall_to_mono_nsec: Wall-to-monotonic offset (nanoseconds part). | ||
58 | * @seq_count: Counter to synchronise updates (odd = updating). | ||
59 | * @cs_shift: Clocksource shift value. | ||
60 | * @clock_mode: Clocksource to use for time functions. | ||
61 | * @cs_mult: Clocksource multiplier value. | ||
62 | * @cs_cycle_last: Clock cycle value at last update. | ||
63 | * @cs_mask: Clocksource mask value. | ||
64 | * @tz_minuteswest: Minutes west of Greenwich (from timezone). | ||
65 | * @tz_dsttime: Type of DST correction (from timezone). | ||
66 | * | ||
67 | * This structure contains data needed by functions within the VDSO. It is | ||
68 | * populated by the kernel and mapped read-only into user memory. The time | ||
69 | * fields are mirrors of internal data from the timekeeping infrastructure. | ||
70 | * | ||
71 | * Note: Care should be taken when modifying as the layout must remain the same | ||
72 | * for both 64- and 32-bit (for 32-bit userland on 64-bit kernel). | ||
73 | */ | ||
74 | union mips_vdso_data { | 53 | union mips_vdso_data { |
75 | struct { | 54 | struct vdso_data data[CS_BASES]; |
76 | u64 xtime_sec; | ||
77 | u64 xtime_nsec; | ||
78 | u64 wall_to_mono_sec; | ||
79 | u64 wall_to_mono_nsec; | ||
80 | u32 seq_count; | ||
81 | u32 cs_shift; | ||
82 | u8 clock_mode; | ||
83 | u32 cs_mult; | ||
84 | u64 cs_cycle_last; | ||
85 | u64 cs_mask; | ||
86 | s32 tz_minuteswest; | ||
87 | s32 tz_dsttime; | ||
88 | }; | ||
89 | |||
90 | u8 page[PAGE_SIZE]; | 55 | u8 page[PAGE_SIZE]; |
91 | }; | 56 | }; |
92 | 57 | ||
93 | static inline u32 vdso_data_read_begin(const union mips_vdso_data *data) | ||
94 | { | ||
95 | u32 seq; | ||
96 | |||
97 | while (true) { | ||
98 | seq = READ_ONCE(data->seq_count); | ||
99 | if (likely(!(seq & 1))) { | ||
100 | /* Paired with smp_wmb() in vdso_data_write_*(). */ | ||
101 | smp_rmb(); | ||
102 | return seq; | ||
103 | } | ||
104 | |||
105 | cpu_relax(); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static inline bool vdso_data_read_retry(const union mips_vdso_data *data, | ||
110 | u32 start_seq) | ||
111 | { | ||
112 | /* Paired with smp_wmb() in vdso_data_write_*(). */ | ||
113 | smp_rmb(); | ||
114 | return unlikely(data->seq_count != start_seq); | ||
115 | } | ||
116 | |||
117 | static inline void vdso_data_write_begin(union mips_vdso_data *data) | ||
118 | { | ||
119 | ++data->seq_count; | ||
120 | |||
121 | /* Ensure sequence update is written before other data page values. */ | ||
122 | smp_wmb(); | ||
123 | } | ||
124 | |||
125 | static inline void vdso_data_write_end(union mips_vdso_data *data) | ||
126 | { | ||
127 | /* Ensure data values are written before updating sequence again. */ | ||
128 | smp_wmb(); | ||
129 | ++data->seq_count; | ||
130 | } | ||
131 | |||
132 | #endif /* __ASM_VDSO_H */ | 58 | #endif /* __ASM_VDSO_H */ |
diff --git a/arch/mips/include/asm/vdso/gettimeofday.h b/arch/mips/include/asm/vdso/gettimeofday.h new file mode 100644 index 000000000000..aa20865b288b --- /dev/null +++ b/arch/mips/include/asm/vdso/gettimeofday.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 ARM Limited | ||
3 | * Copyright (C) 2015 Imagination Technologies | ||
4 | * Author: Alex Smith <alex.smith@imgtec.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | #ifndef __ASM_VDSO_GETTIMEOFDAY_H | ||
12 | #define __ASM_VDSO_GETTIMEOFDAY_H | ||
13 | |||
14 | #ifndef __ASSEMBLY__ | ||
15 | |||
16 | #include <linux/compiler.h> | ||
17 | #include <linux/time.h> | ||
18 | |||
19 | #include <asm/vdso/vdso.h> | ||
20 | #include <asm/clocksource.h> | ||
21 | #include <asm/io.h> | ||
22 | #include <asm/unistd.h> | ||
23 | #include <asm/vdso.h> | ||
24 | |||
25 | #ifdef CONFIG_MIPS_CLOCK_VSYSCALL | ||
26 | |||
27 | static __always_inline long gettimeofday_fallback( | ||
28 | struct __kernel_old_timeval *_tv, | ||
29 | struct timezone *_tz) | ||
30 | { | ||
31 | register struct timezone *tz asm("a1") = _tz; | ||
32 | register struct __kernel_old_timeval *tv asm("a0") = _tv; | ||
33 | register long ret asm("v0"); | ||
34 | register long nr asm("v0") = __NR_gettimeofday; | ||
35 | register long error asm("a3"); | ||
36 | |||
37 | asm volatile( | ||
38 | " syscall\n" | ||
39 | : "=r" (ret), "=r" (error) | ||
40 | : "r" (tv), "r" (tz), "r" (nr) | ||
41 | : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", | ||
42 | "$14", "$15", "$24", "$25", "hi", "lo", "memory"); | ||
43 | |||
44 | return error ? -ret : ret; | ||
45 | } | ||
46 | |||
47 | #else | ||
48 | |||
49 | static __always_inline long gettimeofday_fallback( | ||
50 | struct __kernel_old_timeval *_tv, | ||
51 | struct timezone *_tz) | ||
52 | { | ||
53 | return -1; | ||
54 | } | ||
55 | |||
56 | #endif | ||
57 | |||
58 | static __always_inline long clock_gettime_fallback( | ||
59 | clockid_t _clkid, | ||
60 | struct __kernel_timespec *_ts) | ||
61 | { | ||
62 | register struct __kernel_timespec *ts asm("a1") = _ts; | ||
63 | register clockid_t clkid asm("a0") = _clkid; | ||
64 | register long ret asm("v0"); | ||
65 | #if _MIPS_SIM == _MIPS_SIM_ABI64 | ||
66 | register long nr asm("v0") = __NR_clock_gettime; | ||
67 | #else | ||
68 | register long nr asm("v0") = __NR_clock_gettime64; | ||
69 | #endif | ||
70 | register long error asm("a3"); | ||
71 | |||
72 | asm volatile( | ||
73 | " syscall\n" | ||
74 | : "=r" (ret), "=r" (error) | ||
75 | : "r" (clkid), "r" (ts), "r" (nr) | ||
76 | : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", | ||
77 | "$14", "$15", "$24", "$25", "hi", "lo", "memory"); | ||
78 | |||
79 | return error ? -ret : ret; | ||
80 | } | ||
81 | |||
82 | #ifdef CONFIG_CSRC_R4K | ||
83 | |||
84 | static __always_inline u64 read_r4k_count(void) | ||
85 | { | ||
86 | unsigned int count; | ||
87 | |||
88 | __asm__ __volatile__( | ||
89 | " .set push\n" | ||
90 | " .set mips32r2\n" | ||
91 | " rdhwr %0, $2\n" | ||
92 | " .set pop\n" | ||
93 | : "=r" (count)); | ||
94 | |||
95 | return count; | ||
96 | } | ||
97 | |||
98 | #endif | ||
99 | |||
100 | #ifdef CONFIG_CLKSRC_MIPS_GIC | ||
101 | |||
102 | static __always_inline u64 read_gic_count(const struct vdso_data *data) | ||
103 | { | ||
104 | void __iomem *gic = get_gic(data); | ||
105 | u32 hi, hi2, lo; | ||
106 | |||
107 | do { | ||
108 | hi = __raw_readl(gic + sizeof(lo)); | ||
109 | lo = __raw_readl(gic); | ||
110 | hi2 = __raw_readl(gic + sizeof(lo)); | ||
111 | } while (hi2 != hi); | ||
112 | |||
113 | return (((u64)hi) << 32) + lo; | ||
114 | } | ||
115 | |||
116 | #endif | ||
117 | |||
118 | static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) | ||
119 | { | ||
120 | #ifdef CONFIG_CLKSRC_MIPS_GIC | ||
121 | const struct vdso_data *data = get_vdso_data(); | ||
122 | #endif | ||
123 | u64 cycle_now; | ||
124 | |||
125 | switch (clock_mode) { | ||
126 | #ifdef CONFIG_CSRC_R4K | ||
127 | case VDSO_CLOCK_R4K: | ||
128 | cycle_now = read_r4k_count(); | ||
129 | break; | ||
130 | #endif | ||
131 | #ifdef CONFIG_CLKSRC_MIPS_GIC | ||
132 | case VDSO_CLOCK_GIC: | ||
133 | cycle_now = read_gic_count(data); | ||
134 | break; | ||
135 | #endif | ||
136 | default: | ||
137 | cycle_now = 0; | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | return cycle_now; | ||
142 | } | ||
143 | |||
144 | static __always_inline const struct vdso_data *__arch_get_vdso_data(void) | ||
145 | { | ||
146 | return get_vdso_data(); | ||
147 | } | ||
148 | |||
149 | #endif /* !__ASSEMBLY__ */ | ||
150 | |||
151 | #endif /* __ASM_VDSO_GETTIMEOFDAY_H */ | ||
diff --git a/arch/mips/vdso/vdso.h b/arch/mips/include/asm/vdso/vdso.h index 14b1931be69c..526695bc65ee 100644 --- a/arch/mips/vdso/vdso.h +++ b/arch/mips/include/asm/vdso/vdso.h | |||
@@ -68,14 +68,14 @@ static inline unsigned long get_vdso_base(void) | |||
68 | return addr; | 68 | return addr; |
69 | } | 69 | } |
70 | 70 | ||
71 | static inline const union mips_vdso_data *get_vdso_data(void) | 71 | static inline const struct vdso_data *get_vdso_data(void) |
72 | { | 72 | { |
73 | return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE); | 73 | return (const struct vdso_data *)(get_vdso_base() - PAGE_SIZE); |
74 | } | 74 | } |
75 | 75 | ||
76 | #ifdef CONFIG_CLKSRC_MIPS_GIC | 76 | #ifdef CONFIG_CLKSRC_MIPS_GIC |
77 | 77 | ||
78 | static inline void __iomem *get_gic(const union mips_vdso_data *data) | 78 | static inline void __iomem *get_gic(const struct vdso_data *data) |
79 | { | 79 | { |
80 | return (void __iomem *)data - PAGE_SIZE; | 80 | return (void __iomem *)data - PAGE_SIZE; |
81 | } | 81 | } |
diff --git a/arch/mips/include/asm/vdso/vsyscall.h b/arch/mips/include/asm/vdso/vsyscall.h new file mode 100644 index 000000000000..195314732233 --- /dev/null +++ b/arch/mips/include/asm/vdso/vsyscall.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef __ASM_VDSO_VSYSCALL_H | ||
3 | #define __ASM_VDSO_VSYSCALL_H | ||
4 | |||
5 | #ifndef __ASSEMBLY__ | ||
6 | |||
7 | #include <linux/timekeeper_internal.h> | ||
8 | #include <vdso/datapage.h> | ||
9 | |||
10 | extern struct vdso_data *vdso_data; | ||
11 | |||
12 | /* | ||
13 | * Update the vDSO data page to keep in sync with kernel timekeeping. | ||
14 | */ | ||
15 | static __always_inline | ||
16 | struct vdso_data *__mips_get_k_vdso_data(void) | ||
17 | { | ||
18 | return vdso_data; | ||
19 | } | ||
20 | #define __arch_get_k_vdso_data __mips_get_k_vdso_data | ||
21 | |||
22 | static __always_inline | ||
23 | int __mips_get_clock_mode(struct timekeeper *tk) | ||
24 | { | ||
25 | u32 clock_mode = tk->tkr_mono.clock->archdata.vdso_clock_mode; | ||
26 | |||
27 | return clock_mode; | ||
28 | } | ||
29 | #define __arch_get_clock_mode __mips_get_clock_mode | ||
30 | |||
31 | static __always_inline | ||
32 | int __mips_use_vsyscall(struct vdso_data *vdata) | ||
33 | { | ||
34 | return (vdata[CS_HRES_COARSE].clock_mode != VDSO_CLOCK_NONE); | ||
35 | } | ||
36 | #define __arch_use_vsyscall __mips_use_vsyscall | ||
37 | |||
38 | /* The asm-generic header needs to be included after the definitions above */ | ||
39 | #include <asm-generic/vdso/vsyscall.h> | ||
40 | |||
41 | #endif /* !__ASSEMBLY__ */ | ||
42 | |||
43 | #endif /* __ASM_VDSO_VSYSCALL_H */ | ||
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index 3a372686ffca..bc35f8499111 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c | |||
@@ -20,9 +20,12 @@ | |||
20 | #include <asm/mips-cps.h> | 20 | #include <asm/mips-cps.h> |
21 | #include <asm/page.h> | 21 | #include <asm/page.h> |
22 | #include <asm/vdso.h> | 22 | #include <asm/vdso.h> |
23 | #include <vdso/helpers.h> | ||
24 | #include <vdso/vsyscall.h> | ||
23 | 25 | ||
24 | /* Kernel-provided data used by the VDSO. */ | 26 | /* Kernel-provided data used by the VDSO. */ |
25 | static union mips_vdso_data vdso_data __page_aligned_data; | 27 | static union mips_vdso_data mips_vdso_data __page_aligned_data; |
28 | struct vdso_data *vdso_data = mips_vdso_data.data; | ||
26 | 29 | ||
27 | /* | 30 | /* |
28 | * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as | 31 | * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as |
@@ -66,34 +69,6 @@ static int __init init_vdso(void) | |||
66 | } | 69 | } |
67 | subsys_initcall(init_vdso); | 70 | subsys_initcall(init_vdso); |
68 | 71 | ||
69 | void update_vsyscall(struct timekeeper *tk) | ||
70 | { | ||
71 | vdso_data_write_begin(&vdso_data); | ||
72 | |||
73 | vdso_data.xtime_sec = tk->xtime_sec; | ||
74 | vdso_data.xtime_nsec = tk->tkr_mono.xtime_nsec; | ||
75 | vdso_data.wall_to_mono_sec = tk->wall_to_monotonic.tv_sec; | ||
76 | vdso_data.wall_to_mono_nsec = tk->wall_to_monotonic.tv_nsec; | ||
77 | vdso_data.cs_shift = tk->tkr_mono.shift; | ||
78 | |||
79 | vdso_data.clock_mode = tk->tkr_mono.clock->archdata.vdso_clock_mode; | ||
80 | if (vdso_data.clock_mode != VDSO_CLOCK_NONE) { | ||
81 | vdso_data.cs_mult = tk->tkr_mono.mult; | ||
82 | vdso_data.cs_cycle_last = tk->tkr_mono.cycle_last; | ||
83 | vdso_data.cs_mask = tk->tkr_mono.mask; | ||
84 | } | ||
85 | |||
86 | vdso_data_write_end(&vdso_data); | ||
87 | } | ||
88 | |||
89 | void update_vsyscall_tz(void) | ||
90 | { | ||
91 | if (vdso_data.clock_mode != VDSO_CLOCK_NONE) { | ||
92 | vdso_data.tz_minuteswest = sys_tz.tz_minuteswest; | ||
93 | vdso_data.tz_dsttime = sys_tz.tz_dsttime; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static unsigned long vdso_base(void) | 72 | static unsigned long vdso_base(void) |
98 | { | 73 | { |
99 | unsigned long base; | 74 | unsigned long base; |
@@ -163,7 +138,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
163 | */ | 138 | */ |
164 | if (cpu_has_dc_aliases) { | 139 | if (cpu_has_dc_aliases) { |
165 | base = __ALIGN_MASK(base, shm_align_mask); | 140 | base = __ALIGN_MASK(base, shm_align_mask); |
166 | base += ((unsigned long)&vdso_data - gic_size) & shm_align_mask; | 141 | base += ((unsigned long)vdso_data - gic_size) & shm_align_mask; |
167 | } | 142 | } |
168 | 143 | ||
169 | data_addr = base + gic_size; | 144 | data_addr = base + gic_size; |
@@ -189,7 +164,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
189 | 164 | ||
190 | /* Map data page. */ | 165 | /* Map data page. */ |
191 | ret = remap_pfn_range(vma, data_addr, | 166 | ret = remap_pfn_range(vma, data_addr, |
192 | virt_to_phys(&vdso_data) >> PAGE_SHIFT, | 167 | virt_to_phys(vdso_data) >> PAGE_SHIFT, |
193 | PAGE_SIZE, PAGE_READONLY); | 168 | PAGE_SIZE, PAGE_READONLY); |
194 | if (ret) | 169 | if (ret) |
195 | goto out; | 170 | goto out; |
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile index 7221df24cb23..de853c6aab28 100644 --- a/arch/mips/vdso/Makefile +++ b/arch/mips/vdso/Makefile | |||
@@ -1,6 +1,12 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | # Objects to go into the VDSO. | 2 | # Objects to go into the VDSO. |
3 | obj-vdso-y := elf.o gettimeofday.o sigreturn.o | 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 | ||
4 | 10 | ||
5 | # Common compiler flags between ABIs. | 11 | # Common compiler flags between ABIs. |
6 | ccflags-vdso := \ | 12 | ccflags-vdso := \ |
@@ -15,15 +21,31 @@ ifdef CONFIG_CC_IS_CLANG | |||
15 | ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS)) | 21 | ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS)) |
16 | endif | 22 | endif |
17 | 23 | ||
24 | # | ||
25 | # The -fno-jump-tables flag only prevents the compiler from generating | ||
26 | # jump tables but does not prevent the compiler from emitting absolute | ||
27 | # offsets. | ||
18 | cflags-vdso := $(ccflags-vdso) \ | 28 | cflags-vdso := $(ccflags-vdso) \ |
19 | $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ | 29 | $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ |
20 | -O2 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \ | 30 | -O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \ |
21 | -DDISABLE_BRANCH_PROFILING \ | 31 | -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \ |
22 | $(call cc-option, -fno-asynchronous-unwind-tables) \ | 32 | $(call cc-option, -fno-asynchronous-unwind-tables) \ |
23 | $(call cc-option, -fno-stack-protector) | 33 | $(call cc-option, -fno-stack-protector) |
24 | aflags-vdso := $(ccflags-vdso) \ | 34 | aflags-vdso := $(ccflags-vdso) \ |
25 | -D__ASSEMBLY__ -Wa,-gdwarf-2 | 35 | -D__ASSEMBLY__ -Wa,-gdwarf-2 |
26 | 36 | ||
37 | ifneq ($(c-gettimeofday-y),) | ||
38 | CFLAGS_vgettimeofday.o = -include $(c-gettimeofday-y) | ||
39 | |||
40 | # config-n32-o32-env.c prepares the environment to build a 32bit vDSO | ||
41 | # library on a 64bit kernel. | ||
42 | # Note: Needs to be included before than the generic library. | ||
43 | CFLAGS_vgettimeofday-o32.o = -include $(src)/config-n32-o32-env.c -include $(c-gettimeofday-y) | ||
44 | CFLAGS_vgettimeofday-n32.o = -include $(src)/config-n32-o32-env.c -include $(c-gettimeofday-y) | ||
45 | endif | ||
46 | |||
47 | CFLAGS_REMOVE_vgettimeofday.o = -pg | ||
48 | |||
27 | # | 49 | # |
28 | # For the pre-R6 code in arch/mips/vdso/vdso.h for locating | 50 | # For the pre-R6 code in arch/mips/vdso/vdso.h for locating |
29 | # the base address of VDSO, the linker will emit a R_MIPS_PC32 | 51 | # the base address of VDSO, the linker will emit a R_MIPS_PC32 |
@@ -48,6 +70,8 @@ VDSO_LDFLAGS := \ | |||
48 | $(addprefix -Wl$(comma),$(filter -E%,$(KBUILD_CFLAGS))) \ | 70 | $(addprefix -Wl$(comma),$(filter -E%,$(KBUILD_CFLAGS))) \ |
49 | -nostdlib -shared -Wl,--hash-style=sysv -Wl,--build-id | 71 | -nostdlib -shared -Wl,--hash-style=sysv -Wl,--build-id |
50 | 72 | ||
73 | CFLAGS_REMOVE_vdso.o = -pg | ||
74 | |||
51 | GCOV_PROFILE := n | 75 | GCOV_PROFILE := n |
52 | UBSAN_SANITIZE := n | 76 | UBSAN_SANITIZE := n |
53 | 77 | ||
@@ -96,6 +120,7 @@ $(obj)/vdso.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) $(native-abi) | |||
96 | 120 | ||
97 | $(obj)/vdso.so.dbg.raw: $(obj)/vdso.lds $(obj-vdso) FORCE | 121 | $(obj)/vdso.so.dbg.raw: $(obj)/vdso.lds $(obj-vdso) FORCE |
98 | $(call if_changed,vdsold) | 122 | $(call if_changed,vdsold) |
123 | $(call if_changed,vdso_check) | ||
99 | 124 | ||
100 | $(obj)/vdso-image.c: $(obj)/vdso.so.dbg.raw $(obj)/vdso.so.raw \ | 125 | $(obj)/vdso-image.c: $(obj)/vdso.so.dbg.raw $(obj)/vdso.so.raw \ |
101 | $(obj)/genvdso FORCE | 126 | $(obj)/genvdso FORCE |
@@ -134,6 +159,7 @@ $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE | |||
134 | 159 | ||
135 | $(obj)/vdso-o32.so.dbg.raw: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE | 160 | $(obj)/vdso-o32.so.dbg.raw: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE |
136 | $(call if_changed,vdsold) | 161 | $(call if_changed,vdsold) |
162 | $(call if_changed,vdso_check) | ||
137 | 163 | ||
138 | $(obj)/vdso-o32-image.c: VDSO_NAME := o32 | 164 | $(obj)/vdso-o32-image.c: VDSO_NAME := o32 |
139 | $(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg.raw $(obj)/vdso-o32.so.raw \ | 165 | $(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg.raw $(obj)/vdso-o32.so.raw \ |
@@ -174,6 +200,7 @@ $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE | |||
174 | 200 | ||
175 | $(obj)/vdso-n32.so.dbg.raw: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE | 201 | $(obj)/vdso-n32.so.dbg.raw: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE |
176 | $(call if_changed,vdsold) | 202 | $(call if_changed,vdsold) |
203 | $(call if_changed,vdso_check) | ||
177 | 204 | ||
178 | $(obj)/vdso-n32-image.c: VDSO_NAME := n32 | 205 | $(obj)/vdso-n32-image.c: VDSO_NAME := n32 |
179 | $(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg.raw $(obj)/vdso-n32.so.raw \ | 206 | $(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg.raw $(obj)/vdso-n32.so.raw \ |
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 000000000000..da4994b2b3e5 --- /dev/null +++ b/arch/mips/vdso/config-n32-o32-env.c | |||
@@ -0,0 +1,17 @@ | |||
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 CONFIG_32BIT 1 | ||
14 | #define CONFIG_GENERIC_ATOMIC64 1 | ||
15 | |||
16 | #endif | ||
17 | |||
diff --git a/arch/mips/vdso/elf.S b/arch/mips/vdso/elf.S index e7543e8f426c..a25cb147f1ca 100644 --- a/arch/mips/vdso/elf.S +++ b/arch/mips/vdso/elf.S | |||
@@ -4,7 +4,7 @@ | |||
4 | * Author: Alex Smith <alex.smith@imgtec.com> | 4 | * Author: Alex Smith <alex.smith@imgtec.com> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "vdso.h" | 7 | #include <asm/vdso/vdso.h> |
8 | 8 | ||
9 | #include <asm/isa-rev.h> | 9 | #include <asm/isa-rev.h> |
10 | 10 | ||
diff --git a/arch/mips/vdso/sigreturn.S b/arch/mips/vdso/sigreturn.S index c3597632874b..e5c0ab98ab46 100644 --- a/arch/mips/vdso/sigreturn.S +++ b/arch/mips/vdso/sigreturn.S | |||
@@ -4,7 +4,7 @@ | |||
4 | * Author: Alex Smith <alex.smith@imgtec.com> | 4 | * Author: Alex Smith <alex.smith@imgtec.com> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "vdso.h" | 7 | #include <asm/vdso/vdso.h> |
8 | 8 | ||
9 | #include <uapi/asm/unistd.h> | 9 | #include <uapi/asm/unistd.h> |
10 | 10 | ||
diff --git a/arch/mips/vdso/vgettimeofday.c b/arch/mips/vdso/vgettimeofday.c new file mode 100644 index 000000000000..1c46dace041e --- /dev/null +++ b/arch/mips/vdso/vgettimeofday.c | |||
@@ -0,0 +1,40 @@ | |||
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 | int __vdso_gettimeofday(struct __kernel_old_timeval *tv, | ||
21 | struct timezone *tz) | ||
22 | { | ||
23 | return __cvdso_gettimeofday(tv, tz); | ||
24 | } | ||
25 | |||
26 | #else | ||
27 | |||
28 | int __vdso_clock_gettime(clockid_t clock, | ||
29 | struct __kernel_timespec *ts) | ||
30 | { | ||
31 | return __cvdso_clock_gettime(clock, ts); | ||
32 | } | ||
33 | |||
34 | int __vdso_gettimeofday(struct __kernel_old_timeval *tv, | ||
35 | struct timezone *tz) | ||
36 | { | ||
37 | return __cvdso_gettimeofday(tv, tz); | ||
38 | } | ||
39 | |||
40 | #endif | ||