On Sat, Apr 03, 2021 at 10:21:02PM -0500, Scott Cheloha wrote: > On Fri, Apr 02, 2021 at 10:37:36AM -0700, Mike Larkin wrote: > > On Thu, Apr 01, 2021 at 06:43:30PM -0500, Scott Cheloha wrote: > > > > > > [...] > > > > > > Hmmm. Being able to work around this would be nice. > > > > > > FreeBSD has code that uses WRMSR to synchronize the TSC: > > > > > > https://cgit.freebsd.org/src/commit/sys/x86/x86/tsc.c?id=b2c63698d4b81576e0c8842263ee86e86cd34e76 > > > > > > My guess is that support for writing the TSC is not implemented by > > > every hypervisor, so we would need to be very careful in deciding when > > > to try it. Otherwise we end up with protection faults and other crap > > > we don't want. > > > > > > > We implemented rdmsr_safe for things like this. We could probably do the > > same > > for wrmsr. > > Like this? > > Sorry if this is not idiomatic. I don't write much assembly. > > I tested this a bit on my laptop. Stuff like: > > wrmsr_safe(MSR_TSC, rdtsc() + 100); > > Which seems to desync the normally synchronized TSCs here. > > Unclear what the rules are for RETGUARD. I just copied what was in > rdmsr_safe(). We're not using R10 so we can use R10? > > -Scott > > Index: include/cpufunc.h > =================================================================== > RCS file: /cvs/src/sys/arch/amd64/include/cpufunc.h,v > retrieving revision 1.36 > diff -u -p -r1.36 cpufunc.h > --- include/cpufunc.h 13 Sep 2020 11:53:16 -0000 1.36 > +++ include/cpufunc.h 4 Apr 2021 03:16:48 -0000 > @@ -398,6 +398,7 @@ struct cpu_info_full; > void cpu_enter_pages(struct cpu_info_full *); > > int rdmsr_safe(u_int msr, uint64_t *); > +int wrmsr_safe(uint32_t msr, uint64_t); > > #endif /* _KERNEL */ > > Index: amd64/locore.S > =================================================================== > RCS file: /cvs/src/sys/arch/amd64/amd64/locore.S,v > retrieving revision 1.122 > diff -u -p -r1.122 locore.S > --- amd64/locore.S 3 Nov 2020 18:19:31 -0000 1.122 > +++ amd64/locore.S 4 Apr 2021 03:16:48 -0000 > @@ -1154,6 +1154,30 @@ NENTRY(rdmsr_resume) > ret > END(rdmsr_safe) > > +/* int wrmsr_safe(uint32_t msr, uint64_t val) */ > +ENTRY(wrmsr_safe) > + RETGUARD_SETUP(wrmsr_safe, r10) > + > + movl %edi, %ecx /* uint32_t msr */ > + > + movl %esi, %eax /* uint64_t val */ > + sarq $32, %rsi > + movl %esi, %edx > + > + .globl wrmsr_safe_fault > +wrmsr_safe_fault: > + wrmsr > + > + xorq %rax, %rax > + RETGUARD_CHECK(rdmsr_safe, r10) > + ret > + > +NENTRY(wrmsr_resume) > + movq $0x1, %rax > + RETGUARD_CHECK(wrmsr_safe, r10) > + ret > +END(wrmsr_safe) > + > #if NXEN > 0 > /* Hypercall page needs to be page aligned */ > .text >
You will need the handler case in vector.S also (like we did for rdmsr_safe). (Sorry if this reply hits the list twice; mailer error on previous attempt). -ml