summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2004-11-21 18:11:39 +0000
committercognet <cognet@FreeBSD.org>2004-11-21 18:11:39 +0000
commit22b168ab2449334b15b55b276945245bb1660a9d (patch)
treedf736a61622aa96c6e0acdf37b6a2125c736826d /sys/arm
parent774795721abcc723b01400a6ab6a346139fcd6b8 (diff)
downloadFreeBSD-src-22b168ab2449334b15b55b276945245bb1660a9d.zip
FreeBSD-src-22b168ab2449334b15b55b276945245bb1660a9d.tar.gz
Implement breakpoints and single stepping on arm.
Obtained from: NetBSD
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/db_interface.c97
-rw-r--r--sys/arm/arm/undefined.c14
-rw-r--r--sys/arm/include/db_machdep.h17
-rw-r--r--sys/arm/include/kdb.h2
4 files changed, 109 insertions, 21 deletions
diff --git a/sys/arm/arm/db_interface.c b/sys/arm/arm/db_interface.c
index d1c349a..8832097 100644
--- a/sys/arm/arm/db_interface.c
+++ b/sys/arm/arm/db_interface.c
@@ -43,6 +43,9 @@ __FBSDID("$FreeBSD$");
#include <sys/reboot.h>
#include <sys/systm.h> /* just for boothowto */
#include <sys/exec.h>
+#ifdef KDB
+#include <sys/kdb.h>
+#endif
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -192,11 +195,6 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data)
char *dst;
size_t loop;
- /* If any part is in kernel text, use db_write_text() */
- if (addr >= (vm_offset_t) btext && addr < (vm_offset_t) etext) {
- return (-1);
- }
-
dst = (char *)addr;
if (db_validate_address((u_int)dst)) {
db_printf("address %p is invalid\n", dst);
@@ -229,4 +227,93 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data)
}
+static u_int
+db_fetch_reg(int reg)
+{
+
+ switch (reg) {
+ case 0:
+ return (kdb_frame->tf_r0);
+ case 1:
+ return (kdb_frame->tf_r1);
+ case 2:
+ return (kdb_frame->tf_r2);
+ case 3:
+ return (kdb_frame->tf_r3);
+ case 4:
+ return (kdb_frame->tf_r4);
+ case 5:
+ return (kdb_frame->tf_r5);
+ case 6:
+ return (kdb_frame->tf_r6);
+ case 7:
+ return (kdb_frame->tf_r7);
+ case 8:
+ return (kdb_frame->tf_r8);
+ case 9:
+ return (kdb_frame->tf_r9);
+ case 10:
+ return (kdb_frame->tf_r10);
+ case 11:
+ return (kdb_frame->tf_r11);
+ case 12:
+ return (kdb_frame->tf_r12);
+ case 13:
+ return (kdb_frame->tf_svc_sp);
+ case 14:
+ return (kdb_frame->tf_svc_lr);
+ case 15:
+ return (kdb_frame->tf_pc);
+ default:
+ panic("db_fetch_reg: botch");
+ }
+}
+
+u_int
+branch_taken(u_int insn, db_addr_t pc)
+{
+ u_int addr, nregs;
+
+ switch ((insn >> 24) & 0xf) {
+ case 0xa: /* b ... */
+ case 0xb: /* bl ... */
+ addr = ((insn << 2) & 0x03ffffff);
+ if (addr & 0x02000000)
+ addr |= 0xfc000000;
+ return (pc + 8 + addr);
+ case 0x7: /* ldr pc, [pc, reg, lsl #2] */
+ addr = db_fetch_reg(insn & 0xf);
+ addr = pc + 8 + (addr << 2);
+ db_read_bytes(addr, 4, (char *)&addr);
+ return (addr);
+ case 0x1: /* mov pc, reg */
+ addr = db_fetch_reg(insn & 0xf);
+ return (addr);
+ case 0x8: /* ldmxx reg, {..., pc} */
+ case 0x9:
+ addr = db_fetch_reg((insn >> 16) & 0xf);
+ nregs = (insn & 0x5555) + ((insn >> 1) & 0x5555);
+ nregs = (nregs & 0x3333) + ((nregs >> 2) & 0x3333);
+ nregs = (nregs + (nregs >> 4)) & 0x0f0f;
+ nregs = (nregs + (nregs >> 8)) & 0x001f;
+ switch ((insn >> 23) & 0x3) {
+ case 0x0: /* ldmda */
+ addr = addr - 0;
+ break;
+ case 0x1: /* ldmia */
+ addr = addr + 0 + ((nregs - 1) << 2);
+ break;
+ case 0x2: /* ldmdb */
+ addr = addr - 4;
+ break;
+ case 0x3: /* ldmib */
+ addr = addr + 4 + ((nregs - 1) << 2);
+ break;
+ }
+ db_read_bytes(addr, 4, (char *)&addr);
+ return (addr);
+ default:
+ panic("branch_taken: botch");
+ }
+}
diff --git a/sys/arm/arm/undefined.c b/sys/arm/arm/undefined.c
index 0c8ea41..8632867 100644
--- a/sys/arm/arm/undefined.c
+++ b/sys/arm/arm/undefined.c
@@ -45,6 +45,8 @@
*/
+#include "opt_ddb.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -263,21 +265,13 @@ undefinedinstruction(trapframe_t *frame)
if ((fault_code & FAULT_USER) == 0) {
if (fault_instruction == KERNEL_BREAKPOINT) {
#ifdef KDB
- kdb_trap(0, 0, frame);
+ kdb_trap(T_BREAKPOINT, 0, frame);
#else
printf("No debugger in kernel.\n");
#endif
- frame->tf_pc += 4;
return;
- } else {
-#ifdef KDB
- printf("Undefined instruction in kernel.\n");
- kdb_trap(0, 0, frame);
-#else
+ } else
panic("Undefined instruction in kernel.\n");
-#endif
- }
-
}
#ifdef FAST_FPE
diff --git a/sys/arm/include/db_machdep.h b/sys/arm/include/db_machdep.h
index f40daa5..0682311 100644
--- a/sys/arm/include/db_machdep.h
+++ b/sys/arm/include/db_machdep.h
@@ -34,8 +34,6 @@
#include <machine/trap.h>
#include <machine/armreg.h>
-#define BYTE_MSF (1)
-
#define T_BREAKPOINT (1)
typedef vm_offset_t db_addr_t;
typedef int db_expr_t;
@@ -50,8 +48,7 @@ typedef int db_expr_t;
kdb_frame->tf_pc += BKPT_SIZE; \
} while (0)
-#define db_clear_single_step(regs)
-#define db_set_single_step(regs)
+#define SOFTWARE_SSTEP 1
#define IS_BREAKPOINT_TRAP(type, code) (type == T_BREAKPOINT)
#define IS_WATCHPOINT_TRAP(type, code) (0)
@@ -65,7 +62,8 @@ typedef int db_expr_t;
/* mov pc, reg
0000000f register */
#define inst_return(ins) (((ins) & 0x0e108000) == 0x08108000 || \
- ((ins) & 0x0ff0fff0) == 0x01a0f000)
+ ((ins) & 0x0ff0fff0) == 0x01a0f000 || \
+ ((ins) & 0x0ffffff0) == 0x012fff10) /* bx */
/* bl ...
00ffffff offset>>2 */
#define inst_call(ins) (((ins) & 0x0f000000) == 0x0b000000)
@@ -74,14 +72,21 @@ typedef int db_expr_t;
/* ldr pc, [pc, reg, lsl #2]
0000000f register */
+#define inst_branch(ins) (((ins) & 0x0f000000) == 0x0a000000 || \
+ ((ins) & 0x0fdffff0) == 0x079ff100)
#define inst_load(ins) (0)
#define inst_store(ins) (0)
+#define next_instr_address(pc, bd) ((bd) ? (pc) : ((pc) + INSN_SIZE))
+
#define DB_SMALL_VALUE_MAX (0x7fffffff)
#define DB_SMALL_VALUE_MIN (-0x40001)
-#define DB_ELFSIZE 64
+#define DB_ELFSIZE 32
int db_validate_address(vm_offset_t);
+
+u_int branch_taken (u_int insn, u_int pc);
+
#endif /* !_MACHINE_DB_MACHDEP_H_ */
diff --git a/sys/arm/include/kdb.h b/sys/arm/include/kdb.h
index ba8b3b9..0adf7e1 100644
--- a/sys/arm/include/kdb.h
+++ b/sys/arm/include/kdb.h
@@ -31,6 +31,7 @@
#include <machine/frame.h>
#include <machine/psl.h>
+#include <machine/cpufunc.h>
static __inline void
kdb_cpu_clear_singlestep(void)
@@ -45,6 +46,7 @@ kdb_cpu_set_singlestep(void)
static __inline void
kdb_cpu_trap(int type, int code)
{
+ cpu_idcache_wbinv_all();
}
#endif /* _MACHINE_KDB_H_ */
OpenPOWER on IntegriCloud