mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
(cherry picked from commit 328ed39c59)
This commit is contained in:
1 parent
d109962a2a
commit
2aa9922c89
2 files changed
+18
-3
No files matched your search
@@ -209,10 +209,12 @@ static void 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;
|
||||
|
||||
BUG_ON(a->repl_len > total_len);
|
||||
BUG_ON(total_len > sizeof(buf));
|
||||
BUG_ON(a->cpuid >= NCAPINTS * 32);
|
||||
BUG_ON(feat >= NCAPINTS * 32);
|
||||
|
||||
/*
|
||||
* Detect sequences of alt_instr's patching the same origin site, and
|
||||
@@ -235,8 +237,14 @@ static void 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 )
|
||||
|
||||
@@ -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
|
||||
@@ -11,7 +18,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 */
|
||||
|
||||