aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRobin Getz <robin.getz@analog.com>2010-03-16 10:40:17 -0400
committerMike Frysinger <vapier@gentoo.org>2010-05-22 14:18:56 -0400
commit6ce3e9c2a2cfb8849dd471349fe5e6bc37c0f13f (patch)
tree9575e410b1fd9bbd3fab680ea4f5c3d7d8e832e0 /arch
parent2620c83668660d950cb4295aeb7147f1e599c638 (diff)
Blackfin: add support for the DBGA (debug assert) pseudo insn
A few pseudo debug insns exist to make testing of simulators easier. Since these don't actually exist in the hardware, we have to have the exception handler take care of emulating these. This allows sim test cases to be executed unmodified under Linux and thus simplify debugging greatly. Signed-off-by: Robin Getz <robin.getz@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/blackfin/Kconfig.debug9
-rw-r--r--arch/blackfin/include/asm/pseudo_instructions.h17
-rw-r--r--arch/blackfin/kernel/Makefile1
-rw-r--r--arch/blackfin/kernel/pseudodbg.c73
-rw-r--r--arch/blackfin/kernel/traps.c15
5 files changed, 115 insertions, 0 deletions
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug
index aec89a5280b..3c49f76b37b 100644
--- a/arch/blackfin/Kconfig.debug
+++ b/arch/blackfin/Kconfig.debug
@@ -264,4 +264,13 @@ config BFIN_ISRAM_SELF_TEST
264 help 264 help
265 Run some self tests of the isram driver code at boot. 265 Run some self tests of the isram driver code at boot.
266 266
267config BFIN_PSEUDODBG_INSNS
268 bool "Support pseudo debug instructions"
269 default n
270 help
271 This option allows the kernel to emulate some pseudo instructions which
272 allow simulator test cases to be run under Linux with no changes.
273
274 Most people should say N here.
275
267endmenu 276endmenu
diff --git a/arch/blackfin/include/asm/pseudo_instructions.h b/arch/blackfin/include/asm/pseudo_instructions.h
new file mode 100644
index 00000000000..7173719fb53
--- /dev/null
+++ b/arch/blackfin/include/asm/pseudo_instructions.h
@@ -0,0 +1,17 @@
1/*
2 * header file for pseudo instructions
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#ifndef _BLACKFIN_PSEUDO_
10#define _BLACKFIN_PSEUDO_
11
12#include <linux/types.h>
13#include <asm/ptrace.h>
14
15extern bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode);
16
17#endif
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 2fc7f32ae32..30d0d1f01dc 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
31obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o 31obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o
32obj-$(CONFIG_STACKTRACE) += stacktrace.o 32obj-$(CONFIG_STACKTRACE) += stacktrace.o
33obj-$(CONFIG_DEBUG_VERBOSE) += trace.o 33obj-$(CONFIG_DEBUG_VERBOSE) += trace.o
34obj-$(CONFIG_BFIN_PSEUDODBG_INSNS) += pseudodbg.o
34 35
35# the kgdb test puts code into L2 and without linker 36# the kgdb test puts code into L2 and without linker
36# relaxation, we need to force long calls to/from it 37# relaxation, we need to force long calls to/from it
diff --git a/arch/blackfin/kernel/pseudodbg.c b/arch/blackfin/kernel/pseudodbg.c
new file mode 100644
index 00000000000..4474b8db350
--- /dev/null
+++ b/arch/blackfin/kernel/pseudodbg.c
@@ -0,0 +1,73 @@
1/* The fake debug assert instructions
2 *
3 * Copyright 2010 Analog Devices Inc.
4 *
5 * Licensed under the GPL-2 or later
6 */
7
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/ptrace.h>
11
12#define PseudoDbg_Assert_opcode 0xf0000000
13#define PseudoDbg_Assert_expected_bits 0
14#define PseudoDbg_Assert_expected_mask 0xffff
15#define PseudoDbg_Assert_regtest_bits 16
16#define PseudoDbg_Assert_regtest_mask 0x7
17#define PseudoDbg_Assert_grp_bits 19
18#define PseudoDbg_Assert_grp_mask 0x7
19#define PseudoDbg_Assert_dbgop_bits 22
20#define PseudoDbg_Assert_dbgop_mask 0x3
21#define PseudoDbg_Assert_dontcare_bits 24
22#define PseudoDbg_Assert_dontcare_mask 0x7
23#define PseudoDbg_Assert_code_bits 27
24#define PseudoDbg_Assert_code_mask 0x1f
25
26bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode)
27{
28 int expected = ((opcode >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
29 int dbgop = ((opcode >> (PseudoDbg_Assert_dbgop_bits)) & PseudoDbg_Assert_dbgop_mask);
30 int grp = ((opcode >> (PseudoDbg_Assert_grp_bits)) & PseudoDbg_Assert_grp_mask);
31 int regtest = ((opcode >> (PseudoDbg_Assert_regtest_bits)) & PseudoDbg_Assert_regtest_mask);
32 long *value = &fp->r0;
33
34 if ((opcode & 0xFF000000) != PseudoDbg_Assert_opcode)
35 return false;
36
37 /* Only do Dregs and Pregs for now */
38 if (grp > 1)
39 return false;
40
41 /*
42 * Unfortunately, the pt_regs structure is not laid out the same way as the
43 * hardware register file, so we need to do some fix ups.
44 */
45 if (grp == 0 || (grp == 1 && regtest < 6))
46 value -= (regtest + 8 * grp);
47 else if (grp == 1 && regtest == 6)
48 value = &fp->usp;
49 else if (grp == 1 && regtest == 7)
50 value = &fp->fp;
51
52 if (dbgop == 0 || dbgop == 2) {
53 /* DBGA ( regs_lo , uimm16 ) */
54 /* DBGAL ( regs , uimm16 ) */
55 if (expected != (*value & 0xFFFF)) {
56 pr_notice("DBGA (%s%i.L,0x%x) failure, got 0x%x\n", grp ? "P" : "R",
57 regtest, expected, (unsigned int)(*value & 0xFFFF));
58 return false;
59 }
60
61 } else if (dbgop == 1 || dbgop == 3) {
62 /* DBGA ( regs_hi , uimm16 ) */
63 /* DBGAH ( regs , uimm16 ) */
64 if (expected != ((*value >> 16) & 0xFFFF)) {
65 pr_notice("DBGA (%s%i.H,0x%x) failure, got 0x%x\n", grp ? "P" : "R",
66 regtest, expected, (unsigned int)((*value >> 16) & 0xFFFF));
67 return false;
68 }
69 }
70
71 fp->pc += 4;
72 return true;
73}
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index fffcf8a516b..9369836365b 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -16,6 +16,7 @@
16#include <linux/irq.h> 16#include <linux/irq.h>
17#include <asm/trace.h> 17#include <asm/trace.h>
18#include <asm/fixed_code.h> 18#include <asm/fixed_code.h>
19#include <asm/pseudo_instructions.h>
19 20
20#ifdef CONFIG_KGDB 21#ifdef CONFIG_KGDB
21# include <linux/kgdb.h> 22# include <linux/kgdb.h>
@@ -68,6 +69,9 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
68#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 69#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
69 int j; 70 int j;
70#endif 71#endif
72#ifdef CONFIG_BFIN_PSEUDODBG_INSNS
73 int opcode;
74#endif
71 unsigned int cpu = raw_smp_processor_id(); 75 unsigned int cpu = raw_smp_processor_id();
72 const char *strerror = NULL; 76 const char *strerror = NULL;
73 int sig = 0; 77 int sig = 0;
@@ -200,6 +204,17 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
200 } 204 }
201 } 205 }
202#endif 206#endif
207#ifdef CONFIG_BFIN_PSEUDODBG_INSNS
208 /*
209 * Support for the fake instructions, if the instruction fails,
210 * then just execute a illegal opcode failure (like normal).
211 * Don't support these instructions inside the kernel
212 */
213 if (!kernel_mode_regs(fp) && get_instruction(&opcode, (unsigned short *)fp->pc)) {
214 if (execute_pseudodbg_assert(fp, opcode))
215 goto traps_done;
216 }
217#endif
203 info.si_code = ILL_ILLOPC; 218 info.si_code = ILL_ILLOPC;
204 sig = SIGILL; 219 sig = SIGILL;
205 strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE); 220 strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE);