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