Skip to content

Commit 20e2fc4

Browse files
fvincenzoRussell King
authored andcommitted
ARM: 8930/1: Add support for generic vDSO
The arm vDSO library requires some adaptations to take advantage of the newly introduced generic vDSO library. Introduce the following changes: - Modification vdso.c to be compliant with the common vdso datapage - Use of lib/vdso for gettimeofday - Implementation of elf note Signed-off-by: Vincenzo Frascino <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent 9f1984c commit 20e2fc4

File tree

8 files changed

+195
-357
lines changed

8 files changed

+195
-357
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2018 ARM Limited
4+
*/
5+
#ifndef __ASM_VDSO_GETTIMEOFDAY_H
6+
#define __ASM_VDSO_GETTIMEOFDAY_H
7+
8+
#ifndef __ASSEMBLY__
9+
10+
#include <asm/barrier.h>
11+
#include <asm/cp15.h>
12+
#include <asm/unistd.h>
13+
#include <uapi/linux/time.h>
14+
15+
extern struct vdso_data *__get_datapage(void);
16+
17+
static __always_inline int gettimeofday_fallback(
18+
struct __kernel_old_timeval *_tv,
19+
struct timezone *_tz)
20+
{
21+
register struct timezone *tz asm("r1") = _tz;
22+
register struct __kernel_old_timeval *tv asm("r0") = _tv;
23+
register long ret asm ("r0");
24+
register long nr asm("r7") = __NR_gettimeofday;
25+
26+
asm volatile(
27+
" swi #0\n"
28+
: "=r" (ret)
29+
: "r" (tv), "r" (tz), "r" (nr)
30+
: "memory");
31+
32+
return ret;
33+
}
34+
35+
static __always_inline long clock_gettime_fallback(
36+
clockid_t _clkid,
37+
struct __kernel_timespec *_ts)
38+
{
39+
register struct __kernel_timespec *ts asm("r1") = _ts;
40+
register clockid_t clkid asm("r0") = _clkid;
41+
register long ret asm ("r0");
42+
register long nr asm("r7") = __NR_clock_gettime64;
43+
44+
asm volatile(
45+
" swi #0\n"
46+
: "=r" (ret)
47+
: "r" (clkid), "r" (ts), "r" (nr)
48+
: "memory");
49+
50+
return ret;
51+
}
52+
53+
static __always_inline u64 __arch_get_hw_counter(int clock_mode)
54+
{
55+
#ifdef CONFIG_ARM_ARCH_TIMER
56+
u64 cycle_now;
57+
58+
isb();
59+
cycle_now = read_sysreg(CNTVCT);
60+
61+
return cycle_now;
62+
#else
63+
return -EINVAL; /* use fallback */
64+
#endif
65+
}
66+
67+
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
68+
{
69+
return __get_datapage();
70+
}
71+
72+
#endif /* !__ASSEMBLY__ */
73+
74+
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */

arch/arm/include/asm/vdso/vsyscall.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
#include <asm/cacheflush.h>
10+
11+
extern struct vdso_data *vdso_data;
12+
extern bool cntvct_ok;
13+
14+
static __always_inline
15+
bool tk_is_cntvct(const struct timekeeper *tk)
16+
{
17+
if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
18+
return false;
19+
20+
if (!tk->tkr_mono.clock->archdata.vdso_direct)
21+
return false;
22+
23+
return true;
24+
}
25+
26+
/*
27+
* Update the vDSO data page to keep in sync with kernel timekeeping.
28+
*/
29+
static __always_inline
30+
struct vdso_data *__arm_get_k_vdso_data(void)
31+
{
32+
return vdso_data;
33+
}
34+
#define __arch_get_k_vdso_data __arm_get_k_vdso_data
35+
36+
static __always_inline
37+
int __arm_update_vdso_data(void)
38+
{
39+
return !cntvct_ok;
40+
}
41+
#define __arch_update_vdso_data __arm_update_vdso_data
42+
43+
static __always_inline
44+
int __arm_get_clock_mode(struct timekeeper *tk)
45+
{
46+
u32 __tk_is_cntvct = tk_is_cntvct(tk);
47+
48+
return __tk_is_cntvct;
49+
}
50+
#define __arch_get_clock_mode __arm_get_clock_mode
51+
52+
static __always_inline
53+
int __arm_use_vsyscall(struct vdso_data *vdata)
54+
{
55+
return vdata[CS_HRES_COARSE].clock_mode;
56+
}
57+
#define __arch_use_vsyscall __arm_use_vsyscall
58+
59+
static __always_inline
60+
void __arm_sync_vdso_data(struct vdso_data *vdata)
61+
{
62+
flush_dcache_page(virt_to_page(vdata));
63+
}
64+
#define __arch_sync_vdso_data __arm_sync_vdso_data
65+
66+
/* The asm-generic header needs to be included after the definitions above */
67+
#include <asm-generic/vdso/vsyscall.h>
68+
69+
#endif /* !__ASSEMBLY__ */
70+
71+
#endif /* __ASM_VDSO_VSYSCALL_H */

