44 lines
1.3 KiB
C
44 lines
1.3 KiB
C
|
#ifndef __ASM_ALTERNATIVE_H
|
||
|
#define __ASM_ALTERNATIVE_H
|
||
|
|
||
|
#include <linux/types.h>
|
||
|
#include <linux/stddef.h>
|
||
|
#include <linux/stringify.h>
|
||
|
|
||
|
struct alt_instr {
|
||
|
s32 orig_offset; /* offset to original instruction */
|
||
|
s32 alt_offset; /* offset to replacement instruction */
|
||
|
u16 cpufeature; /* cpufeature bit set for replacement */
|
||
|
u8 orig_len; /* size of original instruction(s) */
|
||
|
u8 alt_len; /* size of new instruction(s), <= orig_len */
|
||
|
};
|
||
|
|
||
|
void apply_alternatives(void);
|
||
|
void free_alternatives_memory(void);
|
||
|
|
||
|
#define ALTINSTR_ENTRY(feature) \
|
||
|
" .word 661b - .\n" /* label */ \
|
||
|
" .word 663f - .\n" /* new instruction */ \
|
||
|
" .hword " __stringify(feature) "\n" /* feature bit */ \
|
||
|
" .byte 662b-661b\n" /* source len */ \
|
||
|
" .byte 664f-663f\n" /* replacement len */
|
||
|
|
||
|
/* alternative assembly primitive: */
|
||
|
#define ALTERNATIVE(oldinstr, newinstr, feature) \
|
||
|
"661:\n\t" \
|
||
|
oldinstr "\n" \
|
||
|
"662:\n" \
|
||
|
".pushsection .altinstructions,\"a\"\n" \
|
||
|
ALTINSTR_ENTRY(feature) \
|
||
|
".popsection\n" \
|
||
|
".pushsection .altinstr_replacement, \"a\"\n" \
|
||
|
"663:\n\t" \
|
||
|
newinstr "\n" \
|
||
|
"664:\n\t" \
|
||
|
".popsection\n\t" \
|
||
|
".if ((664b-663b) != (662b-661b))\n\t" \
|
||
|
" .error \"Alternatives instruction length mismatch\"\n\t"\
|
||
|
".endif\n"
|
||
|
|
||
|
#endif /* __ASM_ALTERNATIVE_H */
|