]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.9/arm64-vdso-fix-clock_getres-for-clock_realtime.patch
Linux 4.14.123
[thirdparty/kernel/stable-queue.git] / queue-4.9 / arm64-vdso-fix-clock_getres-for-clock_realtime.patch
1 From 796b5a9a42a8d56d008809b67c84d29c0766c84f Mon Sep 17 00:00:00 2001
2 From: Vincenzo Frascino <vincenzo.frascino@arm.com>
3 Date: Tue, 16 Apr 2019 17:14:30 +0100
4 Subject: arm64: vdso: Fix clock_getres() for CLOCK_REALTIME
5
6 [ Upstream commit 81fb8736dd81da3fe94f28968dac60f392ec6746 ]
7
8 clock_getres() in the vDSO library has to preserve the same behaviour
9 of posix_get_hrtimer_res().
10
11 In particular, posix_get_hrtimer_res() does:
12
13 sec = 0;
14 ns = hrtimer_resolution;
15
16 where 'hrtimer_resolution' depends on whether or not high resolution
17 timers are enabled, which is a runtime decision.
18
19 The vDSO incorrectly returns the constant CLOCK_REALTIME_RES. Fix this
20 by exposing 'hrtimer_resolution' in the vDSO datapage and returning that
21 instead.
22
23 Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
24 Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
25 [will: Use WRITE_ONCE(), move adr off COARSE path, renumber labels, use 'w' reg]
26 Signed-off-by: Will Deacon <will.deacon@arm.com>
27 Signed-off-by: Sasha Levin <sashal@kernel.org>
28 ---
29 arch/arm64/include/asm/vdso_datapage.h | 1 +
30 arch/arm64/kernel/asm-offsets.c | 2 +-
31 arch/arm64/kernel/vdso.c | 3 +++
32 arch/arm64/kernel/vdso/gettimeofday.S | 7 +++----
33 4 files changed, 8 insertions(+), 5 deletions(-)
34
35 diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h
36 index 2b9a63771eda8..f89263c8e11af 100644
37 --- a/arch/arm64/include/asm/vdso_datapage.h
38 +++ b/arch/arm64/include/asm/vdso_datapage.h
39 @@ -38,6 +38,7 @@ struct vdso_data {
40 __u32 tz_minuteswest; /* Whacky timezone stuff */
41 __u32 tz_dsttime;
42 __u32 use_syscall;
43 + __u32 hrtimer_res;
44 };
45
46 #endif /* !__ASSEMBLY__ */
47 diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
48 index bd239b1b7a681..95878bea27f93 100644
49 --- a/arch/arm64/kernel/asm-offsets.c
50 +++ b/arch/arm64/kernel/asm-offsets.c
51 @@ -92,7 +92,7 @@ int main(void)
52 DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
53 DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
54 DEFINE(CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC_RAW);
55 - DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
56 + DEFINE(CLOCK_REALTIME_RES, offsetof(struct vdso_data, hrtimer_res));
57 DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
58 DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE);
59 DEFINE(CLOCK_COARSE_RES, LOW_RES_NSEC);
60 diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
61 index 4bcfe01b5aad4..c9b9a5a322eb1 100644
62 --- a/arch/arm64/kernel/vdso.c
63 +++ b/arch/arm64/kernel/vdso.c
64 @@ -213,6 +213,9 @@ void update_vsyscall(struct timekeeper *tk)
65 vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec;
66 vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
67
68 + /* Read without the seqlock held by clock_getres() */
69 + WRITE_ONCE(vdso_data->hrtimer_res, hrtimer_resolution);
70 +
71 if (!use_syscall) {
72 /* tkr_mono.cycle_last == tkr_raw.cycle_last */
73 vdso_data->cs_cycle_last = tk->tkr_mono.cycle_last;
74 diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
75 index 76320e9209651..df829c4346fac 100644
76 --- a/arch/arm64/kernel/vdso/gettimeofday.S
77 +++ b/arch/arm64/kernel/vdso/gettimeofday.S
78 @@ -301,13 +301,14 @@ ENTRY(__kernel_clock_getres)
79 ccmp w0, #CLOCK_MONOTONIC_RAW, #0x4, ne
80 b.ne 1f
81
82 - ldr x2, 5f
83 + adr vdso_data, _vdso_data
84 + ldr w2, [vdso_data, #CLOCK_REALTIME_RES]
85 b 2f
86 1:
87 cmp w0, #CLOCK_REALTIME_COARSE
88 ccmp w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
89 b.ne 4f
90 - ldr x2, 6f
91 + ldr x2, 5f
92 2:
93 cbz w1, 3f
94 stp xzr, x2, [x1]
95 @@ -321,8 +322,6 @@ ENTRY(__kernel_clock_getres)
96 svc #0
97 ret
98 5:
99 - .quad CLOCK_REALTIME_RES
100 -6:
101 .quad CLOCK_COARSE_RES
102 .cfi_endproc
103 ENDPROC(__kernel_clock_getres)
104 --
105 2.20.1
106