Reimplement CET intrinsics for rdssp/incssp insn.
authorIgor Tsimbalist <igor.v.tsimbalist@intel.com>
Wed, 14 Feb 2018 15:06:21 +0000 (16:06 +0100)
committerIgor Tsimbalist <itsimbal@gcc.gnu.org>
Wed, 14 Feb 2018 15:06:21 +0000 (16:06 +0100)
Introduce a couple of new CET intrinsics for reading and updating a
shadow stack pointer (_get_ssp and _inc_ssp). They replace the existing
_rdssp[d|q] and _incssp[d|q] instrinsics.

PR target/84239
* gcc/config/i386/cetintrin.h: Remove _rdssp[d|q] and
add _get_ssp intrinsics. Remove argument from
__builtin_ia32_rdssp[d|q].
* gcc/config/i386/i386-builtin-types.def: Add UINT_FTYPE_VOID.
* gcc/config/i386/i386-builtin.def: Remove argument from
__builtin_ia32_rdssp[d|q].
* gcc/config/i386/i386.c: Use UINT_FTYPE_VOID. Use
ix86_expand_special_args_builtin for _rdssp[d|q].
* gcc/config/i386/i386.md: Remove argument from rdssp[si|di] insn.
Clear register before usage.
* doc/extend.texi: Remove argument from __builtin_ia32_rdssp[d|q].
Add documentation for new _get_ssp and _inc_ssp intrinsics.
* testsuite/gcc.target/i386/cet-intrin-3.c: Use new _get_ssp and
_inc_ssp intrinsics.
* testsuite/gcc.target/i386/cet-intrin-4.c: Likewise.
* testsuite/gcc.target/i386/cet-rdssp-1.c: Remove argument from
__builtin_ia32_rdssp[d|q].
* libgcc/config/i386/shadow-stack-unwind.hi (_Unwind_Frames_Extra):
Use new _get_ssp and _inc_ssp intrinsics.

From-SVN: r257660

13 files changed:
gcc/ChangeLog
gcc/config/i386/cetintrin.h
gcc/config/i386/i386-builtin-types.def
gcc/config/i386/i386-builtin.def
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/cet-intrin-3.c
gcc/testsuite/gcc.target/i386/cet-intrin-4.c
gcc/testsuite/gcc.target/i386/cet-rdssp-1.c
libgcc/ChangeLog
libgcc/config/i386/shadow-stack-unwind.h

index cc294407691ba2feb7d823e4a64a52dcdfab50f6..b2bec8b574f97c36c6224ac2cb89f10a7c4d4a9a 100644 (file)
@@ -1,3 +1,19 @@
+2018-02-14  Igor Tsimbalist  <igor.v.tsimbalist@intel.com>
+
+       PR target/84239
+       * config/i386/cetintrin.h: Remove _rdssp[d|q] and
+       add _get_ssp intrinsics. Remove argument from
+       __builtin_ia32_rdssp[d|q].
+       * config/i386/i386-builtin-types.def: Add UINT_FTYPE_VOID.
+       * config/i386/i386-builtin.def: Remove argument from
+       __builtin_ia32_rdssp[d|q].
+       * config/i386/i386.c: Use UINT_FTYPE_VOID. Use
+       ix86_expand_special_args_builtin for _rdssp[d|q].
+       * config/i386/i386.md: Remove argument from rdssp[si|di] insn.
+       Clear register before usage.
+       * doc/extend.texi: Remove argument from __builtin_ia32_rdssp[d|q].
+       Add documentation for new _get_ssp and _inc_ssp intrinsics.
+
 2018-02-14  Richard Sandiford  <richard.sandiford@linaro.org>
 
        PR tree-optimization/84357
index 7a4b4d8bf24cc9db177e69426667a6deadf5042a..e9abcf3c580e53aa02b82e2eaed9559fb7de2000 100644 (file)
 #define __DISABLE_SHSTK__
 #endif /* __SHSTK__ */
 
-extern __inline unsigned int
-__attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_rdsspd (unsigned int __B)
-{
-  return __builtin_ia32_rdsspd (__B);
-}
-
 #ifdef __x86_64__
 extern __inline unsigned long long
 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_rdsspq (unsigned long long __B)
+_get_ssp (void)
 {
-  return __builtin_ia32_rdsspq (__B);
+  return __builtin_ia32_rdsspq ();
 }
-#endif
-
-extern __inline void
+#else
+extern __inline unsigned int
 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_incsspd (unsigned int __B)
+_get_ssp (void)
 {
-  __builtin_ia32_incsspd (__B);
+  return __builtin_ia32_rdsspd ();
 }
+#endif
 
-#ifdef __x86_64__
 extern __inline void
 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
