Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/gpl3/gcc.old/dist/gcc add the spectre mitigation op...



details:   https://anonhg.NetBSD.org/src/rev/a33deb47ba7c
branches:  trunk
changeset: 831393:a33deb47ba7c
user:      mrg <mrg%NetBSD.org@localhost>
date:      Wed Mar 28 19:24:52 2018 +0000

description:
add the spectre mitigation options for x86:

  -mindirect-branch=<choice>
  -mfunction-return=<choice>
  -mindirect-branch-register

the values for 'choice' are "keep" (default, existing behaviour),
"thunk", "thunk-inline", and "thunk-extern".

as taken from the Ubuntu port of these changes in their
ubuntu:gcc-5_5.5.0-8ubuntu1.diff.  i've also included the doc
updates that are missing from ubuntu from gcc itself.


i've tested both i386 and amd64 fairly heavily with these options
enabled in both kernels and userland, atf runs and hundreds of
package builds.

XXX: pullup-8 to gcc/ not gcc.old/

diffstat:

 external/gpl3/gcc.old/dist/gcc/config/i386/constraints.md |    6 +-
 external/gpl3/gcc.old/dist/gcc/config/i386/i386-opts.h    |   13 +
 external/gpl3/gcc.old/dist/gcc/config/i386/i386-protos.h  |    2 +
 external/gpl3/gcc.old/dist/gcc/config/i386/i386.c         |  873 ++++++++++++-
 external/gpl3/gcc.old/dist/gcc/config/i386/i386.h         |   68 +-
 external/gpl3/gcc.old/dist/gcc/config/i386/i386.md        |   69 +-
 external/gpl3/gcc.old/dist/gcc/config/i386/i386.opt       |   28 +
 external/gpl3/gcc.old/dist/gcc/config/i386/predicates.md  |    9 +-
 external/gpl3/gcc.old/dist/gcc/doc/extend.texi            |   19 +
 external/gpl3/gcc.old/dist/gcc/doc/invoke.texi            |   36 +
 10 files changed, 1022 insertions(+), 101 deletions(-)

diffs (truncated from 1581 to 300 lines):

diff -r 3938eb50ac38 -r a33deb47ba7c external/gpl3/gcc.old/dist/gcc/config/i386/constraints.md
--- a/external/gpl3/gcc.old/dist/gcc/config/i386/constraints.md Wed Mar 28 19:22:32 2018 +0000
+++ b/external/gpl3/gcc.old/dist/gcc/config/i386/constraints.md Wed Mar 28 19:24:52 2018 +0000
@@ -157,12 +157,14 @@
 
 (define_constraint "Bs"
   "@internal Sibcall memory operand."
-  (and (not (match_test "TARGET_X32"))
+  (and (not (match_test "ix86_indirect_branch_register"))
+       (not (match_test "TARGET_X32"))
        (match_operand 0 "sibcall_memory_operand")))
 
 (define_constraint "Bw"
   "@internal Call memory operand."
-  (and (not (match_test "TARGET_X32"))
+  (and (not (match_test "ix86_indirect_branch_register"))
+       (not (match_test "TARGET_X32"))
        (match_operand 0 "memory_operand")))
 
 (define_constraint "Bz"
diff -r 3938eb50ac38 -r a33deb47ba7c external/gpl3/gcc.old/dist/gcc/config/i386/i386-opts.h
--- a/external/gpl3/gcc.old/dist/gcc/config/i386/i386-opts.h    Wed Mar 28 19:22:32 2018 +0000
+++ b/external/gpl3/gcc.old/dist/gcc/config/i386/i386-opts.h    Wed Mar 28 19:24:52 2018 +0000
@@ -99,4 +99,17 @@
   SSP_GLOBAL    /* global canary */
 };
 
+/* This is used to mitigate variant #2 of the speculative execution
+   vulnerabilities on x86 processors identified by CVE-2017-5715, aka
+   Spectre.  They convert indirect branches and function returns to
+   call and return thunks to avoid speculative execution via indirect
+   call, jmp and ret.  */
+enum indirect_branch {
+  indirect_branch_unset = 0,
+  indirect_branch_keep,
+  indirect_branch_thunk,
+  indirect_branch_thunk_inline,
+  indirect_branch_thunk_extern
+};
+
 #endif
diff -r 3938eb50ac38 -r a33deb47ba7c external/gpl3/gcc.old/dist/gcc/config/i386/i386-protos.h
--- a/external/gpl3/gcc.old/dist/gcc/config/i386/i386-protos.h  Wed Mar 28 19:22:32 2018 +0000
+++ b/external/gpl3/gcc.old/dist/gcc/config/i386/i386-protos.h  Wed Mar 28 19:24:52 2018 +0000
@@ -306,6 +306,8 @@
 #endif
 
 extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
+extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
+extern const char * ix86_output_function_return (bool long_p);
 
 #ifdef RTX_CODE
 /* Target data for multipass lookahead scheduling.
diff -r 3938eb50ac38 -r a33deb47ba7c external/gpl3/gcc.old/dist/gcc/config/i386/i386.c
--- a/external/gpl3/gcc.old/dist/gcc/config/i386/i386.c Wed Mar 28 19:22:32 2018 +0000
+++ b/external/gpl3/gcc.old/dist/gcc/config/i386/i386.c Wed Mar 28 19:24:52 2018 +0000
@@ -2306,53 +2306,6 @@
   struct stack_local_entry *next;
 };
 
-/* Structure describing stack frame layout.
-   Stack grows downward:
-
-   [arguments]
-                                       <- ARG_POINTER
-   saved pc
-
-   saved static chain                  if ix86_static_chain_on_stack
-
-   saved frame pointer                 if frame_pointer_needed
-                                       <- HARD_FRAME_POINTER
-   [saved regs]
-                                       <- regs_save_offset
-   [padding0]
-
-   [saved SSE regs]
-                                       <- sse_regs_save_offset
-   [padding1]          |
-                      |                <- FRAME_POINTER
-   [va_arg registers]  |
-                      |
-   [frame]            |
-                      |
-   [padding2]         | = to_allocate
-                                       <- STACK_POINTER
-  */
-struct ix86_frame
-{
-  int nsseregs;
-  int nregs;
-  int va_arg_size;
-  int red_zone_size;
-  int outgoing_arguments_size;
-
-  /* The offsets relative to ARG_POINTER.  */
-  HOST_WIDE_INT frame_pointer_offset;
-  HOST_WIDE_INT hard_frame_pointer_offset;
-  HOST_WIDE_INT stack_pointer_offset;
-  HOST_WIDE_INT hfp_save_offset;
-  HOST_WIDE_INT reg_save_offset;
-  HOST_WIDE_INT sse_reg_save_offset;
-
-  /* When save_regs_using_mov is set, emit prologue using
-     move instead of push instructions.  */
-  bool save_regs_using_mov;
-};
-
 /* Which cpu are we scheduling for.  */
 enum attr_cpu ix86_schedule;
 
@@ -2443,7 +2396,7 @@
                                                const_tree);
 static rtx ix86_static_chain (const_tree, bool);
 static int ix86_function_regparm (const_tree, const_tree);
-static void ix86_compute_frame_layout (struct ix86_frame *);
+static void ix86_compute_frame_layout (void);
 static bool ix86_expand_vector_init_one_nonzero (bool, machine_mode,
                                                 rtx, rtx, int);
 static void ix86_add_new_builtins (HOST_WIDE_INT);
@@ -2601,12 +2554,23 @@
   return new pass_insert_vzeroupper (ctxt);
 }
 
-/* Return true if a red-zone is in use.  */
+/* Return true if a red-zone is in use.  We can't use red-zone when
+   there are local indirect jumps, like "indirect_jump" or "tablejump",
+   which jumps to another place in the function, since "call" in the
+   indirect thunk pushes the return address onto stack, destroying
+   red-zone.
+
+   TODO: If we can reserve the first 2 WORDs, for PUSH and, another
+   for CALL, in red-zone, we can allow local indirect jumps with
+   indirect thunk.  */
 
 static inline bool
 ix86_using_red_zone (void)
 {
-  return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
+  return (TARGET_RED_ZONE
+         && !TARGET_64BIT_MS_ABI
+         && (!cfun->machine->has_local_indirect_jump
+             || cfun->machine->indirect_branch_type == indirect_branch_keep));
 }
 
 /* Return a string that documents the current -m options.  The caller is
@@ -5173,6 +5137,88 @@
   ix86_previous_fndecl = NULL_TREE;
 }
 
+/* Set the indirect_branch_type field from the function FNDECL.  */
+
+static void
+ix86_set_indirect_branch_type (tree fndecl)
+{
+  if (cfun->machine->indirect_branch_type == indirect_branch_unset)
+    {
+      tree attr = lookup_attribute ("indirect_branch",
+                                   DECL_ATTRIBUTES (fndecl));
+      if (attr != NULL)
+       {
+         tree args = TREE_VALUE (attr);
+         if (args == NULL)
+           gcc_unreachable ();
+         tree cst = TREE_VALUE (args);
+         if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
+           cfun->machine->indirect_branch_type = indirect_branch_keep;
+         else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
+           cfun->machine->indirect_branch_type = indirect_branch_thunk;
+         else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
+           cfun->machine->indirect_branch_type = indirect_branch_thunk_inline;
+         else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
+           cfun->machine->indirect_branch_type = indirect_branch_thunk_extern;
+         else
+           gcc_unreachable ();
+       }
+      else
+       cfun->machine->indirect_branch_type = ix86_indirect_branch;
+
+      /* -mcmodel=large is not compatible with -mindirect-branch=thunk
+        nor -mindirect-branch=thunk-extern.  */
+      if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
+         && ((cfun->machine->indirect_branch_type
+              == indirect_branch_thunk_extern)
+             || (cfun->machine->indirect_branch_type
+                 == indirect_branch_thunk)))
+       error ("%<-mindirect-branch=%s%> and %<-mcmodel=large%> are not "
+              "compatible",
+              ((cfun->machine->indirect_branch_type
+                == indirect_branch_thunk_extern)
+               ? "thunk-extern" : "thunk"));
+    }
+
+  if (cfun->machine->function_return_type == indirect_branch_unset)
+    {
+      tree attr = lookup_attribute ("function_return",
+                                   DECL_ATTRIBUTES (fndecl));
+      if (attr != NULL)
+       {
+         tree args = TREE_VALUE (attr);
+         if (args == NULL)
+           gcc_unreachable ();
+         tree cst = TREE_VALUE (args);
+         if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
+           cfun->machine->function_return_type = indirect_branch_keep;
+         else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
+           cfun->machine->function_return_type = indirect_branch_thunk;
+         else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
+           cfun->machine->function_return_type = indirect_branch_thunk_inline;
+         else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
+           cfun->machine->function_return_type = indirect_branch_thunk_extern;
+         else
+           gcc_unreachable ();
+       }
+      else
+       cfun->machine->function_return_type = ix86_function_return;
+
+      /* -mcmodel=large is not compatible with -mfunction-return=thunk
+        nor -mfunction-return=thunk-extern.  */
+      if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
+         && ((cfun->machine->function_return_type
+              == indirect_branch_thunk_extern)
+             || (cfun->machine->function_return_type
+                 == indirect_branch_thunk)))
+       error ("%<-mfunction-return=%s%> and %<-mcmodel=large%> are not "
+              "compatible",
+              ((cfun->machine->function_return_type
+                == indirect_branch_thunk_extern)
+               ? "thunk-extern" : "thunk"));
+    }
+}
+
 /* Establish appropriate back-end context for processing the function
    FNDECL.  The argument might be NULL to indicate processing at top
    level, outside of any function scope.  */
@@ -5183,7 +5229,11 @@
      several times in the course of compiling a function, and we don't want to
      slow things down too much or call target_reinit when it isn't safe.  */
   if (fndecl == ix86_previous_fndecl)
-    return;
+    {
+      if (fndecl != NULL_TREE)
+         ix86_set_indirect_branch_type (fndecl);
+      return;
+    }
 
   tree old_tree;
   if (ix86_previous_fndecl == NULL_TREE)
@@ -5200,6 +5250,8 @@
       return;
     }
 
+  ix86_set_indirect_branch_type (fndecl);
+
   tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
   if (new_tree == NULL_TREE)
     new_tree = target_option_default_node;
@@ -9654,8 +9706,6 @@
 bool
 ix86_can_use_return_insn_p (void)
 {
-  struct ix86_frame frame;
-
   if (! reload_completed || frame_pointer_needed)
     return 0;
 
@@ -9664,7 +9714,8 @@
   if (crtl->args.pops_args && crtl->args.size >= 32768)
     return 0;
 
-  ix86_compute_frame_layout (&frame);
+  ix86_compute_frame_layout ();
+  struct ix86_frame &frame = cfun->machine->frame;
   return (frame.stack_pointer_offset == UNITS_PER_WORD
          && (frame.nregs + frame.nsseregs) == 0);
 }
@@ -9729,6 +9780,267 @@
 # endif
 #endif
 
+/* Label count for call and return thunks.  It is used to make unique
+   labels in call and return thunks.  */
+static int indirectlabelno;
+
+/* True if call and return thunk functions are needed.  */
+static bool indirect_thunk_needed = false;
+/* True if call and return thunk functions with the BND prefix are
+   needed.  */
+static bool indirect_thunk_bnd_needed = false;
+
+/* Bit masks of integer registers, which contain branch target, used
+   by call and return thunks functions.  */
+static int indirect_thunks_used;
+/* Bit masks of integer registers, which contain branch target, used
+   by call and return thunks functions with the BND prefix.  */
+static int indirect_thunks_bnd_used;
+
+#ifndef INDIRECT_LABEL
+# define INDIRECT_LABEL "LIND"
+#endif
+



Home | Main Index | Thread Index | Old Index