[PATCH] D41761: Introduce llvm.nospeculateload intrinsic

Kristof Beyls via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 10 07:38:55 PST 2018


kristof.beyls added a comment.

Thanks for the feedback, Chandler and Philip!

Please let me explain how we've ended up with the API design as proposed.

We started from the observation that:

1. We need an API/intrinsic that can be implemented well in all major compilers, including gcc and clang/llvm.
2. We need an API/intrinsic that works well across architectures.

For Arm, the recommended mitigation for protecting against Spectre variant 1 is to generate a LOAD->CSEL->CSDB instruction sequence, where CSDB is a new barrier instruction.
This sequence gives protection on all Arm implementations.
This is explained in far more detail at https://developer.arm.com/support/security-update/download-the-whitepaper, in section "Software mitigations", pages 4-8.

The need to generate the full LOAD->CSEL->CSDB sequence explains why the proposed intrinsic contains the semantics of loading a value, providing it is within bounds.
Being able to generate the LOAD->CSEL->CSDB sequence from the intrinsic is essential for AArch64 and ARM targets.

Hopefully that explains the needs for the ptr, lower_bound and upper_bound parameters.

The cmpptr and failval parameters are there to make it easier to use in certain scenarios, for example:

For failval, the idea is that for code like

  if (ptr >= base && ptr < limit) // bounds check
    return *ptr;
  return FAILVAL;

to be able to be easily rewritten as

  return __builtin_load_no_speculate (ptr, base, limit, FAILVAL);

The cmpptr parameter was introduced after hearing a need from the linux kernel. They have some cases where cmpptr may be a pointer to an atomic type and want to do something like

  if (cmpptr >= lower && cmpptr < upper)
    val = __atomic_read_and_inc (cmpptr);

By separating out cmpptr from ptr you can now write the following, which removes the need to try and wrestle "no-speculate" semantics into the atomic builtins:

  if (cmpptr >= lower && cmpptr < upper)
    {
      T tmp_val = __atomic_read_and_inc (cmpptr);
      val = builtin_load_no_speculate (&tmp_val, lower, upper, 0,
                                       cmpptr);
    }

There is a bit more explanation on the rationale for the failval and cmpptr parameters at https://gcc.gnu.org/ml/gcc-patches/2018-01/msg00594.html.

Furthermore, there are a few more details on the use of this intrinsic at https://developer.arm.com/support/security-update/compiler-support-for-mitigations

I hope the above helps to explain the rationale for the proposed API design?


https://reviews.llvm.org/D41761





More information about the llvm-commits mailing list