> Date: Wed, 15 Jul 2020 20:36:04 -0500 > From: Scott Cheloha <scottchel...@gmail.com> > > On Sat, Jul 11, 2020 at 01:16:43PM +0200, Mark Kettenis wrote: > > > From: Paul Irofti <p...@irofti.net> > > > Date: Sat, 11 Jul 2020 13:50:37 +0300 > > > > > > On 2020-07-11 13:46, Mark Kettenis wrote: > > > >> From: Paul Irofti <p...@irofti.net> > > > >> Date: Sat, 11 Jul 2020 13:32:22 +0300 > > > >> > > > >> Hi, > > > >> > > > >> Getting lots of messages about people loving the new timekeep > > > >> functionality, which I am very happy about, but also some that have the > > > >> skew too large for it to be enabled. > > > >> > > > >> I plan on sending a diff next week to improve the situation via RDTSCP > > > >> on the machines that have it. Which is basically all modern machines. > > > >> > > > >> The plan is to have an auxiliary value returned by RDTSCP which > > > >> identifies the CPU we got the info from so that we can look-up its > > > >> associated skew in a table saved at init inside the timekeep structure: > > > > > > > > I think that is the wrong approach. Instead we should synchronize the > > > > TSC counters themselves. There are special MSRs you can write the > > > > offset into IIRC. That seems to be what FreeBSD does. > > > > > > Yes, that is another option. I have not looked to see which are more > > > popular in terms of hardware. Did the MSRs come with RDTSCP? Before? Or > > > after? We should choose the most inclusive solution I guess. Or we could > > > have both... > > > > One thing to keep in mind is that we only use the TSC as a timecounter > > on CPUs that have the ITSC feature. > > In the meantime... > > Can we add the missing LFENCE instructions to userspace and the > kernel? And can we excise the upper 32 bits? IIRC there was talk of > doing these things anyway, regardless of how the skew problem is > addressed. > > My understanding is that you need an "LFENCE sandwich" to prevent the > RDTSC from being reordered in the pipeline.
Hmm, it is my understanding that only the lfence before is needed, that is why rdtsc_lfence() looks the way it looks. If that isn't the case, that function should probably be adapted. > Index: lib/libc/arch/amd64/gen/usertc.c > =================================================================== > RCS file: /cvs/src/lib/libc/arch/amd64/gen/usertc.c,v > retrieving revision 1.2 > diff -u -p -r1.2 usertc.c > --- lib/libc/arch/amd64/gen/usertc.c 8 Jul 2020 09:17:48 -0000 1.2 > +++ lib/libc/arch/amd64/gen/usertc.c 16 Jul 2020 01:31:31 -0000 > @@ -21,9 +21,13 @@ > static inline u_int > rdtsc(void) > { > - uint32_t hi, lo; > - asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); > - return ((uint64_t)lo)|(((uint64_t)hi)<<32); > + uint32_t lo; > + > + asm volatile("lfence"); > + asm volatile("rdtsc" : "=a"(lo)); > + asm volatile("lfence"); > + > + return lo; > } > > static int > Index: sys/arch/amd64/amd64/tsc.c > =================================================================== > RCS file: /cvs/src/sys/arch/amd64/amd64/tsc.c,v > retrieving revision 1.19 > diff -u -p -r1.19 tsc.c > --- sys/arch/amd64/amd64/tsc.c 6 Jul 2020 13:33:06 -0000 1.19 > +++ sys/arch/amd64/amd64/tsc.c 16 Jul 2020 01:31:31 -0000 > @@ -211,7 +211,13 @@ cpu_recalibrate_tsc(struct timecounter * > u_int > tsc_get_timecount(struct timecounter *tc) > { > - return rdtsc() + curcpu()->ci_tsc_skew; > + uint32_t lo; > + > + asm volatile("lfence"); > + asm volatile("rdtsc" : "=a" (lo)); > + asm volatile("lfence"); > + > + return lo + curcpu()->ci_tsc_skew; > } > > void > >