aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/vdso64/gettimeofday.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/vdso64/gettimeofday.S')
-rw-r--r--arch/powerpc/kernel/vdso64/gettimeofday.S141
1 files changed, 76 insertions, 65 deletions
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
index c6401f9e37f1..262cd5857a56 100644
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -75,90 +75,49 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
75 75
76 mflr r12 /* r12 saves lr */ 76 mflr r12 /* r12 saves lr */
77 .cfi_register lr,r12 77 .cfi_register lr,r12
78 mr r10,r3 /* r10 saves id */
79 mr r11,r4 /* r11 saves tp */ 78 mr r11,r4 /* r11 saves tp */
80 bl V_LOCAL_FUNC(__get_datapage) /* get data page */ 79 bl V_LOCAL_FUNC(__get_datapage) /* get data page */
81 beq cr1,50f /* if monotonic -> jump there */ 8050: bl V_LOCAL_FUNC(__do_get_tspec) /* get time from tb & kernel */
82 81 bne cr1,80f /* if not monotonic, all done */
83 /*
84 * CLOCK_REALTIME
85 */
86
87 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
88
89 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
90 ori r7,r7,16960
91 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
92 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
93 std r5,TSPC64_TV_SEC(r11) /* store sec in tv */
94 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
95 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
96 * XSEC_PER_SEC
97 */
98 rldicl r0,r0,44,20
99 mulli r0,r0,1000 /* nsec = usec * 1000 */
100 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */
101
102 mtlr r12
103 crclr cr0*4+so
104 li r3,0
105 blr
106 82
107 /* 83 /*
108 * CLOCK_MONOTONIC 84 * CLOCK_MONOTONIC
109 */ 85 */
110 86
11150: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
112
113 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
114 ori r7,r7,16960
115 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
116 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
117 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
118 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
119 * XSEC_PER_SEC
120 */
121 rldicl r6,r0,44,20
122 mulli r6,r6,1000 /* nsec = usec * 1000 */
123
124 /* now we must fixup using wall to monotonic. We need to snapshot 87 /* now we must fixup using wall to monotonic. We need to snapshot
125 * that value and do the counter trick again. Fortunately, we still 88 * that value and do the counter trick again. Fortunately, we still
126 * have the counter value in r8 that was returned by __do_get_xsec. 89 * have the counter value in r8 that was returned by __do_get_tspec.
127 * At this point, r5,r6 contain our sec/nsec values. 90 * At this point, r4,r5 contain our sec/nsec values.
128 * can be used
129 */ 91 */
130 92
131 lwa r4,WTOM_CLOCK_SEC(r3) 93 lwa r6,WTOM_CLOCK_SEC(r3)
132 lwa r7,WTOM_CLOCK_NSEC(r3) 94 lwa r9,WTOM_CLOCK_NSEC(r3)
133 95
134 /* We now have our result in r4,r7. We create a fake dependency 96 /* We now have our result in r6,r9. We create a fake dependency
135 * on that result and re-check the counter 97 * on that result and re-check the counter
136 */ 98 */
137 or r9,r4,r7 99 or r0,r6,r9
138 xor r0,r9,r9 100 xor r0,r0,r0
139 add r3,r3,r0 101 add r3,r3,r0
140 ld r0,CFG_TB_UPDATE_COUNT(r3) 102 ld r0,CFG_TB_UPDATE_COUNT(r3)
141 cmpld cr0,r0,r8 /* check if updated */ 103 cmpld cr0,r0,r8 /* check if updated */
142 bne- 50b 104 bne- 50b
143 105
144 /* Calculate and store result. Note that this mimmics the C code, 106 /* Add wall->monotonic offset and check for overflow or underflow.
145 * which may cause funny results if nsec goes negative... is that
146 * possible at all ?
147 */ 107 */
148 add r4,r4,r5 108 add r4,r4,r6
149 add r7,r7,r6 109 add r5,r5,r9
150 lis r9,NSEC_PER_SEC@h 110 cmpd cr0,r5,r7
151 ori r9,r9,NSEC_PER_SEC@l 111 cmpdi cr1,r5,0
152 cmpl cr0,r7,r9
153 cmpli cr1,r7,0
154 blt 1f 112 blt 1f
155 subf r7,r9,r7 113 subf r5,r7,r5
156 addi r4,r4,1 114 addi r4,r4,1
1571: bge cr1,1f 1151: bge cr1,80f
158 addi r4,r4,-1 116 addi r4,r4,-1
159 add r7,r7,r9 117 add r5,r5,r7
1601: std r4,TSPC64_TV_SEC(r11) 118
161 std r7,TSPC64_TV_NSEC(r11) 11980: std r4,TSPC64_TV_SEC(r11)
120 std r5,TSPC64_TV_NSEC(r11)
162 121
163 mtlr r12 122 mtlr r12
164 crclr cr0*4+so 123 crclr cr0*4+so
@@ -168,10 +127,6 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
168 /* 127 /*
169 * syscall fallback 128 * syscall fallback
170 */ 129 */
17198:
172 mtlr r12
173 mr r3,r10
174 mr r4,r11
17599: 13099:
176 li r0,__NR_clock_gettime 131 li r0,__NR_clock_gettime
177 sc 132 sc
@@ -253,3 +208,59 @@ V_FUNCTION_BEGIN(__do_get_xsec)
253 blr 208 blr
254 .cfi_endproc 209 .cfi_endproc
255V_FUNCTION_END(__do_get_xsec) 210V_FUNCTION_END(__do_get_xsec)
211
212/*
213 * This is the core of clock_gettime(), it returns the current
214 * time in seconds and nanoseconds in r4 and r5.
215 * It expects the datapage ptr in r3 and doesn't clobber it.
216 * It clobbers r0 and r6 and returns NSEC_PER_SEC in r7.
217 * On return, r8 contains the counter value that can be reused.
218 * This clobbers cr0 but not any other cr field.
219 */
220V_FUNCTION_BEGIN(__do_get_tspec)
221 .cfi_startproc
222 /* check for update count & load values */
2231: ld r8,CFG_TB_UPDATE_COUNT(r3)
224 andi. r0,r8,1 /* pending update ? loop */
225 bne- 1b
226 xor r0,r8,r8 /* create dependency */
227 add r3,r3,r0
228
229 /* Get TB & offset it. We use the MFTB macro which will generate
230 * workaround code for Cell.
231 */
232 MFTB(r7)
233 ld r9,CFG_TB_ORIG_STAMP(r3)
234 subf r7,r9,r7
235
236 /* Scale result */
237 ld r5,CFG_TB_TO_XS(r3)
238 sldi r7,r7,12 /* compute time since stamp_xtime */
239 mulhdu r6,r7,r5 /* in units of 2^-32 seconds */
240
241 /* Add stamp since epoch */
242 ld r4,STAMP_XTIME+TSPC64_TV_SEC(r3)
243 ld r5,STAMP_XTIME+TSPC64_TV_NSEC(r3)
244 or r0,r4,r5
245 or r0,r0,r6
246 xor r0,r0,r0
247 add r3,r3,r0
248 ld r0,CFG_TB_UPDATE_COUNT(r3)
249 cmpld r0,r8 /* check if updated */
250 bne- 1b /* reload if so */
251
252 /* convert to seconds & nanoseconds and add to stamp */
253 lis r7,NSEC_PER_SEC@h
254 ori r7,r7,NSEC_PER_SEC@l
255 mulhwu r0,r6,r7 /* compute nanoseconds and */
256 srdi r6,r6,32 /* seconds since stamp_xtime */
257 clrldi r0,r0,32
258 add r5,r5,r0 /* add nanoseconds together */
259 cmpd r5,r7 /* overflow? */
260 add r4,r4,r6
261 bltlr /* all done if no overflow */
262 subf r5,r7,r5 /* if overflow, adjust */
263 addi r4,r4,1
264 blr
265 .cfi_endproc
266V_FUNCTION_END(__do_get_tspec)