.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Userland implementation of gettimeofday() for 32 bits processes in a |
---|
3 | 4 | * ppc64 kernel for use in the vDSO |
---|
4 | 5 | * |
---|
5 | 6 | * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org, |
---|
6 | 7 | * IBM Corp. |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or |
---|
9 | | - * modify it under the terms of the GNU General Public License |
---|
10 | | - * as published by the Free Software Foundation; either version |
---|
11 | | - * 2 of the License, or (at your option) any later version. |
---|
12 | 8 | */ |
---|
13 | 9 | #include <asm/processor.h> |
---|
14 | 10 | #include <asm/ppc_asm.h> |
---|
15 | 11 | #include <asm/vdso.h> |
---|
| 12 | +#include <asm/vdso_datapage.h> |
---|
16 | 13 | #include <asm/asm-offsets.h> |
---|
17 | 14 | #include <asm/unistd.h> |
---|
18 | 15 | |
---|
19 | 16 | /* Offset for the low 32-bit part of a field of long type */ |
---|
20 | 17 | #ifdef CONFIG_PPC64 |
---|
21 | 18 | #define LOPART 4 |
---|
22 | | -#define TSPEC_TV_SEC TSPC64_TV_SEC+LOPART |
---|
23 | 19 | #else |
---|
24 | 20 | #define LOPART 0 |
---|
25 | | -#define TSPEC_TV_SEC TSPC32_TV_SEC |
---|
26 | 21 | #endif |
---|
27 | 22 | |
---|
28 | 23 | .text |
---|
.. | .. |
---|
37 | 32 | mflr r12 |
---|
38 | 33 | .cfi_register lr,r12 |
---|
39 | 34 | |
---|
40 | | - mr r10,r3 /* r10 saves tv */ |
---|
| 35 | + mr. r10,r3 /* r10 saves tv */ |
---|
41 | 36 | mr r11,r4 /* r11 saves tz */ |
---|
42 | | - bl __get_datapage@local /* get data page */ |
---|
43 | | - mr r9, r3 /* datapage ptr in r9 */ |
---|
44 | | - cmplwi r10,0 /* check if tv is NULL */ |
---|
| 37 | + get_datapage r9, r0 |
---|
45 | 38 | beq 3f |
---|
46 | | - lis r7,1000000@ha /* load up USEC_PER_SEC */ |
---|
47 | | - addi r7,r7,1000000@l /* so we get microseconds in r4 */ |
---|
| 39 | + LOAD_REG_IMMEDIATE(r7, 1000000) /* load up USEC_PER_SEC */ |
---|
48 | 40 | bl __do_get_tspec@local /* get sec/usec from tb & kernel */ |
---|
49 | 41 | stw r3,TVAL32_TV_SEC(r10) |
---|
50 | 42 | stw r4,TVAL32_TV_USEC(r10) |
---|
51 | 43 | |
---|
52 | 44 | 3: cmplwi r11,0 /* check if tz is NULL */ |
---|
53 | | - beq 1f |
---|
| 45 | + mtlr r12 |
---|
| 46 | + crclr cr0*4+so |
---|
| 47 | + li r3,0 |
---|
| 48 | + beqlr |
---|
| 49 | + |
---|
54 | 50 | lwz r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */ |
---|
55 | 51 | lwz r5,CFG_TZ_DSTTIME(r9) |
---|
56 | 52 | stw r4,TZONE_TZ_MINWEST(r11) |
---|
57 | 53 | stw r5,TZONE_TZ_DSTTIME(r11) |
---|
58 | 54 | |
---|
59 | | -1: mtlr r12 |
---|
60 | | - crclr cr0*4+so |
---|
61 | | - li r3,0 |
---|
62 | 55 | blr |
---|
63 | 56 | .cfi_endproc |
---|
64 | 57 | V_FUNCTION_END(__kernel_gettimeofday) |
---|
.. | .. |
---|
75 | 68 | cmpli cr0,r3,CLOCK_REALTIME |
---|
76 | 69 | cmpli cr1,r3,CLOCK_MONOTONIC |
---|
77 | 70 | cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
---|
78 | | - bne cr0,99f |
---|
| 71 | + |
---|
| 72 | + cmpli cr5,r3,CLOCK_REALTIME_COARSE |
---|
| 73 | + cmpli cr6,r3,CLOCK_MONOTONIC_COARSE |
---|
| 74 | + cror cr5*4+eq,cr5*4+eq,cr6*4+eq |
---|
| 75 | + |
---|
| 76 | + cror cr0*4+eq,cr0*4+eq,cr5*4+eq |
---|
| 77 | + bne cr0, .Lgettime_fallback |
---|
79 | 78 | |
---|
80 | 79 | mflr r12 /* r12 saves lr */ |
---|
81 | 80 | .cfi_register lr,r12 |
---|
82 | 81 | mr r11,r4 /* r11 saves tp */ |
---|
83 | | - bl __get_datapage@local /* get data page */ |
---|
84 | | - mr r9,r3 /* datapage ptr in r9 */ |
---|
85 | | - lis r7,NSEC_PER_SEC@h /* want nanoseconds */ |
---|
86 | | - ori r7,r7,NSEC_PER_SEC@l |
---|
87 | | -50: bl __do_get_tspec@local /* get sec/nsec from tb & kernel */ |
---|
88 | | - bne cr1,80f /* not monotonic -> all done */ |
---|
| 82 | + get_datapage r9, r0 |
---|
| 83 | + LOAD_REG_IMMEDIATE(r7, NSEC_PER_SEC) /* load up NSEC_PER_SEC */ |
---|
| 84 | + beq cr5, .Lcoarse_clocks |
---|
| 85 | +.Lprecise_clocks: |
---|
| 86 | + bl __do_get_tspec@local /* get sec/nsec from tb & kernel */ |
---|
| 87 | + bne cr1, .Lfinish /* not monotonic -> all done */ |
---|
89 | 88 | |
---|
90 | 89 | /* |
---|
91 | 90 | * CLOCK_MONOTONIC |
---|
.. | .. |
---|
109 | 108 | add r9,r9,r0 |
---|
110 | 109 | lwz r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9) |
---|
111 | 110 | cmpl cr0,r8,r0 /* check if updated */ |
---|
112 | | - bne- 50b |
---|
| 111 | + bne- .Lprecise_clocks |
---|
| 112 | + b .Lfinish_monotonic |
---|
| 113 | + |
---|
| 114 | + /* |
---|
| 115 | + * For coarse clocks we get data directly from the vdso data page, so |
---|
| 116 | + * we don't need to call __do_get_tspec, but we still need to do the |
---|
| 117 | + * counter trick. |
---|
| 118 | + */ |
---|
| 119 | +.Lcoarse_clocks: |
---|
| 120 | + lwz r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9) |
---|
| 121 | + andi. r0,r8,1 /* pending update ? loop */ |
---|
| 122 | + bne- .Lcoarse_clocks |
---|
| 123 | + add r9,r9,r0 /* r0 is already 0 */ |
---|
| 124 | + |
---|
| 125 | + /* |
---|
| 126 | + * CLOCK_REALTIME_COARSE, below values are needed for MONOTONIC_COARSE |
---|
| 127 | + * too |
---|
| 128 | + */ |
---|
| 129 | + lwz r3,STAMP_XTIME_SEC+LOPART(r9) |
---|
| 130 | + lwz r4,STAMP_XTIME_NSEC+LOPART(r9) |
---|
| 131 | + bne cr6,1f |
---|
| 132 | + |
---|
| 133 | + /* CLOCK_MONOTONIC_COARSE */ |
---|
| 134 | + lwz r5,(WTOM_CLOCK_SEC+LOPART)(r9) |
---|
| 135 | + lwz r6,WTOM_CLOCK_NSEC(r9) |
---|
| 136 | + |
---|
| 137 | + /* check if counter has updated */ |
---|
| 138 | + or r0,r6,r5 |
---|
| 139 | +1: or r0,r0,r3 |
---|
| 140 | + or r0,r0,r4 |
---|
| 141 | + xor r0,r0,r0 |
---|
| 142 | + add r3,r3,r0 |
---|
| 143 | + lwz r0,CFG_TB_UPDATE_COUNT+LOPART(r9) |
---|
| 144 | + cmpl cr0,r0,r8 /* check if updated */ |
---|
| 145 | + bne- .Lcoarse_clocks |
---|
| 146 | + |
---|
| 147 | + /* Counter has not updated, so continue calculating proper values for |
---|
| 148 | + * sec and nsec if monotonic coarse, or just return with the proper |
---|
| 149 | + * values for realtime. |
---|
| 150 | + */ |
---|
| 151 | + bne cr6, .Lfinish |
---|
113 | 152 | |
---|
114 | 153 | /* Calculate and store result. Note that this mimics the C code, |
---|
115 | 154 | * which may cause funny results if nsec goes negative... is that |
---|
116 | 155 | * possible at all ? |
---|
117 | 156 | */ |
---|
| 157 | +.Lfinish_monotonic: |
---|
118 | 158 | add r3,r3,r5 |
---|
119 | 159 | add r4,r4,r6 |
---|
120 | 160 | cmpw cr0,r4,r7 |
---|
.. | .. |
---|
122 | 162 | blt 1f |
---|
123 | 163 | subf r4,r7,r4 |
---|
124 | 164 | addi r3,r3,1 |
---|
125 | | -1: bge cr1,80f |
---|
| 165 | +1: bge cr1, .Lfinish |
---|
126 | 166 | addi r3,r3,-1 |
---|
127 | 167 | add r4,r4,r7 |
---|
128 | 168 | |
---|
129 | | -80: stw r3,TSPC32_TV_SEC(r11) |
---|
| 169 | +.Lfinish: |
---|
| 170 | + stw r3,TSPC32_TV_SEC(r11) |
---|
130 | 171 | stw r4,TSPC32_TV_NSEC(r11) |
---|
131 | 172 | |
---|
132 | 173 | mtlr r12 |
---|
.. | .. |
---|
137 | 178 | /* |
---|
138 | 179 | * syscall fallback |
---|
139 | 180 | */ |
---|
140 | | -99: |
---|
| 181 | +.Lgettime_fallback: |
---|
141 | 182 | li r0,__NR_clock_gettime |
---|
142 | 183 | .cfi_restore lr |
---|
143 | 184 | sc |
---|
.. | .. |
---|
155 | 196 | V_FUNCTION_BEGIN(__kernel_clock_getres) |
---|
156 | 197 | .cfi_startproc |
---|
157 | 198 | /* Check for supported clock IDs */ |
---|
158 | | - cmpwi cr0,r3,CLOCK_REALTIME |
---|
159 | | - cmpwi cr1,r3,CLOCK_MONOTONIC |
---|
160 | | - cror cr0*4+eq,cr0*4+eq,cr1*4+eq |
---|
161 | | - bne cr0,99f |
---|
| 199 | + cmplwi cr0, r3, CLOCK_MAX |
---|
| 200 | + cmpwi cr1, r3, CLOCK_REALTIME_COARSE |
---|
| 201 | + cmpwi cr7, r3, CLOCK_MONOTONIC_COARSE |
---|
| 202 | + bgt cr0, 99f |
---|
| 203 | + LOAD_REG_IMMEDIATE(r5, KTIME_LOW_RES) |
---|
| 204 | + beq cr1, 1f |
---|
| 205 | + beq cr7, 1f |
---|
162 | 206 | |
---|
163 | 207 | mflr r12 |
---|
164 | 208 | .cfi_register lr,r12 |
---|
165 | | - bl __get_datapage@local /* get data page */ |
---|
| 209 | + get_datapage r3, r0 |
---|
166 | 210 | lwz r5, CLOCK_HRTIMER_RES(r3) |
---|
167 | 211 | mtlr r12 |
---|
168 | | - li r3,0 |
---|
| 212 | +1: li r3,0 |
---|
169 | 213 | cmpli cr0,r4,0 |
---|
170 | 214 | crclr cr0*4+so |
---|
171 | 215 | beqlr |
---|
.. | .. |
---|
196 | 240 | .cfi_register lr,r12 |
---|
197 | 241 | |
---|
198 | 242 | mr r11,r3 /* r11 holds t */ |
---|
199 | | - bl __get_datapage@local |
---|
200 | | - mr r9, r3 /* datapage ptr in r9 */ |
---|
| 243 | + get_datapage r9, r0 |
---|
201 | 244 | |
---|
202 | | - lwz r3,STAMP_XTIME+TSPEC_TV_SEC(r9) |
---|
| 245 | + lwz r3,STAMP_XTIME_SEC+LOPART(r9) |
---|
203 | 246 | |
---|
204 | 247 | cmplwi r11,0 /* check if t is NULL */ |
---|
205 | | - beq 2f |
---|
206 | | - stw r3,0(r11) /* store result at *t */ |
---|
207 | | -2: mtlr r12 |
---|
| 248 | + mtlr r12 |
---|
208 | 249 | crclr cr0*4+so |
---|
| 250 | + beqlr |
---|
| 251 | + stw r3,0(r11) /* store result at *t */ |
---|
209 | 252 | blr |
---|
210 | 253 | .cfi_endproc |
---|
211 | 254 | V_FUNCTION_END(__kernel_time) |
---|
.. | .. |
---|
275 | 318 | * as a 32.32 fixed-point number in r3 and r4. |
---|
276 | 319 | * Load & add the xtime stamp. |
---|
277 | 320 | */ |
---|
278 | | - lwz r5,STAMP_XTIME+TSPEC_TV_SEC(r9) |
---|
| 321 | + lwz r5,STAMP_XTIME_SEC+LOPART(r9) |
---|
279 | 322 | lwz r6,STAMP_SEC_FRAC(r9) |
---|
280 | 323 | addc r4,r4,r6 |
---|
281 | 324 | adde r3,r3,r5 |
---|