[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen stable-4.20] x86/alternative: Support replacements when a feature is not present
commit cf818880122c257c6c79506aacc69ee190a1e11e Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> AuthorDate: Mon Apr 21 15:52:56 2025 +0100 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Mon May 12 17:27:09 2025 +0100 x86/alternative: Support replacements when a feature is not present Use the top bit of a->cpuid to express inverted polarity. This requires stripping the top bit back out when performing the sanity checks. Despite only being used once, create a replace boolean to express the decision more clearly in _apply_alternatives(). Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> (cherry picked from commit 328ed39c59e0af06d594f5e64a52b57aa0b02340) --- xen/arch/x86/alternative.c | 14 +++++++++++--- xen/arch/x86/include/asm/alternative-asm.h | 2 +- xen/arch/x86/include/asm/alternative.h | 11 +++++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/alternative.c b/xen/arch/x86/alternative.c index 1ba35cb9ed..88c90044c2 100644 --- a/xen/arch/x86/alternative.c +++ b/xen/arch/x86/alternative.c @@ -197,6 +197,8 @@ static int init_or_livepatch _apply_alternatives(struct alt_instr *start, uint8_t *repl = ALT_REPL_PTR(a); uint8_t buf[MAX_PATCH_LEN]; unsigned int total_len = a->orig_len + a->pad_len; + unsigned int feat = a->cpuid & ~ALT_FLAG_NOT; + bool inv = a->cpuid & ALT_FLAG_NOT, replace; if ( a->repl_len > total_len ) { @@ -214,11 +216,11 @@ static int init_or_livepatch _apply_alternatives(struct alt_instr *start, return -ENOSPC; } - if ( a->cpuid >= NCAPINTS * 32 ) + if ( feat >= NCAPINTS * 32 ) { printk(XENLOG_ERR "Alt for %ps, feature %#x outside of featureset range %#x\n", - ALT_ORIG_PTR(a), a->cpuid, NCAPINTS * 32); + ALT_ORIG_PTR(a), feat, NCAPINTS * 32); return -ERANGE; } @@ -243,8 +245,14 @@ static int init_or_livepatch _apply_alternatives(struct alt_instr *start, continue; } + /* + * Should a replacement be performed? Most replacements have positive + * polarity, but we support negative polarity too. + */ + replace = boot_cpu_has(feat) ^ inv; + /* If there is no replacement to make, see about optimising the nops. */ - if ( !boot_cpu_has(a->cpuid) ) + if ( !replace ) { /* Origin site site already touched? Don't nop anything. */ if ( base->priv ) diff --git a/xen/arch/x86/include/asm/alternative-asm.h b/xen/arch/x86/include/asm/alternative-asm.h index 83e8594f0e..ed3f4cb055 100644 --- a/xen/arch/x86/include/asm/alternative-asm.h +++ b/xen/arch/x86/include/asm/alternative-asm.h @@ -12,7 +12,7 @@ * instruction. See apply_alternatives(). */ .macro altinstruction_entry orig, repl, feature, orig_len, repl_len, pad_len - .if \feature >= NCAPINTS * 32 + .if ((\feature) & ~ALT_FLAG_NOT) >= NCAPINTS * 32 .error "alternative feature outside of featureset range" .endif .long \orig - . diff --git a/xen/arch/x86/include/asm/alternative.h b/xen/arch/x86/include/asm/alternative.h index 38472fb58e..ef63e257ad 100644 --- a/xen/arch/x86/include/asm/alternative.h +++ b/xen/arch/x86/include/asm/alternative.h @@ -1,6 +1,13 @@ #ifndef __X86_ALTERNATIVE_H__ #define __X86_ALTERNATIVE_H__ +/* + * Common to both C and ASM. Express a replacement when a feature is not + * available. + */ +#define ALT_FLAG_NOT (1 << 15) +#define ALT_NOT(x) (ALT_FLAG_NOT | (x)) + #ifdef __ASSEMBLY__ #include <asm/alternative-asm.h> #else @@ -12,7 +19,7 @@ struct __packed alt_instr { int32_t orig_offset; /* original instruction */ int32_t repl_offset; /* offset to replacement instruction */ - uint16_t cpuid; /* cpuid bit set for replacement */ + uint16_t cpuid; /* cpuid bit set for replacement (top bit is polarity) */ uint8_t orig_len; /* length of original instruction */ uint8_t repl_len; /* length of new instruction */ uint8_t pad_len; /* length of build-time padding */ @@ -60,7 +67,7 @@ extern void alternative_branches(void); alt_repl_len(n2)) "-" alt_orig_len) #define ALTINSTR_ENTRY(feature, num) \ - " .if " STR(feature) " >= " STR(NCAPINTS * 32) "\n" \ + " .if (" STR(feature & ~ALT_FLAG_NOT) ") >= " STR(NCAPINTS * 32) "\n" \ " .error \"alternative feature outside of featureset range\"\n" \ " .endif\n" \ " .long .LXEN%=_orig_s - .\n" /* label */ \ -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.20
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |