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

x86/vdso: Use generic VDSO clock mode storage

Switch to the generic VDSO clock mode storage.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com> (VDSO parts)
Acked-by: Juergen Gross <jgross@suse.com> (Xen parts)
Acked-by: Paolo Bonzini <pbonzini@redhat.com> (KVM parts)
Link: https://lkml.kernel.org/r/20200207124403.152039903@linutronix.de


+46 -63
+1 -1
arch/x86/Kconfig
··· 57 57 select ACPI_LEGACY_TABLES_LOOKUP if ACPI 58 58 select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI 59 59 select ARCH_32BIT_OFF_T if X86_32 60 - select ARCH_CLOCKSOURCE_DATA 61 60 select ARCH_CLOCKSOURCE_INIT 62 61 select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI 63 62 select ARCH_HAS_DEBUG_VIRTUAL ··· 125 126 select GENERIC_STRNLEN_USER 126 127 select GENERIC_TIME_VSYSCALL 127 128 select GENERIC_GETTIMEOFDAY 129 + select GENERIC_VDSO_CLOCK_MODE 128 130 select GENERIC_VDSO_TIME_NS 129 131 select GUP_GET_PTE_LOW_HIGH if X86_PAE 130 132 select HARDLOCKUP_CHECK_TIMESTAMP if X86_64
+3 -3
arch/x86/entry/vdso/vma.c
··· 221 221 } else if (sym_offset == image->sym_pvclock_page) { 222 222 struct pvclock_vsyscall_time_info *pvti = 223 223 pvclock_get_pvti_cpu0_va(); 224 - if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) { 224 + if (pvti && vclock_was_used(VDSO_CLOCKMODE_PVCLOCK)) { 225 225 return vmf_insert_pfn_prot(vma, vmf->address, 226 226 __pa(pvti) >> PAGE_SHIFT, 227 227 pgprot_decrypted(vma->vm_page_prot)); ··· 229 229 } else if (sym_offset == image->sym_hvclock_page) { 230 230 struct ms_hyperv_tsc_page *tsc_pg = hv_get_tsc_page(); 231 231 232 - if (tsc_pg && vclock_was_used(VCLOCK_HVCLOCK)) 232 + if (tsc_pg && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK)) 233 233 return vmf_insert_pfn(vma, vmf->address, 234 234 virt_to_phys(tsc_pg) >> PAGE_SHIFT); 235 235 } else if (sym_offset == image->sym_timens_page) { ··· 447 447 448 448 static int __init init_vdso(void) 449 449 { 450 - BUILD_BUG_ON(VCLOCK_MAX >= 32); 450 + BUILD_BUG_ON(VDSO_CLOCKMODE_MAX >= 32); 451 451 452 452 init_vdso_image(&vdso_image_64); 453 453
+4 -9
arch/x86/include/asm/clocksource.h
··· 4 4 #ifndef _ASM_X86_CLOCKSOURCE_H 5 5 #define _ASM_X86_CLOCKSOURCE_H 6 6 7 - #define VCLOCK_NONE 0 /* No vDSO clock available. */ 8 - #define VCLOCK_TSC 1 /* vDSO should use vread_tsc. */ 9 - #define VCLOCK_PVCLOCK 2 /* vDSO should use vread_pvclock. */ 10 - #define VCLOCK_HVCLOCK 3 /* vDSO should use vread_hvclock. */ 11 - #define VCLOCK_MAX 3 12 - 13 - struct arch_clocksource_data { 14 - int vclock_mode; 15 - }; 7 + #define VDSO_ARCH_CLOCKMODES \ 8 + VDSO_CLOCKMODE_TSC, \ 9 + VDSO_CLOCKMODE_PVCLOCK, \ 10 + VDSO_CLOCKMODE_HVCLOCK 16 11 17 12 extern unsigned int vclocks_used; 18 13
+2 -2
arch/x86/include/asm/mshyperv.h
··· 46 46 #define hv_set_reference_tsc(val) \ 47 47 wrmsrl(HV_X64_MSR_REFERENCE_TSC, val) 48 48 #define hv_set_clocksource_vdso(val) \ 49 - ((val).archdata.vclock_mode = VCLOCK_HVCLOCK) 49 + ((val).vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK) 50 50 #define hv_enable_vdso_clocksource() \ 51 - vclocks_set_used(VCLOCK_HVCLOCK); 51 + vclocks_set_used(VDSO_CLOCKMODE_HVCLOCK); 52 52 #define hv_get_raw_timer() rdtsc_ordered() 53 53 54 54 void hyperv_callback_vector(void);
+3 -3
arch/x86/include/asm/vdso/gettimeofday.h
··· 243 243 244 244 static inline u64 __arch_get_hw_counter(s32 clock_mode) 245 245 { 246 - if (likely(clock_mode == VCLOCK_TSC)) 246 + if (likely(clock_mode == VDSO_CLOCKMODE_TSC)) 247 247 return (u64)rdtsc_ordered(); 248 248 /* 249 249 * For any memory-mapped vclock type, we need to make sure that gcc ··· 252 252 * question isn't enabled, which will segfault. Hence the barriers. 253 253 */ 254 254 #ifdef CONFIG_PARAVIRT_CLOCK 255 - if (clock_mode == VCLOCK_PVCLOCK) { 255 + if (clock_mode == VDSO_CLOCKMODE_PVCLOCK) { 256 256 barrier(); 257 257 return vread_pvclock(); 258 258 } 259 259 #endif 260 260 #ifdef CONFIG_HYPERV_TIMER 261 - if (clock_mode == VCLOCK_HVCLOCK) { 261 + if (clock_mode == VDSO_CLOCKMODE_HVCLOCK) { 262 262 barrier(); 263 263 return vread_hvclock(); 264 264 }
-7
arch/x86/include/asm/vdso/vsyscall.h
··· 21 21 } 22 22 #define __arch_get_k_vdso_data __x86_get_k_vdso_data 23 23 24 - static __always_inline 25 - int __x86_get_clock_mode(struct timekeeper *tk) 26 - { 27 - return tk->tkr_mono.clock->archdata.vclock_mode; 28 - } 29 - #define __arch_get_clock_mode __x86_get_clock_mode 30 - 31 24 /* The asm-generic header needs to be included after the definitions above */ 32 25 #include <asm-generic/vdso/vsyscall.h> 33 26
+2 -2
arch/x86/kernel/kvmclock.c
··· 161 161 162 162 static int kvm_cs_enable(struct clocksource *cs) 163 163 { 164 - vclocks_set_used(VCLOCK_PVCLOCK); 164 + vclocks_set_used(VDSO_CLOCKMODE_PVCLOCK); 165 165 return 0; 166 166 } 167 167 ··· 279 279 if (!(flags & PVCLOCK_TSC_STABLE_BIT)) 280 280 return 0; 281 281 282 - kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK; 282 + kvm_clock.vdso_clock_mode = VDSO_CLOCKMODE_PVCLOCK; 283 283 #endif 284 284 285 285 kvmclock_init_mem();
+1 -1
arch/x86/kernel/pvclock.c
··· 145 145 146 146 void pvclock_set_pvti_cpu0_va(struct pvclock_vsyscall_time_info *pvti) 147 147 { 148 - WARN_ON(vclock_was_used(VCLOCK_PVCLOCK)); 148 + WARN_ON(vclock_was_used(VDSO_CLOCKMODE_PVCLOCK)); 149 149 pvti_cpu0_va = pvti; 150 150 } 151 151
+3 -9
arch/x86/kernel/time.c
··· 122 122 */ 123 123 void clocksource_arch_init(struct clocksource *cs) 124 124 { 125 - if (cs->archdata.vclock_mode == VCLOCK_NONE) 125 + if (cs->vdso_clock_mode == VDSO_CLOCKMODE_NONE) 126 126 return; 127 127 128 - if (cs->archdata.vclock_mode > VCLOCK_MAX) { 129 - pr_warn("clocksource %s registered with invalid vclock_mode %d. Disabling vclock.\n", 130 - cs->name, cs->archdata.vclock_mode); 131 - cs->archdata.vclock_mode = VCLOCK_NONE; 132 - } 133 - 134 128 if (cs->mask != CLOCKSOURCE_MASK(64)) { 135 - pr_warn("clocksource %s registered with invalid mask %016llx. Disabling vclock.\n", 129 + pr_warn("clocksource %s registered with invalid mask %016llx for VDSO. Disabling VDSO support.\n", 136 130 cs->name, cs->mask); 137 - cs->archdata.vclock_mode = VCLOCK_NONE; 131 + cs->vdso_clock_mode = VDSO_CLOCKMODE_NONE; 138 132 } 139 133 }
+3 -3
arch/x86/kernel/tsc.c
··· 1110 1110 1111 1111 static int tsc_cs_enable(struct clocksource *cs) 1112 1112 { 1113 - vclocks_set_used(VCLOCK_TSC); 1113 + vclocks_set_used(VDSO_CLOCKMODE_TSC); 1114 1114 return 0; 1115 1115 } 1116 1116 ··· 1124 1124 .mask = CLOCKSOURCE_MASK(64), 1125 1125 .flags = CLOCK_SOURCE_IS_CONTINUOUS | 1126 1126 CLOCK_SOURCE_MUST_VERIFY, 1127 - .archdata = { .vclock_mode = VCLOCK_TSC }, 1127 + .vdso_clock_mode = VDSO_CLOCKMODE_TSC, 1128 1128 .enable = tsc_cs_enable, 1129 1129 .resume = tsc_resume, 1130 1130 .mark_unstable = tsc_cs_mark_unstable, ··· 1145 1145 .flags = CLOCK_SOURCE_IS_CONTINUOUS | 1146 1146 CLOCK_SOURCE_VALID_FOR_HRES | 1147 1147 CLOCK_SOURCE_MUST_VERIFY, 1148 - .archdata = { .vclock_mode = VCLOCK_TSC }, 1148 + .vdso_clock_mode = VDSO_CLOCKMODE_TSC, 1149 1149 .enable = tsc_cs_enable, 1150 1150 .resume = tsc_resume, 1151 1151 .mark_unstable = tsc_cs_mark_unstable,
+2 -2
arch/x86/kvm/trace.h
··· 815 815 #ifdef CONFIG_X86_64 816 816 817 817 #define host_clocks \ 818 - {VCLOCK_NONE, "none"}, \ 819 - {VCLOCK_TSC, "tsc"} \ 818 + {VDSO_CLOCKMODE_NONE, "none"}, \ 819 + {VDSO_CLOCKMODE_TSC, "tsc"} \ 820 820 821 821 TRACE_EVENT(kvm_update_master_clock, 822 822 TP_PROTO(bool use_master_clock, unsigned int host_clock, bool offset_matched),
+11 -11
arch/x86/kvm/x86.c
··· 1631 1631 write_seqcount_begin(&vdata->seq); 1632 1632 1633 1633 /* copy pvclock gtod data */ 1634 - vdata->clock.vclock_mode = tk->tkr_mono.clock->archdata.vclock_mode; 1634 + vdata->clock.vclock_mode = tk->tkr_mono.clock->vdso_clock_mode; 1635 1635 vdata->clock.cycle_last = tk->tkr_mono.cycle_last; 1636 1636 vdata->clock.mask = tk->tkr_mono.mask; 1637 1637 vdata->clock.mult = tk->tkr_mono.mult; ··· 1639 1639 vdata->clock.base_cycles = tk->tkr_mono.xtime_nsec; 1640 1640 vdata->clock.offset = tk->tkr_mono.base; 1641 1641 1642 - vdata->raw_clock.vclock_mode = tk->tkr_raw.clock->archdata.vclock_mode; 1642 + vdata->raw_clock.vclock_mode = tk->tkr_raw.clock->vdso_clock_mode; 1643 1643 vdata->raw_clock.cycle_last = tk->tkr_raw.cycle_last; 1644 1644 vdata->raw_clock.mask = tk->tkr_raw.mask; 1645 1645 vdata->raw_clock.mult = tk->tkr_raw.mult; ··· 1840 1840 1841 1841 static inline int gtod_is_based_on_tsc(int mode) 1842 1842 { 1843 - return mode == VCLOCK_TSC || mode == VCLOCK_HVCLOCK; 1843 + return mode == VDSO_CLOCKMODE_TSC || mode == VDSO_CLOCKMODE_HVCLOCK; 1844 1844 } 1845 1845 1846 1846 static void kvm_track_tsc_matching(struct kvm_vcpu *vcpu) ··· 1933 1933 * TSC is marked unstable when we're running on Hyper-V, 1934 1934 * 'TSC page' clocksource is good. 1935 1935 */ 1936 - if (pvclock_gtod_data.clock.vclock_mode == VCLOCK_HVCLOCK) 1936 + if (pvclock_gtod_data.clock.vclock_mode == VDSO_CLOCKMODE_HVCLOCK) 1937 1937 return false; 1938 1938 #endif 1939 1939 return check_tsc_unstable(); ··· 2088 2088 u64 tsc_pg_val; 2089 2089 2090 2090 switch (clock->vclock_mode) { 2091 - case VCLOCK_HVCLOCK: 2091 + case VDSO_CLOCKMODE_HVCLOCK: 2092 2092 tsc_pg_val = hv_read_tsc_page_tsc(hv_get_tsc_page(), 2093 2093 tsc_timestamp); 2094 2094 if (tsc_pg_val != U64_MAX) { 2095 2095 /* TSC page valid */ 2096 - *mode = VCLOCK_HVCLOCK; 2096 + *mode = VDSO_CLOCKMODE_HVCLOCK; 2097 2097 v = (tsc_pg_val - clock->cycle_last) & 2098 2098 clock->mask; 2099 2099 } else { 2100 2100 /* TSC page invalid */ 2101 - *mode = VCLOCK_NONE; 2101 + *mode = VDSO_CLOCKMODE_NONE; 2102 2102 } 2103 2103 break; 2104 - case VCLOCK_TSC: 2105 - *mode = VCLOCK_TSC; 2104 + case VDSO_CLOCKMODE_TSC: 2105 + *mode = VDSO_CLOCKMODE_TSC; 2106 2106 *tsc_timestamp = read_tsc(); 2107 2107 v = (*tsc_timestamp - clock->cycle_last) & 2108 2108 clock->mask; 2109 2109 break; 2110 2110 default: 2111 - *mode = VCLOCK_NONE; 2111 + *mode = VDSO_CLOCKMODE_NONE; 2112 2112 } 2113 2113 2114 - if (*mode == VCLOCK_NONE) 2114 + if (*mode == VDSO_CLOCKMODE_NONE) 2115 2115 *tsc_timestamp = v = 0; 2116 2116 2117 2117 return v * clock->mult;
+11 -10
arch/x86/xen/time.c
··· 147 147 148 148 static int xen_cs_enable(struct clocksource *cs) 149 149 { 150 - vclocks_set_used(VCLOCK_PVCLOCK); 150 + vclocks_set_used(VDSO_CLOCKMODE_PVCLOCK); 151 151 return 0; 152 152 } 153 153 ··· 419 419 ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t); 420 420 421 421 /* 422 - * We don't disable VCLOCK_PVCLOCK entirely if it fails to register the 423 - * secondary time info with Xen or if we migrated to a host without the 424 - * necessary flags. On both of these cases what happens is either 425 - * process seeing a zeroed out pvti or seeing no PVCLOCK_TSC_STABLE_BIT 426 - * bit set. Userspace checks the latter and if 0, it discards the data 427 - * in pvti and fallbacks to a system call for a reliable timestamp. 422 + * We don't disable VDSO_CLOCKMODE_PVCLOCK entirely if it fails to 423 + * register the secondary time info with Xen or if we migrated to a 424 + * host without the necessary flags. On both of these cases what 425 + * happens is either process seeing a zeroed out pvti or seeing no 426 + * PVCLOCK_TSC_STABLE_BIT bit set. Userspace checks the latter and 427 + * if 0, it discards the data in pvti and fallbacks to a system 428 + * call for a reliable timestamp. 428 429 */ 429 430 if (ret != 0) 430 431 pr_notice("Cannot restore secondary vcpu_time_info (err %d)", ··· 451 450 452 451 ret = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_time_memory_area, 0, &t); 453 452 if (ret) { 454 - pr_notice("xen: VCLOCK_PVCLOCK not supported (err %d)\n", ret); 453 + pr_notice("xen: VDSO_CLOCKMODE_PVCLOCK not supported (err %d)\n", ret); 455 454 free_page((unsigned long)ti); 456 455 return; 457 456 } ··· 468 467 if (!ret) 469 468 free_page((unsigned long)ti); 470 469 471 - pr_notice("xen: VCLOCK_PVCLOCK not supported (tsc unstable)\n"); 470 + pr_notice("xen: VDSO_CLOCKMODE_PVCLOCK not supported (tsc unstable)\n"); 472 471 return; 473 472 } 474 473 475 474 xen_clock = ti; 476 475 pvclock_set_pvti_cpu0_va(xen_clock); 477 476 478 - xen_clocksource.archdata.vclock_mode = VCLOCK_PVCLOCK; 477 + xen_clocksource.vdso_clock_mode = VDSO_CLOCKMODE_PVCLOCK; 479 478 } 480 479 481 480 static void __init xen_time_init(void)