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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Ingo writes:
"x86 fixes:

Misc fixes:

- fix various vDSO bugs: asm constraints and retpolines
- add vDSO test units to make sure they never re-appear
- fix UV platform TSC initialization bug
- fix build warning on Clang"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/vdso: Fix vDSO syscall fallback asm constraint regression
x86/cpu/amd: Remove unnecessary parentheses
x86/vdso: Only enable vDSO retpolines when enabled and supported
x86/tsc: Fix UV TSC initialization
x86/platform/uv: Provide is_early_uv_system()
selftests/x86: Add clock_gettime() tests to test_vdso
x86/vdso: Fix asm constraints on vDSO syscall fallbacks

+211 -15
+14 -2
arch/x86/entry/vdso/Makefile
··· 68 68 CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \ 69 69 $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \ 70 70 -fno-omit-frame-pointer -foptimize-sibling-calls \ 71 - -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO $(RETPOLINE_VDSO_CFLAGS) 71 + -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO 72 + 73 + ifdef CONFIG_RETPOLINE 74 + ifneq ($(RETPOLINE_VDSO_CFLAGS),) 75 + CFL += $(RETPOLINE_VDSO_CFLAGS) 76 + endif 77 + endif 72 78 73 79 $(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL) 74 80 ··· 144 138 KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls) 145 139 KBUILD_CFLAGS_32 += -fno-omit-frame-pointer 146 140 KBUILD_CFLAGS_32 += -DDISABLE_BRANCH_PROFILING 147 - KBUILD_CFLAGS_32 += $(RETPOLINE_VDSO_CFLAGS) 141 + 142 + ifdef CONFIG_RETPOLINE 143 + ifneq ($(RETPOLINE_VDSO_CFLAGS),) 144 + KBUILD_CFLAGS_32 += $(RETPOLINE_VDSO_CFLAGS) 145 + endif 146 + endif 147 + 148 148 $(obj)/vdso32.so.dbg: KBUILD_CFLAGS = $(KBUILD_CFLAGS_32) 149 149 150 150 $(obj)/vdso32.so.dbg: FORCE \
+14 -12
arch/x86/entry/vdso/vclock_gettime.c
··· 43 43 notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) 44 44 { 45 45 long ret; 46 - asm("syscall" : "=a" (ret) : 47 - "0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory"); 46 + asm ("syscall" : "=a" (ret), "=m" (*ts) : 47 + "0" (__NR_clock_gettime), "D" (clock), "S" (ts) : 48 + "memory", "rcx", "r11"); 48 49 return ret; 49 50 } 50 51 ··· 53 52 { 54 53 long ret; 55 54 56 - asm("syscall" : "=a" (ret) : 57 - "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory"); 55 + asm ("syscall" : "=a" (ret), "=m" (*tv), "=m" (*tz) : 56 + "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : 57 + "memory", "rcx", "r11"); 58 58 return ret; 59 59 } 60 60 ··· 66 64 { 67 65 long ret; 68 66 69 - asm( 67 + asm ( 70 68 "mov %%ebx, %%edx \n" 71 - "mov %2, %%ebx \n" 69 + "mov %[clock], %%ebx \n" 72 70 "call __kernel_vsyscall \n" 73 71 "mov %%edx, %%ebx \n" 74 - : "=a" (ret) 75 - : "0" (__NR_clock_gettime), "g" (clock), "c" (ts) 72 + : "=a" (ret), "=m" (*ts) 73 + : "0" (__NR_clock_gettime), [clock] "g" (clock), "c" (ts) 76 74 : "memory", "edx"); 77 75 return ret; 78 76 } ··· 81 79 { 82 80 long ret; 83 81 84 - asm( 82 + asm ( 85 83 "mov %%ebx, %%edx \n" 86 - "mov %2, %%ebx \n" 84 + "mov %[tv], %%ebx \n" 87 85 "call __kernel_vsyscall \n" 88 86 "mov %%edx, %%ebx \n" 89 - : "=a" (ret) 90 - : "0" (__NR_gettimeofday), "g" (tv), "c" (tz) 87 + : "=a" (ret), "=m" (*tv), "=m" (*tz) 88 + : "0" (__NR_gettimeofday), [tv] "g" (tv), "c" (tz) 91 89 : "memory", "edx"); 92 90 return ret; 93 91 }
+6
arch/x86/include/asm/uv/uv.h
··· 10 10 struct mm_struct; 11 11 12 12 #ifdef CONFIG_X86_UV 13 + #include <linux/efi.h> 13 14 14 15 extern enum uv_system_type get_uv_system_type(void); 16 + static inline bool is_early_uv_system(void) 17 + { 18 + return !((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || !efi.uv_systab); 19 + } 15 20 extern int is_uv_system(void); 16 21 extern int is_uv_hubless(void); 17 22 extern void uv_cpu_init(void); ··· 28 23 #else /* X86_UV */ 29 24 30 25 static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } 26 + static inline bool is_early_uv_system(void) { return 0; } 31 27 static inline int is_uv_system(void) { return 0; } 32 28 static inline int is_uv_hubless(void) { return 0; } 33 29 static inline void uv_cpu_init(void) { }
+1 -1
arch/x86/kernel/cpu/amd.c
··· 922 922 static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) 923 923 { 924 924 /* AMD errata T13 (order #21922) */ 925 - if ((c->x86 == 6)) { 925 + if (c->x86 == 6) { 926 926 /* Duron Rev A0 */ 927 927 if (c->x86_model == 3 && c->x86_stepping == 0) 928 928 size = 64;
+4
arch/x86/kernel/tsc.c
··· 26 26 #include <asm/apic.h> 27 27 #include <asm/intel-family.h> 28 28 #include <asm/i8259.h> 29 + #include <asm/uv/uv.h> 29 30 30 31 unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ 31 32 EXPORT_SYMBOL(cpu_khz); ··· 1433 1432 void __init tsc_early_init(void) 1434 1433 { 1435 1434 if (!boot_cpu_has(X86_FEATURE_TSC)) 1435 + return; 1436 + /* Don't change UV TSC multi-chassis synchronization */ 1437 + if (is_early_uv_system()) 1436 1438 return; 1437 1439 if (!determine_cpu_tsc_frequencies(true)) 1438 1440 return;
+172
tools/testing/selftests/x86/test_vdso.c
··· 17 17 #include <errno.h> 18 18 #include <sched.h> 19 19 #include <stdbool.h> 20 + #include <limits.h> 20 21 21 22 #ifndef SYS_getcpu 22 23 # ifdef __x86_64__ ··· 31 30 #define MAPS_LINE_LEN 128 32 31 33 32 int nerrs = 0; 33 + 34 + typedef int (*vgettime_t)(clockid_t, struct timespec *); 35 + 36 + vgettime_t vdso_clock_gettime; 37 + 38 + typedef long (*vgtod_t)(struct timeval *tv, struct timezone *tz); 39 + 40 + vgtod_t vdso_gettimeofday; 34 41 35 42 typedef long (*getcpu_t)(unsigned *, unsigned *, void *); 36 43 ··· 104 95 printf("Warning: failed to find getcpu in vDSO\n"); 105 96 106 97 vgetcpu = (getcpu_t) vsyscall_getcpu(); 98 + 99 + vdso_clock_gettime = (vgettime_t)dlsym(vdso, "__vdso_clock_gettime"); 100 + if (!vdso_clock_gettime) 101 + printf("Warning: failed to find clock_gettime in vDSO\n"); 102 + 103 + vdso_gettimeofday = (vgtod_t)dlsym(vdso, "__vdso_gettimeofday"); 104 + if (!vdso_gettimeofday) 105 + printf("Warning: failed to find gettimeofday in vDSO\n"); 106 + 107 107 } 108 108 109 109 static long sys_getcpu(unsigned * cpu, unsigned * node, 110 110 void* cache) 111 111 { 112 112 return syscall(__NR_getcpu, cpu, node, cache); 113 + } 114 + 115 + static inline int sys_clock_gettime(clockid_t id, struct timespec *ts) 116 + { 117 + return syscall(__NR_clock_gettime, id, ts); 118 + } 119 + 120 + static inline int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 121 + { 122 + return syscall(__NR_gettimeofday, tv, tz); 113 123 } 114 124 115 125 static void test_getcpu(void) ··· 183 155 } 184 156 } 185 157 158 + static bool ts_leq(const struct timespec *a, const struct timespec *b) 159 + { 160 + if (a->tv_sec != b->tv_sec) 161 + return a->tv_sec < b->tv_sec; 162 + else 163 + return a->tv_nsec <= b->tv_nsec; 164 + } 165 + 166 + static bool tv_leq(const struct timeval *a, const struct timeval *b) 167 + { 168 + if (a->tv_sec != b->tv_sec) 169 + return a->tv_sec < b->tv_sec; 170 + else 171 + return a->tv_usec <= b->tv_usec; 172 + } 173 + 174 + static char const * const clocknames[] = { 175 + [0] = "CLOCK_REALTIME", 176 + [1] = "CLOCK_MONOTONIC", 177 + [2] = "CLOCK_PROCESS_CPUTIME_ID", 178 + [3] = "CLOCK_THREAD_CPUTIME_ID", 179 + [4] = "CLOCK_MONOTONIC_RAW", 180 + [5] = "CLOCK_REALTIME_COARSE", 181 + [6] = "CLOCK_MONOTONIC_COARSE", 182 + [7] = "CLOCK_BOOTTIME", 183 + [8] = "CLOCK_REALTIME_ALARM", 184 + [9] = "CLOCK_BOOTTIME_ALARM", 185 + [10] = "CLOCK_SGI_CYCLE", 186 + [11] = "CLOCK_TAI", 187 + }; 188 + 189 + static void test_one_clock_gettime(int clock, const char *name) 190 + { 191 + struct timespec start, vdso, end; 192 + int vdso_ret, end_ret; 193 + 194 + printf("[RUN]\tTesting clock_gettime for clock %s (%d)...\n", name, clock); 195 + 196 + if (sys_clock_gettime(clock, &start) < 0) { 197 + if (errno == EINVAL) { 198 + vdso_ret = vdso_clock_gettime(clock, &vdso); 199 + if (vdso_ret == -EINVAL) { 200 + printf("[OK]\tNo such clock.\n"); 201 + } else { 202 + printf("[FAIL]\tNo such clock, but __vdso_clock_gettime returned %d\n", vdso_ret); 203 + nerrs++; 204 + } 205 + } else { 206 + printf("[WARN]\t clock_gettime(%d) syscall returned error %d\n", clock, errno); 207 + } 208 + return; 209 + } 210 + 211 + vdso_ret = vdso_clock_gettime(clock, &vdso); 212 + end_ret = sys_clock_gettime(clock, &end); 213 + 214 + if (vdso_ret != 0 || end_ret != 0) { 215 + printf("[FAIL]\tvDSO returned %d, syscall errno=%d\n", 216 + vdso_ret, errno); 217 + nerrs++; 218 + return; 219 + } 220 + 221 + printf("\t%llu.%09ld %llu.%09ld %llu.%09ld\n", 222 + (unsigned long long)start.tv_sec, start.tv_nsec, 223 + (unsigned long long)vdso.tv_sec, vdso.tv_nsec, 224 + (unsigned long long)end.tv_sec, end.tv_nsec); 225 + 226 + if (!ts_leq(&start, &vdso) || !ts_leq(&vdso, &end)) { 227 + printf("[FAIL]\tTimes are out of sequence\n"); 228 + nerrs++; 229 + } 230 + } 231 + 232 + static void test_clock_gettime(void) 233 + { 234 + for (int clock = 0; clock < sizeof(clocknames) / sizeof(clocknames[0]); 235 + clock++) { 236 + test_one_clock_gettime(clock, clocknames[clock]); 237 + } 238 + 239 + /* Also test some invalid clock ids */ 240 + test_one_clock_gettime(-1, "invalid"); 241 + test_one_clock_gettime(INT_MIN, "invalid"); 242 + test_one_clock_gettime(INT_MAX, "invalid"); 243 + } 244 + 245 + static void test_gettimeofday(void) 246 + { 247 + struct timeval start, vdso, end; 248 + struct timezone sys_tz, vdso_tz; 249 + int vdso_ret, end_ret; 250 + 251 + if (!vdso_gettimeofday) 252 + return; 253 + 254 + printf("[RUN]\tTesting gettimeofday...\n"); 255 + 256 + if (sys_gettimeofday(&start, &sys_tz) < 0) { 257 + printf("[FAIL]\tsys_gettimeofday failed (%d)\n", errno); 258 + nerrs++; 259 + return; 260 + } 261 + 262 + vdso_ret = vdso_gettimeofday(&vdso, &vdso_tz); 263 + end_ret = sys_gettimeofday(&end, NULL); 264 + 265 + if (vdso_ret != 0 || end_ret != 0) { 266 + printf("[FAIL]\tvDSO returned %d, syscall errno=%d\n", 267 + vdso_ret, errno); 268 + nerrs++; 269 + return; 270 + } 271 + 272 + printf("\t%llu.%06ld %llu.%06ld %llu.%06ld\n", 273 + (unsigned long long)start.tv_sec, start.tv_usec, 274 + (unsigned long long)vdso.tv_sec, vdso.tv_usec, 275 + (unsigned long long)end.tv_sec, end.tv_usec); 276 + 277 + if (!tv_leq(&start, &vdso) || !tv_leq(&vdso, &end)) { 278 + printf("[FAIL]\tTimes are out of sequence\n"); 279 + nerrs++; 280 + } 281 + 282 + if (sys_tz.tz_minuteswest == vdso_tz.tz_minuteswest && 283 + sys_tz.tz_dsttime == vdso_tz.tz_dsttime) { 284 + printf("[OK]\ttimezones match: minuteswest=%d, dsttime=%d\n", 285 + sys_tz.tz_minuteswest, sys_tz.tz_dsttime); 286 + } else { 287 + printf("[FAIL]\ttimezones do not match\n"); 288 + nerrs++; 289 + } 290 + 291 + /* And make sure that passing NULL for tz doesn't crash. */ 292 + vdso_gettimeofday(&vdso, NULL); 293 + } 294 + 186 295 int main(int argc, char **argv) 187 296 { 188 297 fill_function_pointers(); 189 298 299 + test_clock_gettime(); 300 + test_gettimeofday(); 301 + 302 + /* 303 + * Test getcpu() last so that, if something goes wrong setting affinity, 304 + * we still run the other tests. 305 + */ 190 306 test_getcpu(); 191 307 192 308 return nerrs ? 1 : 0;