@@ -59,6 +59,39 @@ extern void alternative_instructions(void);
ALTINSTR_REPLACEMENT(newinstr, feature, 1) \
".popsection"
+#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
+ OLDINSTR(oldinstr) \
+ ".pushsection .altinstructions,\"a\"\n" \
+ ALTINSTR_ENTRY(feature1, 1) \
+ ALTINSTR_ENTRY(feature2, 2) \
+ ".popsection\n" \
+ ".pushsection .discard,\"aw\",@progbits\n" \
+ DISCARD_ENTRY(1) \
+ DISCARD_ENTRY(2) \
+ ".popsection\n" \
+ ".pushsection .altinstr_replacement, \"ax\"\n" \
+ ALTINSTR_REPLACEMENT(newinstr1, feature1, 1) \
+ ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \
+ ".popsection"
+
+#define ALTERNATIVE_3(oldinstr, newinstr1, feature1, newinstr2, feature2, \
+ newinstr3, feature3) \
+ OLDINSTR(oldinstr) \
+ ".pushsection .altinstructions,\"a\"\n" \
+ ALTINSTR_ENTRY(feature1, 1) \
+ ALTINSTR_ENTRY(feature2, 2) \
+ ALTINSTR_ENTRY(feature3, 3) \
+ ".popsection\n" \
+ ".pushsection .discard,\"aw\",@progbits\n" \
+ DISCARD_ENTRY(1) \
+ DISCARD_ENTRY(2) \
+ DISCARD_ENTRY(3) \
+ ".popsection\n" \
+ ".pushsection .altinstr_replacement, \"ax\"\n" \
+ ALTINSTR_REPLACEMENT(newinstr1, feature1, 1) \
+ ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \
+ ALTINSTR_REPLACEMENT(newinstr3, feature3, 3) \
+ ".popsection"
/*
* Alternative instructions for different CPU types or capabilities.
*
@@ -93,6 +126,38 @@ extern void alternative_instructions(void);
asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
: output : input)
+/*
+ * This is similar to alternative_io. But it has two features and
+ * respective instructions.
+ *
+ * If CPU has feature2, newinstr2 is used.
+ * if CPU has feature1, newinstr1 is used.
+ * Otherwise, oldinstr is used.
+ */
+
+#define alternative_io_2(oldinstr, newinstr1, feature1, newinstr2, \
+ feature2, out_put, input...) \
+ asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, \
+ newinstr2, feature2) \
+ : output : input)
+
+/*
+ * This is similar to alternative_io. But it has three features and
+ * respective instructions.
+ *
+ * If CPU has feature3, newinstr3 is used.
+ * If CPU has feature2, newinstr2 is used.
+ * if CPU has feature1, newinstr1 is used.
+ * Otherwise, oldinstr is used.
+ */
+
+#define alternative_io_3(oldinstr, newinstr1, feature1, newinstr2, \
+ feature2, newinstr3, feature3, output, \
+ input...) \
+ asm volatile(ALTERNATIVE_3(oldinstr, newinstr1, feature1, \
+ newinstr2, feature2, newinstr3, feature3) \
+ : output : input)
+
/* Use this macro(s) if you need more than one output parameter. */
#define ASM_OUTPUT2(a...) a
Most of the code is porting from linux with some changes. alternative_io_2 replaces old instruction with new instructions based on two features. alternative_io_3 replaces old instruction with new instructions based on three features. Signed-off-by: Shuai Ruan <shuai.ruan@linux.intel.com> --- xen/include/asm-x86/alternative.h | 65 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)