Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Benjamin Herrenschmidt and committed by
Paul Mackerras
0c37ec2a 50092b23

+39 -24
+4 -2
arch/powerpc/kernel/asm-offsets.c
··· 270 270 DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); 271 271 DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); 272 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 275 DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec)); 274 276 DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); 275 277 #else 276 278 DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec)); 277 279 DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec)); 278 - DEFINE(TSPEC32_TV_SEC, offsetof(struct timespec, tv_sec)); 279 - DEFINE(TSPEC32_TV_NSEC, offsetof(struct timespec, tv_nsec)); 280 + DEFINE(TSPC32_TV_SEC, offsetof(struct timespec, tv_sec)); 281 + DEFINE(TSPC32_TV_NSEC, offsetof(struct timespec, tv_nsec)); 280 282 #endif 281 283 /* timeval/timezone offsets for use by vdso */ 282 284 DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
+2 -1
arch/powerpc/kernel/vdso32/datapage.S
··· 77 77 mflr r12 78 78 .cfi_register lr,r12 79 79 bl __get_datapage@local 80 - lwz r3,CFG_TB_TICKS_PER_SEC(r3) 81 80 lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) 81 + lwz r3,CFG_TB_TICKS_PER_SEC(r3) 82 82 mtlr r12 83 + blr 83 84 .cfi_endproc 84 85 V_FUNCTION_END(__kernel_get_tbfreq)
+8 -4
arch/powerpc/kernel/vdso32/gettimeofday.S
··· 83 83 /* Check for supported clock IDs */ 84 84 cmpli cr0,r3,CLOCK_REALTIME 85 85 cmpli cr1,r3,CLOCK_MONOTONIC 86 - cror cr0,cr0,cr1 86 + cror cr0*4+eq,cr0*4+eq,cr1*4+eq 87 87 bne cr0,99f 88 88 89 89 mflr r12 /* r12 saves lr */ ··· 91 91 mr r10,r3 /* r10 saves id */ 92 92 mr r11,r4 /* r11 saves tp */ 93 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 95 beq cr1,50f /* if monotonic -> jump there */ 96 96 97 97 /* ··· 173 173 add r4,r4,r7 174 174 lis r5,NSEC_PER_SEC@h 175 175 ori r5,r5,NSEC_PER_SEC@l 176 - cmpli cr0,r4,r5 176 + cmpl cr0,r4,r5 177 + cmpli cr1,r4,0 177 178 blt 1f 178 179 subf r4,r5,r4 179 180 addi r3,r3,1 181 + 1: bge cr1,1f 182 + addi r3,r3,-1 183 + add r4,r4,r5 180 184 1: stw r3,TSPC32_TV_SEC(r11) 181 185 stw r4,TSPC32_TV_NSEC(r11) 182 186 ··· 214 210 /* Check for supported clock IDs */ 215 211 cmpwi cr0,r3,CLOCK_REALTIME 216 212 cmpwi cr1,r3,CLOCK_MONOTONIC 217 - cror cr0,cr0,cr1 213 + cror cr0*4+eq,cr0*4+eq,cr1*4+eq 218 214 bne cr0,99f 219 215 220 216 li r3,0
+1
arch/powerpc/kernel/vdso64/datapage.S
··· 80 80 bl V_LOCAL_FUNC(__get_datapage) 81 81 ld r3,CFG_TB_TICKS_PER_SEC(r3) 82 82 mtlr r12 83 + blr 83 84 .cfi_endproc 84 85 V_FUNCTION_END(__kernel_get_tbfreq)
+19 -12
arch/powerpc/kernel/vdso64/gettimeofday.S
··· 1 - /* 1 + 2 + /* 2 3 * Userland implementation of gettimeofday() for 64 bits processes in a 3 4 * ppc64 kernel for use in the vDSO 4 5 * ··· 69 68 /* Check for supported clock IDs */ 70 69 cmpwi cr0,r3,CLOCK_REALTIME 71 70 cmpwi cr1,r3,CLOCK_MONOTONIC 72 - cror cr0,cr0,cr1 71 + cror cr0*4+eq,cr0*4+eq,cr1*4+eq 73 72 bne cr0,99f 74 73 75 74 mflr r12 /* r12 saves lr */ ··· 85 84 86 85 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ 87 86 88 - lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ 89 - ori r7,r7,0xca00 87 + lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */ 88 + ori r7,r7,16960 90 89 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ 91 90 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ 92 91 std r5,TSPC64_TV_SEC(r11) /* store sec in tv */ 93 92 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ 94 - mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / 93 + mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / 95 94 * XSEC_PER_SEC 96 95 */ 97 96 rldicl r0,r0,44,20 97 + mulli r0,r0,1000 /* nsec = usec * 1000 */ 98 98 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */ 99 99 100 100 mtlr r12 ··· 108 106 109 107 50: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ 110 108 111 - lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ 112 - ori r7,r7,0xca00 109 + lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */ 110 + ori r7,r7,16960 113 111 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ 114 112 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ 115 113 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ 116 - mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / 114 + mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / 117 115 * XSEC_PER_SEC 118 116 */ 119 117 rldicl r6,r0,44,20 118 + mulli r6,r6,1000 /* nsec = usec * 1000 */ 120 119 121 120 /* now we must fixup using wall to monotonic. We need to snapshot 122 121 * that value and do the counter trick again. Fortunately, we still ··· 126 123 * can be used 127 124 */ 128 125 129 - lwz r4,WTOM_CLOCK_SEC(r9) 130 - lwz r7,WTOM_CLOCK_NSEC(r9) 126 + lwa r4,WTOM_CLOCK_SEC(r3) 127 + lwa r7,WTOM_CLOCK_NSEC(r3) 131 128 132 129 /* We now have our result in r4,r7. We create a fake dependency 133 130 * on that result and re-check the counter ··· 147 144 add r7,r7,r6 148 145 lis r9,NSEC_PER_SEC@h 149 146 ori r9,r9,NSEC_PER_SEC@l 150 - cmpli cr0,r7,r9 147 + cmpl cr0,r7,r9 148 + cmpli cr1,r7,0 151 149 blt 1f 152 150 subf r7,r9,r7 153 151 addi r4,r4,1 152 + 1: bge cr1,1f 153 + addi r4,r4,-1 154 + add r7,r7,r9 154 155 1: std r4,TSPC64_TV_SEC(r11) 155 156 std r7,TSPC64_TV_NSEC(r11) 156 157 ··· 188 181 /* Check for supported clock IDs */ 189 182 cmpwi cr0,r3,CLOCK_REALTIME 190 183 cmpwi cr1,r3,CLOCK_MONOTONIC 191 - cror cr0,cr0,cr1 184 + cror cr0*4+eq,cr0*4+eq,cr1*4+eq 192 185 bne cr0,99f 193 186 194 187 li r3,0
+4 -4
arch/powerpc/platforms/powermac/time.c
··· 102 102 static unsigned long cuda_get_time(void) 103 103 { 104 104 struct adb_request req; 105 - unsigned long now; 105 + unsigned int now; 106 106 107 107 if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) 108 108 return 0; ··· 113 113 req.reply_len); 114 114 now = (req.reply[3] << 24) + (req.reply[4] << 16) 115 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 119 #define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) ··· 146 146 static unsigned long pmu_get_time(void) 147 147 { 148 148 struct adb_request req; 149 - unsigned long now; 149 + unsigned int now; 150 150 151 151 if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) 152 152 return 0; ··· 156 156 req.reply_len); 157 157 now = (req.reply[0] << 24) + (req.reply[1] << 16) 158 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 162 #define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm))
+1 -1
include/asm-powerpc/vdso_datapage.h
··· 73 73 /* those additional ones don't have to be located anywhere 74 74 * special as they were not part of the original systemcfg 75 75 */ 76 - __s64 wtom_clock_sec; /* Wall to monotonic clock */ 76 + __s32 wtom_clock_sec; /* Wall to monotonic clock */ 77 77 __s32 wtom_clock_nsec; 78 78 __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */ 79 79 __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */