diff mbox

[v5,2/3] x86/asm: Add suffix macro for GEN_*_RMWcc()

Message ID 1496180392-98718-3-git-send-email-keescook@chromium.org (mailing list archive)
State New, archived
Headers show

Commit Message

Kees Cook May 30, 2017, 9:39 p.m. UTC
The coming x86 refcount protection needs to be able to add trailing
instructions to the GEN_*_RMWcc() operations. This extracts the
difference between the goto/non-goto cases so the helper macros
can be defined outside the #ifdef cases. Additionally adds argument
naming to the resulting asm for referencing from suffixed
instructions, and adds clobbers for "cc", and "cx" to let suffixes
use _ASM_CX, and retain any set flags.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/x86/include/asm/rmwcc.h | 37 ++++++++++++++++++++++++-------------
 1 file changed, 24 insertions(+), 13 deletions(-)

Comments

Peter Zijlstra May 31, 2017, 11:13 a.m. UTC | #1
On Tue, May 30, 2017 at 02:39:51PM -0700, Kees Cook wrote:
> The coming x86 refcount protection needs to be able to add trailing
> instructions to the GEN_*_RMWcc() operations. This extracts the
> difference between the goto/non-goto cases so the helper macros
> can be defined outside the #ifdef cases. Additionally adds argument
> naming to the resulting asm for referencing from suffixed
> instructions, and adds clobbers for "cc", and "cx" to let suffixes
> use _ASM_CX, and retain any set flags.

Another option is to simply require __GCC_ASM_FLAG_OUTPUT__ for the fast
refcount stuff. That would result in simpler and more readable code.
Kees Cook May 31, 2017, 1:17 p.m. UTC | #2
On Wed, May 31, 2017 at 4:13 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Tue, May 30, 2017 at 02:39:51PM -0700, Kees Cook wrote:
>> The coming x86 refcount protection needs to be able to add trailing
>> instructions to the GEN_*_RMWcc() operations. This extracts the
>> difference between the goto/non-goto cases so the helper macros
>> can be defined outside the #ifdef cases. Additionally adds argument
>> naming to the resulting asm for referencing from suffixed
>> instructions, and adds clobbers for "cc", and "cx" to let suffixes
>> use _ASM_CX, and retain any set flags.
>
> Another option is to simply require __GCC_ASM_FLAG_OUTPUT__ for the fast
> refcount stuff. That would result in simpler and more readable code.

What versions of GCC support that?

-Kees
Peter Zijlstra May 31, 2017, 2:03 p.m. UTC | #3
On Wed, May 31, 2017 at 06:17:16AM -0700, Kees Cook wrote:
> On Wed, May 31, 2017 at 4:13 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> > On Tue, May 30, 2017 at 02:39:51PM -0700, Kees Cook wrote:
> >> The coming x86 refcount protection needs to be able to add trailing
> >> instructions to the GEN_*_RMWcc() operations. This extracts the
> >> difference between the goto/non-goto cases so the helper macros
> >> can be defined outside the #ifdef cases. Additionally adds argument
> >> naming to the resulting asm for referencing from suffixed
> >> instructions, and adds clobbers for "cc", and "cx" to let suffixes
> >> use _ASM_CX, and retain any set flags.
> >
> > Another option is to simply require __GCC_ASM_FLAG_OUTPUT__ for the fast
> > refcount stuff. That would result in simpler and more readable code.
> 
> What versions of GCC support that?

IIRC 6+
Kees Cook May 31, 2017, 4:09 p.m. UTC | #4
On Wed, May 31, 2017 at 7:03 AM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Wed, May 31, 2017 at 06:17:16AM -0700, Kees Cook wrote:
>> On Wed, May 31, 2017 at 4:13 AM, Peter Zijlstra <peterz@infradead.org> wrote:
>> > On Tue, May 30, 2017 at 02:39:51PM -0700, Kees Cook wrote:
>> >> The coming x86 refcount protection needs to be able to add trailing
>> >> instructions to the GEN_*_RMWcc() operations. This extracts the
>> >> difference between the goto/non-goto cases so the helper macros
>> >> can be defined outside the #ifdef cases. Additionally adds argument
>> >> naming to the resulting asm for referencing from suffixed
>> >> instructions, and adds clobbers for "cc", and "cx" to let suffixes
>> >> use _ASM_CX, and retain any set flags.
>> >
>> > Another option is to simply require __GCC_ASM_FLAG_OUTPUT__ for the fast
>> > refcount stuff. That would result in simpler and more readable code.
>>
>> What versions of GCC support that?
>
> IIRC 6+

Given how many folks are still using 4.9 (and lower, see the thread
with Arnd[1]), I'd like to just keep this as I have it. It's not much
less readable, IMO (It was already pretty complex). I cleaned it up a
little before making it more ugly, so I think on sum, it's only a
little more weird. I think that's better than making this
compiler-specific or copy/pasting.

-Kees

[1] https://lkml.org/lkml/2017/4/25/66
diff mbox

Patch

diff --git a/arch/x86/include/asm/rmwcc.h b/arch/x86/include/asm/rmwcc.h
index 661dd305694a..045f99211a99 100644
--- a/arch/x86/include/asm/rmwcc.h
+++ b/arch/x86/include/asm/rmwcc.h
@@ -1,45 +1,56 @@ 
 #ifndef _ASM_X86_RMWcc
 #define _ASM_X86_RMWcc
 
+#define __CLOBBERS_MEM		"memory"
+#define __CLOBBERS_MEM_CC_CX	"memory", "cc", "cx"
+
 #if !defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(CC_HAVE_ASM_GOTO)
 
 /* Use asm goto */
 
-#define __GEN_RMWcc(fullop, var, cc, ...)				\
+#define __GEN_RMWcc(fullop, var, cc, clobbers, ...)			\
 do {									\
 	asm_volatile_goto (fullop "; j" #cc " %l[cc_label]"		\
-			: : "m" (var), ## __VA_ARGS__ 			\
-			: "memory" : cc_label);				\
+			: : [counter] "m" (var), ## __VA_ARGS__		\
+			: clobbers : cc_label);				\
 	return 0;							\
 cc_label:								\
 	return 1;							\
 } while (0)
 
-#define GEN_UNARY_RMWcc(op, var, arg0, cc) 				\
-	__GEN_RMWcc(op " " arg0, var, cc)
+#define __BINARY_RMWcc_ARG	" %1, "
 
-#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)			\
-	__GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val))
 
 #else /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CC_HAVE_ASM_GOTO) */
 
 /* Use flags output or a set instruction */
 
-#define __GEN_RMWcc(fullop, var, cc, ...)				\
+#define __GEN_RMWcc(fullop, var, cc, clobbers, ...)			\
 do {									\
 	bool c;								\
 	asm volatile (fullop ";" CC_SET(cc)				\
-			: "+m" (var), CC_OUT(cc) (c)			\
-			: __VA_ARGS__ : "memory");			\
+			: [counter] "+m" (var), CC_OUT(cc) (c)		\
+			: __VA_ARGS__ : clobbers);			\
 	return c;							\
 } while (0)
 
+#define __BINARY_RMWcc_ARG	" %2, "
+
+#endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CC_HAVE_ASM_GOTO) */
+
 #define GEN_UNARY_RMWcc(op, var, arg0, cc)				\
-	__GEN_RMWcc(op " " arg0, var, cc)
+	__GEN_RMWcc(op " " arg0, var, cc, __CLOBBERS_MEM)
+
+#define GEN_UNARY_SUFFIXED_RMWcc(op, suffix, var, arg0, cc)		\
+	__GEN_RMWcc(op " " arg0 "\n\t" suffix, var, cc,			\
+		    __CLOBBERS_MEM_CC_CX)
 
 #define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)			\
-	__GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val))
+	__GEN_RMWcc(op __BINARY_RMWcc_ARG arg0, var, cc,		\
+		    __CLOBBERS_MEM, vcon (val))
 
-#endif /* defined(__GCC_ASM_FLAG_OUTPUTS__) || !defined(CC_HAVE_ASM_GOTO) */
+#define GEN_BINARY_SUFFIXED_RMWcc(op, suffix, var, vcon, val, arg0, cc)	\
+	__GEN_RMWcc(op __BINARY_RMWcc_ARG arg0 "\n\t" suffix, var, cc,	\
+		    __CLOBBERS_MEM_CC_CX, vcon (val))
 
 #endif /* _ASM_X86_RMWcc */