[PATCH 14/24] x86: Add a type field to alt_instr

From: Peter Zijlstra
Date: Tue Jan 23 2018 - 10:41:58 EST


Add a type field to the alternative description. For now this will be
used to annotate static_cpu_has() but possible future uses include
using it to implement alternative alignment and special NOP handling.

Suggested-by: Borislav Petkov <bp@xxxxxxxxx>
Reviewed-by: Borislav Petkov <bp@xxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
---
arch/x86/include/asm/alternative-asm.h | 3 ++-
arch/x86/include/asm/alternative.h | 6 +++++-
arch/x86/include/asm/cpufeature.h | 2 ++
arch/x86/kernel/alternative.c | 4 ++--
tools/objtool/special.c | 2 +-
5 files changed, 12 insertions(+), 5 deletions(-)

--- a/arch/x86/include/asm/alternative-asm.h
+++ b/arch/x86/include/asm/alternative-asm.h
@@ -25,13 +25,14 @@
* enough information for the alternatives patching code to patch an
* instruction. See apply_alternatives().
*/
-.macro altinstruction_entry orig alt feature orig_len alt_len pad_len
+.macro altinstruction_entry orig alt feature orig_len alt_len pad_len type=0
.long \orig - .
.long \alt - .
.word \feature
.byte \orig_len
.byte \alt_len
.byte \pad_len
+ .byte \type
.endm

/*
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -45,6 +45,8 @@
#define LOCK_PREFIX ""
#endif

+#define ALT_TYPE_DEFAULT 0
+
struct alt_instr {
s32 instr_offset; /* original instruction */
s32 repl_offset; /* offset to replacement instruction */
@@ -52,6 +54,7 @@ struct alt_instr {
u8 instrlen; /* length of original instruction */
u8 replacementlen; /* length of new instruction */
u8 padlen; /* length of build-time padding */
+ u8 type; /* type of alternative */
} __packed;

/*
@@ -127,7 +130,8 @@ static inline int alternatives_text_rese
" .word " __stringify(feature) "\n" /* feature bit */ \
" .byte " alt_total_slen "\n" /* source len */ \
" .byte " alt_rlen(num) "\n" /* replacement len */ \
- " .byte " alt_pad_len "\n" /* pad len */
+ " .byte " alt_pad_len "\n" /* pad len */ \
+ " .byte 0 \n" /* type */

#define ALTINSTR_REPLACEMENT(newinstr, feature, num) /* replacement */ \
b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n\t"
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -157,6 +157,7 @@ static __always_inline __pure bool _stat
" .byte 3b - 1b\n" /* src len */
" .byte 5f - 4f\n" /* repl len */
" .byte 3b - 2b\n" /* pad len */
+ " .byte 0\n" /* type */
".previous\n"
".section .altinstr_replacement,\"ax\"\n"
"4: jmp %l[t_no]\n"
@@ -169,6 +170,7 @@ static __always_inline __pure bool _stat
" .byte 3b - 1b\n" /* src len */
" .byte 0\n" /* repl len */
" .byte 0\n" /* pad len */
+ " .byte 0\n" /* type */
".previous\n"
".section .altinstr_aux,\"ax\"\n"
"6:\n"
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -400,11 +400,11 @@ void __init_or_module noinline apply_alt
continue;
}

- DPRINTK("feat: %d*32+%d, old: (%p, len: %d), repl: (%p, len: %d), pad: %d",
+ DPRINTK("feat: %d*32+%d, old: (%p, len: %d), repl: (%p, len: %d), pad: %d, type: %d",
a->cpuid >> 5,
a->cpuid & 0x1f,
instr, a->instrlen,
- replacement, a->replacementlen, a->padlen);
+ replacement, a->replacementlen, a->padlen, a->type);

DUMP_BYTES(instr, a->instrlen, "%p: old_insn: ", instr);
DUMP_BYTES(replacement, a->replacementlen, "%p: rpl_insn: ", replacement);
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -34,7 +34,7 @@
#define JUMP_ORIG_OFFSET 0
#define JUMP_NEW_OFFSET 8

-#define ALT_ENTRY_SIZE 13
+#define ALT_ENTRY_SIZE 14
#define ALT_ORIG_OFFSET 0
#define ALT_NEW_OFFSET 4
#define ALT_FEATURE_OFFSET 8