]>
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 | |
10 | .macro LOCK_PREFIX | |
ceb7b40b | 11 | 672: lock |
9cebed42 | 12 | .pushsection .smp_locks,"a" |
5967ed87 | 13 | .balign 4 |
ceb7b40b | 14 | .long 672b - . |
9cebed42 | 15 | .popsection |
7e02cb94 AB |
16 | .endm |
17 | #else | |
18 | .macro LOCK_PREFIX | |
19 | .endm | |
20 | #endif | |
21 | ||
5b673a48 BP |
22 | /* |
23 | * Issue one struct alt_instr descriptor entry (need to put it into | |
24 | * the section .altinstructions, see below). This entry contains | |
25 | * enough information for the alternatives patching code to patch an | |
26 | * instruction. See apply_alternatives(). | |
27 | */ | |
4332195c | 28 | .macro altinstruction_entry orig alt feature orig_len alt_len pad_len |
59e97e4d AL |
29 | .long \orig - . |
30 | .long \alt - . | |
9072d11d FY |
31 | .word \feature |
32 | .byte \orig_len | |
33 | .byte \alt_len | |
4332195c BP |
34 | .byte \pad_len |
35 | .endm | |
36 | ||
5b673a48 BP |
37 | /* |
38 | * Define an alternative between two instructions. If @feature is | |
39 | * present, early code in apply_alternatives() replaces @oldinstr with | |
40 | * @newinstr. ".skip" directive takes care of proper instruction padding | |
41 | * in case @newinstr is longer than @oldinstr. | |
42 | */ | |
4332195c BP |
43 | .macro ALTERNATIVE oldinstr, newinstr, feature |
44 | 140: | |
45 | \oldinstr | |
46 | 141: | |
47 | .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90 | |
48 | 142: | |
49 | ||
50 | .pushsection .altinstructions,"a" | |
51 | altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b | |
52 | .popsection | |
53 | ||
54 | .pushsection .altinstr_replacement,"ax" | |
55 | 143: | |
56 | \newinstr | |
57 | 144: | |
58 | .popsection | |
59 | .endm | |
60 | ||
dbe4058a BP |
61 | #define old_len 141b-140b |
62 | #define new_len1 144f-143f | |
63 | #define new_len2 145f-144f | |
64 | ||
65 | /* | |
6b32c126 | 66 | * gas compatible max based on the idea from: |
dbe4058a | 67 | * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax |
6b32c126 MK |
68 | * |
69 | * The additional "-" is needed because gas uses a "true" value of -1. | |
dbe4058a BP |
70 | */ |
71 | #define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b))))) | |
72 | ||
5b673a48 BP |
73 | |
74 | /* | |
75 | * Same as ALTERNATIVE macro above but for two alternatives. If CPU | |
76 | * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has | |
77 | * @feature2, it replaces @oldinstr with @feature2. | |
78 | */ | |
4332195c BP |
79 | .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2 |
80 | 140: | |
81 | \oldinstr | |
82 | 141: | |
dbe4058a BP |
83 | .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \ |
84 | (alt_max_short(new_len1, new_len2) - (old_len)),0x90 | |
4332195c BP |
85 | 142: |
86 | ||
87 | .pushsection .altinstructions,"a" | |
88 | altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b | |
89 | altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b | |
90 | .popsection | |
91 | ||
92 | .pushsection .altinstr_replacement,"ax" | |
93 | 143: | |
94 | \newinstr1 | |
95 | 144: | |
96 | \newinstr2 | |
97 | 145: | |
98 | .popsection | |
9072d11d FY |
99 | .endm |
100 | ||
7e02cb94 | 101 | #endif /* __ASSEMBLY__ */ |
76f30759 PA |
102 | |
103 | #endif /* _ASM_X86_ALTERNATIVE_ASM_H */ |