* [PATCH 0/4] ARM: opcodes: Facilitate custom opcode injection
@ 2012-03-15 16:32 Dave Martin
2012-03-15 16:32 ` [PATCH 1/4] ARM: opcodes: Don't define the thumb32 byteswapping macros for BE32 Dave Martin
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Dave Martin @ 2012-03-15 16:32 UTC (permalink / raw)
To: linux-arm-kernel
Since my "uniform assembler" series had some problems and did not
meet with widespread agreement, this can't be used as a basis for a
mechanism to safely inject custom instruction opcodes (which was my
immediate reason for writing those patchse).
This series follows a more conventional approach to achieve the
goal for safe opcode injection across all kernel endianness and
instruction set configurations.
I have made best efforts to verify that these patches do the right
thing for big-endian configurations, but review/testing from people
who are actively working with big-endian targets would be
appreciated. There's no code in the kernel using these macros yet,
but you can experiment with the __HVC() macro added by the final
patch. If this disassembles correctly in vmlinux (see below), then
the macros should be safe for your configuration.
Note that for BE8 targets, you _will_ get weird-looking instruction
data in your .o files: because the ".inst" family of assembler
directives is relatively new I use data directives instead. This
means that the data for those directives has to be pre-swapped by
the opcode injection macros, whereas _instruction_ data should get
byteswapped by the linker in the final link (with ld --be8). Using
data directives brings some complexity, but it is the only way to
ensure compatibility with older assembler versions.
To check correctness, you should therefore review the final linker
output (vmlinux) if you want to be certain what the final
instruction stream looks like. You may need to strip data mapping
symbols (strip -N'$d') from vmlinux in order for the injected
instructions to be disassembled properly -- note that this has no
effect on the run-time meaning of the image.
For BE32 the situation is simpler again, because like LE, BE32 uses
the same endianness for data and instructions.
Dave Martin (4):
ARM: opcodes: Don't define the thumb32 byteswapping macros for BE32
ARM: opcodes: Make opcode byteswapping macros assembly-compatible
ARM: opcodes: Add helpers for emitting custom opcodes
ARM: opcodes: Opcode definitions for the Virtualization Extensions
arch/arm/include/asm/opcodes-virt.h | 29 ++++++
arch/arm/include/asm/opcodes.h | 181 ++++++++++++++++++++++++++++++++---
2 files changed, 195 insertions(+), 15 deletions(-)
create mode 100644 arch/arm/include/asm/opcodes-virt.h
--
1.7.4.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/4] ARM: opcodes: Don't define the thumb32 byteswapping macros for BE32
2012-03-15 16:32 [PATCH 0/4] ARM: opcodes: Facilitate custom opcode injection Dave Martin
@ 2012-03-15 16:32 ` Dave Martin
2012-03-15 17:40 ` Nicolas Pitre
2012-03-15 16:32 ` [PATCH 2/4] ARM: opcodes: Make opcode byteswapping macros assembly-compatible Dave Martin
` (2 subsequent siblings)
3 siblings, 1 reply; 11+ messages in thread
From: Dave Martin @ 2012-03-15 16:32 UTC (permalink / raw)
To: linux-arm-kernel
The existing __mem_to_opcode_thumb32() is incorrect for BE32
platforms. However, these don't support Thumb-2 kernels, so this
option is not so relevant for those platforms anyway.
This operation is complicated by the lack of unaligned memory
access support prior to ARMv6.
Rather than provide a "working" macro which will probably won't get
used (or worse, will get misused), this patch removes the macro for
BE32 kernels. People manipulating Thumb opcodes prior to ARMv6
should almost certainly be splitting these operations into
halfwords anyway, using __opcode_thumb32_{first,second,compose}()
and the 16-bit opcode transformations.
Signed-off-by: Dave Martin <dave.martin@linaro.org>
---
arch/arm/include/asm/opcodes.h | 15 ++++++++++++++-
1 files changed, 14 insertions(+), 1 deletions(-)
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index 19c48de..cf877c8 100644
--- a/arch/arm/include/asm/opcodes.h
+++ b/arch/arm/include/asm/opcodes.h
@@ -49,18 +49,31 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
#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
+
+#else /* ! CONFIG_CPU_ENDIAN_BE8 */
+
#define __opcode_to_mem_arm(x) ((u32)(x))
#define __opcode_to_mem_thumb16(x) ((u16)(x))
+#ifndef CONFIG_CPU_ENDIAN_BE32
+/*
+ * On BE32 systems, using 32-bit accesses to store Thumb instructions will not
+ * work in all cases, due to alignment constraints. For now, a correct
+ * version is not proivided for BE32.
+ */
#define __opcode_to_mem_thumb32(x) swahw32(x)
#endif
+#endif /* ! CONFIG_CPU_ENDIAN_BE8 */
+
#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
+#ifndef CONFIG_CPU_ENDIAN_BE32
#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
+#endif
/* Operations specific to Thumb opcodes */
--
1.7.4.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/4] ARM: opcodes: Make opcode byteswapping macros assembly-compatible
2012-03-15 16:32 [PATCH 0/4] ARM: opcodes: Facilitate custom opcode injection Dave Martin
2012-03-15 16:32 ` [PATCH 1/4] ARM: opcodes: Don't define the thumb32 byteswapping macros for BE32 Dave Martin
@ 2012-03-15 16:32 ` Dave Martin
2012-03-15 17:53 ` Nicolas Pitre
2012-03-15 16:32 ` [PATCH 3/4] ARM: opcodes: Add helpers for emitting custom opcodes Dave Martin
2012-03-15 16:32 ` [PATCH 4/4] ARM: opcodes: Opcode definitions for the Virtualization Extensions Dave Martin
3 siblings, 1 reply; 11+ messages in thread
From: Dave Martin @ 2012-03-15 16:32 UTC (permalink / raw)
To: linux-arm-kernel
Most of the existing macros don't work with assembler, due to the
use of type casts and C functions from <linux/swab.h>.
This patch abstracts out those operations and provides simple
explicit versions for use in assembly code.
__opcode_is_thumb32() and __opcode_is_thumb16() are also converted
to do bitmask-based testing to avoid confusion if these are used in
assembly code (the assembler typically treats all arithmetic values
as signed).
Signed-off-by: Dave Martin <dave.martin@linaro.org>
---
arch/arm/include/asm/opcodes.h | 97 +++++++++++++++++++++++++++++++++------
1 files changed, 82 insertions(+), 15 deletions(-)
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index cf877c8..32730a8 100644
--- a/arch/arm/include/asm/opcodes.h
+++ b/arch/arm/include/asm/opcodes.h
@@ -19,6 +19,33 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
/*
+ * Assembler opcode byteswap helpers.
+ * These are only intended for use by this header: don't use them directly,
+ * because they will be suboptimal in most cases.
+ */
+#define ___asm_opcode_swab32(x) ( \
+ (((x) << 24) & 0xFF000000) \
+ | (((x) << 8) & 0x00FF0000) \
+ | (((x) >> 8) & 0x0000FF00) \
+ | (((x) >> 24) & 0x000000FF) \
+)
+#define ___asm_opcode_swab16(x) ( \
+ (((x) << 8) & 0xFF00) \
+ | (((x) >> 8) & 0x00FF) \
+)
+#define ___asm_opcode_swahb32(x) ( \
+ (((x) << 8) & 0xFF00FF00) \
+ | (((x) >> 8) & 0x00FF00FF) \
+)
+#define ___asm_opcode_swahw32(x) ( \
+ (((x) << 16) & 0xFFFF0000) \
+ | (((x) >> 16) & 0x0000FFFF) \
+)
+#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
+#define ___asm_opcode_identity16(x) ((x) & 0xFFFF)
+
+
+/*
* Opcode byteswap helpers
*
* These macros help with converting instructions between a canonical integer
@@ -41,30 +68,58 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
* 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.
+ *
+ * The ___asm variants are intended only for use by this header, in situations
+ * involving inline assembler. For .S files, the normal __opcode_*() macros
+ * should do the right thing.
*/
+#ifdef __ASSEMBLY__
-#ifndef __ASSEMBLY__
+#define ___opcode_swab32(x) ___asm_opcode_swab32(x)
+#define ___opcode_swab16(x) ___asm_opcode_swab16(x)
+#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x)
+#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x)
+#define ___opcode_identity32(x) ___asm_opcode_identity32(x)
+#define ___opcode_identity16(x) ___asm_opcode_identity16(x)
+
+#else /* ! __ASSEMBLY__ */
#include <linux/types.h>
#include <linux/swab.h>
+#define ___opcode_swab32(x) swab32(x)
+#define ___opcode_swab16(x) swab16(x)
+#define ___opcode_swahb32(x) swahb32(x)
+#define ___opcode_swahw32(x) swahw32(x)
+#define ___opcode_identity32(x) ((u32)(x))
+#define ___opcode_identity16(x) ((u16)(x))
+
+#endif /* ! __ASSEMBLY__ */
+
+
#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)
+#define __opcode_to_mem_arm(x) ___opcode_swab32(x)
+#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x)
+#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x)
+#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x)
+#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x)
+#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x)
#else /* ! CONFIG_CPU_ENDIAN_BE8 */
-#define __opcode_to_mem_arm(x) ((u32)(x))
-#define __opcode_to_mem_thumb16(x) ((u16)(x))
+#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
+#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x)
+#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
+#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x)
#ifndef CONFIG_CPU_ENDIAN_BE32
/*
* On BE32 systems, using 32-bit accesses to store Thumb instructions will not
* work in all cases, due to alignment constraints. For now, a correct
* version is not proivided for BE32.
*/
-#define __opcode_to_mem_thumb32(x) swahw32(x)
+#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x)
+#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x)
#endif
#endif /* ! CONFIG_CPU_ENDIAN_BE8 */
@@ -78,15 +133,27 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
/* Operations specific to Thumb opcodes */
/* Instruction size checks: */
-#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
-#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
+#define __opcode_is_thumb32(x) ( \
+ ((x) & 0xF8000000) == 0xE8000000 \
+ || ((x) & 0xF0000000) == 0xF0000000 \
+)
+#define __opcode_is_thumb16(x) ( \
+ ((x) & 0xFFFF0000) == 0 \
+ && !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000) \
+)
/* 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__ */
+#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16))
+#define __opcode_thumb32_second(x) (___opcode_identity16(x))
+#define __opcode_thumb32_compose(first, second) ( \
+ (___opcode_identity32(___opcode_identity16(first)) << 16) \
+ | ___opcode_identity32(___opcode_identity16(second)) \
+)
+#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16))
+#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x))
+#define ___asm_opcode_thumb32_compose(first, second) ( \
+ (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \
+ | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
+)
#endif /* __ASM_ARM_OPCODES_H */
--
1.7.4.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/4] ARM: opcodes: Add helpers for emitting custom opcodes
2012-03-15 16:32 [PATCH 0/4] ARM: opcodes: Facilitate custom opcode injection Dave Martin
2012-03-15 16:32 ` [PATCH 1/4] ARM: opcodes: Don't define the thumb32 byteswapping macros for BE32 Dave Martin
2012-03-15 16:32 ` [PATCH 2/4] ARM: opcodes: Make opcode byteswapping macros assembly-compatible Dave Martin
@ 2012-03-15 16:32 ` Dave Martin
2012-03-15 17:54 ` Nicolas Pitre
2012-03-15 16:32 ` [PATCH 4/4] ARM: opcodes: Opcode definitions for the Virtualization Extensions Dave Martin
3 siblings, 1 reply; 11+ messages in thread
From: Dave Martin @ 2012-03-15 16:32 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds some __inst_() macros for injecting custom opcodes
in assembler (both inline and in .S files). They should make it
easier and cleaner to get things right in little-/big-
endian/ARM/Thumb-2 kernels without a lot of #ifdefs.
Signed-off-by: Dave Martin <dave.martin@linaro.org>
---
arch/arm/include/asm/opcodes.h | 69 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index 32730a8..50ef0be 100644
--- a/arch/arm/include/asm/opcodes.h
+++ b/arch/arm/include/asm/opcodes.h
@@ -156,4 +156,73 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
| ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
)
+/*
+ * Opcode injection helpers
+ *
+ * In rare cases it is necessary to assemble an opcode which the
+ * assembler does not support directly, or which would normally be
+ * rejected because of the CFLAGS or AFLAGS used to build the affected
+ * file.
+ *
+ * Before using these macros, consider carefully whether it is feasible
+ * instead to change the build flags for your file, or whether it really
+ * makes sense to support old assembler versions when building that
+ * particular kernel feature.
+ *
+ * The macros defined here should only be used where there is no viable
+ * alternative.
+ *
+ *
+ * __inst_arm(x): emit the specified ARM opcode
+ * __inst_thumb16(x): emit the specified 16-bit Thumb opcode
+ * __inst_thumb32(x): emit the specified 32-bit Thumb opcode
+ *
+ * __inst_arm_thumb16(arm, thumb): emit either the specified arm or
+ * 16-bit Thumb opcode, depending on whether an ARM or Thumb-2
+ * kernel is being built
+ *
+ * __inst_arm_thumb32(arm, thumb): emit either the specified arm or
+ * 32-bit Thumb opcode, depending on whether an ARM or Thumb-2
+ * kernel is being built
+ *
+ *
+ * Note that using these macros directly is poor practice. Instead, you
+ * should use them to define human-readable wrapper macros to encode the
+ * instructions that you care about. In code which might run on ARMv7 or
+ * above, you can usually use the __inst_arm_thumb{16,32} macros to
+ * specify the ARM and Thumb alternatives at the same time. This ensures
+ * that the correct opcode gets emitted depending on the instruction set
+ * used for the kernel build.
+ */
+#include <linux/stringify.h>
+
+#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
+#define __inst_thumb32(x) ___inst_thumb32( \
+ ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)), \
+ ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x)) \
+)
+#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
+ __inst_thumb16(thumb_opcode)
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
+ __inst_thumb32(thumb_opcode)
+#else
+#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+#endif
+
+/* Helpers for the helpers. Don't use these directly. */
+#ifdef __ASSEMBLY__
+#define ___inst_arm(x) .long x
+#define ___inst_thumb16(x) .short x
+#define ___inst_thumb32(first, second) .short first, second
+#else
+#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
+#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
+#define ___inst_thumb32(first, second) \
+ ".short " __stringify(first) ", " __stringify(second) "\n\t"
+#endif
+
#endif /* __ASM_ARM_OPCODES_H */
--
1.7.4.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/4] ARM: opcodes: Opcode definitions for the Virtualization Extensions
2012-03-15 16:32 [PATCH 0/4] ARM: opcodes: Facilitate custom opcode injection Dave Martin
` (2 preceding siblings ...)
2012-03-15 16:32 ` [PATCH 3/4] ARM: opcodes: Add helpers for emitting custom opcodes Dave Martin
@ 2012-03-15 16:32 ` Dave Martin
2012-03-15 17:58 ` Nicolas Pitre
3 siblings, 1 reply; 11+ messages in thread
From: Dave Martin @ 2012-03-15 16:32 UTC (permalink / raw)
To: linux-arm-kernel
For now, this patch just adds a definition for the HVC instruction.
More can be added here later, as needed.
Now that we have a real example of how to use the opcode injection
macros properly, this patch also adds a cross-reference from the
explanation in opcodes.h (since without an example, figuring out
how to use the macros is not that easy).
Signed-off-by: Dave Martin <dave.martin@linaro.org>
---
arch/arm/include/asm/opcodes-virt.h | 29 +++++++++++++++++++++++++++++
arch/arm/include/asm/opcodes.h | 2 ++
2 files changed, 31 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/include/asm/opcodes-virt.h
diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h
new file mode 100644
index 0000000..b85665a
--- /dev/null
+++ b/arch/arm/include/asm/opcodes-virt.h
@@ -0,0 +1,29 @@
+/*
+ * opcodes-virt.h: Opcode 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.
+ */
+#ifndef __ASM_ARM_OPCODES_VIRT_H
+#define __ASM_ARM_OPCODES_VIRT_H
+
+#include <asm/opcodes.h>
+
+#define __HVC(imm16) __inst_arm_thumb32( \
+ 0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F), \
+ 0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF) \
+)
+
+#endif /* ! __ASM_ARM_OPCODES_VIRT_H */
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index 50ef0be..89ff5b9 100644
--- a/arch/arm/include/asm/opcodes.h
+++ b/arch/arm/include/asm/opcodes.h
@@ -193,6 +193,8 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
* specify the ARM and Thumb alternatives at the same time. This ensures
* that the correct opcode gets emitted depending on the instruction set
* used for the kernel build.
+ *
+ * Look@opcodes-virt.h for an example of how to use these macros.
*/
#include <linux/stringify.h>
--
1.7.4.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 1/4] ARM: opcodes: Don't define the thumb32 byteswapping macros for BE32
2012-03-15 16:32 ` [PATCH 1/4] ARM: opcodes: Don't define the thumb32 byteswapping macros for BE32 Dave Martin
@ 2012-03-15 17:40 ` Nicolas Pitre
0 siblings, 0 replies; 11+ messages in thread
From: Nicolas Pitre @ 2012-03-15 17:40 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 15 Mar 2012, Dave Martin wrote:
> The existing __mem_to_opcode_thumb32() is incorrect for BE32
> platforms. However, these don't support Thumb-2 kernels, so this
> option is not so relevant for those platforms anyway.
>
> This operation is complicated by the lack of unaligned memory
> access support prior to ARMv6.
>
> Rather than provide a "working" macro which will probably won't get
> used (or worse, will get misused), this patch removes the macro for
> BE32 kernels. People manipulating Thumb opcodes prior to ARMv6
> should almost certainly be splitting these operations into
> halfwords anyway, using __opcode_thumb32_{first,second,compose}()
> and the 16-bit opcode transformations.
>
> Signed-off-by: Dave Martin <dave.martin@linaro.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
> +/*
> + * On BE32 systems, using 32-bit accesses to store Thumb instructions will not
> + * work in all cases, due to alignment constraints. For now, a correct
> + * version is not proivided for BE32.
s/proivided/provided/
Nicolas
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/4] ARM: opcodes: Make opcode byteswapping macros assembly-compatible
2012-03-15 16:32 ` [PATCH 2/4] ARM: opcodes: Make opcode byteswapping macros assembly-compatible Dave Martin
@ 2012-03-15 17:53 ` Nicolas Pitre
2012-03-16 10:59 ` Dave Martin
0 siblings, 1 reply; 11+ messages in thread
From: Nicolas Pitre @ 2012-03-15 17:53 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 15 Mar 2012, Dave Martin wrote:
> Most of the existing macros don't work with assembler, due to the
> use of type casts and C functions from <linux/swab.h>.
>
> This patch abstracts out those operations and provides simple
> explicit versions for use in assembly code.
>
> __opcode_is_thumb32() and __opcode_is_thumb16() are also converted
> to do bitmask-based testing to avoid confusion if these are used in
> assembly code (the assembler typically treats all arithmetic values
> as signed).
>
> Signed-off-by: Dave Martin <dave.martin@linaro.org>
OK. One really has to read through the whole series to see the point of
this.
Acked-by: Nicolas Pitre <nico@linaro.org>
> ---
> arch/arm/include/asm/opcodes.h | 97 +++++++++++++++++++++++++++++++++------
> 1 files changed, 82 insertions(+), 15 deletions(-)
>
> diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> index cf877c8..32730a8 100644
> --- a/arch/arm/include/asm/opcodes.h
> +++ b/arch/arm/include/asm/opcodes.h
> @@ -19,6 +19,33 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
>
>
> /*
> + * Assembler opcode byteswap helpers.
> + * These are only intended for use by this header: don't use them directly,
> + * because they will be suboptimal in most cases.
> + */
> +#define ___asm_opcode_swab32(x) ( \
> + (((x) << 24) & 0xFF000000) \
> + | (((x) << 8) & 0x00FF0000) \
> + | (((x) >> 8) & 0x0000FF00) \
> + | (((x) >> 24) & 0x000000FF) \
> +)
> +#define ___asm_opcode_swab16(x) ( \
> + (((x) << 8) & 0xFF00) \
> + | (((x) >> 8) & 0x00FF) \
> +)
> +#define ___asm_opcode_swahb32(x) ( \
> + (((x) << 8) & 0xFF00FF00) \
> + | (((x) >> 8) & 0x00FF00FF) \
> +)
> +#define ___asm_opcode_swahw32(x) ( \
> + (((x) << 16) & 0xFFFF0000) \
> + | (((x) >> 16) & 0x0000FFFF) \
> +)
> +#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
> +#define ___asm_opcode_identity16(x) ((x) & 0xFFFF)
> +
> +
> +/*
> * Opcode byteswap helpers
> *
> * These macros help with converting instructions between a canonical integer
> @@ -41,30 +68,58 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
> * 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.
> + *
> + * The ___asm variants are intended only for use by this header, in situations
> + * involving inline assembler. For .S files, the normal __opcode_*() macros
> + * should do the right thing.
> */
> +#ifdef __ASSEMBLY__
>
> -#ifndef __ASSEMBLY__
> +#define ___opcode_swab32(x) ___asm_opcode_swab32(x)
> +#define ___opcode_swab16(x) ___asm_opcode_swab16(x)
> +#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x)
> +#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x)
> +#define ___opcode_identity32(x) ___asm_opcode_identity32(x)
> +#define ___opcode_identity16(x) ___asm_opcode_identity16(x)
> +
> +#else /* ! __ASSEMBLY__ */
>
> #include <linux/types.h>
> #include <linux/swab.h>
>
> +#define ___opcode_swab32(x) swab32(x)
> +#define ___opcode_swab16(x) swab16(x)
> +#define ___opcode_swahb32(x) swahb32(x)
> +#define ___opcode_swahw32(x) swahw32(x)
> +#define ___opcode_identity32(x) ((u32)(x))
> +#define ___opcode_identity16(x) ((u16)(x))
> +
> +#endif /* ! __ASSEMBLY__ */
> +
> +
> #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)
> +#define __opcode_to_mem_arm(x) ___opcode_swab32(x)
> +#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x)
> +#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x)
> +#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x)
> +#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x)
> +#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x)
>
> #else /* ! CONFIG_CPU_ENDIAN_BE8 */
>
> -#define __opcode_to_mem_arm(x) ((u32)(x))
> -#define __opcode_to_mem_thumb16(x) ((u16)(x))
> +#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
> +#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x)
> +#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
> +#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x)
> #ifndef CONFIG_CPU_ENDIAN_BE32
> /*
> * On BE32 systems, using 32-bit accesses to store Thumb instructions will not
> * work in all cases, due to alignment constraints. For now, a correct
> * version is not proivided for BE32.
> */
> -#define __opcode_to_mem_thumb32(x) swahw32(x)
> +#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x)
> +#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x)
> #endif
>
> #endif /* ! CONFIG_CPU_ENDIAN_BE8 */
> @@ -78,15 +133,27 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
> /* Operations specific to Thumb opcodes */
>
> /* Instruction size checks: */
> -#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
> -#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
> +#define __opcode_is_thumb32(x) ( \
> + ((x) & 0xF8000000) == 0xE8000000 \
> + || ((x) & 0xF0000000) == 0xF0000000 \
> +)
> +#define __opcode_is_thumb16(x) ( \
> + ((x) & 0xFFFF0000) == 0 \
> + && !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000) \
> +)
>
> /* 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__ */
> +#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16))
> +#define __opcode_thumb32_second(x) (___opcode_identity16(x))
> +#define __opcode_thumb32_compose(first, second) ( \
> + (___opcode_identity32(___opcode_identity16(first)) << 16) \
> + | ___opcode_identity32(___opcode_identity16(second)) \
> +)
> +#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16))
> +#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x))
> +#define ___asm_opcode_thumb32_compose(first, second) ( \
> + (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \
> + | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
> +)
>
> #endif /* __ASM_ARM_OPCODES_H */
> --
> 1.7.4.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/4] ARM: opcodes: Add helpers for emitting custom opcodes
2012-03-15 16:32 ` [PATCH 3/4] ARM: opcodes: Add helpers for emitting custom opcodes Dave Martin
@ 2012-03-15 17:54 ` Nicolas Pitre
0 siblings, 0 replies; 11+ messages in thread
From: Nicolas Pitre @ 2012-03-15 17:54 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 15 Mar 2012, Dave Martin wrote:
> This patch adds some __inst_() macros for injecting custom opcodes
> in assembler (both inline and in .S files). They should make it
> easier and cleaner to get things right in little-/big-
> endian/ARM/Thumb-2 kernels without a lot of #ifdefs.
>
> Signed-off-by: Dave Martin <dave.martin@linaro.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
> ---
> arch/arm/include/asm/opcodes.h | 69 ++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 69 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> index 32730a8..50ef0be 100644
> --- a/arch/arm/include/asm/opcodes.h
> +++ b/arch/arm/include/asm/opcodes.h
> @@ -156,4 +156,73 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
> | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
> )
>
> +/*
> + * Opcode injection helpers
> + *
> + * In rare cases it is necessary to assemble an opcode which the
> + * assembler does not support directly, or which would normally be
> + * rejected because of the CFLAGS or AFLAGS used to build the affected
> + * file.
> + *
> + * Before using these macros, consider carefully whether it is feasible
> + * instead to change the build flags for your file, or whether it really
> + * makes sense to support old assembler versions when building that
> + * particular kernel feature.
> + *
> + * The macros defined here should only be used where there is no viable
> + * alternative.
> + *
> + *
> + * __inst_arm(x): emit the specified ARM opcode
> + * __inst_thumb16(x): emit the specified 16-bit Thumb opcode
> + * __inst_thumb32(x): emit the specified 32-bit Thumb opcode
> + *
> + * __inst_arm_thumb16(arm, thumb): emit either the specified arm or
> + * 16-bit Thumb opcode, depending on whether an ARM or Thumb-2
> + * kernel is being built
> + *
> + * __inst_arm_thumb32(arm, thumb): emit either the specified arm or
> + * 32-bit Thumb opcode, depending on whether an ARM or Thumb-2
> + * kernel is being built
> + *
> + *
> + * Note that using these macros directly is poor practice. Instead, you
> + * should use them to define human-readable wrapper macros to encode the
> + * instructions that you care about. In code which might run on ARMv7 or
> + * above, you can usually use the __inst_arm_thumb{16,32} macros to
> + * specify the ARM and Thumb alternatives at the same time. This ensures
> + * that the correct opcode gets emitted depending on the instruction set
> + * used for the kernel build.
> + */
> +#include <linux/stringify.h>
> +
> +#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
> +#define __inst_thumb32(x) ___inst_thumb32( \
> + ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)), \
> + ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x)) \
> +)
> +#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
> +
> +#ifdef CONFIG_THUMB2_KERNEL
> +#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
> + __inst_thumb16(thumb_opcode)
> +#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
> + __inst_thumb32(thumb_opcode)
> +#else
> +#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
> +#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
> +#endif
> +
> +/* Helpers for the helpers. Don't use these directly. */
> +#ifdef __ASSEMBLY__
> +#define ___inst_arm(x) .long x
> +#define ___inst_thumb16(x) .short x
> +#define ___inst_thumb32(first, second) .short first, second
> +#else
> +#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
> +#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
> +#define ___inst_thumb32(first, second) \
> + ".short " __stringify(first) ", " __stringify(second) "\n\t"
> +#endif
> +
> #endif /* __ASM_ARM_OPCODES_H */
> --
> 1.7.4.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4/4] ARM: opcodes: Opcode definitions for the Virtualization Extensions
2012-03-15 16:32 ` [PATCH 4/4] ARM: opcodes: Opcode definitions for the Virtualization Extensions Dave Martin
@ 2012-03-15 17:58 ` Nicolas Pitre
2012-03-16 11:04 ` Dave Martin
0 siblings, 1 reply; 11+ messages in thread
From: Nicolas Pitre @ 2012-03-15 17:58 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 15 Mar 2012, Dave Martin wrote:
> For now, this patch just adds a definition for the HVC instruction.
> More can be added here later, as needed.
>
> Now that we have a real example of how to use the opcode injection
> macros properly, this patch also adds a cross-reference from the
> explanation in opcodes.h (since without an example, figuring out
> how to use the macros is not that easy).
>
> Signed-off-by: Dave Martin <dave.martin@linaro.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
Maybe this would be a good idea to document in one of the patch logs why
you didn't go with the assembler macro route like it is done in
unified.h for the various it instructions.
> ---
> arch/arm/include/asm/opcodes-virt.h | 29 +++++++++++++++++++++++++++++
> arch/arm/include/asm/opcodes.h | 2 ++
> 2 files changed, 31 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/include/asm/opcodes-virt.h
>
> diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h
> new file mode 100644
> index 0000000..b85665a
> --- /dev/null
> +++ b/arch/arm/include/asm/opcodes-virt.h
> @@ -0,0 +1,29 @@
> +/*
> + * opcodes-virt.h: Opcode 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.
> + */
> +#ifndef __ASM_ARM_OPCODES_VIRT_H
> +#define __ASM_ARM_OPCODES_VIRT_H
> +
> +#include <asm/opcodes.h>
> +
> +#define __HVC(imm16) __inst_arm_thumb32( \
> + 0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F), \
> + 0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF) \
> +)
> +
> +#endif /* ! __ASM_ARM_OPCODES_VIRT_H */
> diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> index 50ef0be..89ff5b9 100644
> --- a/arch/arm/include/asm/opcodes.h
> +++ b/arch/arm/include/asm/opcodes.h
> @@ -193,6 +193,8 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
> * specify the ARM and Thumb alternatives at the same time. This ensures
> * that the correct opcode gets emitted depending on the instruction set
> * used for the kernel build.
> + *
> + * Look at opcodes-virt.h for an example of how to use these macros.
> */
> #include <linux/stringify.h>
>
> --
> 1.7.4.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/4] ARM: opcodes: Make opcode byteswapping macros assembly-compatible
2012-03-15 17:53 ` Nicolas Pitre
@ 2012-03-16 10:59 ` Dave Martin
0 siblings, 0 replies; 11+ messages in thread
From: Dave Martin @ 2012-03-16 10:59 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Mar 15, 2012 at 01:53:20PM -0400, Nicolas Pitre wrote:
> On Thu, 15 Mar 2012, Dave Martin wrote:
>
> > Most of the existing macros don't work with assembler, due to the
> > use of type casts and C functions from <linux/swab.h>.
> >
> > This patch abstracts out those operations and provides simple
> > explicit versions for use in assembly code.
> >
> > __opcode_is_thumb32() and __opcode_is_thumb16() are also converted
> > to do bitmask-based testing to avoid confusion if these are used in
> > assembly code (the assembler typically treats all arithmetic values
> > as signed).
> >
> > Signed-off-by: Dave Martin <dave.martin@linaro.org>
>
> OK. One really has to read through the whole series to see the point of
> this.
That's a fair comment -- I'll try to add a bit more clarification with
reference to the other patches.
The real reason for this is that the C preprocessor doesn't resolve
arithmetic expressions, so if we stringify them into inline asm, the
whole expressions just get dumped out to the assembler without getting
evaluated first. Which means that we need the expressions in a form
which the assembler can evaluate too.
I see you understood that -- but as you say, it's non-obvious.
(This can be avoided by using an "i" constraint to pass those numbers
to the inline asm. I had a local series which did things that way, but
it makes the macros very awkward to use, since you need some macros
to show where in the inline asm to insert the instructions, and different
macros to pass the correct constraints.)
> Acked-by: Nicolas Pitre <nico@linaro.org>
Thanks
---Dave
>
>
>
> > ---
> > arch/arm/include/asm/opcodes.h | 97 +++++++++++++++++++++++++++++++++------
> > 1 files changed, 82 insertions(+), 15 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> > index cf877c8..32730a8 100644
> > --- a/arch/arm/include/asm/opcodes.h
> > +++ b/arch/arm/include/asm/opcodes.h
> > @@ -19,6 +19,33 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
> >
> >
> > /*
> > + * Assembler opcode byteswap helpers.
> > + * These are only intended for use by this header: don't use them directly,
> > + * because they will be suboptimal in most cases.
> > + */
> > +#define ___asm_opcode_swab32(x) ( \
> > + (((x) << 24) & 0xFF000000) \
> > + | (((x) << 8) & 0x00FF0000) \
> > + | (((x) >> 8) & 0x0000FF00) \
> > + | (((x) >> 24) & 0x000000FF) \
> > +)
> > +#define ___asm_opcode_swab16(x) ( \
> > + (((x) << 8) & 0xFF00) \
> > + | (((x) >> 8) & 0x00FF) \
> > +)
> > +#define ___asm_opcode_swahb32(x) ( \
> > + (((x) << 8) & 0xFF00FF00) \
> > + | (((x) >> 8) & 0x00FF00FF) \
> > +)
> > +#define ___asm_opcode_swahw32(x) ( \
> > + (((x) << 16) & 0xFFFF0000) \
> > + | (((x) >> 16) & 0x0000FFFF) \
> > +)
> > +#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
> > +#define ___asm_opcode_identity16(x) ((x) & 0xFFFF)
> > +
> > +
> > +/*
> > * Opcode byteswap helpers
> > *
> > * These macros help with converting instructions between a canonical integer
> > @@ -41,30 +68,58 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
> > * 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.
> > + *
> > + * The ___asm variants are intended only for use by this header, in situations
> > + * involving inline assembler. For .S files, the normal __opcode_*() macros
> > + * should do the right thing.
> > */
> > +#ifdef __ASSEMBLY__
> >
> > -#ifndef __ASSEMBLY__
> > +#define ___opcode_swab32(x) ___asm_opcode_swab32(x)
> > +#define ___opcode_swab16(x) ___asm_opcode_swab16(x)
> > +#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x)
> > +#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x)
> > +#define ___opcode_identity32(x) ___asm_opcode_identity32(x)
> > +#define ___opcode_identity16(x) ___asm_opcode_identity16(x)
> > +
> > +#else /* ! __ASSEMBLY__ */
> >
> > #include <linux/types.h>
> > #include <linux/swab.h>
> >
> > +#define ___opcode_swab32(x) swab32(x)
> > +#define ___opcode_swab16(x) swab16(x)
> > +#define ___opcode_swahb32(x) swahb32(x)
> > +#define ___opcode_swahw32(x) swahw32(x)
> > +#define ___opcode_identity32(x) ((u32)(x))
> > +#define ___opcode_identity16(x) ((u16)(x))
> > +
> > +#endif /* ! __ASSEMBLY__ */
> > +
> > +
> > #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)
> > +#define __opcode_to_mem_arm(x) ___opcode_swab32(x)
> > +#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x)
> > +#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x)
> > +#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x)
> > +#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x)
> > +#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x)
> >
> > #else /* ! CONFIG_CPU_ENDIAN_BE8 */
> >
> > -#define __opcode_to_mem_arm(x) ((u32)(x))
> > -#define __opcode_to_mem_thumb16(x) ((u16)(x))
> > +#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
> > +#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x)
> > +#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
> > +#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x)
> > #ifndef CONFIG_CPU_ENDIAN_BE32
> > /*
> > * On BE32 systems, using 32-bit accesses to store Thumb instructions will not
> > * work in all cases, due to alignment constraints. For now, a correct
> > * version is not proivided for BE32.
> > */
> > -#define __opcode_to_mem_thumb32(x) swahw32(x)
> > +#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x)
> > +#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x)
> > #endif
> >
> > #endif /* ! CONFIG_CPU_ENDIAN_BE8 */
> > @@ -78,15 +133,27 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
> > /* Operations specific to Thumb opcodes */
> >
> > /* Instruction size checks: */
> > -#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
> > -#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
> > +#define __opcode_is_thumb32(x) ( \
> > + ((x) & 0xF8000000) == 0xE8000000 \
> > + || ((x) & 0xF0000000) == 0xF0000000 \
> > +)
> > +#define __opcode_is_thumb16(x) ( \
> > + ((x) & 0xFFFF0000) == 0 \
> > + && !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000) \
> > +)
> >
> > /* 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__ */
> > +#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16))
> > +#define __opcode_thumb32_second(x) (___opcode_identity16(x))
> > +#define __opcode_thumb32_compose(first, second) ( \
> > + (___opcode_identity32(___opcode_identity16(first)) << 16) \
> > + | ___opcode_identity32(___opcode_identity16(second)) \
> > +)
> > +#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16))
> > +#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x))
> > +#define ___asm_opcode_thumb32_compose(first, second) ( \
> > + (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \
> > + | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
> > +)
> >
> > #endif /* __ASM_ARM_OPCODES_H */
> > --
> > 1.7.4.1
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4/4] ARM: opcodes: Opcode definitions for the Virtualization Extensions
2012-03-15 17:58 ` Nicolas Pitre
@ 2012-03-16 11:04 ` Dave Martin
0 siblings, 0 replies; 11+ messages in thread
From: Dave Martin @ 2012-03-16 11:04 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Mar 15, 2012 at 01:58:28PM -0400, Nicolas Pitre wrote:
> On Thu, 15 Mar 2012, Dave Martin wrote:
>
> > For now, this patch just adds a definition for the HVC instruction.
> > More can be added here later, as needed.
> >
> > Now that we have a real example of how to use the opcode injection
> > macros properly, this patch also adds a cross-reference from the
> > explanation in opcodes.h (since without an example, figuring out
> > how to use the macros is not that easy).
> >
> > Signed-off-by: Dave Martin <dave.martin@linaro.org>
>
> Acked-by: Nicolas Pitre <nico@linaro.org>
>
> Maybe this would be a good idea to document in one of the patch logs why
> you didn't go with the assembler macro route like it is done in
> unified.h for the various it instructions.
Yes, that's a good idea. I'll add a brief note somewhere -- probably on
the previous patch.
Cheers
---Dave
>
> > ---
> > arch/arm/include/asm/opcodes-virt.h | 29 +++++++++++++++++++++++++++++
> > arch/arm/include/asm/opcodes.h | 2 ++
> > 2 files changed, 31 insertions(+), 0 deletions(-)
> > create mode 100644 arch/arm/include/asm/opcodes-virt.h
> >
> > diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h
> > new file mode 100644
> > index 0000000..b85665a
> > --- /dev/null
> > +++ b/arch/arm/include/asm/opcodes-virt.h
> > @@ -0,0 +1,29 @@
> > +/*
> > + * opcodes-virt.h: Opcode 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.
> > + */
> > +#ifndef __ASM_ARM_OPCODES_VIRT_H
> > +#define __ASM_ARM_OPCODES_VIRT_H
> > +
> > +#include <asm/opcodes.h>
> > +
> > +#define __HVC(imm16) __inst_arm_thumb32( \
> > + 0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F), \
> > + 0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF) \
> > +)
> > +
> > +#endif /* ! __ASM_ARM_OPCODES_VIRT_H */
> > diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> > index 50ef0be..89ff5b9 100644
> > --- a/arch/arm/include/asm/opcodes.h
> > +++ b/arch/arm/include/asm/opcodes.h
> > @@ -193,6 +193,8 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
> > * specify the ARM and Thumb alternatives at the same time. This ensures
> > * that the correct opcode gets emitted depending on the instruction set
> > * used for the kernel build.
> > + *
> > + * Look at opcodes-virt.h for an example of how to use these macros.
> > */
> > #include <linux/stringify.h>
> >
> > --
> > 1.7.4.1
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2012-03-16 11:04 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-15 16:32 [PATCH 0/4] ARM: opcodes: Facilitate custom opcode injection Dave Martin
2012-03-15 16:32 ` [PATCH 1/4] ARM: opcodes: Don't define the thumb32 byteswapping macros for BE32 Dave Martin
2012-03-15 17:40 ` Nicolas Pitre
2012-03-15 16:32 ` [PATCH 2/4] ARM: opcodes: Make opcode byteswapping macros assembly-compatible Dave Martin
2012-03-15 17:53 ` Nicolas Pitre
2012-03-16 10:59 ` Dave Martin
2012-03-15 16:32 ` [PATCH 3/4] ARM: opcodes: Add helpers for emitting custom opcodes Dave Martin
2012-03-15 17:54 ` Nicolas Pitre
2012-03-15 16:32 ` [PATCH 4/4] ARM: opcodes: Opcode definitions for the Virtualization Extensions Dave Martin
2012-03-15 17:58 ` Nicolas Pitre
2012-03-16 11:04 ` Dave Martin
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).