[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