932ded4b0b
Currently the kernel patches all necessary instructions once at boot time, so modules are not covered by this. Change the apply_alternatives() function to take a beginning and an end pointer and introduce a new variant (apply_alternatives_all()) to cover the existing use case for the static kernel image section. Add a module_finalize() function to arm64 to check for an alternatives section in a module and patch only the instructions from that specific area. Since that module code is not touched before the module initialization has ended, we don't need to halt the machine before doing the patching in the module's code. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
44 lines
1.4 KiB
C
44 lines
1.4 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_all(void);
|
|
void apply_alternatives(void *start, size_t length);
|
|
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 */
|