[PATCH v2 2/2] arm64: Work around broken .inst when defective gas is detected

Dave Martin Dave.Martin at arm.com
Tue Dec 6 08:28:26 PST 2016


On Tue, Dec 06, 2016 at 03:27:45PM +0000, Marc Zyngier wrote:
> .inst being largely broken with older binutils, it'd be better not
> to emit it altogether when detecting such configuration (as it
> leads to all kind of horrors when using alternatives).

GAS seems to provide few guarantees about the constantness of anything
other than an expression composed purely of literal constants.  So,
this may rather be lack of a useful feature rather than a bug per se.

> Generalize the __emit_inst macro and use it extensively in
> asm/sysreg.h, and make it generate a .long when a broken gas is
> detected. The disassembly will be crap, but at least we can write
> semi-sane code.

Don't know how much this helps, but if we want decent disassembly then
one option is to use macros instead of symbols, so that the argument to
.inst involves only literals after macro expansion.

Something like:

.ifndef .L__with_reg_defined
	.set .L__with_reg_defined, 1

	.macro __def_reg name, num
		.macro __with_reg__\name instr:vararg
			\instr \num
		.endm
	.endm

	.irp n, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
		__def_reg x\n, \n
	.endr
	__def_reg xzr, 31

	.macro __with_reg regname, instr:vararg
		__with_reg__\regname \instr
	.endm
.endif

.ifndef .L__msr_s_defined
	.set .L__msr_s_defined, 1

	.macro __msr_s sreg, rn
		.inst	0xd5000000 | (\sreg) | (\rn)
	.endm

	.macro msr_s sreg, rn
		__with_reg \rn, __msr_s \sreg,
	.endm
.endif

For the inline asm case, gcc will think that the asm assembles to much
larger code that it really does in this, but I suspect this won't matter
in realistic situations.

For the .S case, we would define the macros once only, in the header (as
at present) -- the guards won't be necessary for that.

Cheers
---Dave

> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
>  arch/arm64/include/asm/sysreg.h | 29 +++++++++++++++++++++++++----
>  1 file changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 9e16a18..98ae03f 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -35,12 +35,33 @@
>  #define sys_reg(op0, op1, crn, crm, op2) \
>  	((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
>  
> +#ifndef CONFIG_BROKEN_GAS_INST
> +
>  #ifdef __ASSEMBLY__
>  #define __emit_inst(x)			.inst (x)
>  #else
>  #define __emit_inst(x)			".inst " __stringify((x)) "\n\t"
>  #endif
>  
> +#else  /* CONFIG_BROKEN_GAS_INST */
> +
> +#ifndef CONFIG_CPU_BIG_ENDIAN
> +#define __INSTR_BSWAP(x)		(x)
> +#else  /* CONFIG_CPU_BIG_ENDIAN */
> +#define __INSTR_BSWAP(x)		((((x) << 24) & 0xff000000)	| \
> +					 (((x) <<  8) & 0x00ff0000)	| \
> +					 (((x) >>  8) & 0x0000ff00)	| \
> +					 (((x) >> 24) & 0x000000ff))
> +#endif	/* CONFIG_CPU_BIG_ENDIAN */
> +
> +#ifdef __ASSEMBLY__
> +#define __emit_inst(x)			.long __INSTR_BSWAP(x)
> +#else  /* __ASSEMBLY__ */
> +#define __emit_inst(x)			".long " __stringify(__INSTR_BSWAP(x)) "\n\t"
> +#endif	/* __ASSEMBLY__ */
> +
> +#endif	/* CONFIG_BROKEN_GAS_INST */
> +
>  #define SYS_MIDR_EL1			sys_reg(3, 0, 0, 0, 0)
>  #define SYS_MPIDR_EL1			sys_reg(3, 0, 0, 0, 5)
>  #define SYS_REVIDR_EL1			sys_reg(3, 0, 0, 0, 6)
> @@ -232,11 +253,11 @@
>  	.equ	.L__reg_num_xzr, 31
>  
>  	.macro	mrs_s, rt, sreg
> -	.inst	0xd5200000|(\sreg)|(.L__reg_num_\rt)
> +	 __emit_inst(0xd5200000|(\sreg)|(.L__reg_num_\rt))
>  	.endm
>  
>  	.macro	msr_s, sreg, rt
> -	.inst	0xd5000000|(\sreg)|(.L__reg_num_\rt)
> +	__emit_inst(0xd5000000|(\sreg)|(.L__reg_num_\rt))
>  	.endm
>  
>  #else
> @@ -250,11 +271,11 @@ asm(
>  "	.equ	.L__reg_num_xzr, 31\n"
>  "\n"
>  "	.macro	mrs_s, rt, sreg\n"
> -"	.inst	0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n"
> +	__emit_inst(0xd5200000|(\\sreg)|(.L__reg_num_\\rt))
>  "	.endm\n"
>  "\n"
>  "	.macro	msr_s, sreg, rt\n"
> -"	.inst	0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n"
> +	__emit_inst(0xd5000000|(\\sreg)|(.L__reg_num_\\rt))
>  "	.endm\n"
>  );
>  
> -- 
> 2.1.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



More information about the linux-arm-kernel mailing list