Minor coding comments > diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h > index d324dce..4ff25436 100644 > --- a/arch/x86/include/asm/mshyperv.h > +++ b/arch/x86/include/asm/mshyperv.h > @@ -178,6 +178,56 @@ void hyperv_cleanup(void); > #endif > #ifdef CONFIG_HYPERV_TSCPAGE > struct ms_hyperv_tsc_page *hv_get_tsc_page(void); > +static inline u64 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) > +{ > + u64 scale, offset, current_tick, cur_tsc; > + u32 sequence; > + > + /* > + * The protocol for reading Hyper-V TSC page is specified in Hypervisor > + * Top-Level Functional Specification ver. 3.0 and above. To get the > + * reference time we must do the following: > + * - READ ReferenceTscSequence > + * A special '0' value indicates the time source is unreliable and we > + * need to use something else. The currently published specification > + * versions (up to 4.0b) contain a mistake and wrongly claim '-1' > + * instead of '0' as the special value, see commit c35b82ef0294. > + * - ReferenceTime = > + * ((RDTSC() * ReferenceTscScale) >> 64) + ReferenceTscOffset > + * - READ ReferenceTscSequence again. In case its value has changed > + * since our first reading we need to discard ReferenceTime and repeat > + * the whole sequence as the hypervisor was updating the page in > + * between. > + */ > + while (1) { > + sequence = READ_ONCE(tsc_pg->tsc_sequence); > + if (!sequence) > + break; It would be clearer to just return U64_MAX here (and not fall out) since this is only case here. Also since this failure only occurs if host clock is not available, probably should be unlikely. > + /* > + * Make sure we read sequence before we read other values from > + * TSC page. > + */ > + smp_rmb(); > + > + scale = READ_ONCE(tsc_pg->tsc_scale); > + offset = READ_ONCE(tsc_pg->tsc_offset); > + cur_tsc = rdtsc_ordered(); Since you already have smp_ barriers and rdtsc_ordered is a barrier, the compiler barriers (READ_ONCE()) shouldn't be necessary. > + > + current_tick = mul_u64_u64_shr(cur_tsc, scale, 64) + offset; > + > + /* > + * Make sure we read sequence after we read all other values > + * from TSC page. > + */ > + smp_rmb(); > + > + if (READ_ONCE(tsc_pg->tsc_sequence) == sequence) > + return current_tick; > + } Why not make do { } while out of this. do { ... } while (unlikely(READ_ONCE(tsc_pg->tsc_sequence) != sequence); return current_tick; Also don't need to calculate tick value until have good data. As in: static inline u32 hv_clock_sequence(const struct ms_hyperv_tsc_page *tsc_pg) { u32 sequence = return sequence; } static inline u64 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) { u64 scale, offset, cur_tsc; u32 start; /* * The protocol for reading Hyper-V TSC page is specified in Hypervisor * Top-Level Functional Specification ver. 3.0 and above. To get the * reference time we must do the following: * - READ ReferenceTscSequence * A special '0' value indicates the time source is unreliable and we * need to use something else. The currently published specification * versions (up to 4.0b) contain a mistake and wrongly claim '-1' * instead of '0' as the special value, see commit c35b82ef0294. * - ReferenceTime = * ((RDTSC() * ReferenceTscScale) >> 64) + ReferenceTscOffset * - READ ReferenceTscSequence again. In case its value has changed * since our first reading we need to discard ReferenceTime and repeat * the whole sequence as the hypervisor was updating the page in * between. */ do { start = READ_ONCE(tsc_pg->tsc_sequence); smp_rmb(); if (unlikely(!start)) return U64_MAX; scale = tsc_pg->tsc_scale; offset = tsc_pg->tsc_offset; /* * Make sure we read sequence after we read all other values * from TSC page. */ smp_rmb(); } while (unlikely(READ_ONCE(tsc_pg->tsc_sequence != start))); cur_tsc = rdtsc_ordered(); return mul_u64_u64_shr(cur_tsc, scale, 64) + offset; } _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/virtualization