[PATCH, rs6000] Add -msafe-indirect-jumps option and implement safe bctrl

Bill Schmidt wschmidt@linux.vnet.ibm.com
Sun Jan 14 04:59:00 GMT 2018


Hi, 

This is now superceded by https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01204.html.
Sorry for the noise.

Thanks,
Bill

> On Jan 12, 2018, at 4:33 PM, Bill Schmidt <wschmidt@linux.vnet.ibm.com> wrote:
> 
> Hi,
> 
> This patch adds a new option for the compiler to produce only "safe" indirect
> jumps, in the sense that these jumps are deliberately mispredicted to inhibit
> speculative execution.  For now, this option is undocumented; this may change
> at some future date.  It is intended eventually for the linker to also honor
> this flag when creating PLT stubs, for example.
> 
> In addition to the new option, I've included changes to indirect calls for
> the ELFv2 ABI when the option is specified.  In place of bctrl, we generate
> a seteq followed by a beqctrl-.  Using the CR0.eq bit is safe since CR0 is
> volatile over the call.
> 
> Future patches will address uses of the bctr instruction, which will require
> a virtual condition register, since no assumptions can be made about CR
> availability at bctr locations.
> 
> Bootstrapped and tested on powerpc64le-linux-gnu with no regressions.  Is this
> okay for trunk?
> 
> Thanks,
> Bill
> 
> 
> [gcc]
> 
> 2018-01-12  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
> 
> 	* config/rs6000/rs6000.c (rs6000_opt_vars): Add entry for
> 	safe-indirect-jumps.
> 	* config/rs6000/rs6000.md (*call_indirect_elfv2<mode>): Restrict
> 	to case where -msafe-indirect-jumps is not in effect.
> 	(*call_indirect_elf2<mode>_safe): New define_insn.
> 	(*call_value_indirect_elfv2<mode>): Restrict to case where
> 	-msafe-indirect-jumps is not in effect.
> 	(*call_value_indirect_elfv2<mode>_safe): New define_insn.
> 	* config/rs6000/rs6000.opt (msafe-indirect-jumps): New option.
> 
> [gcc/testsuite]
> 
> 2018-01-12  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
> 
> 	* gcc.target/powerpc/safe-indirect-jump-1.c: New file.
> 
> 
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c	(revision 256364)
> +++ gcc/config/rs6000/rs6000.c	(working copy)
> @@ -36726,6 +36726,9 @@ static struct rs6000_opt_var const rs6000_opt_vars
>   { "sched-epilog",
>     offsetof (struct gcc_options, x_TARGET_SCHED_PROLOG),
>     offsetof (struct cl_target_option, x_TARGET_SCHED_PROLOG), },
> +  { "safe-indirect-jumps",
> +    offsetof (struct gcc_options, x_rs6000_safe_indirect_jumps),
> +    offsetof (struct cl_target_option, x_rs6000_safe_indirect_jumps), },
> };
> 
> /* Inner function to handle attribute((target("..."))) and #pragma GCC target
> Index: gcc/config/rs6000/rs6000.md
> ===================================================================
> --- gcc/config/rs6000/rs6000.md	(revision 256364)
> +++ gcc/config/rs6000/rs6000.md	(working copy)
> @@ -11222,11 +11222,22 @@
> 	 (match_operand 1 "" "g,g"))
>    (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
>    (clobber (reg:P LR_REGNO))]
> -  "DEFAULT_ABI == ABI_ELFv2"
> +  "DEFAULT_ABI == ABI_ELFv2 && !rs6000_safe_indirect_jumps"
>   "b%T0l\;<ptrload> 2,%2(1)"
>   [(set_attr "type" "jmpreg")
>    (set_attr "length" "8")])
> 
> +;; Variant with deliberate misprediction.
> +(define_insn "*call_indirect_elfv2<mode>_safe"
> +  [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
> +	 (match_operand 1 "" "g,g"))
> +   (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
> +   (clobber (reg:P LR_REGNO))]
> +  "DEFAULT_ABI == ABI_ELFv2 && rs6000_safe_indirect_jumps"
> +  "seteq\;beq%T0l-\;<ptrload> 2,%2(1)"
> +  [(set_attr "type" "jmpreg")
> +   (set_attr "length" "12")])
> +
> (define_insn "*call_value_indirect_elfv2<mode>"
>   [(set (match_operand 0 "" "")
> 	(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
> @@ -11233,11 +11244,22 @@
> 	      (match_operand 2 "" "g,g")))
>    (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
>    (clobber (reg:P LR_REGNO))]
> -  "DEFAULT_ABI == ABI_ELFv2"
> +  "DEFAULT_ABI == ABI_ELFv2 && !rs6000_safe_indirect_jumps"
>   "b%T1l\;<ptrload> 2,%3(1)"
>   [(set_attr "type" "jmpreg")
>    (set_attr "length" "8")])
> 
> +; Variant with deliberate misprediction.
> +(define_insn "*call_value_indirect_elfv2<mode>_safe"
> +  [(set (match_operand 0 "" "")
> +	(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
> +	      (match_operand 2 "" "g,g")))
> +   (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
> +   (clobber (reg:P LR_REGNO))]
> +  "DEFAULT_ABI == ABI_ELFv2 && rs6000_safe_indirect_jumps"
> +  "seteq\;beq%T1l-\;<ptrload> 2,%3(1)"
> +  [(set_attr "type" "jmpreg")
> +   (set_attr "length" "12")])
> 
> ;; Call subroutine returning any type.
> (define_expand "untyped_call"
> Index: gcc/config/rs6000/rs6000.opt
> ===================================================================
> --- gcc/config/rs6000/rs6000.opt	(revision 256364)
> +++ gcc/config/rs6000/rs6000.opt	(working copy)
> @@ -617,3 +617,8 @@ Use the given offset for addressing the stack-prot
> 
> TargetVariable
> long rs6000_stack_protector_guard_offset = 0
> +
> +;; -msafe-indirect-jumps adds deliberate misprediction to indirect
> +;; branches via the CTR.
> +msafe-indirect-jumps
> +Target Undocumented Var(rs6000_safe_indirect_jumps) Init(0) Save
> Index: gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c
> ===================================================================
> --- gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c	(nonexistent)
> +++ gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c	(working copy)
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target { powerpc64le-*-* } } } */
> +/* { dg-options "-msafe-indirect-jumps" } */
> +
> +/* Test for deliberate misprediction of indirect calls for ELFv2.  */
> +
> +extern int (*f)();
> +
> +int bar ()
> +{
> +  return (*f) ();
> +}
> +
> +/* { dg-final { scan-assembler "seteq" } } */
> +/* { dg-final { scan-assembler "beqctrl-" } } */
> 



More information about the Gcc-patches mailing list