On Sun, 2021-04-25 at 20:50 -0500, Bill Schmidt via Gcc-patches wrote:
> Insert the hashst and hashchk instructions when -mrop-protect has been
> selected.  The encrypted save slot for ROP mitigation is placed
> between the parameter save area and the alloca space (if any;
> otherwise the local variable space).
> 
> Note that ROP-mitigation instructions are currently only provided for
> the ELFv2 ABI.
> 
> 2021-03-25  Bill Schmidt  <wschm...@linux.ibm.com>
> 
> gcc/
>       * config/rs6000/rs6000-internal.h (rs6000_stack): Add
>       rop_check_save_offset and rop_check_size.
>       * config/rs6000/rs6000-logue.c (rs6000_stack_info): Compute
>       rop_check_size and rop_check_save_offset.
>       (debug_stack_info): Dump rop_save_offset and rop_check_size.
>       (rs6000_emit_prologue): Assert if WORLD_SAVE used with
>       -mrop-protect; emit hashst[p] in prologue; emit hashchk[p] in
>       epilogue.
>       * config/rs6000/rs6000.md (unspec): Add UNSPEC_HASHST[P] and
>       UNSPEC_HASHCHK[P].
>       (hashst): New define_insn.
>       (hashstp): Likewise.
>       (hashchk): Likewise.
>       (hashchkp): Likewise.

ok

> ---
>  gcc/config/rs6000/rs6000-internal.h |  2 +
>  gcc/config/rs6000/rs6000-logue.c    | 86 +++++++++++++++++++++++++----
>  gcc/config/rs6000/rs6000.md         | 39 +++++++++++++
>  3 files changed, 116 insertions(+), 11 deletions(-)
> 
> diff --git a/gcc/config/rs6000/rs6000-internal.h 
> b/gcc/config/rs6000/rs6000-internal.h
> index 428a7861a98..8fc77ba6138 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_check_save_offset; /* offset to save ROP check 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_check_size;                /* size of ROP check 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 */

ok

> diff --git a/gcc/config/rs6000/rs6000-logue.c 
> b/gcc/config/rs6000/rs6000-logue.c
> index b0ac183ceff..10cf7a2de93 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 check 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

ok

> @@ -717,6 +719,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);
> 
> +  if (TARGET_POWER10 && info->calls_p
> +      && DEFAULT_ABI == ABI_ELFv2 && rs6000_rop_protect)
> +    info->rop_check_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");
> +      info->rop_check_size = 0;
ok
> +    }
> +  else
> +    info->rop_check_size = 0;
> +
ok

>    /* Determine if we need to save the condition code registers.  */
>    if (save_reg_p (CR2_REGNO)
>        || save_reg_p (CR3_REGNO)
> @@ -806,8 +821,14 @@ rs6000_stack_info (void)
>         gcc_assert (info->altivec_size == 0
>                     || info->altivec_save_offset % 16 == 0);
> 
> -       /* Adjust for AltiVec case.  */
> -       info->ehrd_offset = info->altivec_save_offset - ehrd_size;
> +       if (info->rop_check_size != 0)
> +         {
> +           info->rop_check_save_offset
> +             = info->altivec_save_offset - info->rop_check_size;
> +           info->ehrd_offset = info->rop_check_save_offset - ehrd_size;
> +         }
> +       else
> +         info->ehrd_offset = info->altivec_save_offset - ehrd_size;
ok

>       }
>        else
>       info->ehrd_offset = info->gp_save_offset - ehrd_size;
> @@ -849,6 +870,7 @@ rs6000_stack_info (void)
>                                 + info->gp_size
>                                 + info->altivec_size
>                                 + info->altivec_padding_size
> +                               + info->rop_check_size
>                                 + ehrd_size
>                                 + ehcr_size
>                                 + info->cr_size
> @@ -987,6 +1009,10 @@ debug_stack_info (rs6000_stack_t *info)
>      fprintf (stderr, "\tvrsave_save_offset  = %5d\n",
>            info->vrsave_save_offset);
> 
> +  if (info->rop_check_size)
> +    fprintf (stderr, "\trop_check_save_offset = %5d\n",
> +          info->rop_check_save_offset);
> +

ok

>    if (info->lr_save_p)
>      fprintf (stderr, "\tlr_save_offset      = %5d\n", info->lr_save_offset);
> 
> @@ -1026,6 +1052,9 @@ debug_stack_info (rs6000_stack_t *info)
>      fprintf (stderr, "\taltivec_padding_size= %5d\n",
>            info->altivec_padding_size);
> 
> +  if (info->rop_check_size)
> +    fprintf (stderr, "\trop_check_size      = %5d\n", info->rop_check_size);
> +
>    if (info->cr_size)
>      fprintf (stderr, "\tcr_size             = %5d\n", info->cr_size);
> 
> @@ -3044,7 +3073,6 @@ rs6000_emit_prologue (void)
>       cfun->machine->r2_setup_needed = true;
>      }
> 
> -
>    if (flag_stack_usage_info)
>      current_function_static_stack_size = info->total_size;
> 
> @@ -3105,7 +3133,8 @@ rs6000_emit_prologue (void)
>                 && (!crtl->calls_eh_return
>                     || info->ehrd_offset == -432)
>                 && info->vrsave_save_offset == -224
> -               && info->altivec_save_offset == -416);
> +               && info->altivec_save_offset == -416
> +               && !rs6000_rop_protect);
> 

ok


>        treg = gen_rtx_REG (SImode, 11);
>        emit_move_insn (treg, GEN_INT (-info->total_size));
> @@ -3252,6 +3281,24 @@ rs6000_emit_prologue (void)
>       }
>      }
> 
> +  /* The ROP hash store must occur before a stack frame is created.  */
> +  /* 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_check_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_check_save_offset));
> +      rtx mem = gen_rtx_MEM (Pmode, addr);
> +      rtx reg0 = gen_rtx_REG (Pmode, 0);
> +      if (rs6000_privileged)
> +     emit_insn (gen_hashstp (mem, reg0));
> +      else
> +     emit_insn (gen_hashst (mem, reg0));
> +    }
> +

ok


>    /* 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 +5027,23 @@ 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,
> +     and is not performed for a sibcall.  */
> +  if (TARGET_POWER10 && rs6000_rop_protect && info->rop_check_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_check_save_offset));
> +      rtx mem = gen_rtx_MEM (Pmode, addr);
> +      rtx reg0 = gen_rtx_REG (Pmode, 0);
> +      if (rs6000_privileged)
> +     emit_insn (gen_hashchkp (reg0, mem));
> +      else
> +     emit_insn (gen_hashchk (reg0, mem));
> +    }
> +

ok

>    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..eec2e7532e1 100644
> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -154,6 +154,10 @@ (define_c_enum "unspec"
>     UNSPEC_CNTTZDM
>     UNSPEC_PDEPD
>     UNSPEC_PEXTD
> +   UNSPEC_HASHST
> +   UNSPEC_HASHSTP
> +   UNSPEC_HASHCHK
> +   UNSPEC_HASHCHKP
>    ])
> 
>  ;;
> @@ -14948,6 +14952,41 @@ (define_insn "*cmpeqb_internal"
>    "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:DI [(match_operand:DI 1 "int_reg_operand" "r")]
> +                UNSPEC_HASHST))]
> +  "TARGET_POWER10 && rs6000_rop_protect"
> +  "hashst %1,%0"
> +  [(set_attr "type" "store")])
> +
> +(define_insn "hashstp"
> +  [(set (match_operand:DI 0 "simple_offsettable_mem_operand" "=m")
> +        (unspec:DI [(match_operand:DI 1 "int_reg_operand" "r")]
> +                UNSPEC_HASHSTP))]
> +  "TARGET_POWER10 && rs6000_rop_protect && rs6000_privileged"
> +  "hashstp %1,%0"
> +  [(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"
> +  "hashchk %0,%1"
> +  [(set_attr "type" "load")])
> +
> +(define_insn "hashchkp"
> +  [(unspec_volatile [(match_operand:DI 0 "int_reg_operand" "r")
> +                  (match_operand:DI 1 "simple_offsettable_mem_operand" "m")]
> +                 UNSPEC_HASHCHKP)]
> +  "TARGET_POWER10 && rs6000_rop_protect && rs6000_privileged"
> +  "hashchkp %0,%1"
> +  [(set_attr "type" "load")])

ok


lgtm, 
thanks,
-Will

>  
> 
>  (include "sync.md")

Reply via email to