-_incsspq (unsigned long long __B)
+_inc_ssp (unsigned int __B)
 {
-  __builtin_ia32_incsspq (__B);
-}
+#ifdef __x86_64__
+  __builtin_ia32_incsspq ((unsigned long long) __B);
+#else
+  __builtin_ia32_incsspd (__B);
 #endif
+}
 
 extern __inline void
 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
index ba3354904897e9af8270565ab873c2c78be877e1..08360d23cbbba889f7895574c33d2a84d4794a21 100644 (file)
@@ -192,6 +192,7 @@ DEF_POINTER_TYPE (PCV64QI, V64QI, CONST)
 DEF_FUNCTION_TYPE (FLOAT128)
 DEF_FUNCTION_TYPE (UINT64)
 DEF_FUNCTION_TYPE (UNSIGNED)
+DEF_FUNCTION_TYPE (UINT)
 DEF_FUNCTION_TYPE (USHORT)
 DEF_FUNCTION_TYPE (INT)
 DEF_FUNCTION_TYPE (VOID)
index 169189d962c9ec88b04b1fd08fe7adfa30f3c746..a48019499bd2166a7cd3ba9ce0d45febc9ab5b87 100644 (file)
@@ -3043,7 +3043,7 @@ BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_clrssbsy, "__builtin_ia32_clrssbsy", IX86
 BDESC_END (CET, CET_NORMAL)
 
 BDESC_FIRST (cet_rdssp, CET_NORMAL,
-       OPTION_MASK_ISA_SHSTK, CODE_FOR_rdsspsi, "__builtin_ia32_rdsspd", IX86_BUILTIN_RDSSPD, UNKNOWN, (int) UINT_FTYPE_UINT)
-BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_rdsspdi, "__builtin_ia32_rdsspq", IX86_BUILTIN_RDSSPQ, UNKNOWN, (int) UINT64_FTYPE_UINT64)
+       OPTION_MASK_ISA_SHSTK, CODE_FOR_rdsspsi, "__builtin_ia32_rdsspd", IX86_BUILTIN_RDSSPD, UNKNOWN, (int) UINT_FTYPE_VOID)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_rdsspdi, "__builtin_ia32_rdsspq", IX86_BUILTIN_RDSSPQ, UNKNOWN, (int) UINT64_FTYPE_VOID)
 
 BDESC_END (CET_NORMAL, MAX)
index 020eef9fd7bd7d54fdd5f2f8479f394195aa56de..fa31f94d3e092a0af47d7dacc96ae2a31bc885a6 100644 (file)
@@ -35708,6 +35708,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
     case INT_FTYPE_VOID:
     case USHORT_FTYPE_VOID:
     case UINT64_FTYPE_VOID:
+    case UINT_FTYPE_VOID:
     case UNSIGNED_FTYPE_VOID:
       nargs = 0;
       klass = load;
@@ -38497,7 +38498,7 @@ s4fma_expand:
       && fcode <= IX86_BUILTIN__BDESC_CET_NORMAL_LAST)
     {
       i = fcode - IX86_BUILTIN__BDESC_CET_NORMAL_FIRST;
-      return ix86_expand_args_builtin (bdesc_cet_rdssp + i, exp,
+      return ix86_expand_special_args_builtin (bdesc_cet_rdssp + i, exp,
                                       target);
     }
 
index a4832bf696f321e8ee5aad71fa946ca198d9d689..3998053a50644d000d54576f98525ceafab1cd48 100644 (file)
       reg_ssp = gen_reg_rtx (word_mode);
       emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
       emit_insn ((word_mode == SImode)
-                ? gen_rdsspsi (reg_ssp, reg_ssp)
-                : gen_rdsspdi (reg_ssp, reg_ssp));
+                ? gen_rdsspsi (reg_ssp)
+                : gen_rdsspdi (reg_ssp));
       emit_move_insn (mem, reg_ssp);
     }
   DONE;
       reg_ssp = gen_reg_rtx (word_mode);
       emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
       emit_insn ((word_mode == SImode)
-                ? gen_rdsspsi (reg_ssp, reg_ssp)
-                : gen_rdsspdi (reg_ssp, reg_ssp));
+                ? gen_rdsspsi (reg_ssp)
+                : gen_rdsspdi (reg_ssp));
       mem_buf = gen_rtx_MEM (word_mode,
                             plus_constant (Pmode, operands[0],
                                            3 * GET_MODE_SIZE (ptr_mode)));
 ;; CET instructions
 (define_insn "rdssp<mode>"
   [(set (match_operand:SWI48x 0 "register_operand" "=r")
-       (unspec_volatile:SWI48x
-         [(match_operand:SWI48x 1 "register_operand" "0")]
-         UNSPECV_NOP_RDSSP))]
+       (unspec_volatile:SWI48x [(const_int 0)] UNSPECV_NOP_RDSSP))]
   "TARGET_SHSTK"
-  "rdssp<mskmodesuffix>\t%0"
-  [(set_attr "length" "4")
+  "xor{l}\t%k0, %k0\n\trdssp<mskmodesuffix>\t%0"
+  [(set_attr "length" "6")
    (set_attr "type" "other")])
 
 (define_insn "incssp<mode>"
index 4f79a92fc1d261e46b017dd3fde45dc8f09acb85..5c3c5ec2dc84413e65f416c6332ebf5dbbf91250 100644 (file)
@@ -12461,6 +12461,7 @@ instructions, but allow the compiler to schedule those calls.
 * TILEPro Built-in Functions::
 * x86 Built-in Functions::
 * x86 transactional memory intrinsics::
+* x86 control-flow protection intrinsics::
 @end menu
 
 @node AArch64 Built-in Functions
@@ -21772,13 +21773,17 @@ void __builtin_ia32_wrpkru (unsigned int)
 unsigned int __builtin_ia32_rdpkru ()
 @end smallexample
 
-The following built-in functions are available when @option{-mcet} is used.
-They are used to support Intel Control-flow Enforcment Technology (CET).
-Each built-in function generates the  machine instruction that is part of the
-function's name.
+The following built-in functions are available when @option{-mcet} or
+@option{-mshstk} option is used.  They support shadow stack
+machine instructions from Intel Control-flow Enforcement Technology (CET).
+Each built-in function generates the  machine instruction that is part
+of the function's name.  These are the internal low-level functions.
+Normally the functions in @ref{x86 control-flow protection intrinsics}
+should be used instead.
+
 @smallexample
-unsigned int __builtin_ia32_rdsspd (unsigned int)
-unsigned long long __builtin_ia32_rdsspq (unsigned long long)
+unsigned int __builtin_ia32_rdsspd (void)
+unsigned long long __builtin_ia32_rdsspq (void)
 void __builtin_ia32_incsspd (unsigned int)
 void __builtin_ia32_incsspq (unsigned long long)
 void __builtin_ia32_saveprevssp(void);
@@ -21885,6 +21890,51 @@ else
 Note that, in most cases, the transactional and non-transactional code
 must synchronize together to ensure consistency.
 
+@node x86 control-flow protection intrinsics
+@subsection x86 Control-Flow Protection Intrinsics
+
+@deftypefn {CET Function} {ret_type} _get_ssp (void)
+Get the current value of shadow stack pointer if shadow stack support
+from Intel CET is enabled in the hardware or @code{0} otherwise.
+The @code{ret_type} is @code{unsigned long long} for 64-bit targets 
+and @code{unsigned int} for 32-bit targets.
+@end deftypefn
+
+@deftypefn {CET Function} void _inc_ssp (unsigned int)
+Increment the current shadow stack pointer by the size specified by the
+function argument.  The argument is masked to a byte value for security
+reasons, so to increment by more than 255 bytes you must call the function
+multiple times.
+@end deftypefn
+
+The shadow stack unwind code looks like:
+
+@smallexample
+#include <immintrin.h>
+
+/* Unwind the shadow stack for EH.  */
+#define _Unwind_Frames_Extra(x)       \
+  do                                  \
+    @{                                \
+      _Unwind_Word ssp = _get_ssp (); \
+      if (ssp != 0)                   \
+        @{                            \
+          _Unwind_Word tmp = (x);     \
+          while (tmp > 255)           \
+            @{                        \
+              _inc_ssp (tmp);         \
+              tmp -= 255;             \
+            @}                        \
+          _inc_ssp (tmp);             \
+        @}                            \
+    @}                                \
+    while (0)
+@end smallexample
+
+@noindent
+This code runs unconditionally on all 64-bit processors.  For 32-bit
+processors the code runs on those that support multi-byte NOP instructions.
+
 @node Target Format Checks
 @section Format Checks Specific to Particular Target Machines
 
index 473a2723012b298c207ac94fc5229e1359815b3c..51aeba332d3e0d37c594883ef18c2c8dbef5205e 100644 (file)
@@ -1,3 +1,12 @@
+2018-02-14  Igor Tsimbalist  <igor.v.tsimbalist@intel.com>
+
+       PR target/84239
+       * gcc.target/i386/cet-intrin-3.c: Use new _get_ssp and
+       _inc_ssp intrinsics.
+       * gcc.target/i386/cet-intrin-4.c: Likewise.
+       * gcc.target/i386/cet-rdssp-1.c: Remove argument from
+       __builtin_ia32_rdssp[d|q].
+
 2018-02-14  Richard Sandiford  <richard.sandiford@linaro.org>
 
        PR tree-optimization/84357
index bcd7203fdb4288fff391fef96b17fe5a0526141b..b98c1e928d5cec691d3bcb1086546cb1c075ecdb 100644 (file)
 
 unsigned int f1 ()
 {
-  unsigned int x = 0;
-  return _rdsspd (x);
+  return _get_ssp ();
 }
 
 void f3 (unsigned int _a)
 {
-  _incsspd (_a);
+  _inc_ssp (_a);
 }
 
 #ifdef __x86_64__
 unsigned long long f2 ()
 {
-  unsigned long long x = 0;
-  return _rdsspq (x);
+  return _get_ssp ();
 }
 
 void f4 (unsigned int _a)
 {
-  _incsspq (_a);
+  _inc_ssp (_a);
 }
 #endif
index 437a4cd690c9b05202c8f9e7508b8da77dac14ea..86957b2eebed0e7863f97aa1fd6105bd73f1ba48 100644 (file)
@@ -5,27 +5,4 @@
 /* { dg-final { scan-assembler "incssp\[dq]\[ \t]+(%|)\[re]di" { target { ! ia32 } } } } */
 
 #include <immintrin.h>
-
-unsigned int f1 ()
-{
-  unsigned int x = 0;
-  return _rdsspd (x);
-}
-
-void f3 (unsigned int _a)
-{
-  _incsspd (_a);
-}
-
-#ifdef __x86_64__
-unsigned long long f2 ()
-{
-  unsigned long long x = 0;
-  return _rdsspq (x);
-}
-
-void f4 (unsigned int _a)
-{
-  _incsspq (_a);
-}
-#endif
+#include "cet-intrin-3.c"
index fb50ff4350491600e4f636b2972d215d6bedead7..6cd24f63384b943851a6e87fbda1d32ad38132f6 100644 (file)
@@ -5,18 +5,18 @@ void _exit(int status) __attribute__ ((__noreturn__));
 
 #ifdef __x86_64__
 # define incssp(x) __builtin_ia32_incsspq (x)
-# define rdssp(x) __builtin_ia32_rdsspq (x)
+# define rdssp() __builtin_ia32_rdsspq ()
 #else
 # define incssp(x) __builtin_ia32_incsspd (x)
-# define rdssp(x) __builtin_ia32_rdsspd (x)
+# define rdssp() __builtin_ia32_rdsspd ()
 #endif
 
 static void
 __attribute__ ((noinline, noclone))
 test (unsigned long frames)
 {
-  unsigned long ssp = 0;
-  ssp = rdssp (ssp);
+  unsigned long ssp;
+  ssp = rdssp ();
   if (ssp != 0)
     {
       unsigned long tmp = frames;
index 1eb16631e03b789b6e65f40605673f4633b1397e..692773d7d2db0677e8bbb73faa7fd3ccd1da7134 100644 (file)
@@ -1,3 +1,9 @@
+2018-02-08  Igor Tsimbalist  <igor.v.tsimbalist@intel.com>
+
+       PR target/84239
+       * config/i386/shadow-stack-unwind.hi (_Unwind_Frames_Extra):
+       Use new _get_ssp and _inc_ssp intrinsics.
+
 2018-02-02  Julia Koval  <julia.koval@intel.com>
 
        * config/i386/cpuinfo.h (processor_subtypes): Add INTEL_COREI7_ICELAKE.
index ef75d97aa2fe04f39619e7af78c8b38ff2643c25..416e061dd46d5754661469b9496379060018a4c1 100644 (file)
@@ -22,30 +22,23 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
-#ifdef __x86_64__
-# define incssp(x) __builtin_ia32_incsspq ((x))
-# define rdssp(x) __builtin_ia32_rdsspq (x)
-#else
-# define incssp(x) __builtin_ia32_incsspd ((x))
-# define rdssp(x) __builtin_ia32_rdsspd (x)
-#endif
+#include <x86intrin.h>
 
 /* Unwind the shadow stack for EH.  */
 #undef _Unwind_Frames_Extra
 #define _Unwind_Frames_Extra(x)                        \
   do                                           \
     {                                          \
-      unsigned long ssp = 0;                   \
-      ssp = rdssp (ssp);                       \
+      _Unwind_Word ssp = _get_ssp ();          \
       if (ssp != 0)                            \
        {                                       \
-         unsigned long tmp = (x);              \
+         _Unwind_Word tmp = (x);               \
          while (tmp > 255)                     \
            {                                   \
-             incssp (tmp);                     \
+             _inc_ssp (tmp);                   \
              tmp -= 255;                       \
            }                                   \
-         incssp (tmp);                         \
+         _inc_ssp (tmp);                       \
        }                                       \
     }                                          \
     while (0)