Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
76f30759 PA |
2 | #ifndef _ASM_X86_ALTERNATIVE_ASM_H |
3 | #define _ASM_X86_ALTERNATIVE_ASM_H | |
4 | ||
7e02cb94 AB |
5 | #ifdef __ASSEMBLY__ |
6 | ||
99063c0b | 7 | #include <asm/asm.h> |
7e02cb94 AB |
8 | |
9 | #ifdef CONFIG_SMP | |
851a4cd7 IM |
10 | .macro LOCK_PREFIX |
11 | 672: lock | |
9cebed42 | 12 | .pushsection .smp_locks,"a" |
5967ed87 | 13 | .balign 4 |
851a4cd7 | 14 | .long 672b - . |
9cebed42 | 15 | .popsection |
851a4cd7 | 16 | .endm |
7e02cb94 | 17 | #else |
851a4cd7 IM |
18 | .macro LOCK_PREFIX |
19 | .endm | |
7e02cb94 AB |
20 | #endif |
21 | ||
ff05ab23 PZ |
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 | ||
5b673a48 BP |
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 | */ | |
4332195c | 39 | .macro altinstruction_entry orig alt feature orig_len alt_len pad_len |
59e97e4d AL |
40 | .long \orig - . |
41 | .long \alt - . | |
9072d11d FY |
42 | .word \feature |
43 | .byte \orig_len | |
44 | .byte \alt_len | |
4332195c BP |
45 | .byte \pad_len |
46 | .endm | |
47 | ||
5b673a48 BP |
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 | */ | |
4332195c BP |
54 | .macro ALTERNATIVE oldinstr, newinstr, feature |
55 | 140: | |
56 | \oldinstr | |
57 | 141: | |
58 | .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90 | |
59 | 142: | |
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" | |
66 | 143: | |
67 | \newinstr | |
68 | 144: | |
69 | .popsection | |
70 | .endm | |
71 | ||
dbe4058a BP |
72 | #define old_len 141b-140b |
73 | #define new_len1 144f-143f | |
74 | #define new_len2 145f-144f | |
75 | ||
76 | /* | |
6b32c126 | 77 | * gas compatible max based on the idea from: |
dbe4058a | 78 | * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax |
6b32c126 MK |
79 | * |
80 | * The additional "-" is needed because gas uses a "true" value of -1. | |
dbe4058a BP |
81 | */ |
82 | #define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b))))) | |
83 | ||
5b673a48 BP |
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 | */ | |
4332195c BP |
90 | .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2 |
91 | 140: | |
92 | \oldinstr | |
93 | 141: | |
dbe4058a BP |
94 | .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \ |
95 | (alt_max_short(new_len1, new_len2) - (old_len)),0x90 | |
4332195c BP |
96 | 142: |
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" | |
104 | 143: | |
105 | \newinstr1 | |
106 | 144: | |
107 | \newinstr2 | |
108 | 145: | |
109 | .popsection | |
9072d11d FY |
110 | .endm |
111 | ||
7e02cb94 | 112 | #endif /* __ASSEMBLY__ */ |
76f30759 PA |
113 | |
114 | #endif /* _ASM_X86_ALTERNATIVE_ASM_H */ |