aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-11-13 22:55:58 -0500
committerPaul Mackerras <paulus@samba.org>2005-11-14 00:35:58 -0500
commit0c37ec2aa88bd8a6aaeb284ff5c86f4c6d8e8469 (patch)
treed70e4b48664b86a9abfe21ff26561318316fb9c2 /arch
parent50092b233afa96b4c9a4b24ac38199c34e0880cd (diff)
[PATCH] powerpc: vdso fixes (take #2)
This fixes various errors in the new functions added in the vDSO's, I've now verified all functions on both 32 and 64 bits vDSOs. It also fix a sign extension bug getting the initial time of day at boot that could cause the monotonic clock value to be completely on bogus for 64 bits applications (with either the vDSO or the syscall) on powermacs. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/asm-offsets.c6
-rw-r--r--arch/powerpc/kernel/vdso32/datapage.S3
-rw-r--r--arch/powerpc/kernel/vdso32/gettimeofday.S12
-rw-r--r--arch/powerpc/kernel/vdso64/datapage.S1
-rw-r--r--arch/powerpc/kernel/vdso64/gettimeofday.S31
-rw-r--r--arch/powerpc/platforms/powermac/time.c8
6 files changed, 38 insertions, 23 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 4550eb4f4fbd..91538d2445bf 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -270,13 +270,15 @@ int main(void)
270 DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); 270 DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec));
271 DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); 271 DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec));
272 DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); 272 DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec));
273 DEFINE(TSPC64_TV_SEC, offsetof(struct timespec, tv_sec));
274 DEFINE(TSPC64_TV_NSEC, offsetof(struct timespec, tv_nsec));
273 DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec)); 275 DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec));
274 DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); 276 DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec));
275#else 277#else
276 DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec)); 278 DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec));
277 DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec)); 279 DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec));
278 DEFINE(TSPEC32_TV_SEC, offsetof(struct timespec, tv_sec)); 280 DEFINE(TSPC32_TV_SEC, offsetof(struct timespec, tv_sec));
279 DEFINE(TSPEC32_TV_NSEC, offsetof(struct timespec, tv_nsec)); 281 DEFINE(TSPC32_TV_NSEC, offsetof(struct timespec, tv_nsec));
280#endif 282#endif
281 /* timeval/timezone offsets for use by vdso */ 283 /* timeval/timezone offsets for use by vdso */
282 DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); 284 DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S
index a08c26e87835..f6b38472318d 100644
--- a/arch/powerpc/kernel/vdso32/datapage.S
+++ b/arch/powerpc/kernel/vdso32/datapage.S
@@ -77,8 +77,9 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
77 mflr r12 77 mflr r12
78 .cfi_register lr,r12 78 .cfi_register lr,r12
79 bl __get_datapage@local 79 bl __get_datapage@local
80 lwz r3,CFG_TB_TICKS_PER_SEC(r3)
81 lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) 80 lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
81 lwz r3,CFG_TB_TICKS_PER_SEC(r3)
82 mtlr r12 82 mtlr r12
83 blr
83 .cfi_endproc 84 .cfi_endproc
84V_FUNCTION_END(__kernel_get_tbfreq) 85V_FUNCTION_END(__kernel_get_tbfreq)
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
index aeb5fc9b87b3..0a32a41d50b0 100644
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -83,7 +83,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
83 /* Check for supported clock IDs */ 83 /* Check for supported clock IDs */
84 cmpli cr0,r3,CLOCK_REALTIME 84 cmpli cr0,r3,CLOCK_REALTIME
85 cmpli cr1,r3,CLOCK_MONOTONIC 85 cmpli cr1,r3,CLOCK_MONOTONIC
86 cror cr0,cr0,cr1 86 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
87 bne cr0,99f 87 bne cr0,99f
88 88
89 mflr r12 /* r12 saves lr */ 89 mflr r12 /* r12 saves lr */
@@ -91,7 +91,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
91 mr r10,r3 /* r10 saves id */ 91 mr r10,r3 /* r10 saves id */
92 mr r11,r4 /* r11 saves tp */ 92 mr r11,r4 /* r11 saves tp */
93 bl __get_datapage@local /* get data page */ 93 bl __get_datapage@local /* get data page */
94 mr r9, r3 /* datapage ptr in r9 */ 94 mr r9,r3 /* datapage ptr in r9 */
95 beq cr1,50f /* if monotonic -> jump there */ 95 beq cr1,50f /* if monotonic -> jump there */
96 96
97 /* 97 /*
@@ -173,10 +173,14 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
173 add r4,r4,r7 173 add r4,r4,r7
174 lis r5,NSEC_PER_SEC@h 174 lis r5,NSEC_PER_SEC@h
175 ori r5,r5,NSEC_PER_SEC@l 175 ori r5,r5,NSEC_PER_SEC@l
176 cmpli cr0,r4,r5 176 cmpl cr0,r4,r5
177 cmpli cr1,r4,0
177 blt 1f 178 blt 1f
178 subf r4,r5,r4 179 subf r4,r5,r4
179 addi r3,r3,1 180 addi r3,r3,1
1811: bge cr1,1f
182 addi r3,r3,-1
183 add r4,r4,r5
1801: stw r3,TSPC32_TV_SEC(r11) 1841: stw r3,TSPC32_TV_SEC(r11)
181 stw r4,TSPC32_TV_NSEC(r11) 185 stw r4,TSPC32_TV_NSEC(r11)
182 186
@@ -210,7 +214,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
210 /* Check for supported clock IDs */ 214 /* Check for supported clock IDs */
211 cmpwi cr0,r3,CLOCK_REALTIME 215 cmpwi cr0,r3,CLOCK_REALTIME
212 cmpwi cr1,r3,CLOCK_MONOTONIC 216 cmpwi cr1,r3,CLOCK_MONOTONIC
213 cror cr0,cr0,cr1 217 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
214 bne cr0,99f 218 bne cr0,99f
215 219
216 li r3,0 220 li r3,0
diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S
index e67eda0f8cda..6393e4137bc7 100644
--- a/arch/powerpc/kernel/vdso64/datapage.S
+++ b/arch/powerpc/kernel/vdso64/datapage.S
@@ -80,5 +80,6 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
80 bl V_LOCAL_FUNC(__get_datapage) 80 bl V_LOCAL_FUNC(__get_datapage)
81 ld r3,CFG_TB_TICKS_PER_SEC(r3) 81 ld r3,CFG_TB_TICKS_PER_SEC(r3)
82 mtlr r12 82 mtlr r12
83 blr
83 .cfi_endproc 84 .cfi_endproc
84V_FUNCTION_END(__kernel_get_tbfreq) 85V_FUNCTION_END(__kernel_get_tbfreq)
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
index d371c02a8c0e..1a89094715cc 100644
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -1,4 +1,5 @@
1/* 1
2 /*
2 * Userland implementation of gettimeofday() for 64 bits processes in a 3 * Userland implementation of gettimeofday() for 64 bits processes in a
3 * ppc64 kernel for use in the vDSO 4 * ppc64 kernel for use in the vDSO
4 * 5 *
@@ -68,7 +69,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
68 /* Check for supported clock IDs */ 69 /* Check for supported clock IDs */
69 cmpwi cr0,r3,CLOCK_REALTIME 70 cmpwi cr0,r3,CLOCK_REALTIME
70 cmpwi cr1,r3,CLOCK_MONOTONIC 71 cmpwi cr1,r3,CLOCK_MONOTONIC
71 cror cr0,cr0,cr1 72 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
72 bne cr0,99f 73 bne cr0,99f
73 74
74 mflr r12 /* r12 saves lr */ 75 mflr r12 /* r12 saves lr */
@@ -84,16 +85,17 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
84 85
85 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ 86 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
86 87
87 lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ 88 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
88 ori r7,r7,0xca00 89 ori r7,r7,16960
89 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ 90 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
90 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ 91 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
91 std r5,TSPC64_TV_SEC(r11) /* store sec in tv */ 92 std r5,TSPC64_TV_SEC(r11) /* store sec in tv */
92 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ 93 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
93 mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / 94 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
94 * XSEC_PER_SEC 95 * XSEC_PER_SEC
95 */ 96 */
96 rldicl r0,r0,44,20 97 rldicl r0,r0,44,20
98 mulli r0,r0,1000 /* nsec = usec * 1000 */
97 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */ 99 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */
98 100
99 mtlr r12 101 mtlr r12
@@ -106,15 +108,16 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
106 108
10750: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ 10950: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
108 110
109 lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ 111 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
110 ori r7,r7,0xca00 112 ori r7,r7,16960
111 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ 113 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
112 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ 114 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
113 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ 115 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
114 mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / 116 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
115 * XSEC_PER_SEC 117 * XSEC_PER_SEC
116 */ 118 */
117 rldicl r6,r0,44,20 119 rldicl r6,r0,44,20
120 mulli r6,r6,1000 /* nsec = usec * 1000 */
118 121
119 /* now we must fixup using wall to monotonic. We need to snapshot 122 /* now we must fixup using wall to monotonic. We need to snapshot
120 * that value and do the counter trick again. Fortunately, we still 123 * that value and do the counter trick again. Fortunately, we still
@@ -123,8 +126,8 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
123 * can be used 126 * can be used
124 */ 127 */
125 128
126 lwz r4,WTOM_CLOCK_SEC(r9) 129 lwa r4,WTOM_CLOCK_SEC(r3)
127 lwz r7,WTOM_CLOCK_NSEC(r9) 130 lwa r7,WTOM_CLOCK_NSEC(r3)
128 131
129 /* We now have our result in r4,r7. We create a fake dependency 132 /* We now have our result in r4,r7. We create a fake dependency
130 * on that result and re-check the counter 133 * on that result and re-check the counter
@@ -144,10 +147,14 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
144 add r7,r7,r6 147 add r7,r7,r6
145 lis r9,NSEC_PER_SEC@h 148 lis r9,NSEC_PER_SEC@h
146 ori r9,r9,NSEC_PER_SEC@l 149 ori r9,r9,NSEC_PER_SEC@l
147 cmpli cr0,r7,r9 150 cmpl cr0,r7,r9
151 cmpli cr1,r7,0
148 blt 1f 152 blt 1f
149 subf r7,r9,r7 153 subf r7,r9,r7
150 addi r4,r4,1 154 addi r4,r4,1
1551: bge cr1,1f
156 addi r4,r4,-1
157 add r7,r7,r9
1511: std r4,TSPC64_TV_SEC(r11) 1581: std r4,TSPC64_TV_SEC(r11)
152 std r7,TSPC64_TV_NSEC(r11) 159 std r7,TSPC64_TV_NSEC(r11)
153 160
@@ -181,7 +188,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
181 /* Check for supported clock IDs */ 188 /* Check for supported clock IDs */
182 cmpwi cr0,r3,CLOCK_REALTIME 189 cmpwi cr0,r3,CLOCK_REALTIME
183 cmpwi cr1,r3,CLOCK_MONOTONIC 190 cmpwi cr1,r3,CLOCK_MONOTONIC
184 cror cr0,cr0,cr1 191 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
185 bne cr0,99f 192 bne cr0,99f
186 193
187 li r3,0 194 li r3,0
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 5947b21a8588..4c7682a65227 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -102,7 +102,7 @@ static unsigned long from_rtc_time(struct rtc_time *tm)
102static unsigned long cuda_get_time(void) 102static unsigned long cuda_get_time(void)
103{ 103{
104 struct adb_request req; 104 struct adb_request req;
105 unsigned long now; 105 unsigned int now;
106 106
107 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) 107 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
108 return 0; 108 return 0;
@@ -113,7 +113,7 @@ static unsigned long cuda_get_time(void)
113 req.reply_len); 113 req.reply_len);
114 now = (req.reply[3] << 24) + (req.reply[4] << 16) 114 now = (req.reply[3] << 24) + (req.reply[4] << 16)
115 + (req.reply[5] << 8) + req.reply[6]; 115 + (req.reply[5] << 8) + req.reply[6];
116 return now - RTC_OFFSET; 116 return ((unsigned long)now) - RTC_OFFSET;
117} 117}
118 118
119#define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) 119#define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm))
@@ -146,7 +146,7 @@ static int cuda_set_rtc_time(struct rtc_time *tm)
146static unsigned long pmu_get_time(void) 146static unsigned long pmu_get_time(void)
147{ 147{
148 struct adb_request req; 148 struct adb_request req;
149 unsigned long now; 149 unsigned int now;
150 150
151 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) 151 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
152 return 0; 152 return 0;
@@ -156,7 +156,7 @@ static unsigned long pmu_get_time(void)
156 req.reply_len); 156 req.reply_len);
157 now = (req.reply[0] << 24) + (req.reply[1] << 16) 157 now = (req.reply[0] << 24) + (req.reply[1] << 16)
158 + (req.reply[2] << 8) + req.reply[3]; 158 + (req.reply[2] << 8) + req.reply[3];
159 return now - RTC_OFFSET; 159 return ((unsigned long)now) - RTC_OFFSET;
160} 160}
161 161
162#define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm)) 162#define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm))