public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-812] rs6000: Emit ROP-mitigation instructions in prologue and epilogue
@ 2021-05-15 19:05 William Schmidt
  0 siblings, 0 replies; only message in thread
From: William Schmidt @ 2021-05-15 19:05 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:af979a98bce444082cd5fc5d358dcdf3f65fdfce

commit r12-812-gaf979a98bce444082cd5fc5d358dcdf3f65fdfce
Author: Bill Schmidt <wschmidt@linux.ibm.com>
Date:   Fri May 14 14:25:25 2021 -0500

    rs6000: Emit ROP-mitigation instructions in prologue and epilogue
    
    2021-05-14  Bill Schmidt  <wschmidt@linux.ibm.com>
    
    gcc/
            * config/rs6000/rs6000-internal.h (rs6000_stack): Add
            rop_hash_save_offset and rop_hash_size.
            * config/rs6000/rs6000-logue.c (rs6000_stack_info): Compute
            rop_hash_size and rop_hash_save_offset.
            (debug_stack_info): Dump rop_hash_save_offset and rop_hash_size.
            (rs6000_emit_prologue): Emit hashst[p] in prologue.
            (rs6000_emit_epilogue): Emit hashchk[p] in epilogue.
            * config/rs6000/rs6000.md (unspec): Add UNSPEC_HASHST and
            UNSPEC_HASHCHK.
            (hashst): New define_insn.
            (hashchk): Likewise.

Diff:
---
 gcc/config/rs6000/rs6000-internal.h |  2 +
 gcc/config/rs6000/rs6000-logue.c    | 74 +++++++++++++++++++++++++++++++++----
 gcc/config/rs6000/rs6000.md         | 31 ++++++++++++++++
 3 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h
index 428a7861a98..88cf9bd5692 100644
--- a/gcc/config/rs6000/rs6000-internal.h
+++ b/gcc/config/rs6000/rs6000-internal.h
@@ -39,6 +39,7 @@ typedef struct rs6000_stack {
   int gp_save_offset;		/* offset to save GP regs from initial SP */
   int fp_save_offset;		/* offset to save FP regs from initial SP */
   int altivec_save_offset;	/* offset to save AltiVec regs from initial SP */
+  int rop_hash_save_offset;	/* offset to save ROP hash from initial SP */
   int lr_save_offset;		/* offset to save LR from initial SP */
   int cr_save_offset;		/* offset to save CR from initial SP */
   int vrsave_save_offset;	/* offset to save VRSAVE from initial SP */
@@ -53,6 +54,7 @@ typedef struct rs6000_stack {
   int gp_size;			/* size of saved GP registers */
   int fp_size;			/* size of saved FP registers */
   int altivec_size;		/* size of saved AltiVec registers */
+  int rop_hash_size;		/* size of ROP hash slot */
   int cr_size;			/* size to hold CR if not in fixed area */
   int vrsave_size;		/* size to hold VRSAVE */
   int altivec_padding_size;	/* size of altivec alignment padding */
diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c
index b0ac183ceff..13c00e740d6 100644
--- a/gcc/config/rs6000/rs6000-logue.c
+++ b/gcc/config/rs6000/rs6000-logue.c
@@ -595,19 +595,21 @@ rs6000_savres_strategy (rs6000_stack_t *info,
 		+---------------------------------------+
 		| Parameter save area (+padding*) (P)	|  32
 		+---------------------------------------+
-		| Alloca space (A)			|  32+P
+		| Optional ROP hash slot (R)		|  32+P
 		+---------------------------------------+
-		| Local variable space (L)		|  32+P+A
+		| Alloca space (A)			|  32+P+R
 		+---------------------------------------+
-		| Save area for AltiVec registers (W)	|  32+P+A+L
+		| Local variable space (L)		|  32+P+R+A
 		+---------------------------------------+
-		| AltiVec alignment padding (Y)		|  32+P+A+L+W
+		| Save area for AltiVec registers (W)	|  32+P+R+A+L
 		+---------------------------------------+
-		| Save area for GP registers (G)	|  32+P+A+L+W+Y
+		| AltiVec alignment padding (Y)		|  32+P+R+A+L+W
 		+---------------------------------------+
-		| Save area for FP registers (F)	|  32+P+A+L+W+Y+G
+		| Save area for GP registers (G)	|  32+P+R+A+L+W+Y
 		+---------------------------------------+
-	old SP->| back chain to caller's caller		|  32+P+A+L+W+Y+G+F
+		| Save area for FP registers (F)	|  32+P+R+A+L+W+Y+G
+		+---------------------------------------+
+	old SP->| back chain to caller's caller		|  32+P+R+A+L+W+Y+G+F
 		+---------------------------------------+
 
      * If the alloca area is present, the parameter save area is
@@ -716,6 +718,19 @@ rs6000_stack_info (void)
 
   /* Does this function call anything (apart from sibling calls)?  */
   info->calls_p = (!crtl->is_leaf || cfun->machine->ra_needs_full_frame);
+  info->rop_hash_size = 0;
+
+  if (TARGET_POWER10
+      && info->calls_p
+      && DEFAULT_ABI == ABI_ELFv2
+      && rs6000_rop_protect)
+    info->rop_hash_size = 8;
+  else if (rs6000_rop_protect && DEFAULT_ABI != ABI_ELFv2)
+    {
+      /* We can't check this in rs6000_option_override_internal since
+	 DEFAULT_ABI isn't established yet.  */
+      error ("%qs requires the ELFv2 ABI", "-mrop-protect");
+    }
 
   /* Determine if we need to save the condition code registers.  */
   if (save_reg_p (CR2_REGNO)
@@ -808,6 +823,11 @@ rs6000_stack_info (void)
 
 	  /* Adjust for AltiVec case.  */
 	  info->ehrd_offset = info->altivec_save_offset - ehrd_size;
+
+	  /* Adjust for ROP protection.  */
+	  info->rop_hash_save_offset
+	    = info->altivec_save_offset - info->rop_hash_size;
+	  info->ehrd_offset -= info->rop_hash_size;
 	}
       else
 	info->ehrd_offset = info->gp_save_offset - ehrd_size;
@@ -849,6 +869,7 @@ rs6000_stack_info (void)
 				  + info->gp_size
 				  + info->altivec_size
 				  + info->altivec_padding_size
+				  + info->rop_hash_size
 				  + ehrd_size
 				  + ehcr_size
 				  + info->cr_size
@@ -987,6 +1008,10 @@ debug_stack_info (rs6000_stack_t *info)
     fprintf (stderr, "\tvrsave_save_offset  = %5d\n",
 	     info->vrsave_save_offset);
 
+  if (info->rop_hash_size)
+    fprintf (stderr, "\trop_hash_save_offset = %5d\n",
+	     info->rop_hash_save_offset);
+
   if (info->lr_save_p)
     fprintf (stderr, "\tlr_save_offset      = %5d\n", info->lr_save_offset);
 
@@ -1026,6 +1051,9 @@ debug_stack_info (rs6000_stack_t *info)
     fprintf (stderr, "\taltivec_padding_size= %5d\n",
 	     info->altivec_padding_size);
 
+  if (info->rop_hash_size)
+    fprintf (stderr, "\trop_hash_size       = %5d\n", info->rop_hash_size);
+
   if (info->cr_size)
     fprintf (stderr, "\tcr_size             = %5d\n", info->cr_size);
 
@@ -3252,6 +3280,22 @@ rs6000_emit_prologue (void)
 	}
     }
 
+  /* The ROP hash store must occur before a stack frame is created,
+     since the hash operates on r1.  */
+  /* NOTE: The hashst isn't needed if we're going to do a sibcall,
+     but there's no way to know that here.  Harmless except for
+     performance, of course.  */
+  if (TARGET_POWER10 && rs6000_rop_protect && info->rop_hash_size != 0)
+    {
+      gcc_assert (DEFAULT_ABI == ABI_ELFv2);
+      rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+      rtx addr = gen_rtx_PLUS (Pmode, stack_ptr,
+			       GEN_INT (info->rop_hash_save_offset));
+      rtx mem = gen_rtx_MEM (Pmode, addr);
+      rtx reg0 = gen_rtx_REG (Pmode, 0);
+      emit_insn (gen_hashst (mem, reg0));
+    }
+
   /* If we need to save CR, put it into r12 or r11.  Choose r12 except when
      r12 will be needed by out-of-line gpr save.  */
   cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
@@ -4980,6 +5024,22 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type)
       emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
     }
 