arch/arm/include/asm/vdso_datapage.h

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,12 @@
1111

1212
#ifndef __ASSEMBLY__
1313

14+
#include <vdso/datapage.h>
1415
#include <asm/page.h>
1516

16-
/* Try to be cache-friendly on systems that don't implement the
17-
* generic timer: fit the unconditionally updated fields in the first
18-
* 32 bytes.
19-
*/
20-
struct vdso_data {
21-
u32 seq_count; /* sequence count - odd during updates */
22-
u16 tk_is_cntvct; /* fall back to syscall if false */
23-
u16 cs_shift; /* clocksource shift */
24-
u32 xtime_coarse_sec; /* coarse time */
25-
u32 xtime_coarse_nsec;
26-
27-
u32 wtm_clock_sec; /* wall to monotonic offset */
28-
u32 wtm_clock_nsec;
29-
u32 xtime_clock_sec; /* CLOCK_REALTIME - seconds */
30-
u32 cs_mult; /* clocksource multiplier */
31-
32-
u64 cs_cycle_last; /* last cycle value */
33-
u64 cs_mask; /* clocksource mask */
34-
35-
u64 xtime_clock_snsec; /* CLOCK_REALTIME sub-ns base */
36-
u32 tz_minuteswest; /* timezone info for gettimeofday(2) */
37-
u32 tz_dsttime;
38-
};
39-
4017
union vdso_data_store {
41-
struct vdso_data data;
42-
u8 page[PAGE_SIZE];
18+
struct vdso_data data[CS_BASES];
19+
u8 page[PAGE_SIZE];
4320
};
4421

4522
#endif /* !__ASSEMBLY__ */

arch/arm/kernel/vdso.c

Lines changed: 4 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <asm/vdso.h>
2424
#include <asm/vdso_datapage.h>
2525
#include <clocksource/arm_arch_timer.h>
26+
#include <vdso/helpers.h>
27+
#include <vdso/vsyscall.h>
2628

2729
#define MAX_SYMNAME 64
2830

@@ -37,7 +39,7 @@ unsigned int vdso_total_pages __ro_after_init;
3739
* The VDSO data page.
3840
*/
3941
static union vdso_data_store vdso_data_store __page_aligned_data;
40-
static struct vdso_data *vdso_data = &vdso_data_store.data;
42+
struct vdso_data *vdso_data = vdso_data_store.data;
4143

