On 14/06/2021 17:13, Andrew Cooper wrote:
> +/*
> + * Probe for how RTM behaves, deliberately not inspecting CPUID.
> + * Distinguishes between "no support at all" (i.e. XBEGIN suffers #UD),
> + * working ok, and appearing to always abort.
> + */
> +static enum rtm_behaviour __attribute__((noclone)) probe_rtm_behaviour(void)

This doesn't compile, because Clang doesn't understand noclone.

With it dropped, https://cirrus-ci.com/build/6399801072812032 is the
FreeBSD build, confirming that sigill_handler() below is seemingly ok.

~Andrew

> +{
> +    for ( unsigned int i = 0; i < 1000; ++i )
> +    {
> +        /*
> +         * Opencoding the RTM infrastructure from immintrin.h, because we
> +         * still support older versions of GCC.  ALso so we can include #UD
> +         * detection logic.
> +         */
> +#define XBEGIN_STARTED -1
> +#define XBEGIN_UD      -2
> +        unsigned int status = XBEGIN_STARTED;
> +
> +        asm volatile ( ".Lxbegin: .byte 0xc7,0xf8,0,0,0,0" /* XBEGIN 1f; 1: 
> */
> +                       : "+a" (status) :: "memory" );
> +        if ( status == XBEGIN_STARTED )
> +        {
> +            asm volatile ( ".byte 0x0f,0x01,0xd5" ::: "memory" ); /* XEND */
> +            return RTM_OK;
> +        }
> +        else if ( status == XBEGIN_UD )
> +            return RTM_UD;
> +    }
> +
> +    return RTM_ABORT;
> +}
> +
> +static struct sigaction old_sigill;
> +
> +static void sigill_handler(int signo, siginfo_t *info, void *extra)
> +{
> +    extern const char xbegin_label[] asm(".Lxbegin");
> +
> +    if ( info->si_addr == xbegin_label &&
> +         memcmp(info->si_addr, "\xc7\xf8\x00\x00\x00\x00", 6) == 0 )
> +    {
> +        ucontext_t *context = extra;
> +
> +        /*
> +         * Found the XBEGIN instruction.  Step over it, and update `status` 
> to
> +         * signal #UD.
> +         */
> +#if defined(__linux__)
> +# ifdef __x86_64__
> +        context->uc_mcontext.gregs[REG_RIP] += 6;
> +        context->uc_mcontext.gregs[REG_RAX] = XBEGIN_UD;
> +# else
> +        context->uc_mcontext.gregs[REG_EIP] += 6;
> +        context->uc_mcontext.gregs[REG_EAX] = XBEGIN_UD;
> +# endif
> +
> +#elif defined(__FreeBSD__)
> +# ifdef __x86_64__
> +        context->uc_mcontext.mc_rip += 6;
> +        context->uc_mcontext.mc_rax = XBEGIN_UD;
> +# else
> +        context->uc_mcontext.mc_eip += 6;
> +        context->uc_mcontext.mc_eax = XBEGIN_UD;
> +# endif
> +
> +#elif defined(__NetBSD__)
> +# ifdef __x86_64__
> +        context->uc_mcontext.__gregs[_REG_RIP] += 6;
> +        context->uc_mcontext.__gregs[_REG_RAX] = XBEGIN_UD;
> +# else
> +        context->uc_mcontext.__gregs[_REG_EIP] += 6;
> +        context->uc_mcontext.__gregs[_REG_EAX] = XBEGIN_UD;
> +# endif
> +
> +#else
> +# error Unknown environment - please adjust
> +#endif
> +    }
> +    else
> +    {
> +        /*
> +         * Not the SIGILL we're looking for...  Restore the old handler and
> +         * try again.  Will likely coredump as a result.
> +         */
> +        sigaction(SIGILL, &old_sigill, NULL);
> +    }
> +}


Reply via email to