+  /* The ROP hash check must occur after the stack pointer is restored
+     (since the hash involves r1), and is not performed for a sibcall.  */
+  if (TARGET_POWER10
+      && rs6000_rop_protect
+      && info->rop_hash_size != 0
+      && epilogue_type != EPILOGUE_TYPE_SIBCALL)
+    {
+      gcc_assert (DEFAULT_ABI == ABI_ELFv2);
+      rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+      rtx addr = gen_rtx_PLUS (Pmode, stack_ptr,
+			       GEN_INT (info->rop_hash_save_offset));
+      rtx mem = gen_rtx_MEM (Pmode, addr);
+      rtx reg0 = gen_rtx_REG (Pmode, 0);
+      emit_insn (gen_hashchk (reg0, mem));
+    }
+
   if (epilogue_type != EPILOGUE_TYPE_SIBCALL && restoring_FPRs_inline)
     {
       if (cfa_restores)
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index c8cdc42533c..0bfeb24d9e8 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -154,6 +154,8 @@
    UNSPEC_CNTTZDM
    UNSPEC_PDEPD
    UNSPEC_PEXTD
+   UNSPEC_HASHST
+   UNSPEC_HASHCHK
   ])
 
 ;;
@@ -14948,6 +14950,35 @@
   "TARGET_P9_MISC && TARGET_64BIT"
   "cmpeqb %0,%1,%2"
   [(set_attr "type" "logical")])
+
+
+;; ROP mitigation instructions.
+
+(define_insn "hashst"
+  [(set (match_operand:DI 0 "simple_offsettable_mem_operand" "=m")
+        (unspec_volatile:DI [(match_operand:DI 1 "int_reg_operand" "r")]
+			    UNSPEC_HASHST))]
+  "TARGET_POWER10 && rs6000_rop_protect"
+{
+  static char templ[32];
+  const char *p = rs6000_privileged ? "p" : "";
+  sprintf (templ, "hashst%s %%1,%%0", p);
+  return templ;
+}
+  [(set_attr "type" "store")])
+
+(define_insn "hashchk"
+  [(unspec_volatile [(match_operand:DI 0 "int_reg_operand" "r")
+		     (match_operand:DI 1 "simple_offsettable_mem_operand" "m")]
+		    UNSPEC_HASHCHK)]
+  "TARGET_POWER10 && rs6000_rop_protect"
+{
+  static char templ[32];
+  const char *p = rs6000_privileged ? "p" : "";
+  sprintf (templ, "hashchk%s %%0,%%1", p);
+  return templ;
+}
+  [(set_attr "type" "load")])
 \f
 
 (include "sync.md")


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-05-15 19:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-15 19:05 [gcc r12-812] rs6000: Emit ROP-mitigation instructions in prologue and epilogue William Schmidt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).