4244
static struct page *vdso_data_page __ro_after_init;
4345
static const struct vm_special_mapping vdso_data_mapping = {
@@ -77,7 +79,7 @@ struct elfinfo {
7779
/* Cached result of boot-time check for whether the arch timer exists,
7880
* and if so, whether the virtual counter is useable.
7981
*/
80-
static bool cntvct_ok __ro_after_init;
82+
bool cntvct_ok __ro_after_init;
8183

8284
static bool __init cntvct_functional(void)
8385
{
@@ -262,84 +264,3 @@ void arm_install_vdso(struct mm_struct *mm, unsigned long addr)
262264
mm->context.vdso = addr;
263265
}
264266

265-
static void vdso_write_begin(struct vdso_data *vdata)
266-
{
267-
++vdso_data->seq_count;
268-
smp_wmb(); /* Pairs with smp_rmb in vdso_read_retry */
269-
}
270-
271-
static void vdso_write_end(struct vdso_data *vdata)
272-
{
273-
smp_wmb(); /* Pairs with smp_rmb in vdso_read_begin */
274-
++vdso_data->seq_count;
275-
}
276-
277-
static bool tk_is_cntvct(const struct timekeeper *tk)
278-
{
279-
if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
280-
return false;
281-
282-
if (!tk->tkr_mono.clock->archdata.vdso_direct)
283-
return false;
284-
285-
return true;
286-
}
287-
288-
/**
289-
* update_vsyscall - update the vdso data page
290-
*
291-
* Increment the sequence counter, making it odd, indicating to
292-
* userspace that an update is in progress. Update the fields used
293-
* for coarse clocks and, if the architected system timer is in use,
294-
* the fields used for high precision clocks. Increment the sequence
295-
* counter again, making it even, indicating to userspace that the
296-
* update is finished.
297-
*
298-
* Userspace is expected to sample seq_count before reading any other
299-
* fields from the data page. If seq_count is odd, userspace is
300-
* expected to wait until it becomes even. After copying data from
301-
* the page, userspace must sample seq_count again; if it has changed
302-
* from its previous value, userspace must retry the whole sequence.
303-
*
304-
* Calls to update_vsyscall are serialized by the timekeeping core.
305-
*/
306-
void update_vsyscall(struct timekeeper *tk)
307-
{
308-
struct timespec64 *wtm = &tk->wall_to_monotonic;
309-
310-
if (!cntvct_ok) {
311-
/* The entry points have been zeroed, so there is no
312-
* point in updating the data page.
313-
*/
314-
return;
315-
}
316-
317-
vdso_write_begin(vdso_data);
318-
319-
vdso_data->tk_is_cntvct = tk_is_cntvct(tk);
320-
vdso_data->xtime_coarse_sec = tk->xtime_sec;
321-
vdso_data->xtime_coarse_nsec = (u32)(tk->tkr_mono.xtime_nsec >>
322-
tk->tkr_mono.shift);
323-
vdso_data->wtm_clock_sec = wtm->tv_sec;
324-
vdso_data->wtm_clock_nsec = wtm->tv_nsec;
325-
326-
if (vdso_data->tk_is_cntvct) {
327-
vdso_data->cs_cycle_last = tk->tkr_mono.cycle_last;
328-
vdso_data->xtime_clock_sec = tk->xtime_sec;
329-
vdso_data->xtime_clock_snsec = tk->tkr_mono.xtime_nsec;
330-
vdso_data->cs_mult = tk->tkr_mono.mult;
331-
vdso_data->cs_shift = tk->tkr_mono.shift;
332-
vdso_data->cs_mask = tk->tkr_mono.mask;
333-
}
334-
335-
vdso_write_end(vdso_data);
336-
337-
flush_dcache_page(virt_to_page(vdso_data));
338-
}
339-
340-
void update_vsyscall_tz(void)
341-
{
342-
vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
343-
vdso_data->tz_dsttime = sys_tz.tz_dsttime;
344-
flush_dcache_page(virt_to_page(vdso_data));
345-
}

arch/arm/mm/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,10 @@ config VDSO
896896
bool "Enable VDSO for acceleration of some system calls"
897897
depends on AEABI && MMU && CPU_V7
898898
default y if ARM_ARCH_TIMER
899+
select HAVE_GENERIC_VDSO
899900
select GENERIC_TIME_VSYSCALL
901+
select GENERIC_VDSO_32
902+
select GENERIC_GETTIMEOFDAY
900903
help
901904
Place in the process address space an ELF shared object
902905
providing fast implementations of gettimeofday and

arch/arm/vdso/Makefile

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
# SPDX-License-Identifier: GPL-2.0
2+
3+
# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
4+
# the inclusion of generic Makefile.
5+
ARCH_REL_TYPE_ABS := R_ARM_JUMP_SLOT|R_ARM_GLOB_DAT|R_ARM_ABS32
6+
include $(srctree)/lib/vdso/Makefile
7+
28
hostprogs-y := vdsomunge
39

4-
obj-vdso := vgettimeofday.o datapage.o
10+
obj-vdso := vgettimeofday.o datapage.o note.o
511

612
# Build rules
713
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.so.raw vdso.lds
@@ -24,7 +30,11 @@ CFLAGS_REMOVE_vdso.o = -pg
2430

2531
# Force -O2 to avoid libgcc dependencies
2632
CFLAGS_REMOVE_vgettimeofday.o = -pg -Os
33+
ifeq ($(c-gettimeofday-y),)
2734
CFLAGS_vgettimeofday.o = -O2
35+
else
36+
CFLAGS_vgettimeofday.o = -O2 -include $(c-gettimeofday-y)
37+
endif
2838

2939
# Disable gcov profiling for VDSO code
3040
GCOV_PROFILE := n
@@ -37,7 +47,7 @@ $(obj)/vdso.o : $(obj)/vdso.so
3747

3848
# Link rule for the .so file
3949
$(obj)/vdso.so.raw: $(obj)/vdso.lds $(obj-vdso) FORCE
40-
$(call if_changed,ld)
50+
$(call if_changed,vdsold_and_vdso_check)
4151

4252
$(obj)/vdso.so.dbg: $(obj)/vdso.so.raw $(obj)/vdsomunge FORCE
4353
$(call if_changed,vdsomunge)
@@ -47,6 +57,10 @@ $(obj)/%.so: OBJCOPYFLAGS := -S
4757
$(obj)/%.so: $(obj)/%.so.dbg FORCE
4858
$(call if_changed,objcopy)
4959

60+
# Actual build commands
61+
quiet_cmd_vdsold_and_vdso_check = LD $@
62+
cmd_vdsold_and_vdso_check = $(cmd_ld); $(cmd_vdso_check)
63+
5064
quiet_cmd_vdsomunge = MUNGE $@
5165
cmd_vdsomunge = $(objtree)/$(obj)/vdsomunge $< $@
5266

arch/arm/vdso/note.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2012-2018 ARM Limited
4+
*
5+
* This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
6+
* Here we can supply some information useful to userland.
7+
*/
8+
9+
#include <linux/uts.h>
10+
#include <linux/version.h>
11+
#include <linux/elfnote.h>
12+
#include <linux/build-salt.h>
13+
14+
ELFNOTE32("Linux", 0, LINUX_VERSION_CODE);
15+
BUILD_SALT;

0 commit comments

Comments
 (0)