Commit 5d1dd961 authored by Borislav Petkov (AMD)'s avatar Borislav Petkov (AMD)

x86/alternatives: Add alt_instr.flags

Add a struct alt_instr.flags field which will contain different flags
controlling alternatives patching behavior.

The initial idea was to be able to specify it as a separate macro
parameter but that would mean touching all possible invocations of the
alternatives macros and thus a lot of churn.

What is more, as PeterZ suggested, being able to say ALT_NOT(feature) is
very readable and explains exactly what is meant.

So make the feature field a u32 where the patching flags are the upper
u16 part of the dword quantity while the lower u16 word is the feature.

The highest feature number currently is 0x26a (i.e., word 19) so there
is plenty of space. If that becomes insufficient, the field can be
extended to u64 which will then make struct alt_instr of the nice size
of 16 bytes (14 bytes currently).

There should be no functional changes resulting from this.
Suggested-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: default avatarIngo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/Y6RCoJEtxxZWwotd@zn.tnic
parent 1b929c02
This diff is collapsed.
...@@ -282,27 +282,25 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, ...@@ -282,27 +282,25 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
*/ */
for (a = start; a < end; a++) { for (a = start; a < end; a++) {
int insn_buff_sz = 0; int insn_buff_sz = 0;
/* Mask away "NOT" flag bit for feature to test. */
u16 feature = a->cpuid & ~ALTINSTR_FLAG_INV;
instr = (u8 *)&a->instr_offset + a->instr_offset; instr = (u8 *)&a->instr_offset + a->instr_offset;
replacement = (u8 *)&a->repl_offset + a->repl_offset; replacement = (u8 *)&a->repl_offset + a->repl_offset;
BUG_ON(a->instrlen > sizeof(insn_buff)); BUG_ON(a->instrlen > sizeof(insn_buff));
BUG_ON(feature >= (NCAPINTS + NBUGINTS) * 32); BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
/* /*
* Patch if either: * Patch if either:
* - feature is present * - feature is present
* - feature not present but ALTINSTR_FLAG_INV is set to mean, * - feature not present but ALT_FLAG_NOT is set to mean,
* patch if feature is *NOT* present. * patch if feature is *NOT* present.
*/ */
if (!boot_cpu_has(feature) == !(a->cpuid & ALTINSTR_FLAG_INV)) if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT))
goto next; goto next;
DPRINTK("feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d)", DPRINTK("feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d)",
(a->cpuid & ALTINSTR_FLAG_INV) ? "!" : "", (a->flags & ALT_FLAG_NOT) ? "!" : "",
feature >> 5, a->cpuid >> 5,
feature & 0x1f, a->cpuid & 0x1f,
instr, instr, a->instrlen, instr, instr, a->instrlen,
replacement, a->replacementlen); replacement, a->replacementlen);
......
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
#define JUMP_NEW_OFFSET 4 #define JUMP_NEW_OFFSET 4
#define JUMP_KEY_OFFSET 8 #define JUMP_KEY_OFFSET 8
#define ALT_ENTRY_SIZE 12 #define ALT_ENTRY_SIZE 14
#define ALT_ORIG_OFFSET 0 #define ALT_ORIG_OFFSET 0
#define ALT_NEW_OFFSET 4 #define ALT_NEW_OFFSET 4
#define ALT_FEATURE_OFFSET 8 #define ALT_FEATURE_OFFSET 8
#define ALT_ORIG_LEN_OFFSET 10 #define ALT_ORIG_LEN_OFFSET 12
#define ALT_NEW_LEN_OFFSET 11 #define ALT_NEW_LEN_OFFSET 13
#endif /* _X86_ARCH_SPECIAL_H */ #endif /* _X86_ARCH_SPECIAL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment