|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] x86/alternative: Support replacements when a feature is not present
commit 328ed39c59e0af06d594f5e64a52b57aa0b02340
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:17:38 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>
---
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 43b009888c..4d1bbe7313 100644
--- a/xen/arch/x86/alternative.c
+++ b/xen/arch/x86/alternative.c
@@ -228,6 +228,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 )
{
@@ -245,11 +247,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;
}
@@ -271,8 +273,14 @@ static int init_or_livepatch _apply_alternatives(struct
alt_instr *start,
if ( a->priv )
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 22da9f89f1..3eb0f4e8a0 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 29c3d724b0..b9ea49bd1c 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
@@ -14,7 +21,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 */
@@ -61,7 +68,7 @@ extern void alternative_instructions(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#staging
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |