linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
@ 2012-02-28 18:59 Dave Martin
  2012-02-28 18:59 ` [RFC PATCH 1/2] " Dave Martin
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Dave Martin @ 2012-02-28 18:59 UTC (permalink / raw)
  To: linux-arm-kernel

Currently, we have two substantially different dialects of assembly
language in arch/arm/ -- assmbler for .S files (with macros and
definitions from <asm/assembler.h>) and inline asm in .c files
(with macros and definitions from a variety of other places).

There is often a need to define macros to work around missing or
broken assembler features, abstract architectural features and
enable various magical build-time transformations.  Unfortunately,
such macros often have to be implemented twice, since macros that
work for inline asm often don't work (or are sometimes not easily
implementable) for .S files, and vice-versa.


The first patch in this series makes <asm/assembler.h> a viable
place for common declarations to be passed to the assembler, and
also paves the way for splitting out extra declarations which are
not relevant everywhere into separate headers.

The second patch demonstrated how all this might be used in
practice (and is also likely to be needed by the kvm and Xen guys,
based on previous discussion).


To achieve all this, a script arch/arm/tools/asm-header.pl is now
run by the archprepare target, to preprocess
arch/arm/include/asm/*.h.asm.  In these special headers, blocks of
native assembler declarations are transformed as shown below.

Macros defined in such blocks get transformed into something that
is includable in .c or .S files, with the desired effect:

arch/arm/include/asm/some_header.h.asm:

ASM(
stuff
for
the
assembler
)

--- becomes --->

include/generated/asm-some_header.h:

#ifdef __ASSEMBLY__
stuff
for
the
assembler
#else
asm("stuff");
asm("for");
asm("the");
asm("assembler");
#endif

Of course, there may be other, nicer ways of achieving all this...

Comments appreciated.

Cheers
---Dave

Dave Martin (2):
  ARM: assembler: Add uniform assembler framework
  ARM: virt: Add assembler helpers for the Virtualization Extensions

 arch/arm/Makefile                    |    8 +-
 arch/arm/include/asm/arch-virt.h     |    1 +
 arch/arm/include/asm/arch-virt.h.asm |  104 +++++++++++
 arch/arm/include/asm/assembler.h     |  322 +---------------------------------
 arch/arm/include/asm/assembler.h.asm |  323 ++++++++++++++++++++++++++++++++++
 arch/arm/include/asm/opcodes.h       |   80 +--------
 arch/arm/include/asm/opcodes.h.asm   |  191 ++++++++++++++++++++
 arch/arm/tools/Makefile              |    4 +
 arch/arm/tools/asm-header.pl         |   76 ++++++++
 9 files changed, 708 insertions(+), 401 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-virt.h
 create mode 100644 arch/arm/include/asm/arch-virt.h.asm
 create mode 100644 arch/arm/include/asm/assembler.h.asm
 create mode 100644 arch/arm/include/asm/opcodes.h.asm
 create mode 100644 arch/arm/tools/asm-header.pl

--
1.7.4.1

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

* [RFC PATCH 1/2] ARM: assembler: Add uniform assembler framework
  2012-02-28 18:59 [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Dave Martin
@ 2012-02-28 18:59 ` Dave Martin
  2012-02-28 18:59 ` [RFC PATCH 2/2] ARM: virt: Add assembler helpers for the Virtualization Extensions Dave Martin
  2012-02-28 19:24 ` [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Russell King - ARM Linux
  2 siblings, 0 replies; 11+ messages in thread
From: Dave Martin @ 2012-02-28 18:59 UTC (permalink / raw)
  To: linux-arm-kernel

This patch creates a framework for adding common assembler macros
and declarations usable identically by .S files and inline asm.

A preprocessing rule converts special uniform assembler headers
arch/arm/include/*.h.asm into generated headers
include/generates/asm-*.h.  These headers can be included directly
by .c or .S files to get the common macros.

A simple script arch/arm/tools/asm-header.pl converts marked blocks
of assembler declarations appropriately for inclusion in both types
of file.  These blocks can be intermingled with ordinary C
preprocessing directives (and even C content, if that content is
protected with #ifndef __ASSEMBLY__ as is usual for any header in
<asm/>.  This makes it straightforward to write config-dependent
code in the normal way.

<asm/assembler.h> is converted to the new framework by this patch,
so it is now safe to include that header in .c files.  There are no
common declarations yet, but over time many features from this
header could be replaced with common implementations if this looks
worthwhile.  The content is now in
arch/arm/include/asm/assembler.h.asm (which is where maintenance
should be done).

Signed-off-by: Dave Martin <dave.martin@arm.com>
---
 arch/arm/Makefile                    |    8 +-
 arch/arm/include/asm/assembler.h     |  322 +---------------------------------
 arch/arm/include/asm/assembler.h.asm |  323 ++++++++++++++++++++++++++++++++++
 arch/arm/tools/Makefile              |    4 +
 arch/arm/tools/asm-header.pl         |   76 ++++++++
 5 files changed, 411 insertions(+), 322 deletions(-)
 create mode 100644 arch/arm/include/asm/assembler.h.asm
 create mode 100644 arch/arm/tools/asm-header.pl

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1683bfb..9cfef30 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -269,8 +269,14 @@ all:	$(KBUILD_IMAGE)
 
 boot := arch/arm/boot
 
+asm_headers := $(wildcard arch/arm/include/asm/*.h.asm)
+generated_asm_headers := \
+	$(patsubst arch/arm/include/asm/%.h.asm,include/generated/asm-%.h,$(asm_headers))
+
 archprepare:
-	$(Q)$(MAKE) $(build)=arch/arm/tools include/generated/mach-types.h
+	$(Q)$(MAKE) $(build)=arch/arm/tools \
+		include/generated/mach-types.h \
+		$(generated_asm_headers)
 
 # Convert bzImage to zImage
 bzImage: zImage
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 23371b1..7d4458f 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -1,321 +1 @@
-/*
- *  arch/arm/include/asm/assembler.h
- *
- *  Copyright (C) 1996-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  This file contains arm architecture specific defines
- *  for the different processors.
- *
- *  Do not include any C declarations in this file - it is included by
- *  assembler source.
- */
-#ifndef __ASM_ASSEMBLER_H__
-#define __ASM_ASSEMBLER_H__
-
-#ifndef __ASSEMBLY__
-#error "Only include this from assembly code"
-#endif
-
-#include <asm/ptrace.h>
-#include <asm/domain.h>
-
-/*
- * Endian independent macros for shifting bytes within registers.
- */
-#ifndef __ARMEB__
-#define pull            lsr
-#define push            lsl
-#define get_byte_0      lsl #0
-#define get_byte_1	lsr #8
-#define get_byte_2	lsr #16
-#define get_byte_3	lsr #24
-#define put_byte_0      lsl #0
-#define put_byte_1	lsl #8
-#define put_byte_2	lsl #16
-#define put_byte_3	lsl #24
-#else
-#define pull            lsl
-#define push            lsr
-#define get_byte_0	lsr #24
-#define get_byte_1	lsr #16
-#define get_byte_2	lsr #8
-#define get_byte_3      lsl #0
-#define put_byte_0	lsl #24
-#define put_byte_1	lsl #16
-#define put_byte_2	lsl #8
-#define put_byte_3      lsl #0
-#endif
-
-/*
- * Data preload for architectures that support it
- */
-#if __LINUX_ARM_ARCH__ >= 5
-#define PLD(code...)	code
-#else
-#define PLD(code...)
-#endif
-
-/*
- * This can be used to enable code to cacheline align the destination
- * pointer when bulk writing to memory.  Experiments on StrongARM and
- * XScale didn't show this a worthwhile thing to do when the cache is not
- * set to write-allocate (this would need further testing on XScale when WA
- * is used).
- *
- * On Feroceon there is much to gain however, regardless of cache mode.
- */
-#ifdef CONFIG_CPU_FEROCEON
-#define CALGN(code...) code
-#else
-#define CALGN(code...)
-#endif
-
-/*
- * Enable and disable interrupts
- */
-#if __LINUX_ARM_ARCH__ >= 6
-	.macro	disable_irq_notrace
-	cpsid	i
-	.endm
-
-	.macro	enable_irq_notrace
-	cpsie	i
-	.endm
-#else
-	.macro	disable_irq_notrace
-	msr	cpsr_c, #PSR_I_BIT | SVC_MODE
-	.endm
-
-	.macro	enable_irq_notrace
-	msr	cpsr_c, #SVC_MODE
-	.endm
-#endif
-
-	.macro asm_trace_hardirqs_off
-#if defined(CONFIG_TRACE_IRQFLAGS)
-	stmdb   sp!, {r0-r3, ip, lr}
-	bl	trace_hardirqs_off
-	ldmia	sp!, {r0-r3, ip, lr}
-#endif
-	.endm
-
-	.macro asm_trace_hardirqs_on_cond, cond
-#if defined(CONFIG_TRACE_IRQFLAGS)
-	/*
-	 * actually the registers should be pushed and pop'd conditionally, but
-	 * after bl the flags are certainly clobbered
-	 */
-	stmdb   sp!, {r0-r3, ip, lr}
-	bl\cond	trace_hardirqs_on
-	ldmia	sp!, {r0-r3, ip, lr}
-#endif
-	.endm
-
-	.macro asm_trace_hardirqs_on
-	asm_trace_hardirqs_on_cond al
-	.endm
-
-	.macro disable_irq
-	disable_irq_notrace
-	asm_trace_hardirqs_off
-	.endm
-
-	.macro enable_irq
-	asm_trace_hardirqs_on
-	enable_irq_notrace
-	.endm
-/*
- * Save the current IRQ state and disable IRQs.  Note that this macro
- * assumes FIQs are enabled, and that the processor is in SVC mode.
- */
-	.macro	save_and_disable_irqs, oldcpsr
-	mrs	\oldcpsr, cpsr
-	disable_irq
-	.endm
-
-	.macro	save_and_disable_irqs_notrace, oldcpsr
-	mrs	\oldcpsr, cpsr
-	disable_irq_notrace
-	.endm
-
-/*
- * Restore interrupt state previously stored in a register.  We don't
- * guarantee that this will preserve the flags.
- */
-	.macro	restore_irqs_notrace, oldcpsr
-	msr	cpsr_c, \oldcpsr
-	.endm
-
-	.macro restore_irqs, oldcpsr
-	tst	\oldcpsr, #PSR_I_BIT
-	asm_trace_hardirqs_on_cond eq
-	restore_irqs_notrace \oldcpsr
-	.endm
-
-#define USER(x...)				\
-9999:	x;					\
-	.pushsection __ex_table,"a";		\
-	.align	3;				\
-	.long	9999b,9001f;			\
-	.popsection
-
-#ifdef CONFIG_SMP
-#define ALT_SMP(instr...)					\
-9998:	instr
-/*
- * Note: if you get assembler errors from ALT_UP() when building with
- * CONFIG_THUMB2_KERNEL, you almost certainly need to use
- * ALT_SMP( W(instr) ... )
- */
-#define ALT_UP(instr...)					\
-	.pushsection ".alt.smp.init", "a"			;\
-	.long	9998b						;\
-9997:	instr							;\
-	.if . - 9997b != 4					;\
-		.error "ALT_UP() content must assemble to exactly 4 bytes";\
-	.endif							;\
-	.popsection
-#define ALT_UP_B(label)					\
-	.equ	up_b_offset, label - 9998b			;\
-	.pushsection ".alt.smp.init", "a"			;\
-	.long	9998b						;\
-	W(b)	. + up_b_offset					;\
-	.popsection
-#else
-#define ALT_SMP(instr...)
-#define ALT_UP(instr...) instr
-#define ALT_UP_B(label) b label
-#endif
-
-/*
- * Instruction barrier
- */
-	.macro	instr_sync
-#if __LINUX_ARM_ARCH__ >= 7
-	isb
-#elif __LINUX_ARM_ARCH__ == 6
-	mcr	p15, 0, r0, c7, c5, 4
-#endif
-	.endm
-
-/*
- * SMP data memory barrier
- */
-	.macro	smp_dmb mode
-#ifdef CONFIG_SMP
-#if __LINUX_ARM_ARCH__ >= 7
-	.ifeqs "\mode","arm"
-	ALT_SMP(dmb)
-	.else
-	ALT_SMP(W(dmb))
-	.endif
-#elif __LINUX_ARM_ARCH__ == 6
-	ALT_SMP(mcr	p15, 0, r0, c7, c10, 5)	@ dmb
-#else
-#error Incompatible SMP platform
-#endif
-	.ifeqs "\mode","arm"
-	ALT_UP(nop)
-	.else
-	ALT_UP(W(nop))
-	.endif
-#endif
-	.endm
-
-#ifdef CONFIG_THUMB2_KERNEL
-	.macro	setmode, mode, reg
-	mov	\reg, #\mode
-	msr	cpsr_c, \reg
-	.endm
-#else
-	.macro	setmode, mode, reg
-	msr	cpsr_c, #\mode
-	.endm
-#endif
-
-/*
- * STRT/LDRT access macros with ARM and Thumb-2 variants
- */
-#ifdef CONFIG_THUMB2_KERNEL
-
-	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
-9999:
-	.if	\inc == 1
-	\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
-	.elseif	\inc == 4
-	\instr\cond\()\t\().w \reg, [\ptr, #\off]
-	.else
-	.error	"Unsupported inc macro argument"
-	.endif
-
-	.pushsection __ex_table,"a"
-	.align	3
-	.long	9999b, \abort
-	.popsection
-	.endm
-
-	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
-	@ explicit IT instruction needed because of the label
-	@ introduced by the USER macro
-	.ifnc	\cond,al
-	.if	\rept == 1
-	itt	\cond
-	.elseif	\rept == 2
-	ittt	\cond
-	.else
-	.error	"Unsupported rept macro argument"
-	.endif
-	.endif
-
-	@ Slightly optimised to avoid incrementing the pointer twice
-	usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
-	.if	\rept == 2
-	usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
-	.endif
-
-	add\cond \ptr, #\rept * \inc
-	.endm
-
-#else	/* !CONFIG_THUMB2_KERNEL */
-
-	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
-	.rept	\rept
-9999:
-	.if	\inc == 1
-	\instr\cond\()b\()\t \reg, [\ptr], #\inc
-	.elseif	\inc == 4
-	\instr\cond\()\t \reg, [\ptr], #\inc
-	.else
-	.error	"Unsupported inc macro argument"
-	.endif
-
-	.pushsection __ex_table,"a"
-	.align	3
-	.long	9999b, \abort
-	.popsection
-	.endr
-	.endm
-
-#endif	/* CONFIG_THUMB2_KERNEL */
-
-	.macro	strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
-	usracc	str, \reg, \ptr, \inc, \cond, \rept, \abort
-	.endm
-
-	.macro	ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
-	usracc	ldr, \reg, \ptr, \inc, \cond, \rept, \abort
-	.endm
-
-/* Utility macro for declaring string literals */
-	.macro	string name:req, string
-	.type \name , #object
-\name:
-	.asciz "\string"
-	.size \name , . - \name
-	.endm
-
-#endif /* __ASM_ASSEMBLER_H__ */
+#include <generated/asm-assembler.h>
diff --git a/arch/arm/include/asm/assembler.h.asm b/arch/arm/include/asm/assembler.h.asm
new file mode 100644
index 0000000..c1c3bc9
--- /dev/null
+++ b/arch/arm/include/asm/assembler.h.asm
@@ -0,0 +1,323 @@
+/*
+ *  arch/arm/include/asm/assembler.h
+ *
+ *  Copyright (C) 1996-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  This file contains arm architecture specific defines
+ *  for the different processors.
+ *
+ *  Do not include any C declarations in this file - it is included by
+ *  assembler source.
+ */
+#ifndef __ASM_ASSEMBLER_H__
+#define __ASM_ASSEMBLER_H__
+
+#include <asm/ptrace.h>
+#include <asm/domain.h>
+
+#ifdef __ASSEMBLY__
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define pull            lsr
+#define push            lsl
+#define get_byte_0      lsl #0
+#define get_byte_1	lsr #8
+#define get_byte_2	lsr #16
+#define get_byte_3	lsr #24
+#define put_byte_0      lsl #0
+#define put_byte_1	lsl #8
+#define put_byte_2	lsl #16
+#define put_byte_3	lsl #24
+#else
+#define pull            lsl
+#define push            lsr
+#define get_byte_0	lsr #24
+#define get_byte_1	lsr #16
+#define get_byte_2	lsr #8
+#define get_byte_3      lsl #0
+#define put_byte_0	lsl #24
+#define put_byte_1	lsl #16
+#define put_byte_2	lsl #8
+#define put_byte_3      lsl #0
+#endif
+
+/*
+ * Data preload for architectures that support it
+ */
+#if __LINUX_ARM_ARCH__ >= 5
+#define PLD(code...)	code
+#else
+#define PLD(code...)
+#endif
+
+/*
+ * This can be used to enable code to cacheline align the destination
+ * pointer when bulk writing to memory.  Experiments on StrongARM and
+ * XScale didn't show this a worthwhile thing to do when the cache is not
+ * set to write-allocate (this would need further testing on XScale when WA
+ * is used).
+ *
+ * On Feroceon there is much to gain however, regardless of cache mode.
+ */
+#ifdef CONFIG_CPU_FEROCEON
+#define CALGN(code...) code
+#else
+#define CALGN(code...)
+#endif
+
+/*
+ * Enable and disable interrupts
+ */
+#if __LINUX_ARM_ARCH__ >= 6
+	.macro	disable_irq_notrace
+	cpsid	i
+	.endm
+
+	.macro	enable_irq_notrace
+	cpsie	i
+	.endm
+#else
+	.macro	disable_irq_notrace
+	msr	cpsr_c, #PSR_I_BIT | SVC_MODE
+	.endm
+
+	.macro	enable_irq_notrace
+	msr	cpsr_c, #SVC_MODE
+	.endm
+#endif
+
+	.macro asm_trace_hardirqs_off
+#if defined(CONFIG_TRACE_IRQFLAGS)
+	stmdb   sp!, {r0-r3, ip, lr}
+	bl	trace_hardirqs_off
+	ldmia	sp!, {r0-r3, ip, lr}
+#endif
+	.endm
+
+	.macro asm_trace_hardirqs_on_cond, cond
+#if defined(CONFIG_TRACE_IRQFLAGS)
+	/*
+	 * actually the registers should be pushed and pop'd conditionally, but
+	 * after bl the flags are certainly clobbered
+	 */
+	stmdb   sp!, {r0-r3, ip, lr}
+	bl\cond	trace_hardirqs_on
+	ldmia	sp!, {r0-r3, ip, lr}
+#endif
+	.endm
+
+	.macro asm_trace_hardirqs_on
+	asm_trace_hardirqs_on_cond al
+	.endm
+
+	.macro disable_irq
+	disable_irq_notrace
+	asm_trace_hardirqs_off
+	.endm
+
+	.macro enable_irq
+	asm_trace_hardirqs_on
+	enable_irq_notrace
+	.endm
+/*
+ * Save the current IRQ state and disable IRQs.  Note that this macro
+ * assumes FIQs are enabled, and that the processor is in SVC mode.
+ */
+	.macro	save_and_disable_irqs, oldcpsr
+	mrs	\oldcpsr, cpsr
+	disable_irq
+	.endm
+
+	.macro	save_and_disable_irqs_notrace, oldcpsr
+	mrs	\oldcpsr, cpsr
+	disable_irq_notrace
+	.endm
+
+/*
+ * Restore interrupt state previously stored in a register.  We don't
+ * guarantee that this will preserve the flags.
+ */
+	.macro	restore_irqs_notrace, oldcpsr
+	msr	cpsr_c, \oldcpsr
+	.endm
+
+	.macro restore_irqs, oldcpsr
+	tst	\oldcpsr, #PSR_I_BIT
+	asm_trace_hardirqs_on_cond eq
+	restore_irqs_notrace \oldcpsr
+	.endm
+
+#define USER(x...)				\
+9999:	x;					\
+	.pushsection __ex_table,"a";		\
+	.align	3;				\
+	.long	9999b,9001f;			\
+	.popsection
+
+#ifdef CONFIG_SMP
+#define ALT_SMP(instr...)					\
+9998:	instr
+/*
+ * Note: if you get assembler errors from ALT_UP() when building with
+ * CONFIG_THUMB2_KERNEL, you almost certainly need to use
+ * ALT_SMP( W(instr) ... )
+ */
+#define ALT_UP(instr...)					\
+	.pushsection ".alt.smp.init", "a"			;\
+	.long	9998b						;\
+9997:	instr							;\
+	.if . - 9997b != 4					;\
+		.error "ALT_UP() content must assemble to exactly 4 bytes";\
+	.endif							;\
+	.popsection
+#define ALT_UP_B(label)					\
+	.equ	up_b_offset, label - 9998b			;\
+	.pushsection ".alt.smp.init", "a"			;\
+	.long	9998b						;\
+	W(b)	. + up_b_offset					;\
+	.popsection
+#else
+#define ALT_SMP(instr...)
+#define ALT_UP(instr...) instr
+#define ALT_UP_B(label) b label
+#endif
+
+/*
+ * Instruction barrier
+ */
+	.macro	instr_sync
+#if __LINUX_ARM_ARCH__ >= 7
+	isb
+#elif __LINUX_ARM_ARCH__ == 6
+	mcr	p15, 0, r0, c7, c5, 4
+#endif
+	.endm
+
+/*
+ * SMP data memory barrier
+ */
+	.macro	smp_dmb mode
+#ifdef CONFIG_SMP
+#if __LINUX_ARM_ARCH__ >= 7
+	.ifeqs "\mode","arm"
+	ALT_SMP(dmb)
+	.else
+	ALT_SMP(W(dmb))
+	.endif
+#elif __LINUX_ARM_ARCH__ == 6
+	ALT_SMP(mcr	p15, 0, r0, c7, c10, 5)	@ dmb
+#else
+#error Incompatible SMP platform
+#endif
+	.ifeqs "\mode","arm"
+	ALT_UP(nop)
+	.else
+	ALT_UP(W(nop))
+	.endif
+#endif
+	.endm
+
+#ifdef CONFIG_THUMB2_KERNEL
+	.macro	setmode, mode, reg
+	mov	\reg, #\mode
+	msr	cpsr_c, \reg
+	.endm
+#else
+	.macro	setmode, mode, reg
+	msr	cpsr_c, #\mode
+	.endm
+#endif
+
+/*
+ * STRT/LDRT access macros with ARM and Thumb-2 variants
+ */
+#ifdef CONFIG_THUMB2_KERNEL
+
+	.macro	usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
+9999:
+	.if	\inc == 1
+	\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
+	.elseif	\inc == 4
+	\instr\cond\()\t\().w \reg, [\ptr, #\off]
+	.else
+	.error	"Unsupported inc macro argument"
+	.endif
+
+	.pushsection __ex_table,"a"
+	.align	3
+	.long	9999b, \abort
+	.popsection
+	.endm
+
+	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
+	@ explicit IT instruction needed because of the label
+	@ introduced by the USER macro
+	.ifnc	\cond,al
+	.if	\rept == 1
+	itt	\cond
+	.elseif	\rept == 2
+	ittt	\cond
+	.else
+	.error	"Unsupported rept macro argument"
+	.endif
+	.endif
+
+	@ Slightly optimised to avoid incrementing the pointer twice
+	usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
+	.if	\rept == 2
+	usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
+	.endif
+
+	add\cond \ptr, #\rept * \inc
+	.endm
+
+#else	/* !CONFIG_THUMB2_KERNEL */
+
+	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
+	.rept	\rept
+9999:
+	.if	\inc == 1
+	\instr\cond\()b\()\t \reg, [\ptr], #\inc
+	.elseif	\inc == 4
+	\instr\cond\()\t \reg, [\ptr], #\inc
+	.else
+	.error	"Unsupported inc macro argument"
+	.endif
+
+	.pushsection __ex_table,"a"
+	.align	3
+	.long	9999b, \abort
+	.popsection
+	.endr
+	.endm
+
+#endif	/* CONFIG_THUMB2_KERNEL */
+
+	.macro	strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
+	usracc	str, \reg, \ptr, \inc, \cond, \rept, \abort
+	.endm
+
+	.macro	ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
+	usracc	ldr, \reg, \ptr, \inc, \cond, \rept, \abort
+	.endm
+
+/* Utility macro for declaring string literals */
+	.macro	string name:req, string
+	.type \name , #object
+\name:
+	.asciz "\string"
+	.size \name , . - \name
+	.endm
+#endif /* __ASSEMBLY__ */
+
+ASM(
+/* Add common macros for .S files and C inline assembler here */
+)
+
+#endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile
index 635cb18..f0140b6 100644
--- a/arch/arm/tools/Makefile
+++ b/arch/arm/tools/Makefile
@@ -8,3 +8,7 @@ include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
 	@echo '  Generating $@'
 	@mkdir -p $(dir $@)
 	$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
+
+include/generated/asm-%.h: arch/arm/include/asm/%.h.asm
+	@echo '  GEN     $@'
+	$(Q)$(PERL) $(src)/asm-header.pl $< >$@ || { $(RM) $@; /bin/false; }
diff --git a/arch/arm/tools/asm-header.pl b/arch/arm/tools/asm-header.pl
new file mode 100644
index 0000000..dfdc5c5
--- /dev/null
+++ b/arch/arm/tools/asm-header.pl
@@ -0,0 +1,76 @@
+#!/usr/bin/perl
+
+# asm-header.pl -- converts assembler declarations in header files for
+# inclusion via the compiler.
+#
+# Headers intended for processing by this script should be named
+# arch/arm/include/asm/*.h.asm
+#
+# In these headers, blocks between
+#
+# ASM(
+#
+# ...and...
+#
+# )
+#
+# are passed through to the assembler unmodified.  Use ASM() blocks for
+# common assembler declarations and macros to be shared by .S files and
+# inline asm.
+#
+# You can use C preprocessor directives and C macros in such headers,
+# but the content of ASM() blocks will not be preprocessed in any way
+# except for the collapsing of continuation lines.  The assembler will
+# see the content of these blocks unchanged.
+#
+# For every header file arch/arm/include/asm/NAME.h.asm, you should
+# create a proxy header in arch/arm/include/asm/NAME.h which just
+# contains the line:
+#
+# #include <generated/asm-NAME.h>
+#
+# The correct way to make use of the generated header in a source file
+# (.S or .c) is:
+#
+# #include <asm/NAME.h>
+
+use strict;
+
+print <<EOF;
+/*
+ * Do not edit this file.
+ * Header automatically generated from $ARGV[0] by asm-header.pl
+ */
+
+EOF
+
+my $start_match = qr/^ASM\(/;
+my $end_match = qr/^\)/;
+
+while (<>) {
+	if (/$start_match/) {
+		my @asm = ();
+
+		while (<>) {
+			last if /$end_match/;
+			push @asm, $_;
+		}
+
+		for (my $i = 0; $i <= $#asm - 1; $i++) {
+			while ($asm[$i] =~ s/\\\n$//) {
+				$asm[$i] .= ' ' . $asm[$i + 1];
+				splice @asm, $i + 1, 1;
+			}
+		}
+
+		print "#ifdef __ASSEMBLY__\n";
+		print @asm;
+		print "#else /* ! __ASSEMBLY__ */\n";
+		do { s/[\\\"]/\\$&/g; s/.*/asm("$&");/; print } foreach @asm;
+		print "#endif /* ! __ASSEMBLY__ */\n";
+
+		next;
+	}
+
+	print
+}
-- 
1.7.4.1

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

* [RFC PATCH 2/2] ARM: virt: Add assembler helpers for the Virtualization Extensions
  2012-02-28 18:59 [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Dave Martin
  2012-02-28 18:59 ` [RFC PATCH 1/2] " Dave Martin
@ 2012-02-28 18:59 ` Dave Martin
  2012-02-28 19:24 ` [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Russell King - ARM Linux
  2 siblings, 0 replies; 11+ messages in thread
From: Dave Martin @ 2012-02-28 18:59 UTC (permalink / raw)
  To: linux-arm-kernel

For the benefit of hypervisor implementations such as kvm, Xen
etc., this patch adds support for generating code to use the CPU
virtualization extensions.  This allows hypervisor calls to be
inlined without changing the CFLAGS for the whole kernel, as well
as supporting older binutils.

Signed-off-by: Dave Martin <dave.martin@linaro.org>
---
 arch/arm/include/asm/arch-virt.h     |    1 +
 arch/arm/include/asm/arch-virt.h.asm |  104 ++++++++++++++++++
 arch/arm/include/asm/opcodes.h       |   80 +--------------
 arch/arm/include/asm/opcodes.h.asm   |  191 ++++++++++++++++++++++++++++++++++
 4 files changed, 297 insertions(+), 79 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-virt.h
 create mode 100644 arch/arm/include/asm/arch-virt.h.asm
 create mode 100644 arch/arm/include/asm/opcodes.h.asm

diff --git a/arch/arm/include/asm/arch-virt.h b/arch/arm/include/asm/arch-virt.h
new file mode 100644
index 0000000..de077f8
--- /dev/null
+++ b/arch/arm/include/asm/arch-virt.h
@@ -0,0 +1 @@
+#include <generated/asm-arch-virt.h>
diff --git a/arch/arm/include/asm/arch-virt.h.asm b/arch/arm/include/asm/arch-virt.h.asm
new file mode 100644
index 0000000..18f6e0e
--- /dev/null
+++ b/arch/arm/include/asm/arch-virt.h.asm
@@ -0,0 +1,104 @@
+/*
+ * Assembler definitions for the ARM Virtualization Extensions
+ * Copyright (C) 2012 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *
+ * Older assembler versions lack support for some new instruction forms
+ * which are required by the Virtualization Extensions.  These
+ * definitions provide macros allowing the affected instructions to be
+ * generated in such cases.
+ */
+
+#ifndef __ASM_ARCH_VIRT_H
+#define __ASM_ARCH_VIRT_H
+
+#include <asm/opcodes.h>
+
+/*
+ * Special register names defined by the Virtualization Extensions for
+ * MSR/MRS.
+ *
+ * We could define a lot more, but for the hyp mode registers there is
+ * no conveinent architectural workaround for using MSR/MRS to access
+ * them.
+ */
+ASM(
+.equ .L__asm_msr_elr_hyp,	0x01e
+.equ .L__asm_msr_sp_hyp,	0x01f
+)
+
+/*
+ * System instruction definitions for the Virtualization Extensions
+ */
+#ifdef CONFIG_THUMB2_KERNEL
+ASM(
+.macro _hvc imm16=0
+	_instw	0xf7e08000 | (((\imm16 ) & 0xf000) << 4) | ((\imm16 ) & 0xfff)
+.endm
+.macro _eret
+	_instw	0xf3de8f00
+.endm
+.macro _msr reg:req, Rn:req
+	_check_reg _msr, \Rn
+	_check_msr _msr, \reg
+	_instw	0xf3808020 | \
+		((.L__asm_msr_\reg & 0x00f) <<  8)	| \
+		((.L__asm_msr_\reg & 0x030) <<  0)	| \
+		((.L__asm_msr_\reg & 0x100) << 12)	| \
+		.L__asm_reg_\Rn << 16
+.endm
+.macro _mrs Rd:req, reg:req
+	_check_reg _mrs, \Rd
+	_check_msr _mrs, \reg
+	_instw	0xf3e08020 | \
+		((.L__asm_msr_\reg & 0x00f) << 16)	| \
+		((.L__asm_msr_\reg & 0x030) <<  0)	| \
+		((.L__asm_msr_\reg & 0x100) << 12)	| \
+		.L__asm_reg_\Rd << 8
+.endm
+)
+#else /* ! CONFIG_THUMB2_KERNEL */
+ASM(
+.macro _hvc imm16=0
+	_inst	0xe1400070 | (((\imm16 ) & 0xfff0) << 4) | ((\imm16 ) & 0xf)
+.endm
+.macro _eret
+	_inst	0xe160006e
+.endm
+.macro _msr reg:req, Rn:req
+	_check_reg _msr, \Rn
+	_check_msr _msr, \reg
+	_inst	0xe120f200 | \
+		((.L__asm_msr_\reg & 0x00f) << 16)	| \
+		((.L__asm_msr_\reg & 0x030) <<  4)	| \
+		((.L__asm_msr_\reg & 0x100) << 14)	| \
+		.L__asm_reg_\Rn
+.endm
+.macro _mrs Rd:req, reg:req
+	_check_reg _mrs, \Rd
+	_check_msr _mrs, \reg
+	_inst	0xe1000200 | \
+		((.L__asm_msr_\reg & 0x00f) << 16)	| \
+		((.L__asm_msr_\reg & 0x030) <<  4)	| \
+		((.L__asm_msr_\reg & 0x100) << 14)	| \
+		.L__asm_reg_\Rd << 12
+.endm
+)
+#endif /* ! CONFIG_THUMB2_KERNEL */
+
+#endif /* ! __ASM_ARCH_VIRT_H */
+
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index 19c48de..4be04fc 100644
--- a/arch/arm/include/asm/opcodes.h
+++ b/arch/arm/include/asm/opcodes.h
@@ -1,79 +1 @@
-/*
- *  arch/arm/include/asm/opcodes.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARM_OPCODES_H
-#define __ASM_ARM_OPCODES_H
-
-#ifndef __ASSEMBLY__
-extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
-#endif
-
-#define ARM_OPCODE_CONDTEST_FAIL   0
-#define ARM_OPCODE_CONDTEST_PASS   1
-#define ARM_OPCODE_CONDTEST_UNCOND 2
-
-
-/*
- * Opcode byteswap helpers
- *
- * These macros help with converting instructions between a canonical integer
- * format and in-memory representation, in an endianness-agnostic manner.
- *
- * __mem_to_opcode_*() convert from in-memory representation to canonical form.
- * __opcode_to_mem_*() convert from canonical form to in-memory representation.
- *
- *
- * Canonical instruction representation:
- *
- *	ARM:		0xKKLLMMNN
- *	Thumb 16-bit:	0x0000KKLL, where KK < 0xE8
- *	Thumb 32-bit:	0xKKLLMMNN, where KK >= 0xE8
- *
- * There is no way to distinguish an ARM instruction in canonical representation
- * from a Thumb instruction (just as these cannot be distinguished in memory).
- * Where this distinction is important, it needs to be tracked separately.
- *
- * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
- * represent any valid Thumb-2 instruction.  For this range,
- * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
- */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-#include <linux/swab.h>
-
-#ifdef CONFIG_CPU_ENDIAN_BE8
-#define __opcode_to_mem_arm(x) swab32(x)
-#define __opcode_to_mem_thumb16(x) swab16(x)
-#define __opcode_to_mem_thumb32(x) swahb32(x)
-#else
-#define __opcode_to_mem_arm(x) ((u32)(x))
-#define __opcode_to_mem_thumb16(x) ((u16)(x))
-#define __opcode_to_mem_thumb32(x) swahw32(x)
-#endif
-
-#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
-#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
-#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
-
-/* Operations specific to Thumb opcodes */
-
-/* Instruction size checks: */
-#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
-#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
-
-/* Operations to construct or split 32-bit Thumb instructions: */
-#define __opcode_thumb32_first(x) ((u16)((x) >> 16))
-#define __opcode_thumb32_second(x) ((u16)(x))
-#define __opcode_thumb32_compose(first, second) \
-	(((u32)(u16)(first) << 16) | (u32)(u16)(second))
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_OPCODES_H */
+#include <generated/asm-opcodes.h>
diff --git a/arch/arm/include/asm/opcodes.h.asm b/arch/arm/include/asm/opcodes.h.asm
new file mode 100644
index 0000000..acc4c0e
--- /dev/null
+++ b/arch/arm/include/asm/opcodes.h.asm
@@ -0,0 +1,191 @@
+/*
+ *  arch/arm/include/asm/opcodes.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARM_OPCODES_H
+#define __ASM_ARM_OPCODES_H
+
+#ifndef __ASSEMBLY__
+extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
+#endif
+
+#define ARM_OPCODE_CONDTEST_FAIL   0
+#define ARM_OPCODE_CONDTEST_PASS   1
+#define ARM_OPCODE_CONDTEST_UNCOND 2
+
+
+/*
+ * Opcode byteswap helpers
+ *
+ * These macros help with converting instructions between a canonical integer
+ * format and in-memory representation, in an endianness-agnostic manner.
+ *
+ * __mem_to_opcode_*() convert from in-memory representation to canonical form.
+ * __opcode_to_mem_*() convert from canonical form to in-memory representation.
+ *
+ *
+ * Canonical instruction representation:
+ *
+ *	ARM:		0xKKLLMMNN
+ *	Thumb 16-bit:	0x0000KKLL, where KK < 0xE8
+ *	Thumb 32-bit:	0xKKLLMMNN, where KK >= 0xE8
+ *
+ * There is no way to distinguish an ARM instruction in canonical representation
+ * from a Thumb instruction (just as these cannot be distinguished in memory).
+ * Where this distinction is important, it needs to be tracked separately.
+ *
+ * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
+ * represent any valid Thumb-2 instruction.  For this range,
+ * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/swab.h>
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define __opcode_to_mem_arm(x) swab32(x)
+#define __opcode_to_mem_thumb16(x) swab16(x)
+#define __opcode_to_mem_thumb32(x) swahb32(x)
+#else
+#define __opcode_to_mem_arm(x) ((u32)(x))
+#define __opcode_to_mem_thumb16(x) ((u16)(x))
+#define __opcode_to_mem_thumb32(x) swahw32(x)
+#endif
+
+#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
+#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
+#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
+
+/* Operations specific to Thumb opcodes */
+
+/* Instruction size checks: */
+#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
+#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
+
+/* Operations to construct or split 32-bit Thumb instructions: */
+#define __opcode_thumb32_first(x) ((u16)((x) >> 16))
+#define __opcode_thumb32_second(x) ((u16)(x))
+#define __opcode_thumb32_compose(first, second) \
+	(((u32)(u16)(first) << 16) | (u32)(u16)(second))
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Assembler declarations and helpers for defining macros to emit
+ * instruction opcodes:
+ */
+ASM(
+.equ .L__asm_reg_r0,	0
+.equ .L__asm_reg_r1,	1
+.equ .L__asm_reg_r2,	2
+.equ .L__asm_reg_r3,	3
+.equ .L__asm_reg_r4,	4
+.equ .L__asm_reg_r5,	5
+.equ .L__asm_reg_r6,	6
+.equ .L__asm_reg_r7,	7
+.equ .L__asm_reg_r8,	8
+.equ .L__asm_reg_r9,	9
+.equ .L__asm_reg_r10,	10
+.equ .L__asm_reg_r11,	11
+.equ .L__asm_reg_r12,	12
+.equ .L__asm_reg_ip,	12
+.equ .L__asm_reg_r13,	13
+.equ .L__asm_reg_sp,	13
+.equ .L__asm_reg_r14,	14
+.equ .L__asm_reg_lr,	14
+.equ .L__asm_reg_r15,	15
+.equ .L__asm_reg_pc,	15
+
+@ _check_reg: Fail assembly with a human-readable error if reg is not a known
+@ general-purpose register name:
+
+.macro _check_reg where:req, reg:req
+	.ifndef .L__asm_reg_\reg
+		.error "\where\(): \"\reg\": general-purpose register expected"
+	.endif
+.endm
+
+@ _check_msr: Fail assembler with a human-readable error if reg is not a
+@ known special register name accessible via MSR/MRS
+
+@ No actual register names are defined here, since without the ARM
+@ Virtualization Extensions, the only special registers and CPSR and
+@ SPSR.  For those, you should use the real MRS/MSR instruction
+@ mnemonics, not some helper macro.
+
+.macro _check_msr where:req, reg:req
+	.ifndef .L__asm_msr_\reg
+		.error "\where\(): \"\reg\": special register expected"
+	.endif
+.endm
+)
+
+/*
+ * _inst*: emit a single instruction opcode:
+ *
+ * _inst <opcode>	emit a (32-bit) ARM opcode
+ * _instn <opcode>	emit a 16-bit Thumb opcode
+ * _instw <opcode>	emit a 32-bit Thumb opcode (in canonical form)
+ *
+ * _instw and _inst are deliberately not interchangeable.  If you
+ * are emitting opcodes, you WILL need to write special-case code
+ * for ARM and Thumb kernels.
+ *
+ * Newer versions of the assembler also have .inst, .inst.n, .inst.w
+ * which achieve the same thing, but for now we shouldn't assume that
+ * everyone has those tools.
+ */
+#ifdef CONFIG_THUMB2_KERNEL
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+ASM(
+.macro _instn opcode:req
+	.short \
+		(((\opcode ) << 8) & 0xff00) | \
+		(((\opcode ) >> 8) & 0x00ff)
+.endm
+)
+#else
+ASM(
+.macro _instn opcode:req
+	.short	\opcode
+.endm
+)
+#endif
+
+ASM(
+.macro _instw opcode:req
+	_instn	((\opcode ) >> 16) & 0xffff
+	_instn	(\opcode ) & 0xffff
+.endm
+)
+
+#else /* ! CONFIG_THUMB2_KERNEL */
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+ASM(
+.macro _inst opcode:req
+	.long \
+		(((\opcode ) << 24) & 0xff000000) | \
+		(((\opcode ) <<  8) & 0x00ff0000) | \
+		(((\opcode ) >>  8) & 0x0000ff00) | \
+		(((\opcode ) >> 24) & 0x000000ff)
+.endm
+)
+#else
+ASM(
+.macro _inst opcode:req
+	.long	\opcode
+.endm
+)
+#endif
+
+#endif /* ! CONFIG_THUMB2_KERNEL */
+
+#endif /* __ASM_ARM_OPCODES_H */
-- 
1.7.4.1

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

* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
  2012-02-28 18:59 [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Dave Martin
  2012-02-28 18:59 ` [RFC PATCH 1/2] " Dave Martin
  2012-02-28 18:59 ` [RFC PATCH 2/2] ARM: virt: Add assembler helpers for the Virtualization Extensions Dave Martin
@ 2012-02-28 19:24 ` Russell King - ARM Linux
  2012-02-28 19:44   ` Dave Martin
  2012-03-01 11:49   ` Dave Martin
  2 siblings, 2 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2012-02-28 19:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 28, 2012 at 06:59:44PM +0000, Dave Martin wrote:
> #ifdef __ASSEMBLY__
> stuff
> for
> the
> assembler
> #else
> asm("stuff");
> asm("for");
> asm("the");
> asm("assembler");

That's invalid - nothing guarantees that the compiler won't place
anything in between these asm statements in the output assembly
file.

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

* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
  2012-02-28 19:24 ` [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Russell King - ARM Linux
@ 2012-02-28 19:44   ` Dave Martin
  2012-02-29 19:28     ` Dave Martin
  2012-03-01 11:49   ` Dave Martin
  1 sibling, 1 reply; 11+ messages in thread
From: Dave Martin @ 2012-02-28 19:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 28, 2012 at 07:24:59PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 28, 2012 at 06:59:44PM +0000, Dave Martin wrote:
> > #ifdef __ASSEMBLY__
> > stuff
> > for
> > the
> > assembler
> > #else
> > asm("stuff");
> > asm("for");
> > asm("the");
> > asm("assembler");
> 
> That's invalid - nothing guarantees that the compiler won't place
> anything in between these asm statements in the output assembly
> file.

Within a function that would be certainly true -- at the top-level, I'm
less sure.  Since there is no sequential code at the top level, only
declarations, it's hard to see why the compiler would ever consider
pasting something in the middle of that block or reordering it.
Without constraints, the compiler simply has no idea what's there
(such asms are implicitly "volatile", though that could be added
for clarity).  You're right that all this may amount to less than a
guarantee, though...


One obvious improvement is to emit a single big asm statement for
each block.  There's still an assumption that the compiler will not
reorder stuff around that block -- unified.h actually already relies
on that prepoerty in order to work (though if we can find a better way,
we could migrate some of the unified.h stuff to use it).


Another option is to .include a separate file.

This is possible, but I hadn't figured out how to autogenerate the
correct dependencies if things are one that way.  Alternatively, the
.included file can be the header file itself, but this relies on
the fact that C preprocessor look like line comments to the assembler,
so it's rather painful.


If there is no other way to be certain that the included content really
does appear at the start of the compilation unit, it would be necessary
to wrap the assembler in a script which explicitly pastes that extra
stuff at the start -- but this doesn't feel like a desirable option,
since it's hard to avoid extra complexity and overheads when doing this.


Any thoughts?

Cheers
---Dave

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

* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
  2012-02-28 19:44   ` Dave Martin
@ 2012-02-29 19:28     ` Dave Martin
  0 siblings, 0 replies; 11+ messages in thread
From: Dave Martin @ 2012-02-29 19:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 28, 2012 at 07:44:03PM +0000, Dave Martin wrote:
> On Tue, Feb 28, 2012 at 07:24:59PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 28, 2012 at 06:59:44PM +0000, Dave Martin wrote:
> > > #ifdef __ASSEMBLY__
> > > stuff
> > > for
> > > the
> > > assembler
> > > #else
> > > asm("stuff");
> > > asm("for");
> > > asm("the");
> > > asm("assembler");
> > 
> > That's invalid - nothing guarantees that the compiler won't place
> > anything in between these asm statements in the output assembly
> > file.
> 
> Within a function that would be certainly true -- at the top-level, I'm
> less sure.  Since there is no sequential code at the top level, only
> declarations, it's hard to see why the compiler would ever consider
> pasting something in the middle of that block or reordering it.
> Without constraints, the compiler simply has no idea what's there
> (such asms are implicitly "volatile", though that could be added
> for clarity).  You're right that all this may amount to less than a
> guarantee, though...

A quick follow up on this -- having chatted to tools guys, it sounds
like you're quite right on this: it is indeed unsafe, without
-fno-toplevel-reorder (which would impair some optimisations)

Of course, this also means that unified.h is unsafe for the same
reasons -- there is no guarantee that the big asm block containing
all the IT macro definitions will precede compiler-generated code in
the input to the assembler (and, presumably, inline asms embedded in it)
in the compiler output...


Cheers
---Dave

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

* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
  2012-02-28 19:24 ` [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Russell King - ARM Linux
  2012-02-28 19:44   ` Dave Martin
@ 2012-03-01 11:49   ` Dave Martin
  2012-03-01 13:00     ` Russell King - ARM Linux
  2012-03-02 21:40     ` Nicolas Pitre
  1 sibling, 2 replies; 11+ messages in thread
From: Dave Martin @ 2012-03-01 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 28, 2012 at 07:24:59PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 28, 2012 at 06:59:44PM +0000, Dave Martin wrote:
> > #ifdef __ASSEMBLY__
> > stuff
> > for
> > the
> > assembler
> > #else
> > asm("stuff");
> > asm("for");
> > asm("the");
> > asm("assembler");
> 
> That's invalid - nothing guarantees that the compiler won't place
> anything in between these asm statements in the output assembly
> file.

Are you still interested in this series?

I have a workaround for the above now, but it's not pretty -- I seem to
have opened a can of worms here.


We would need something like

#define EXTENDED_ASM(stuff) asm ( ".include \"macros.inc\"\n\t" stuff )
#define EXTENDED_VASM(stuff) asm volatile ( ".include \"macros.inc\"\n\t" stuff )

...where macros.inc includes some logic to protect against multiple
inclusion.

This would avoid problems caused by reordering done by the compiler.

I think this can work, but it may be a step too far...


The above could help fix the incorrect way that asm/unified.h defines
the it* macros (though admittedly that does not seem to have caused
problems for anyone so far...)

Cheers
---Dave

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

* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
  2012-03-01 11:49   ` Dave Martin
@ 2012-03-01 13:00     ` Russell King - ARM Linux
  2012-03-01 13:20       ` Dave Martin
  2012-03-02 21:42       ` Nicolas Pitre
  2012-03-02 21:40     ` Nicolas Pitre
  1 sibling, 2 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2012-03-01 13:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 01, 2012 at 11:49:42AM +0000, Dave Martin wrote:
> Are you still interested in this series?
> 
> I have a workaround for the above now, but it's not pretty -- I seem to
> have opened a can of worms here.
> 
> 
> We would need something like
> 
> #define EXTENDED_ASM(stuff) asm ( ".include \"macros.inc\"\n\t" stuff )
> #define EXTENDED_VASM(stuff) asm volatile ( ".include \"macros.inc\"\n\t" stuff )
> 
> ...where macros.inc includes some logic to protect against multiple
> inclusion.
> 
> This would avoid problems caused by reordering done by the compiler.
> 
> I think this can work, but it may be a step too far...

I'm fairly tempted to say: "if it ain't broke, don't fix".  AFAIK no one
has reported problems here, so lets not hastily try to fix something that
will error out if it does go wrong.

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

* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
  2012-03-01 13:00     ` Russell King - ARM Linux
@ 2012-03-01 13:20       ` Dave Martin
  2012-03-02 21:42       ` Nicolas Pitre
  1 sibling, 0 replies; 11+ messages in thread
From: Dave Martin @ 2012-03-01 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 01, 2012 at 01:00:51PM +0000, Russell King - ARM Linux wrote:
> On Thu, Mar 01, 2012 at 11:49:42AM +0000, Dave Martin wrote:
> > Are you still interested in this series?
> > 
> > I have a workaround for the above now, but it's not pretty -- I seem to
> > have opened a can of worms here.
> > 
> > 
> > We would need something like
> > 
> > #define EXTENDED_ASM(stuff) asm ( ".include \"macros.inc\"\n\t" stuff )
> > #define EXTENDED_VASM(stuff) asm volatile ( ".include \"macros.inc\"\n\t" stuff )
> > 
> > ...where macros.inc includes some logic to protect against multiple
> > inclusion.
> > 
> > This would avoid problems caused by reordering done by the compiler.
> > 
> > I think this can work, but it may be a step too far...
> 
> I'm fairly tempted to say: "if it ain't broke, don't fix".  AFAIK no one
> has reported problems here, so lets not hastily try to fix something that
> will error out if it does go wrong.

OK -- I'll shelve this series for now and we'll see if we can come up
with something more localised for the kvm/Xen case.

unified.h may work for now, but I don't want to add anything more along
those lines for unless it's definitely correct to do so...

Cheers
---Dave

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

* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
  2012-03-01 11:49   ` Dave Martin
  2012-03-01 13:00     ` Russell King - ARM Linux
@ 2012-03-02 21:40     ` Nicolas Pitre
  1 sibling, 0 replies; 11+ messages in thread
From: Nicolas Pitre @ 2012-03-02 21:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 1 Mar 2012, Dave Martin wrote:

> I have a workaround for the above now, but it's not pretty -- I seem to
> have opened a can of worms here.
> 
> 
> We would need something like
> 
> #define EXTENDED_ASM(stuff) asm ( ".include \"macros.inc\"\n\t" stuff )
> #define EXTENDED_VASM(stuff) asm volatile ( ".include \"macros.inc\"\n\t" stuff )
> 
> ...where macros.inc includes some logic to protect against multiple
> inclusion.
> 
> This would avoid problems caused by reordering done by the compiler.
> 
> I think this can work, but it may be a step too far...
> 
> 
> The above could help fix the incorrect way that asm/unified.h defines
> the it* macros (though admittedly that does not seem to have caused
> problems for anyone so far...)

"If it aint broken dont fix it."

Yes, we might be making assumptions that are not guaranteed by the tools 
here, but as long as you make sure that some assumption going wrong 
won't go unnoticed and produce a broken binary then it is probably fine.

I did like your initial approach better, even if there is a risk that 
future tools might break it.  At least there was very little chances for 
the build to succeed if the global asm macros are not defined early 
enough.


Nicolas

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

* [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework
  2012-03-01 13:00     ` Russell King - ARM Linux
  2012-03-01 13:20       ` Dave Martin
@ 2012-03-02 21:42       ` Nicolas Pitre
  1 sibling, 0 replies; 11+ messages in thread
From: Nicolas Pitre @ 2012-03-02 21:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 1 Mar 2012, Russell King - ARM Linux wrote:

> On Thu, Mar 01, 2012 at 11:49:42AM +0000, Dave Martin wrote:
> > Are you still interested in this series?
> > 
> > I have a workaround for the above now, but it's not pretty -- I seem to
> > have opened a can of worms here.
> > 
> > 
> > We would need something like
> > 
> > #define EXTENDED_ASM(stuff) asm ( ".include \"macros.inc\"\n\t" stuff )
> > #define EXTENDED_VASM(stuff) asm volatile ( ".include \"macros.inc\"\n\t" stuff )
> > 
> > ...where macros.inc includes some logic to protect against multiple
> > inclusion.
> > 
> > This would avoid problems caused by reordering done by the compiler.
> > 
> > I think this can work, but it may be a step too far...
> 
> I'm fairly tempted to say: "if it ain't broke, don't fix".  AFAIK no one
> has reported problems here, so lets not hastily try to fix something that
> will error out if it does go wrong.

OK, exactly what I said.

(I should have read further down the thread before replying)


Nicolas

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

end of thread, other threads:[~2012-03-02 21:42 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-28 18:59 [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Dave Martin
2012-02-28 18:59 ` [RFC PATCH 1/2] " Dave Martin
2012-02-28 18:59 ` [RFC PATCH 2/2] ARM: virt: Add assembler helpers for the Virtualization Extensions Dave Martin
2012-02-28 19:24 ` [RFC PATCH 0/2] ARM: assembler: Add uniform assembler framework Russell King - ARM Linux
2012-02-28 19:44   ` Dave Martin
2012-02-29 19:28     ` Dave Martin
2012-03-01 11:49   ` Dave Martin
2012-03-01 13:00     ` Russell King - ARM Linux
2012-03-01 13:20       ` Dave Martin
2012-03-02 21:42       ` Nicolas Pitre
2012-03-02 21:40     ` Nicolas Pitre

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).