diff mbox

[v2,1/2] x86: support 2- and 3-way alternatives

Message ID 56B202F902000078000CE038@prv-mh.provo.novell.com
State New, archived
Headers show

Commit Message

Jan Beulich Feb. 3, 2016, 12:39 p.m. UTC
Parts taken from Linux, but implementing the ALTERNATIVE*() macros
recursively to avoid needless redundancy.

Also make the .discard section non-writable (we might even consider
dropping its alloc flag too) and limit the pushing and popping of
sections.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
x86: support 2- and 3-way alternatives

Parts taken from Linux, but implementing the ALTERNATIVE*() macros
recursively to avoid needless redundancy.

Also make the .discard section non-writable (we might even consider
dropping its alloc flag too) and limit the pushing and popping of
sections.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/include/asm-x86/alternative.h
+++ b/xen/include/asm-x86/alternative.h
@@ -46,18 +46,28 @@ extern void alternative_instructions(voi
 #define ALTINSTR_REPLACEMENT(newinstr, feature, number) /* replacement */     \
         b_replacement(number)":\n\t" newinstr "\n" e_replacement(number) ":\n\t"
 
+#define ALTERNATIVE_N(newinstr, feature, number)	\
+        ".pushsection .altinstructions,\"a\"\n"		\
+        ALTINSTR_ENTRY(feature, number)			\
+        ".section .discard,\"a\",@progbits\n"		\
+        DISCARD_ENTRY(number)				\
+        ".section .altinstr_replacement, \"ax\"\n"	\
+        ALTINSTR_REPLACEMENT(newinstr, feature, number)	\
+        ".popsection\n"
+
 /* alternative assembly primitive: */
-#define ALTERNATIVE(oldinstr, newinstr, feature)                        \
-        OLDINSTR(oldinstr)                                              \
-        ".pushsection .altinstructions,\"a\"\n"                         \
-        ALTINSTR_ENTRY(feature, 1)                                      \
-        ".popsection\n"                                                 \
-        ".pushsection .discard,\"aw\",@progbits\n"                      \
-        DISCARD_ENTRY(1)                                                \
-        ".popsection\n"                                                 \
-        ".pushsection .altinstr_replacement, \"ax\"\n"                  \
-        ALTINSTR_REPLACEMENT(newinstr, feature, 1)                      \
-        ".popsection"
+#define ALTERNATIVE(oldinstr, newinstr, feature)			  \
+        OLDINSTR(oldinstr)						  \
+	ALTERNATIVE_N(newinstr, feature, 1)
+
+#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
+        ALTERNATIVE(oldinstr, newinstr1, feature1)			  \
+	ALTERNATIVE_N(newinstr2, feature2, 2)
+
+#define ALTERNATIVE_3(oldinstr, newinstr1, feature1, newinstr2, feature2, \
+		      newinstr3, feature3)				  \
+        ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
+	ALTERNATIVE_N(newinstr3, feature3, 3)
 
 /*
  * Alternative instructions for different CPU types or capabilities.
@@ -93,6 +103,37 @@ extern void alternative_instructions(voi
 	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.
+ * Otherwise, if CPU has feature1, newinstr1 is used.
+ * Otherwise, oldinstr is used.
+ */
+#define alternative_io_2(oldinstr, newinstr1, feature1, newinstr2,	\
+			 feature2, output, 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.
+ * Otherwise, if CPU has feature2, newinstr2 is used.
+ * Otherwise, 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

Comments

Andrew Cooper Feb. 3, 2016, 1:15 p.m. UTC | #1
On 03/02/16 12:39, Jan Beulich wrote:
> Parts taken from Linux, but implementing the ALTERNATIVE*() macros
> recursively to avoid needless redundancy.
>
> Also make the .discard section non-writable (we might even consider
> dropping its alloc flag too) and limit the pushing and popping of
> sections.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

There is quite a lot of whitespace damage and mixed tabs/spaces, but the
content looks ok.

Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Jan Beulich Feb. 3, 2016, 1:24 p.m. UTC | #2
>>> On 03.02.16 at 14:15, <andrew.cooper3@citrix.com> wrote:
> On 03/02/16 12:39, Jan Beulich wrote:
>> Parts taken from Linux, but implementing the ALTERNATIVE*() macros
>> recursively to avoid needless redundancy.
>>
>> Also make the .discard section non-writable (we might even consider
>> dropping its alloc flag too) and limit the pushing and popping of
>> sections.
>>
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> 
> There is quite a lot of whitespace damage and mixed tabs/spaces, but the
> content looks ok.

Damage? Mixture? I've tried to make it all Linux style (as the file was
meant to be) for the changes/additions, but I see I failed for some line
of the macro bodies (just fixed).

> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>

Thanks.

Jan
diff mbox

Patch

--- a/xen/include/asm-x86/alternative.h
+++ b/xen/include/asm-x86/alternative.h
@@ -46,18 +46,28 @@  extern void alternative_instructions(voi
 #define ALTINSTR_REPLACEMENT(newinstr, feature, number) /* replacement */     \
         b_replacement(number)":\n\t" newinstr "\n" e_replacement(number) ":\n\t"
 
+#define ALTERNATIVE_N(newinstr, feature, number)	\
+        ".pushsection .altinstructions,\"a\"\n"		\
+        ALTINSTR_ENTRY(feature, number)			\
+        ".section .discard,\"a\",@progbits\n"		\
+        DISCARD_ENTRY(number)				\
+        ".section .altinstr_replacement, \"ax\"\n"	\
+        ALTINSTR_REPLACEMENT(newinstr, feature, number)	\
+        ".popsection\n"
+
 /* alternative assembly primitive: */
-#define ALTERNATIVE(oldinstr, newinstr, feature)                        \
-        OLDINSTR(oldinstr)                                              \
-        ".pushsection .altinstructions,\"a\"\n"                         \
-        ALTINSTR_ENTRY(feature, 1)                                      \
-        ".popsection\n"                                                 \
-        ".pushsection .discard,\"aw\",@progbits\n"                      \
-        DISCARD_ENTRY(1)                                                \
-        ".popsection\n"                                                 \
-        ".pushsection .altinstr_replacement, \"ax\"\n"                  \
-        ALTINSTR_REPLACEMENT(newinstr, feature, 1)                      \
-        ".popsection"
+#define ALTERNATIVE(oldinstr, newinstr, feature)			  \
+        OLDINSTR(oldinstr)						  \
+	ALTERNATIVE_N(newinstr, feature, 1)
+
+#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
+        ALTERNATIVE(oldinstr, newinstr1, feature1)			  \
+	ALTERNATIVE_N(newinstr2, feature2, 2)
+
+#define ALTERNATIVE_3(oldinstr, newinstr1, feature1, newinstr2, feature2, \
+		      newinstr3, feature3)				  \
+        ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
+	ALTERNATIVE_N(newinstr3, feature3, 3)
 
 /*
  * Alternative instructions for different CPU types or capabilities.
@@ -93,6 +103,37 @@  extern void alternative_instructions(voi
 	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.
+ * Otherwise, if CPU has feature1, newinstr1 is used.
+ * Otherwise, oldinstr is used.
+ */
+#define alternative_io_2(oldinstr, newinstr1, feature1, newinstr2,	\
+			 feature2, output, 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.
+ * Otherwise, if CPU has feature2, newinstr2 is used.
+ * Otherwise, 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