freebsd-skq/sys/arm/include/db_machdep.h
Zbigniew Bodek 595f8a5905 Introduce support for HW watchpoints and single stepping for ARMv6/v7
Allows for using hardware watchpoints for 1, 2, 4, 8 byte long addresses.
The default configuration of watchpoint is RW but code allows to select
RO or WO and X.
Since debugging registers are per-CPU (CP14) the watchpoint is set on
the CPU that was lucky (or not) to enter DDB.

HW breakpoints are used to perform single step in KDB.
When HW breakpoint is enabled all watchpoints are temporary disabled
to avoid recursive abort on both watchpoint and breakpoint.
In case of branch, the breakpoint is set to both - next instruction
and possible branch address. This requires at least 2 breakpoints
supported in the CPU however this is a must for ARMv6/v7 CPUs.

Reviewed by:   imp
Submitted by:  Zbigniew Bodek <zbb@semihalf.com>
Obtained from: Semihalf
Sponsored by:  Juniper Networks Inc.
Differential Revision: https://reviews.freebsd.org/D4037
2016-01-25 18:02:28 +00:00

106 lines
3.1 KiB
C

/*-
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*
* from: FreeBSD: src/sys/i386/include/db_machdep.h,v 1.16 1999/10/04
* $FreeBSD$
*/
#ifndef _MACHINE_DB_MACHDEP_H_
#define _MACHINE_DB_MACHDEP_H_
#include <machine/frame.h>
#include <machine/trap.h>
#include <machine/armreg.h>
#include <machine/acle-compat.h>
#define T_BREAKPOINT (1)
#define T_WATCHPOINT (2)
typedef vm_offset_t db_addr_t;
typedef int db_expr_t;
#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_regs.sf_pc)
#define BKPT_INST (KERNEL_BREAKPOINT)
#define BKPT_SIZE (INSN_SIZE)
#define BKPT_SET(inst) (BKPT_INST)
#define BKPT_SKIP do { \
kdb_frame->tf_pc += BKPT_SIZE; \
} while (0)
#if __ARM_ARCH >= 6
#define db_clear_single_step kdb_cpu_clear_singlestep
#define db_set_single_step kdb_cpu_set_singlestep
#define db_pc_is_singlestep kdb_cpu_pc_is_singlestep
#else
#define SOFTWARE_SSTEP 1
#endif
#define IS_BREAKPOINT_TRAP(type, code) (type == T_BREAKPOINT)
#define IS_WATCHPOINT_TRAP(type, code) (type == T_WATCHPOINT)
#define inst_trap_return(ins) (0)
/* ldmxx reg, {..., pc}
01800000 stack mode
000f0000 register
0000ffff register list */
/* mov pc, reg
0000000f register */
#define inst_return(ins) (((ins) & 0x0e108000) == 0x08108000 || \
((ins) & 0x0ff0fff0) == 0x01a0f000 || \
((ins) & 0x0ffffff0) == 0x012fff10) /* bx */
/* bl ...
00ffffff offset>>2 */
#define inst_call(ins) (((ins) & 0x0f000000) == 0x0b000000)
/* b ...
00ffffff offset>>2 */
/* ldr pc, [pc, reg, lsl #2]
0000000f register */
#define inst_branch(ins) (((ins) & 0x0f000000) == 0x0a000000 || \
((ins) & 0x0fdffff0) == 0x079ff100 || \
((ins) & 0x0cd0f000) == 0x0490f000 || \
((ins) & 0x0ffffff0) == 0x012fff30 || /* blx */ \
((ins) & 0x0de0f000) == 0x0080f000)
#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 32
int db_validate_address(vm_offset_t);
u_int branch_taken (u_int insn, db_addr_t pc);
#ifdef __ARMEB__
#define BYTE_MSF (1)
#endif
#endif /* !_MACHINE_DB_MACHDEP_H_ */