linux/arch/x86/include/asm/alternative-asm.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _ASM_X86_ALTERNATIVE_ASM_H
   3#define _ASM_X86_ALTERNATIVE_ASM_H
   4
   5#ifdef __ASSEMBLY__
   6
   7#include <asm/asm.h>
   8
   9#ifdef CONFIG_SMP
  10        .macro LOCK_PREFIX
  11672:    lock
  12        .pushsection .smp_locks,"a"
  13        .balign 4
  14        .long 672b - .
  15        .popsection
  16        .endm
  17#else
  18        .macro LOCK_PREFIX
  19        .endm
  20#endif
  21
  22/*
  23 * objtool annotation to ignore the alternatives and only consider the original
  24 * instruction(s).
  25 */
  26.macro ANNOTATE_IGNORE_ALTERNATIVE
  27        .Lannotate_\@:
  28        .pushsection .discard.ignore_alts
  29        .long .Lannotate_\@ - .
  30        .popsection
  31.endm
  32
  33/*
  34 * Issue one struct alt_instr descriptor entry (need to put it into
  35 * the section .altinstructions, see below). This entry contains
  36 * enough information for the alternatives patching code to patch an
  37 * instruction. See apply_alternatives().
  38 */
  39.macro altinstruction_entry orig alt feature orig_len alt_len pad_len
  40        .long \orig - .
  41        .long \alt - .
  42        .word \feature
  43        .byte \orig_len
  44        .byte \alt_len
  45        .byte \pad_len
  46.endm
  47
  48/*
  49 * Define an alternative between two instructions. If @feature is
  50 * present, early code in apply_alternatives() replaces @oldinstr with
  51 * @newinstr. ".skip" directive takes care of proper instruction padding
  52 * in case @newinstr is longer than @oldinstr.
  53 */
  54.macro ALTERNATIVE oldinstr, newinstr, feature
  55140:
  56        \oldinstr
  57141:
  58        .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90
  59142:
  60
  61        .pushsection .altinstructions,"a"
  62        altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b
  63        .popsection
  64
  65        .pushsection .altinstr_replacement,"ax"
  66143:
  67        \newinstr
  68144:
  69        .popsection
  70.endm
  71
  72#define old_len                 141b-140b
  73#define new_len1                144f-143f
  74#define new_len2                145f-144f
  75
  76/*
  77 * gas compatible max based on the idea from:
  78 * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
  79 *
  80 * The additional "-" is needed because gas uses a "true" value of -1.
  81 */
  82#define alt_max_short(a, b)     ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
  83
  84
  85/*
  86 * Same as ALTERNATIVE macro above but for two alternatives. If CPU
  87 * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
  88 * @feature2, it replaces @oldinstr with @feature2.
  89 */
  90.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
  91140:
  92        \oldinstr
  93141:
  94        .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \
  95                (alt_max_short(new_len1, new_len2) - (old_len)),0x90
  96142:
  97
  98        .pushsection .altinstructions,"a"
  99        altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b
 100        altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b
 101        .popsection
 102
 103        .pushsection .altinstr_replacement,"ax"
 104143:
 105        \newinstr1
 106144:
 107        \newinstr2
 108145:
 109        .popsection
 110.endm
 111
 112#endif  /*  __ASSEMBLY__  */
 113
 114#endif /* _ASM_X86_ALTERNATIVE_ASM_H */
 115