* [PATCH 1/4] Add generic ARM instruction set condition code checks.
2011-11-25 17:19 [PATCH 0/4] Add generic ARM ISA condition code checks Leif Lindholm
@ 2011-11-25 17:19 ` Leif Lindholm
2011-11-25 17:38 ` Dave Martin
2011-11-30 16:59 ` Dave Martin
2011-11-25 17:19 ` [PATCH 2/4] Use generic ARM instruction set condition code checks for nwfpe Leif Lindholm
` (2 subsequent siblings)
3 siblings, 2 replies; 21+ messages in thread
From: Leif Lindholm @ 2011-11-25 17:19 UTC (permalink / raw)
To: linux-arm-kernel
This patch breaks the ARM condition checking code out of nwfpe/fpopcode.{ch}
into a standalone file for opcode operations. It also modifies the code
somewhat for coding style adherence, and adds some temporary variables for
increased readability.
Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
---
arch/arm/include/asm/opcodes.h | 20 ++++++++++++
arch/arm/kernel/Makefile | 2 +
arch/arm/kernel/opcodes.c | 68 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/include/asm/opcodes.h
create mode 100644 arch/arm/kernel/opcodes.c
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
new file mode 100644
index 0000000..aea97bf
--- /dev/null
+++ b/arch/arm/include/asm/opcodes.h
@@ -0,0 +1,20 @@
+/*
+ * 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 unsigned int arm_check_condition(unsigned int opcode, unsigned int psr);
+#endif
+
+#define ARM_OPCODE_CONDTEST_FAIL 0
+#define ARM_OPCODE_CONDTEST_PASS 1
+#define ARM_OPCODE_CONDTEST_UNCOND 2
+
+#endif /* __ASM_ARM_OPCODES_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 16eed6a..43b740d 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -13,7 +13,7 @@ CFLAGS_REMOVE_return_address.o = -pg
# Object file lists.
-obj-y := elf.o entry-armv.o entry-common.o irq.o \
+obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \
process.o ptrace.o return_address.o setup.o signal.o \
sys_arm.o stacktrace.o time.o traps.o
diff --git a/arch/arm/kernel/opcodes.c b/arch/arm/kernel/opcodes.c
new file mode 100644
index 0000000..c3171cc
--- /dev/null
+++ b/arch/arm/kernel/opcodes.c
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/arm/kernel/opcodes.c
+ *
+ * A32 condition code lookup feature moved from nwfpe/fpopcode.c
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <asm/opcodes.h>
+
+#define ARM_OPCODE_CONDITION_UNCOND 0xf
+
+/*
+ * condition code lookup table
+ * index into the table is test code: EQ, NE, ... LT, GT, AL, NV
+ *
+ * bit position in short is condition code: NZCV
+ */
+static const unsigned short cc_map[16] = {
+ 0xF0F0, /* EQ == Z set */
+ 0x0F0F, /* NE */
+ 0xCCCC, /* CS == C set */
+ 0x3333, /* CC */
+ 0xFF00, /* MI == N set */
+ 0x00FF, /* PL */
+ 0xAAAA, /* VS == V set */
+ 0x5555, /* VC */
+ 0x0C0C, /* HI == C set && Z clear */
+ 0xF3F3, /* LS == C clear || Z set */
+ 0xAA55, /* GE == (N==V) */
+ 0x55AA, /* LT == (N!=V) */
+ 0x0A05, /* GT == (!Z && (N==V)) */
+ 0xF5FA, /* LE == (Z || (N!=V)) */
+ 0xFFFF, /* AL always */
+ 0 /* NV */
+};
+
+/*
+ * Returns:
+ * ARM_OPCODE_CONDTEST_FAIL - if condition fails
+ * ARM_OPCODE_CONDTEST_PASS - if condition passes (including AL)
+ * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
+ * opcode space from v5 onwards
+ *
+ * Code that needs to check whether a condition has explicitly passed,
+ * should compare the return value to 1.
+ * Code that wants to check if a condition means that the instruction
+ * should be executed, should compare the return value to !0.
+ */
+unsigned int arm_check_condition(unsigned int opcode, unsigned int psr)
+{
+ unsigned int cc_bits = opcode >> 28;
+ unsigned int psr_cond = psr >> 28;
+
+ if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
+ if ((cc_map[cc_bits] >> (psr_cond)) & 1)
+ return ARM_OPCODE_CONDTEST_PASS;
+ else
+ return ARM_OPCODE_CONDTEST_FAIL;
+ } else {
+ return ARM_OPCODE_CONDTEST_UNCOND;
+ }
+}
+
+EXPORT_SYMBOL(arm_check_condition);
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 1/4] Add generic ARM instruction set condition code checks.
2011-11-25 17:19 ` [PATCH 1/4] Add generic ARM instruction set " Leif Lindholm
@ 2011-11-25 17:38 ` Dave Martin
2011-11-30 16:59 ` Dave Martin
1 sibling, 0 replies; 21+ messages in thread
From: Dave Martin @ 2011-11-25 17:38 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Nov 25, 2011 at 05:19:23PM +0000, Leif Lindholm wrote:
> This patch breaks the ARM condition checking code out of nwfpe/fpopcode.{ch}
> into a standalone file for opcode operations. It also modifies the code
> somewhat for coding style adherence, and adds some temporary variables for
> increased readability.
>
> Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
Heh, looks like I also invented the same header file in the meantime
Would you be able to comment on this?
http://comments.gmane.org/gmane.linux.ports.arm.kernel/141568
I think the content is complementary to what you're proposing.
Cheers
---Dave
> ---
> arch/arm/include/asm/opcodes.h | 20 ++++++++++++
> arch/arm/kernel/Makefile | 2 +
> arch/arm/kernel/opcodes.c | 68 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 89 insertions(+), 1 deletions(-)
> create mode 100644 arch/arm/include/asm/opcodes.h
> create mode 100644 arch/arm/kernel/opcodes.c
>
> diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> new file mode 100644
> index 0000000..aea97bf
> --- /dev/null
> +++ b/arch/arm/include/asm/opcodes.h
> @@ -0,0 +1,20 @@
> +/*
> + * 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 unsigned int arm_check_condition(unsigned int opcode, unsigned int psr);
> +#endif
> +
> +#define ARM_OPCODE_CONDTEST_FAIL 0
> +#define ARM_OPCODE_CONDTEST_PASS 1
> +#define ARM_OPCODE_CONDTEST_UNCOND 2
> +
> +#endif /* __ASM_ARM_OPCODES_H */
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index 16eed6a..43b740d 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -13,7 +13,7 @@ CFLAGS_REMOVE_return_address.o = -pg
>
> # Object file lists.
>
> -obj-y := elf.o entry-armv.o entry-common.o irq.o \
> +obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \
> process.o ptrace.o return_address.o setup.o signal.o \
> sys_arm.o stacktrace.o time.o traps.o
>
> diff --git a/arch/arm/kernel/opcodes.c b/arch/arm/kernel/opcodes.c
> new file mode 100644
> index 0000000..c3171cc
> --- /dev/null
> +++ b/arch/arm/kernel/opcodes.c
> @@ -0,0 +1,68 @@
> +/*
> + * linux/arch/arm/kernel/opcodes.c
> + *
> + * A32 condition code lookup feature moved from nwfpe/fpopcode.c
> + *
> + * 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.
> + */
> +
> +#include <linux/module.h>
> +#include <asm/opcodes.h>
> +
> +#define ARM_OPCODE_CONDITION_UNCOND 0xf
> +
> +/*
> + * condition code lookup table
> + * index into the table is test code: EQ, NE, ... LT, GT, AL, NV
> + *
> + * bit position in short is condition code: NZCV
> + */
> +static const unsigned short cc_map[16] = {
> + 0xF0F0, /* EQ == Z set */
> + 0x0F0F, /* NE */
> + 0xCCCC, /* CS == C set */
> + 0x3333, /* CC */
> + 0xFF00, /* MI == N set */
> + 0x00FF, /* PL */
> + 0xAAAA, /* VS == V set */
> + 0x5555, /* VC */
> + 0x0C0C, /* HI == C set && Z clear */
> + 0xF3F3, /* LS == C clear || Z set */
> + 0xAA55, /* GE == (N==V) */
> + 0x55AA, /* LT == (N!=V) */
> + 0x0A05, /* GT == (!Z && (N==V)) */
> + 0xF5FA, /* LE == (Z || (N!=V)) */
> + 0xFFFF, /* AL always */
> + 0 /* NV */
> +};
> +
> +/*
> + * Returns:
> + * ARM_OPCODE_CONDTEST_FAIL - if condition fails
> + * ARM_OPCODE_CONDTEST_PASS - if condition passes (including AL)
> + * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
> + * opcode space from v5 onwards
> + *
> + * Code that needs to check whether a condition has explicitly passed,
> + * should compare the return value to 1.
> + * Code that wants to check if a condition means that the instruction
> + * should be executed, should compare the return value to !0.
> + */
> +unsigned int arm_check_condition(unsigned int opcode, unsigned int psr)
> +{
> + unsigned int cc_bits = opcode >> 28;
> + unsigned int psr_cond = psr >> 28;
> +
> + if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
> + if ((cc_map[cc_bits] >> (psr_cond)) & 1)
> + return ARM_OPCODE_CONDTEST_PASS;
> + else
> + return ARM_OPCODE_CONDTEST_FAIL;
> + } else {
> + return ARM_OPCODE_CONDTEST_UNCOND;
> + }
> +}
> +
> +EXPORT_SYMBOL(arm_check_condition);
>
>
>
> _______________________________________________
> 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] 21+ messages in thread* [PATCH 1/4] Add generic ARM instruction set condition code checks.
2011-11-25 17:19 ` [PATCH 1/4] Add generic ARM instruction set " Leif Lindholm
2011-11-25 17:38 ` Dave Martin
@ 2011-11-30 16:59 ` Dave Martin
1 sibling, 0 replies; 21+ messages in thread
From: Dave Martin @ 2011-11-30 16:59 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Nov 25, 2011 at 05:19:23PM +0000, Leif Lindholm wrote:
> This patch breaks the ARM condition checking code out of nwfpe/fpopcode.{ch}
> into a standalone file for opcode operations. It also modifies the code
> somewhat for coding style adherence, and adds some temporary variables for
> increased readability.
>
> Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
> ---
> arch/arm/include/asm/opcodes.h | 20 ++++++++++++
> arch/arm/kernel/Makefile | 2 +
> arch/arm/kernel/opcodes.c | 68 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 89 insertions(+), 1 deletions(-)
> create mode 100644 arch/arm/include/asm/opcodes.h
> create mode 100644 arch/arm/kernel/opcodes.c
>
> diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
> new file mode 100644
> index 0000000..aea97bf
> --- /dev/null
> +++ b/arch/arm/include/asm/opcodes.h
> @@ -0,0 +1,20 @@
> +/*
> + * 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 unsigned int arm_check_condition(unsigned int opcode, unsigned int psr);
> +#endif
> +
> +#define ARM_OPCODE_CONDTEST_FAIL 0
> +#define ARM_OPCODE_CONDTEST_PASS 1
> +#define ARM_OPCODE_CONDTEST_UNCOND 2
> +
> +#endif /* __ASM_ARM_OPCODES_H */
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index 16eed6a..43b740d 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -13,7 +13,7 @@ CFLAGS_REMOVE_return_address.o = -pg
>
> # Object file lists.
>
> -obj-y := elf.o entry-armv.o entry-common.o irq.o \
> +obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \
> process.o ptrace.o return_address.o setup.o signal.o \
> sys_arm.o stacktrace.o time.o traps.o
>
> diff --git a/arch/arm/kernel/opcodes.c b/arch/arm/kernel/opcodes.c
> new file mode 100644
> index 0000000..c3171cc
> --- /dev/null
> +++ b/arch/arm/kernel/opcodes.c
> @@ -0,0 +1,68 @@
> +/*
> + * linux/arch/arm/kernel/opcodes.c
> + *
> + * A32 condition code lookup feature moved from nwfpe/fpopcode.c
> + *
> + * 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.
> + */
> +
> +#include <linux/module.h>
> +#include <asm/opcodes.h>
> +
> +#define ARM_OPCODE_CONDITION_UNCOND 0xf
> +
> +/*
> + * condition code lookup table
> + * index into the table is test code: EQ, NE, ... LT, GT, AL, NV
> + *
> + * bit position in short is condition code: NZCV
> + */
> +static const unsigned short cc_map[16] = {
> + 0xF0F0, /* EQ == Z set */
> + 0x0F0F, /* NE */
> + 0xCCCC, /* CS == C set */
> + 0x3333, /* CC */
> + 0xFF00, /* MI == N set */
> + 0x00FF, /* PL */
> + 0xAAAA, /* VS == V set */
> + 0x5555, /* VC */
> + 0x0C0C, /* HI == C set && Z clear */
> + 0xF3F3, /* LS == C clear || Z set */
> + 0xAA55, /* GE == (N==V) */
> + 0x55AA, /* LT == (N!=V) */
> + 0x0A05, /* GT == (!Z && (N==V)) */
> + 0xF5FA, /* LE == (Z || (N!=V)) */
> + 0xFFFF, /* AL always */
> + 0 /* NV */
> +};
> +
> +/*
> + * Returns:
> + * ARM_OPCODE_CONDTEST_FAIL - if condition fails
> + * ARM_OPCODE_CONDTEST_PASS - if condition passes (including AL)
> + * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
> + * opcode space from v5 onwards
> + *
> + * Code that needs to check whether a condition has explicitly passed,
> + * should compare the return value to 1.
This paragraph should refer to the symbolic constants -- there's not so
much point having them if people hard-code integer comparisons into all
the calling code.
The wording feels a bit confusing too. Maybe something like:
"Code that needs to check when an instruction is conditional and would
pass its condition check should check whether the return value ==
ARM_OPCODE_CONDTEST_PASS."
> + * Code that wants to check if a condition means that the instruction
> + * should be executed, should compare the return value to !0.
!0 == 1. I guess this is not what you mean.
Maybe:
"Code that needs to check when an instruction would architecturally
execute (including some instructions on ARMv5 and later which cannot be
conditional) should check whether the return value !=
ARM_OPCODE_CONDTEST_FAIL."
This documentation should perhaps move to opcodes.h, but I don't have a
strong opinion.
> + */
> +unsigned int arm_check_condition(unsigned int opcode, unsigned int psr)
> +{
> + unsigned int cc_bits = opcode >> 28;
> + unsigned int psr_cond = psr >> 28;
> +
> + if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
> + if ((cc_map[cc_bits] >> (psr_cond)) & 1)
> + return ARM_OPCODE_CONDTEST_PASS;
> + else
> + return ARM_OPCODE_CONDTEST_FAIL;
> + } else {
Remove the space before } (checkpatch.pl ought to pick this up)
> + return ARM_OPCODE_CONDTEST_UNCOND;
> + }
> +}
> +
> +EXPORT_SYMBOL(arm_check_condition);
Cheers
---Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 2/4] Use generic ARM instruction set condition code checks for nwfpe.
2011-11-25 17:19 [PATCH 0/4] Add generic ARM ISA condition code checks Leif Lindholm
2011-11-25 17:19 ` [PATCH 1/4] Add generic ARM instruction set " Leif Lindholm
@ 2011-11-25 17:19 ` Leif Lindholm
2011-11-25 17:19 ` [PATCH 3/4] Add condition code checking to SWP emulation handler Leif Lindholm
2011-11-25 17:20 ` [PATCH 4/4] Use generic ARM instruction set condition code checks for kprobes Leif Lindholm
3 siblings, 0 replies; 21+ messages in thread
From: Leif Lindholm @ 2011-11-25 17:19 UTC (permalink / raw)
To: linux-arm-kernel
This patch changes the nwfpe implementation to use the new generic
ARM instruction set condition code checks, rather than a local
implementation. It also removes the existing condition code checking,
which has been used for the generic support (in kernel/opcodes.{ch}).
Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
---
This code has not been tested beyond building, linking and booting.
arch/arm/nwfpe/entry.S | 8 +++++---
arch/arm/nwfpe/fpopcode.c | 26 --------------------------
arch/arm/nwfpe/fpopcode.h | 3 ---
3 files changed, 5 insertions(+), 32 deletions(-)
diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S
index cafa183..d18dde9 100644
--- a/arch/arm/nwfpe/entry.S
+++ b/arch/arm/nwfpe/entry.S
@@ -20,6 +20,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <asm/opcodes.h>
+
/* This is the kernel's entry point into the floating point emulator.
It is called from the kernel with code similar to this:
@@ -81,11 +83,11 @@ nwfpe_enter:
mov r6, r0 @ save the opcode
emulate:
ldr r1, [sp, #S_PSR] @ fetch the PSR
- bl checkCondition @ check the condition
- cmp r0, #0 @ r0 = 0 ==> condition failed
+ bl arm_check_condition @ check the condition
+ cmp r0, #ARM_OPCODE_CONDTEST_PASS @ condition passed?
@ if condition code failed to match, next insn
- beq next @ get the next instruction;
+ bne next @ get the next instruction;
mov r0, r6 @ prepare for EmulateAll()
bl EmulateAll @ emulate the instruction
diff --git a/arch/arm/nwfpe/fpopcode.c b/arch/arm/nwfpe/fpopcode.c
index 922b811..ff98346 100644
--- a/arch/arm/nwfpe/fpopcode.c
+++ b/arch/arm/nwfpe/fpopcode.c
@@ -61,29 +61,3 @@ const float32 float32Constant[] = {
0x41200000 /* single 10.0 */
};
-/* condition code lookup table
- index into the table is test code: EQ, NE, ... LT, GT, AL, NV
- bit position in short is condition code: NZCV */
-static const unsigned short aCC[16] = {
- 0xF0F0, // EQ == Z set
- 0x0F0F, // NE
- 0xCCCC, // CS == C set
- 0x3333, // CC
- 0xFF00, // MI == N set
- 0x00FF, // PL
- 0xAAAA, // VS == V set
- 0x5555, // VC
- 0x0C0C, // HI == C set && Z clear
- 0xF3F3, // LS == C clear || Z set
- 0xAA55, // GE == (N==V)
- 0x55AA, // LT == (N!=V)
- 0x0A05, // GT == (!Z && (N==V))
- 0xF5FA, // LE == (Z || (N!=V))
- 0xFFFF, // AL always
- 0 // NV
-};
-
-unsigned int checkCondition(const unsigned int opcode, const unsigned int ccodes)
-{
- return (aCC[opcode >> 28] >> (ccodes >> 28)) & 1;
-}
diff --git a/arch/arm/nwfpe/fpopcode.h b/arch/arm/nwfpe/fpopcode.h
index 786e4c9..78f02db 100644
--- a/arch/arm/nwfpe/fpopcode.h
+++ b/arch/arm/nwfpe/fpopcode.h
@@ -475,9 +475,6 @@ static inline unsigned int getDestinationSize(const unsigned int opcode)
return (nRc);
}
-extern unsigned int checkCondition(const unsigned int opcode,
- const unsigned int ccodes);
-
extern const float64 float64Constant[];
extern const float32 float32Constant[];
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 3/4] Add condition code checking to SWP emulation handler.
2011-11-25 17:19 [PATCH 0/4] Add generic ARM ISA condition code checks Leif Lindholm
2011-11-25 17:19 ` [PATCH 1/4] Add generic ARM instruction set " Leif Lindholm
2011-11-25 17:19 ` [PATCH 2/4] Use generic ARM instruction set condition code checks for nwfpe Leif Lindholm
@ 2011-11-25 17:19 ` Leif Lindholm
2011-11-30 17:01 ` Dave Martin
2011-11-25 17:20 ` [PATCH 4/4] Use generic ARM instruction set condition code checks for kprobes Leif Lindholm
3 siblings, 1 reply; 21+ messages in thread
From: Leif Lindholm @ 2011-11-25 17:19 UTC (permalink / raw)
To: linux-arm-kernel
This patch fixes two separate issues with the SWP emulation handler:
1: Certain processors implementing ARMv7-A can (legally) take an
undef exception even when the condition code would have meant that
the instruction should not have been executed.
2: Opcodes with all flags set (condition code = 0xf) have been reused
in recent, and not-so-recent, versions of the ARM architecture to
implement unconditional extensions to the instruction set. The
existing code would still have processed any undefs triggered by
executing an opcode with such a value.
This patch uses the new generic ARM instruction set condition code
checks to implement proper handling of these situations.
Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
---
arch/arm/kernel/swp_emulate.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index 5f452f8..8629bf7 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -25,6 +25,7 @@
#include <linux/syscalls.h>
#include <linux/perf_event.h>
+#include <asm/opcodes.h>
#include <asm/traps.h>
#include <asm/uaccess.h>
@@ -185,6 +186,19 @@ static int swp_handler(struct pt_regs *regs, unsigned int instr)
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->ARM_pc);
+ res = arm_check_condition(instr, regs->ARM_cpsr);
+ switch (res) {
+ case ARM_OPCODE_CONDTEST_FAIL: {
+ /* Condition failed - return to next instruction */
+ regs->ARM_pc += 4;
+ return 0;
+ } break;
+ case ARM_OPCODE_CONDTEST_UNCOND: {
+ /* If unconditional encoding - not a SWP, undef */
+ return -EFAULT;
+ } break;
+ }
+
if (current->pid != previous_pid) {
pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
current->comm, (unsigned long)current->pid);
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 3/4] Add condition code checking to SWP emulation handler.
2011-11-25 17:19 ` [PATCH 3/4] Add condition code checking to SWP emulation handler Leif Lindholm
@ 2011-11-30 17:01 ` Dave Martin
0 siblings, 0 replies; 21+ messages in thread
From: Dave Martin @ 2011-11-30 17:01 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Nov 25, 2011 at 05:19:53PM +0000, Leif Lindholm wrote:
> This patch fixes two separate issues with the SWP emulation handler:
> 1: Certain processors implementing ARMv7-A can (legally) take an
> undef exception even when the condition code would have meant that
> the instruction should not have been executed.
> 2: Opcodes with all flags set (condition code = 0xf) have been reused
> in recent, and not-so-recent, versions of the ARM architecture to
> implement unconditional extensions to the instruction set. The
> existing code would still have processed any undefs triggered by
> executing an opcode with such a value.
>
> This patch uses the new generic ARM instruction set condition code
> checks to implement proper handling of these situations.
>
> Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
> ---
> arch/arm/kernel/swp_emulate.c | 14 ++++++++++++++
> 1 files changed, 14 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
> index 5f452f8..8629bf7 100644
> --- a/arch/arm/kernel/swp_emulate.c
> +++ b/arch/arm/kernel/swp_emulate.c
> @@ -25,6 +25,7 @@
> #include <linux/syscalls.h>
> #include <linux/perf_event.h>
>
> +#include <asm/opcodes.h>
> #include <asm/traps.h>
> #include <asm/uaccess.h>
>
> @@ -185,6 +186,19 @@ static int swp_handler(struct pt_regs *regs, unsigned int instr)
>
> perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->ARM_pc);
>
> + res = arm_check_condition(instr, regs->ARM_cpsr);
> + switch (res) {
> + case ARM_OPCODE_CONDTEST_FAIL: {
> + /* Condition failed - return to next instruction */
> + regs->ARM_pc += 4;
> + return 0;
> + } break;
> + case ARM_OPCODE_CONDTEST_UNCOND: {
> + /* If unconditional encoding - not a SWP, undef */
> + return -EFAULT;
> + } break;
> + }
> +
Can we lose the extra { } inside the switch here?
Those cases contain no declarations, so there's no need for a nested
block in either case. This also solves the indentation problem.
Documentation/CodingStyle appears to prefer an unconditional break; to
be indented flush with the contents of the case block that it ends.
Cheers
---Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 4/4] Use generic ARM instruction set condition code checks for kprobes.
2011-11-25 17:19 [PATCH 0/4] Add generic ARM ISA condition code checks Leif Lindholm
` (2 preceding siblings ...)
2011-11-25 17:19 ` [PATCH 3/4] Add condition code checking to SWP emulation handler Leif Lindholm
@ 2011-11-25 17:20 ` Leif Lindholm
2011-11-27 12:24 ` Tixy
2011-11-30 17:02 ` Dave Martin
3 siblings, 2 replies; 21+ messages in thread
From: Leif Lindholm @ 2011-11-25 17:20 UTC (permalink / raw)
To: linux-arm-kernel
This patch changes the kprobes implementation to use the generic ARM
instruction set condition code checks, rather than a dedicated
implementation.
Cc: Tixy <tixy@yxit.co.uk>
Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
---
arch/arm/kernel/kprobes-test.c | 66 ++++------------------------------------
1 files changed, 6 insertions(+), 60 deletions(-)
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
index e17cdd6..278c275 100644
--- a/arch/arm/kernel/kprobes-test.c
+++ b/arch/arm/kernel/kprobes-test.c
@@ -202,6 +202,8 @@
#include <linux/slab.h>
#include <linux/kprobes.h>
+#include <asm/opcodes.h>
+
#include "kprobes.h"
#include "kprobes-test.h"
@@ -1048,67 +1050,11 @@ static int test_instance;
*/
#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
-static unsigned long test_check_cc(int cc, unsigned long cpsr)
+inline unsigned long test_check_cc(int cc, unsigned long cpsr)
{
- unsigned long temp;
-
- switch (cc) {
- case 0x0: /* eq */
- return cpsr & PSR_Z_BIT;
-
- case 0x1: /* ne */
- return (~cpsr) & PSR_Z_BIT;
-
- case 0x2: /* cs */
- return cpsr & PSR_C_BIT;
-
- case 0x3: /* cc */
- return (~cpsr) & PSR_C_BIT;
-
- case 0x4: /* mi */
- return cpsr & PSR_N_BIT;
-
- case 0x5: /* pl */
- return (~cpsr) & PSR_N_BIT;
-
- case 0x6: /* vs */
- return cpsr & PSR_V_BIT;
-
- case 0x7: /* vc */
- return (~cpsr) & PSR_V_BIT;
+ int ret = arm_check_condition(cc << 28, cpsr);
- case 0x8: /* hi */
- cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
- return cpsr & PSR_C_BIT;
-
- case 0x9: /* ls */
- cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
- return (~cpsr) & PSR_C_BIT;
-
- case 0xa: /* ge */
- cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- return (~cpsr) & PSR_N_BIT;
-
- case 0xb: /* lt */
- cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- return cpsr & PSR_N_BIT;
-
- case 0xc: /* gt */
- temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
- return (~temp) & PSR_N_BIT;
-
- case 0xd: /* le */
- temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
- return temp & PSR_N_BIT;
-
- case 0xe: /* al */
- case 0xf: /* unconditional */
- return true;
- }
- BUG();
- return false;
+ return (ret != ARM_OPCODE_CONDTEST_FAIL);
}
static int is_last_scenario;
@@ -1128,7 +1074,7 @@ static unsigned long test_context_cpsr(int scenario)
if (!test_case_is_thumb) {
/* Testing ARM code */
- probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;
+ probe_should_run = arm_check_condition(current_instruction, cpsr) != 0;
if (scenario == 15)
is_last_scenario = true;
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 4/4] Use generic ARM instruction set condition code checks for kprobes.
2011-11-25 17:20 ` [PATCH 4/4] Use generic ARM instruction set condition code checks for kprobes Leif Lindholm
@ 2011-11-27 12:24 ` Tixy
2011-11-30 17:02 ` Dave Martin
1 sibling, 0 replies; 21+ messages in thread
From: Tixy @ 2011-11-27 12:24 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2011-11-25 at 17:20 +0000, Leif Lindholm wrote:
> This patch changes the kprobes implementation to use the generic ARM
> instruction set condition code checks, rather than a dedicated
> implementation.
>
> Cc: Tixy <tixy@yxit.co.uk>
> Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
Acked-by: Jon Medhurst <tixy@yxit.co.uk>
> ---
> arch/arm/kernel/kprobes-test.c | 66 ++++------------------------------------
> 1 files changed, 6 insertions(+), 60 deletions(-)
>
> diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
> index e17cdd6..278c275 100644
> --- a/arch/arm/kernel/kprobes-test.c
> +++ b/arch/arm/kernel/kprobes-test.c
> @@ -202,6 +202,8 @@
> #include <linux/slab.h>
> #include <linux/kprobes.h>
>
> +#include <asm/opcodes.h>
> +
> #include "kprobes.h"
> #include "kprobes-test.h"
>
> @@ -1048,67 +1050,11 @@ static int test_instance;
> */
> #define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
>
> -static unsigned long test_check_cc(int cc, unsigned long cpsr)
> +inline unsigned long test_check_cc(int cc, unsigned long cpsr)
> {
> - unsigned long temp;
> -
> - switch (cc) {
> - case 0x0: /* eq */
> - return cpsr & PSR_Z_BIT;
> -
> - case 0x1: /* ne */
> - return (~cpsr) & PSR_Z_BIT;
> -
> - case 0x2: /* cs */
> - return cpsr & PSR_C_BIT;
> -
> - case 0x3: /* cc */
> - return (~cpsr) & PSR_C_BIT;
> -
> - case 0x4: /* mi */
> - return cpsr & PSR_N_BIT;
> -
> - case 0x5: /* pl */
> - return (~cpsr) & PSR_N_BIT;
> -
> - case 0x6: /* vs */
> - return cpsr & PSR_V_BIT;
> -
> - case 0x7: /* vc */
> - return (~cpsr) & PSR_V_BIT;
> + int ret = arm_check_condition(cc << 28, cpsr);
>
> - case 0x8: /* hi */
> - cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
> - return cpsr & PSR_C_BIT;
> -
> - case 0x9: /* ls */
> - cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
> - return (~cpsr) & PSR_C_BIT;
> -
> - case 0xa: /* ge */
> - cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
> - return (~cpsr) & PSR_N_BIT;
> -
> - case 0xb: /* lt */
> - cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
> - return cpsr & PSR_N_BIT;
> -
> - case 0xc: /* gt */
> - temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
> - temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
> - return (~temp) & PSR_N_BIT;
> -
> - case 0xd: /* le */
> - temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
> - temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
> - return temp & PSR_N_BIT;
> -
> - case 0xe: /* al */
> - case 0xf: /* unconditional */
> - return true;
> - }
> - BUG();
> - return false;
> + return (ret != ARM_OPCODE_CONDTEST_FAIL);
> }
>
> static int is_last_scenario;
> @@ -1128,7 +1074,7 @@ static unsigned long test_context_cpsr(int scenario)
>
> if (!test_case_is_thumb) {
> /* Testing ARM code */
> - probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;
> + probe_should_run = arm_check_condition(current_instruction, cpsr) != 0;
> if (scenario == 15)
> is_last_scenario = true;
>
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread* [PATCH 4/4] Use generic ARM instruction set condition code checks for kprobes.
2011-11-25 17:20 ` [PATCH 4/4] Use generic ARM instruction set condition code checks for kprobes Leif Lindholm
2011-11-27 12:24 ` Tixy
@ 2011-11-30 17:02 ` Dave Martin
1 sibling, 0 replies; 21+ messages in thread
From: Dave Martin @ 2011-11-30 17:02 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Nov 25, 2011 at 05:20:05PM +0000, Leif Lindholm wrote:
> This patch changes the kprobes implementation to use the generic ARM
> instruction set condition code checks, rather than a dedicated
> implementation.
>
> Cc: Tixy <tixy@yxit.co.uk>
> Signed-off-by: Leif Lindholm <leif.lindholm@arm.com>
> ---
> arch/arm/kernel/kprobes-test.c | 66 ++++------------------------------------
> 1 files changed, 6 insertions(+), 60 deletions(-)
>
> diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
> index e17cdd6..278c275 100644
> --- a/arch/arm/kernel/kprobes-test.c
> +++ b/arch/arm/kernel/kprobes-test.c
> @@ -202,6 +202,8 @@
> #include <linux/slab.h>
> #include <linux/kprobes.h>
>
> +#include <asm/opcodes.h>
> +
> #include "kprobes.h"
> #include "kprobes-test.h"
>
> @@ -1048,67 +1050,11 @@ static int test_instance;
> */
> #define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)
>
> -static unsigned long test_check_cc(int cc, unsigned long cpsr)
> +inline unsigned long test_check_cc(int cc, unsigned long cpsr)
> {
> - unsigned long temp;
> -
> - switch (cc) {
> - case 0x0: /* eq */
> - return cpsr & PSR_Z_BIT;
> -
> - case 0x1: /* ne */
> - return (~cpsr) & PSR_Z_BIT;
> -
> - case 0x2: /* cs */
> - return cpsr & PSR_C_BIT;
> -
> - case 0x3: /* cc */
> - return (~cpsr) & PSR_C_BIT;
> -
> - case 0x4: /* mi */
> - return cpsr & PSR_N_BIT;
> -
> - case 0x5: /* pl */
> - return (~cpsr) & PSR_N_BIT;
> -
> - case 0x6: /* vs */
> - return cpsr & PSR_V_BIT;
> -
> - case 0x7: /* vc */
> - return (~cpsr) & PSR_V_BIT;
> + int ret = arm_check_condition(cc << 28, cpsr);
>
> - case 0x8: /* hi */
> - cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
> - return cpsr & PSR_C_BIT;
> -
> - case 0x9: /* ls */
> - cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
> - return (~cpsr) & PSR_C_BIT;
> -
> - case 0xa: /* ge */
> - cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
> - return (~cpsr) & PSR_N_BIT;
> -
> - case 0xb: /* lt */
> - cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
> - return cpsr & PSR_N_BIT;
> -
> - case 0xc: /* gt */
> - temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
> - temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
> - return (~temp) & PSR_N_BIT;
> -
> - case 0xd: /* le */
> - temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
> - temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
> - return temp & PSR_N_BIT;
> -
> - case 0xe: /* al */
> - case 0xf: /* unconditional */
> - return true;
> - }
> - BUG();
> - return false;
> + return (ret != ARM_OPCODE_CONDTEST_FAIL);
Redundant ().
I also don't see a reason not to do the following:
return arm_check_condition(cc << 28, cpsr) != ARM_OPCODE_CONDTEST_FAIL;
Up to you, though. The presence of "ret" is harmless; the compiler
ought to generate the exact same code in any case.
> }
>
> static int is_last_scenario;
> @@ -1128,7 +1074,7 @@ static unsigned long test_context_cpsr(int scenario)
>
> if (!test_case_is_thumb) {
> /* Testing ARM code */
> - probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;
> + probe_should_run = arm_check_condition(current_instruction, cpsr) != 0;
Use the appropriate symbolic constant for this comparison.
Cheers
---Dave
^ permalink raw reply [flat|nested] 21+ messages in thread