linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RESEND PATCH] arm64: fix alternatives with LLVM's integrated assembler
@ 2019-10-31 19:46 Sami Tolvanen
  2019-10-31 20:03 ` Kees Cook
  2019-11-14 16:55 ` Will Deacon
  0 siblings, 2 replies; 4+ messages in thread
From: Sami Tolvanen @ 2019-10-31 19:46 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Marc Zyngier
  Cc: Kees Cook, linux-arm-kernel, linux-kernel, clang-built-linux,
	Sami Tolvanen, Nick Desaulniers

LLVM's integrated assembler fails with the following error when
building KVM:

  <inline asm>:12:6: error: expected absolute expression
   .if kvm_update_va_mask == 0
       ^
  <inline asm>:21:6: error: expected absolute expression
   .if kvm_update_va_mask == 0
       ^
  <inline asm>:24:2: error: unrecognized instruction mnemonic
          NOT_AN_INSTRUCTION
          ^
  LLVM ERROR: Error parsing inline asm

These errors come from ALTERNATIVE_CB and __ALTERNATIVE_CFG,
which test for the existence of the callback parameter in inline
assembly using the following expression:

  " .if " __stringify(cb) " == 0\n"

This works with GNU as, but isn't supported by LLVM. This change
splits __ALTERNATIVE_CFG and ALTINSTR_ENTRY into separate macros
to fix the LLVM build.

Link: https://github.com/ClangBuiltLinux/linux/issues/472
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
---
 arch/arm64/include/asm/alternative.h | 32 ++++++++++++++++++----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
index b9f8d787eea9..324e7d5ab37e 100644
--- a/arch/arm64/include/asm/alternative.h
+++ b/arch/arm64/include/asm/alternative.h
@@ -35,13 +35,16 @@ void apply_alternatives_module(void *start, size_t length);
 static inline void apply_alternatives_module(void *start, size_t length) { }
 #endif
 
-#define ALTINSTR_ENTRY(feature,cb)					      \
+#define ALTINSTR_ENTRY(feature)					              \
 	" .word 661b - .\n"				/* label           */ \
-	" .if " __stringify(cb) " == 0\n"				      \
 	" .word 663f - .\n"				/* new instruction */ \
-	" .else\n"							      \
+	" .hword " __stringify(feature) "\n"		/* feature bit     */ \
+	" .byte 662b-661b\n"				/* source len      */ \
+	" .byte 664f-663f\n"				/* replacement len */
+
+#define ALTINSTR_ENTRY_CB(feature, cb)					      \
+	" .word 661b - .\n"				/* label           */ \
 	" .word " __stringify(cb) "- .\n"		/* callback */	      \
-	" .endif\n"							      \
 	" .hword " __stringify(feature) "\n"		/* feature bit     */ \
 	" .byte 662b-661b\n"				/* source len      */ \
 	" .byte 664f-663f\n"				/* replacement len */
@@ -62,15 +65,14 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
  *
  * Alternatives with callbacks do not generate replacement instructions.
  */
-#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled, cb)	\
+#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled)	\
 	".if "__stringify(cfg_enabled)" == 1\n"				\
 	"661:\n\t"							\
 	oldinstr "\n"							\
 	"662:\n"							\
 	".pushsection .altinstructions,\"a\"\n"				\
-	ALTINSTR_ENTRY(feature,cb)					\
+	ALTINSTR_ENTRY(feature)						\
 	".popsection\n"							\
-	" .if " __stringify(cb) " == 0\n"				\
 	".pushsection .altinstr_replacement, \"a\"\n"			\
 	"663:\n\t"							\
 	newinstr "\n"							\
@@ -78,17 +80,25 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
 	".popsection\n\t"						\
 	".org	. - (664b-663b) + (662b-661b)\n\t"			\
 	".org	. - (662b-661b) + (664b-663b)\n"			\
-	".else\n\t"							\
+	".endif\n"
+
+#define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb)	\
+	".if "__stringify(cfg_enabled)" == 1\n"				\
+	"661:\n\t"							\
+	oldinstr "\n"							\
+	"662:\n"							\
+	".pushsection .altinstructions,\"a\"\n"				\
+	ALTINSTR_ENTRY_CB(feature, cb)					\
+	".popsection\n"							\
 	"663:\n\t"							\
 	"664:\n\t"							\
-	".endif\n"							\
 	".endif\n"
 
 #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...)	\
-	__ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg), 0)
+	__ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
 
 #define ALTERNATIVE_CB(oldinstr, cb) \
-	__ALTERNATIVE_CFG(oldinstr, "NOT_AN_INSTRUCTION", ARM64_CB_PATCH, 1, cb)
+	__ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb)
 #else
 
 #include <asm/assembler.h>
-- 
2.24.0.rc0.303.g954a862665-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RESEND PATCH] arm64: fix alternatives with LLVM's integrated assembler
  2019-10-31 19:46 [RESEND PATCH] arm64: fix alternatives with LLVM's integrated assembler Sami Tolvanen
@ 2019-10-31 20:03 ` Kees Cook
  2019-11-14 16:55 ` Will Deacon
  1 sibling, 0 replies; 4+ messages in thread
From: Kees Cook @ 2019-10-31 20:03 UTC (permalink / raw)
  To: Sami Tolvanen
  Cc: Catalin Marinas, Will Deacon, Marc Zyngier, linux-arm-kernel,
	linux-kernel, clang-built-linux, Nick Desaulniers

On Thu, Oct 31, 2019 at 12:46:52PM -0700, Sami Tolvanen wrote:
> LLVM's integrated assembler fails with the following error when
> building KVM:
> 
>   <inline asm>:12:6: error: expected absolute expression
>    .if kvm_update_va_mask == 0
>        ^
>   <inline asm>:21:6: error: expected absolute expression
>    .if kvm_update_va_mask == 0
>        ^
>   <inline asm>:24:2: error: unrecognized instruction mnemonic
>           NOT_AN_INSTRUCTION
>           ^
>   LLVM ERROR: Error parsing inline asm
> 
> These errors come from ALTERNATIVE_CB and __ALTERNATIVE_CFG,
> which test for the existence of the callback parameter in inline
> assembly using the following expression:
> 
>   " .if " __stringify(cb) " == 0\n"
> 
> This works with GNU as, but isn't supported by LLVM. This change
> splits __ALTERNATIVE_CFG and ALTINSTR_ENTRY into separate macros
> to fix the LLVM build.
> 
> Link: https://github.com/ClangBuiltLinux/linux/issues/472
> Signed-off-by: Sami Tolvanen <samitolvanen@google.com>

Reviewed-by: Kees Cook <keescook@chromium.org>

-Kees

> Tested-by: Nick Desaulniers <ndesaulniers@google.com>
> ---
>  arch/arm64/include/asm/alternative.h | 32 ++++++++++++++++++----------
>  1 file changed, 21 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
> index b9f8d787eea9..324e7d5ab37e 100644
> --- a/arch/arm64/include/asm/alternative.h
> +++ b/arch/arm64/include/asm/alternative.h
> @@ -35,13 +35,16 @@ void apply_alternatives_module(void *start, size_t length);
>  static inline void apply_alternatives_module(void *start, size_t length) { }
>  #endif
>  
> -#define ALTINSTR_ENTRY(feature,cb)					      \
> +#define ALTINSTR_ENTRY(feature)					              \
>  	" .word 661b - .\n"				/* label           */ \
> -	" .if " __stringify(cb) " == 0\n"				      \
>  	" .word 663f - .\n"				/* new instruction */ \
> -	" .else\n"							      \
> +	" .hword " __stringify(feature) "\n"		/* feature bit     */ \
> +	" .byte 662b-661b\n"				/* source len      */ \
> +	" .byte 664f-663f\n"				/* replacement len */
> +
> +#define ALTINSTR_ENTRY_CB(feature, cb)					      \
> +	" .word 661b - .\n"				/* label           */ \
>  	" .word " __stringify(cb) "- .\n"		/* callback */	      \
> -	" .endif\n"							      \
>  	" .hword " __stringify(feature) "\n"		/* feature bit     */ \
>  	" .byte 662b-661b\n"				/* source len      */ \
>  	" .byte 664f-663f\n"				/* replacement len */
> @@ -62,15 +65,14 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
>   *
>   * Alternatives with callbacks do not generate replacement instructions.
>   */
> -#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled, cb)	\
> +#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled)	\
>  	".if "__stringify(cfg_enabled)" == 1\n"				\
>  	"661:\n\t"							\
>  	oldinstr "\n"							\
>  	"662:\n"							\
>  	".pushsection .altinstructions,\"a\"\n"				\
> -	ALTINSTR_ENTRY(feature,cb)					\
> +	ALTINSTR_ENTRY(feature)						\
>  	".popsection\n"							\
> -	" .if " __stringify(cb) " == 0\n"				\
>  	".pushsection .altinstr_replacement, \"a\"\n"			\
>  	"663:\n\t"							\
>  	newinstr "\n"							\
> @@ -78,17 +80,25 @@ static inline void apply_alternatives_module(void *start, size_t length) { }
>  	".popsection\n\t"						\
>  	".org	. - (664b-663b) + (662b-661b)\n\t"			\
>  	".org	. - (662b-661b) + (664b-663b)\n"			\
> -	".else\n\t"							\
> +	".endif\n"
> +
> +#define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb)	\
> +	".if "__stringify(cfg_enabled)" == 1\n"				\
> +	"661:\n\t"							\
> +	oldinstr "\n"							\
> +	"662:\n"							\
> +	".pushsection .altinstructions,\"a\"\n"				\
> +	ALTINSTR_ENTRY_CB(feature, cb)					\
> +	".popsection\n"							\
>  	"663:\n\t"							\
>  	"664:\n\t"							\
> -	".endif\n"							\
>  	".endif\n"
>  
>  #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...)	\
> -	__ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg), 0)
> +	__ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
>  
>  #define ALTERNATIVE_CB(oldinstr, cb) \
> -	__ALTERNATIVE_CFG(oldinstr, "NOT_AN_INSTRUCTION", ARM64_CB_PATCH, 1, cb)
> +	__ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb)
>  #else
>  
>  #include <asm/assembler.h>
> -- 
> 2.24.0.rc0.303.g954a862665-goog
> 

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RESEND PATCH] arm64: fix alternatives with LLVM's integrated assembler
  2019-10-31 19:46 [RESEND PATCH] arm64: fix alternatives with LLVM's integrated assembler Sami Tolvanen
  2019-10-31 20:03 ` Kees Cook
@ 2019-11-14 16:55 ` Will Deacon
  2019-11-18 18:31   ` Nick Desaulniers
  1 sibling, 1 reply; 4+ messages in thread
From: Will Deacon @ 2019-11-14 16:55 UTC (permalink / raw)
  To: Sami Tolvanen
  Cc: Catalin Marinas, Marc Zyngier, Kees Cook, linux-arm-kernel,
	linux-kernel, clang-built-linux, Nick Desaulniers

Hi Sami,

Sorry -- I thought I'd already replied to this, but it had actually
slipped through the cracks.

On Thu, Oct 31, 2019 at 12:46:52PM -0700, Sami Tolvanen wrote:
> LLVM's integrated assembler fails with the following error when
> building KVM:
> 
>   <inline asm>:12:6: error: expected absolute expression
>    .if kvm_update_va_mask == 0
>        ^
>   <inline asm>:21:6: error: expected absolute expression
>    .if kvm_update_va_mask == 0
>        ^
>   <inline asm>:24:2: error: unrecognized instruction mnemonic
>           NOT_AN_INSTRUCTION
>           ^
>   LLVM ERROR: Error parsing inline asm
> 
> These errors come from ALTERNATIVE_CB and __ALTERNATIVE_CFG,
> which test for the existence of the callback parameter in inline
> assembly using the following expression:
> 
>   " .if " __stringify(cb) " == 0\n"
> 
> This works with GNU as, but isn't supported by LLVM. This change
> splits __ALTERNATIVE_CFG and ALTINSTR_ENTRY into separate macros
> to fix the LLVM build.

Please could you explain a bit more about the failure and why LLVM's
integrated assembler rejects this? Could we use something like .ifb or
.ifeqs instead?

Thanks,

Will

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RESEND PATCH] arm64: fix alternatives with LLVM's integrated assembler
  2019-11-14 16:55 ` Will Deacon
@ 2019-11-18 18:31   ` Nick Desaulniers
  0 siblings, 0 replies; 4+ messages in thread
From: Nick Desaulniers @ 2019-11-18 18:31 UTC (permalink / raw)
  To: Will Deacon
  Cc: Sami Tolvanen, Catalin Marinas, Marc Zyngier, Kees Cook,
	Linux ARM, LKML, clang-built-linux, Jian Cai

On Thu, Nov 14, 2019 at 8:55 AM Will Deacon <will@kernel.org> wrote:
>
> Hi Sami,
>
> Sorry -- I thought I'd already replied to this, but it had actually
> slipped through the cracks.
>
> On Thu, Oct 31, 2019 at 12:46:52PM -0700, Sami Tolvanen wrote:
> > LLVM's integrated assembler fails with the following error when
> > building KVM:
> >
> >   <inline asm>:12:6: error: expected absolute expression
> >    .if kvm_update_va_mask == 0
> >        ^
> >   <inline asm>:21:6: error: expected absolute expression
> >    .if kvm_update_va_mask == 0
> >        ^
> >   <inline asm>:24:2: error: unrecognized instruction mnemonic
> >           NOT_AN_INSTRUCTION
> >           ^
> >   LLVM ERROR: Error parsing inline asm
> >
> > These errors come from ALTERNATIVE_CB and __ALTERNATIVE_CFG,
> > which test for the existence of the callback parameter in inline
> > assembly using the following expression:
> >
> >   " .if " __stringify(cb) " == 0\n"
> >
> > This works with GNU as, but isn't supported by LLVM. This change
> > splits __ALTERNATIVE_CFG and ALTINSTR_ENTRY into separate macros
> > to fix the LLVM build.
>
> Please could you explain a bit more about the failure and why LLVM's
> integrated assembler rejects this?

There are currently more than one issue with `.if` assembler
directives we're tracking against Clang's integrated assembler
currently, particularly around the handling of special cases related
to "fragments."
Recommended reading:
https://eli.thegreenplace.net/2013/01/03/assembler-relaxation
This particular case looks like the error is related to referring to
section before it has been seen.  My current understanding is that
Clang's integrated assembler is one pass, unlike GAS, so it chokes on
references to symbols it has not yet seen.

> Could we use something like .ifb or
> .ifeqs instead?
>
> Thanks,
>
> Will



-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-11-18 18:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-31 19:46 [RESEND PATCH] arm64: fix alternatives with LLVM's integrated assembler Sami Tolvanen
2019-10-31 20:03 ` Kees Cook
2019-11-14 16:55 ` Will Deacon
2019-11-18 18:31   ` Nick Desaulniers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).