Commit | Line | Data |
---|---|---|
e039ee4e AP |
1 | #ifndef __ASM_ALTERNATIVE_H |
2 | #define __ASM_ALTERNATIVE_H | |
3 | ||
4 | #include <linux/types.h> | |
5 | #include <linux/stddef.h> | |
6 | #include <linux/stringify.h> | |
7 | ||
8 | struct alt_instr { | |
9 | s32 orig_offset; /* offset to original instruction */ | |
10 | s32 alt_offset; /* offset to replacement instruction */ | |
11 | u16 cpufeature; /* cpufeature bit set for replacement */ | |
12 | u8 orig_len; /* size of original instruction(s) */ | |
13 | u8 alt_len; /* size of new instruction(s), <= orig_len */ | |
14 | }; | |
15 | ||
932ded4b AP |
16 | void apply_alternatives_all(void); |
17 | void apply_alternatives(void *start, size_t length); | |
e039ee4e AP |
18 | void free_alternatives_memory(void); |
19 | ||
20 | #define ALTINSTR_ENTRY(feature) \ | |
21 | " .word 661b - .\n" /* label */ \ | |
22 | " .word 663f - .\n" /* new instruction */ \ | |
23 | " .hword " __stringify(feature) "\n" /* feature bit */ \ | |
24 | " .byte 662b-661b\n" /* source len */ \ | |
25 | " .byte 664f-663f\n" /* replacement len */ | |
26 | ||
27 | /* alternative assembly primitive: */ | |
28 | #define ALTERNATIVE(oldinstr, newinstr, feature) \ | |
29 | "661:\n\t" \ | |
30 | oldinstr "\n" \ | |
31 | "662:\n" \ | |
32 | ".pushsection .altinstructions,\"a\"\n" \ | |
33 | ALTINSTR_ENTRY(feature) \ | |
34 | ".popsection\n" \ | |
35 | ".pushsection .altinstr_replacement, \"a\"\n" \ | |
36 | "663:\n\t" \ | |
37 | newinstr "\n" \ | |
38 | "664:\n\t" \ | |
39 | ".popsection\n\t" \ | |
40 | ".if ((664b-663b) != (662b-661b))\n\t" \ | |
41 | " .error \"Alternatives instruction length mismatch\"\n\t"\ | |
42 | ".endif\n" | |
43 | ||
44 | #endif /* __ASM_ALTERNATIVE_H */ |