From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: 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>

--- a/xen/arch/x86/alternative.c
+++ b/xen/arch/x86/alternative.c
@@ -164,12 +164,22 @@ void init_or_livepatch apply_alternative
      */
     for ( a = start; a < end; a++ )
     {
+        unsigned int feat = a->cpuid & ~ALT_FLAG_NOT;
+        bool inv = a->cpuid & ALT_FLAG_NOT, replace;
+
         instr = (u8 *)&a->instr_offset + a->instr_offset;
         replacement = (u8 *)&a->repl_offset + a->repl_offset;
         BUG_ON(a->replacementlen > a->instrlen);
         BUG_ON(a->instrlen > sizeof(insnbuf));
-        BUG_ON(a->cpuid >= NCAPINTS * 32);
-        if ( !boot_cpu_has(a->cpuid) )
+        BUG_ON(feat >= NCAPINTS * 32);
+
+        /*
+         * Should a replacement be performed?  Most replacements have positive
+         * polarity, but we support negative polarity too.
+         */
+        replace = boot_cpu_has(feat) ^ inv;
+
+        if ( !replace )
             continue;
 
         memcpy(insnbuf, replacement, a->replacementlen);
--- a/xen/include/asm-x86/alternative.h
+++ b/xen/include/asm-x86/alternative.h
@@ -4,6 +4,13 @@
 #include <asm/alternative-asm.h>
 #include <asm/nops.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))
+
 #ifndef __ASSEMBLY__
 #include <xen/stringify.h>
 #include <xen/types.h>
@@ -11,7 +18,7 @@
 struct alt_instr {
     s32 instr_offset;       /* original instruction */
     s32 repl_offset;        /* offset to replacement instruction */
-    u16 cpuid;              /* cpuid bit set for replacement */
+    u16 cpuid;              /* cpuid bit set for replacement (top bit is polarity) */
     u8  instrlen;           /* length of original instruction */
     u8  replacementlen;     /* length of new instruction, <= instrlen */
 };
