svn commit: r322345 - stable/11/lib/libc/x86/sys
Andre Albsmeier
andre at fbsd.e4m.org
Sun Aug 13 13:14:06 UTC 2017
On Thu, 10-Aug-2017 at 09:00:15 +0000, Konstantin Belousov wrote:
> Author: kib
> Date: Thu Aug 10 09:00:15 2017
> New Revision: 322345
> URL: https://svnweb.freebsd.org/changeset/base/322345
>
> Log:
> MFC r321608:
> Use MFENCE to serialize RDTSC on non-Intel CPUs.
This broke libc on my
FreeBSD clang version 4.0.0 (tags/RELEASE_400/final 297347) (based on LLVM 4.0.0)
VT(vga): text 80x25
CPU: AMD-K6tm w/ multimedia extensions (199.44-MHz 586-class CPU)
Origin="AuthenticAMD" Id=0x562 Family=0x5 Model=0x6 Stepping=2
Features=0x8001bf<FPU,VME,DE,PSE,TSC,MSR,MCE,CX8,MMX>
AMD Features=0x400<<b10>>
On system start, it actually makes various programmes hang until
Ctrl-C is pressed. Reboot is not possible (endlessly hanging with
'zillions of defunct processes).
Going back to r322042 fixes it...
-Andre
>
> Modified:
> stable/11/lib/libc/x86/sys/__vdso_gettc.c
> Directory Properties:
> stable/11/ (props changed)
>
> Modified: stable/11/lib/libc/x86/sys/__vdso_gettc.c
> ==============================================================================
> --- stable/11/lib/libc/x86/sys/__vdso_gettc.c Thu Aug 10 06:59:43 2017 (r322344)
> +++ stable/11/lib/libc/x86/sys/__vdso_gettc.c Thu Aug 10 09:00:15 2017 (r322345)
> @@ -52,57 +52,108 @@ __FBSDID("$FreeBSD$");
> #endif
> #include "libc_private.h"
>
> +static enum LMB {
> + LMB_UNKNOWN,
> + LMB_NONE,
> + LMB_MFENCE,
> + LMB_LFENCE
> +} lfence_works = LMB_UNKNOWN;
> +
> static void
> -lfence_mb(void)
> +cpuidp(u_int leaf, u_int p[4])
> {
> +
> + __asm __volatile(
> #if defined(__i386__)
> - static int lfence_works = -1;
> + " pushl %%ebx\n"
> +#endif
> + " cpuid\n"
> +#if defined(__i386__)
> + " movl %%ebx,%1\n"
> + " popl %%ebx"
> +#endif
> + : "=a" (p[0]),
> +#if defined(__i386__)
> + "=r" (p[1]),
> +#elif defined(__amd64__)
> + "=b" (p[1]),
> +#else
> +#error "Arch"
> +#endif
> + "=c" (p[2]), "=d" (p[3])
> + : "0" (leaf));
> +}
> +
> +static enum LMB
> +select_lmb(void)
> +{
> + u_int p[4];
> + static const char intel_id[] = "GenuntelineI";
> +
> + cpuidp(0, p);
> + return (memcmp(p + 1, intel_id, sizeof(intel_id) - 1) == 0 ?
> + LMB_LFENCE : LMB_MFENCE);
> +}
> +
> +static void
> +init_fence(void)
> +{
> +#if defined(__i386__)
> u_int cpuid_supported, p[4];
>
> - if (lfence_works == -1) {
> - __asm __volatile(
> - " pushfl\n"
> - " popl %%eax\n"
> - " movl %%eax,%%ecx\n"
> - " xorl $0x200000,%%eax\n"
> - " pushl %%eax\n"
> - " popfl\n"
> - " pushfl\n"
> - " popl %%eax\n"
> - " xorl %%eax,%%ecx\n"
> - " je 1f\n"
> - " movl $1,%0\n"
> - " jmp 2f\n"
> - "1: movl $0,%0\n"
> - "2:\n"
> - : "=r" (cpuid_supported) : : "eax", "ecx", "cc");
> - if (cpuid_supported) {
> - __asm __volatile(
> - " pushl %%ebx\n"
> - " cpuid\n"
> - " movl %%ebx,%1\n"
> - " popl %%ebx\n"
> - : "=a" (p[0]), "=r" (p[1]), "=c" (p[2]), "=d" (p[3])
> - : "0" (0x1));
> - lfence_works = (p[3] & CPUID_SSE2) != 0;
> - } else
> - lfence_works = 0;
> - }
> - if (lfence_works == 1)
> - lfence();
> + __asm __volatile(
> + " pushfl\n"
> + " popl %%eax\n"
> + " movl %%eax,%%ecx\n"
> + " xorl $0x200000,%%eax\n"
> + " pushl %%eax\n"
> + " popfl\n"
> + " pushfl\n"
> + " popl %%eax\n"
> + " xorl %%eax,%%ecx\n"
> + " je 1f\n"
> + " movl $1,%0\n"
> + " jmp 2f\n"
> + "1: movl $0,%0\n"
> + "2:\n"
> + : "=r" (cpuid_supported) : : "eax", "ecx", "cc");
> + if (cpuid_supported) {
> + cpuidp(0x1, p);
> + if ((p[3] & CPUID_SSE2) != 0)
> + lfence_works = select_lmb();
> + } else
> + lfence_works = LMB_NONE;
> #elif defined(__amd64__)
> - lfence();
> + lfence_works = select_lmb();
> #else
> -#error "arch"
> +#error "Arch"
> #endif
> }
>
> +static void
> +rdtsc_mb(void)
> +{
> +
> +again:
> + if (__predict_true(lfence_works == LMB_LFENCE)) {
> + lfence();
> + return;
> + } else if (lfence_works == LMB_MFENCE) {
> + mfence();
> + return;
> + } else if (lfence_works == LMB_NONE) {
> + return;
> + }
> + init_fence();
> + goto again;
> +}
> +
> static u_int
> __vdso_gettc_rdtsc_low(const struct vdso_timehands *th)
> {
> u_int rv;
>
> - lfence_mb();
> + rdtsc_mb();
> __asm __volatile("rdtsc; shrd %%cl, %%edx, %0"
> : "=a" (rv) : "c" (th->th_x86_shift) : "edx");
> return (rv);
> @@ -112,7 +163,7 @@ static u_int
> __vdso_rdtsc32(void)
> {
>
> - lfence_mb();
> + rdtsc_mb();
> return (rdtsc32());
> }
>
> @@ -211,7 +262,7 @@ __vdso_hyperv_tsc(struct hyperv_reftsc *tsc_ref, u_int
> scale = tsc_ref->tsc_scale;
> ofs = tsc_ref->tsc_ofs;
>
> - lfence_mb();
> + rdtsc_mb();
> tsc = rdtsc();
>
> /* ret = ((tsc * scale) >> 64) + ofs */
> _______________________________________________
> svn-src-stable-11 at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-stable-11
> To unsubscribe, send any mail to "svn-src-stable-11-unsubscribe at freebsd.org"
--
Stuxnet? Find ich gut. Manche lernen nur auf die harte Tour...
More information about the svn-src-stable-11
mailing list