[PATCH 1/3] arm64: alternative: add auto-nop infrastructure

Ard Biesheuvel ard.biesheuvel at linaro.org
Tue Sep 13 01:36:14 PDT 2016


On 7 September 2016 at 11:07, Mark Rutland <mark.rutland at arm.com> wrote:
> In some cases, one side of an alternative sequence is simply a number of
> NOPs used to balance the other side. Keeping track of this manually is
> tedious, and the presence of large chains of NOPs makes the code more
> painful to read than necessary.
>
> To ameliorate matters, this patch adds a new alternative_else_nop_endif,
> which automatically balances an alternative sequence with a trivial NOP
> sled.
>
> In many cases, we would like a NOP-sled in the default case, and
> instructions patched in in the presence of a feature. To enable the NOPs
> to be generated automatically for this case, this patch also adds a new
> alternative_if, and updates alternative_else and alternative_endif to
> work with either alternative_if or alternative_endif.
>
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Andre Przywara <andre.przywara at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Dave Martin <dave.martin at arm.com>
> Cc: James Morse <james.morse at arm.com>
> Cc: Will Deacon <will.deacon at arm.com>
> ---
>  arch/arm64/include/asm/alternative.h | 71 +++++++++++++++++++++++++++---------
>  1 file changed, 54 insertions(+), 17 deletions(-)
>
> diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
> index 8746ff6..4ddbf1c 100644
> --- a/arch/arm64/include/asm/alternative.h
> +++ b/arch/arm64/include/asm/alternative.h
> @@ -90,34 +90,55 @@ void apply_alternatives(void *start, size_t length);
>  .endm
>
>  /*
> - * Begin an alternative code sequence.
> + * Alternative sequences
> + *
> + * The code for the case where the capability is not present will be
> + * assembled and linked as normal. There are no restrictions on this
> + * code.
> + *
> + * The code for the case where the capability is present will be
> + * assembled into a special section to be used for dynamic patching.
> + * Code for that case must:
> + *
> + * 1. Be exactly the same length (in bytes) as the default code
> + *    sequence.
>   *
> - * The code that follows this macro will be assembled and linked as
> - * normal. There are no restrictions on this code.
> + * 2. Not contain a branch target that is used outside of the
> + *    alternative sequence it is defined in (branches into an
> + *    alternative sequence are not fixed up).
> + */
> +
> +/*
> + * Begin an alternative code sequence.
>   */
>  .macro alternative_if_not cap
> +       .set .Lasm_alt_mode, 0

Given that only a single copy of this symbol will exist in an object
file, is it still possible to use both variants in a single
compilation/assembly unit?

>         .pushsection .altinstructions, "a"
>         altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
>         .popsection
>  661:
>  .endm
>
> +.macro alternative_if cap
> +       .set .Lasm_alt_mode, 1
> +       .pushsection .altinstructions, "a"
> +       altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
> +       .popsection
> +       .pushsection .altinstr_replacement, "ax"
> +       .align 2        /* So GAS knows label 661 is suitably aligned */
> +661:
> +.endm
> +
>  /*
> - * Provide the alternative code sequence.
> - *
> - * The code that follows this macro is assembled into a special
> - * section to be used for dynamic patching. Code that follows this
> - * macro must:
> - *
> - * 1. Be exactly the same length (in bytes) as the default code
> - *    sequence.
> - *
> - * 2. Not contain a branch target that is used outside of the
> - *    alternative sequence it is defined in (branches into an
> - *    alternative sequence are not fixed up).
> + * Provide the other half of the alternative code sequence.
>   */
>  .macro alternative_else
> -662:   .pushsection .altinstr_replacement, "ax"
> +662:
> +       .if .Lasm_alt_mode==0
> +       .pushsection .altinstr_replacement, "ax"
> +       .else
> +       .popsection
> +       .endif
>  663:
>  .endm
>
> @@ -125,11 +146,27 @@ void apply_alternatives(void *start, size_t length);
>   * Complete an alternative code sequence.
>   */
>  .macro alternative_endif
> -664:   .popsection
> +664:
> +       .if .Lasm_alt_mode==0
> +       .popsection
> +       .endif
>         .org    . - (664b-663b) + (662b-661b)
>         .org    . - (662b-661b) + (664b-663b)
>  .endm
>
> +/*
> + * Provides a trivial alternative or default sequence consisting solely
> + * of NOPs. The number of NOPs is chosen automatically to match the
> + * previous case.
> + */
> +.macro alternative_else_nop_endif
> +alternative_else
> +.rept (662b-661b) / 4
> +       nop
> +.endr
> +alternative_endif
> +.endm
> +
>  #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...)  \
>         alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
>
> --
> 1.9.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



More information about the linux-arm-kernel mailing list