[POWERPC] Remove ioremap64 and fixup_bigphys_addr
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / powerpc / kernel / vdso64 / gettimeofday.S
CommitLineData
0c37ec2a
BH
1
2 /*
a7f290da
BH
3 * Userland implementation of gettimeofday() for 64 bits processes in a
4 * ppc64 kernel for use in the vDSO
5 *
6 * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
7 * IBM Corp.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
a7f290da
BH
14#include <asm/processor.h>
15#include <asm/ppc_asm.h>
16#include <asm/vdso.h>
17#include <asm/asm-offsets.h>
18#include <asm/unistd.h>
19
20 .text
21/*
22 * Exact prototype of gettimeofday
23 *
24 * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
25 *
26 */
27V_FUNCTION_BEGIN(__kernel_gettimeofday)
28 .cfi_startproc
29 mflr r12
30 .cfi_register lr,r12
31
32 mr r11,r3 /* r11 holds tv */
33 mr r10,r4 /* r10 holds tz */
34 bl V_LOCAL_FUNC(__get_datapage) /* get data page */
35 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
36 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
37 ori r7,r7,16960
38 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
39 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
40 std r5,TVAL64_TV_SEC(r11) /* store sec in tv */
41 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
42 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
43 * XSEC_PER_SEC
44 */
45 rldicl r0,r0,44,20
46 cmpldi cr0,r10,0 /* check if tz is NULL */
47 std r0,TVAL64_TV_USEC(r11) /* store usec in tv */
48 beq 1f
49 lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
50 lwz r5,CFG_TZ_DSTTIME(r3)
51 stw r4,TZONE_TZ_MINWEST(r10)
52 stw r5,TZONE_TZ_DSTTIME(r10)
531: mtlr r12
5d66da3d 54 crclr cr0*4+so
a7f290da
BH
55 li r3,0 /* always success */
56 blr
57 .cfi_endproc
58V_FUNCTION_END(__kernel_gettimeofday)
59
60
61/*
62 * Exact prototype of clock_gettime()
63 *
64 * int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp);
65 *
66 */
67V_FUNCTION_BEGIN(__kernel_clock_gettime)
68 .cfi_startproc
69 /* Check for supported clock IDs */
70 cmpwi cr0,r3,CLOCK_REALTIME
71 cmpwi cr1,r3,CLOCK_MONOTONIC
0c37ec2a 72 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
a7f290da
BH
73 bne cr0,99f
74
75 mflr r12 /* r12 saves lr */
76 .cfi_register lr,r12
77 mr r10,r3 /* r10 saves id */
78 mr r11,r4 /* r11 saves tp */
79 bl V_LOCAL_FUNC(__get_datapage) /* get data page */
80 beq cr1,50f /* if monotonic -> jump there */
81
82 /*
83 * CLOCK_REALTIME
84 */
85
86 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
87
0c37ec2a
BH
88 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
89 ori r7,r7,16960
a7f290da
BH
90 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
91 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
92 std r5,TSPC64_TV_SEC(r11) /* store sec in tv */
93 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
0c37ec2a 94 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
a7f290da
BH
95 * XSEC_PER_SEC
96 */
97 rldicl r0,r0,44,20
0c37ec2a 98 mulli r0,r0,1000 /* nsec = usec * 1000 */
a7f290da
BH
99 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */
100
101 mtlr r12
5d66da3d 102 crclr cr0*4+so
a7f290da
BH
103 li r3,0
104 blr
105
106 /*
107 * CLOCK_MONOTONIC
108 */
109
11050: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
111
0c37ec2a
BH
112 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
113 ori r7,r7,16960
a7f290da
BH
114 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
115 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
116 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
0c37ec2a 117 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
a7f290da
BH
118 * XSEC_PER_SEC
119 */
120 rldicl r6,r0,44,20
0c37ec2a 121 mulli r6,r6,1000 /* nsec = usec * 1000 */
a7f290da
BH
122
123 /* now we must fixup using wall to monotonic. We need to snapshot
124 * that value and do the counter trick again. Fortunately, we still
125 * have the counter value in r8 that was returned by __do_get_xsec.
126 * At this point, r5,r6 contain our sec/nsec values.
127 * can be used
128 */
129
0c37ec2a
BH
130 lwa r4,WTOM_CLOCK_SEC(r3)
131 lwa r7,WTOM_CLOCK_NSEC(r3)
a7f290da
BH
132
133 /* We now have our result in r4,r7. We create a fake dependency
134 * on that result and re-check the counter
135 */
136 or r9,r4,r7
137 xor r0,r9,r9
138 add r3,r3,r0
139 ld r0,CFG_TB_UPDATE_COUNT(r3)
140 cmpld cr0,r0,r8 /* check if updated */
141 bne- 50b
142
143 /* Calculate and store result. Note that this mimmics the C code,
144 * which may cause funny results if nsec goes negative... is that
145 * possible at all ?
146 */
147 add r4,r4,r5
148 add r7,r7,r6
149 lis r9,NSEC_PER_SEC@h
150 ori r9,r9,NSEC_PER_SEC@l
0c37ec2a
BH
151 cmpl cr0,r7,r9
152 cmpli cr1,r7,0
a7f290da
BH
153 blt 1f
154 subf r7,r9,r7
155 addi r4,r4,1
0c37ec2a
BH
1561: bge cr1,1f
157 addi r4,r4,-1
158 add r7,r7,r9
a7f290da
BH
1591: std r4,TSPC64_TV_SEC(r11)
160 std r7,TSPC64_TV_NSEC(r11)
161
162 mtlr r12
5d66da3d 163 crclr cr0*4+so
a7f290da
BH
164 li r3,0
165 blr
166
167 /*
168 * syscall fallback
169 */
17098:
171 mtlr r12
172 mr r3,r10
173 mr r4,r11
17499:
175 li r0,__NR_clock_gettime
176 sc
177 blr
178 .cfi_endproc
179V_FUNCTION_END(__kernel_clock_gettime)
180
181
182/*
183 * Exact prototype of clock_getres()
184 *
185 * int __kernel_clock_getres(clockid_t clock_id, struct timespec *res);
186 *
187 */
188V_FUNCTION_BEGIN(__kernel_clock_getres)
189 .cfi_startproc
190 /* Check for supported clock IDs */
191 cmpwi cr0,r3,CLOCK_REALTIME
192 cmpwi cr1,r3,CLOCK_MONOTONIC
0c37ec2a 193 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
a7f290da
BH
194 bne cr0,99f
195
196 li r3,0
197 cmpli cr0,r4,0
5d66da3d 198 crclr cr0*4+so
a7f290da
BH
199 beqlr
200 lis r5,CLOCK_REALTIME_RES@h
201 ori r5,r5,CLOCK_REALTIME_RES@l
202 std r3,TSPC64_TV_SEC(r4)
203 std r5,TSPC64_TV_NSEC(r4)
204 blr
205
206 /*
207 * syscall fallback
208 */
20999:
210 li r0,__NR_clock_getres
211 sc
212 blr
213 .cfi_endproc
214V_FUNCTION_END(__kernel_clock_getres)
215
216
217/*
218 * This is the core of gettimeofday(), it returns the xsec
219 * value in r4 and expects the datapage ptr (non clobbered)
220 * in r3. clobbers r0,r4,r5,r6,r7,r8
221 * When returning, r8 contains the counter value that can be reused
222 */
223V_FUNCTION_BEGIN(__do_get_xsec)
224 .cfi_startproc
225 /* check for update count & load values */
2261: ld r8,CFG_TB_UPDATE_COUNT(r3)
634473db 227 andi. r0,r8,1 /* pending update ? loop */
a7f290da 228 bne- 1b
634473db 229 xor r0,r8,r8 /* create dependency */
a7f290da
BH
230 add r3,r3,r0
231
859deea9
BH
232 /* Get TB & offset it. We use the MFTB macro which will generate
233 * workaround code for Cell.
234 */
235 MFTB(r7)
a7f290da
BH
236 ld r9,CFG_TB_ORIG_STAMP(r3)
237 subf r7,r9,r7
238
239 /* Scale result */
240 ld r5,CFG_TB_TO_XS(r3)
241 mulhdu r7,r7,r5
242
243 /* Add stamp since epoch */
244 ld r6,CFG_STAMP_XSEC(r3)
245 add r4,r6,r7
246
247 xor r0,r4,r4
248 add r3,r3,r0
249 ld r0,CFG_TB_UPDATE_COUNT(r3)
250 cmpld cr0,r0,r8 /* check if updated */
251 bne- 1b
252 blr
253 .cfi_endproc
254V_FUNCTION_END(__do_get_xsec)