diff options
author | Will Deacon <will.deacon@arm.com> | 2012-03-05 06:49:33 -0500 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2012-09-17 08:42:14 -0400 |
commit | 478fcb2cdb2351dcfc3fb23f42d76f4436ee4149 (patch) | |
tree | f5d0be182e1ca20a1c539d1632cc27d4d910d5db /arch/arm64/include/asm | |
parent | 53631b54c8704fe5de435582c82ddbc0bfabf06a (diff) |
arm64: Debugging support
This patch adds ptrace, debug monitors and hardware breakpoints support.
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Olof Johansson <olof@lixom.net>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm64/include/asm')
-rw-r--r-- | arch/arm64/include/asm/debug-monitors.h | 88 | ||||
-rw-r--r-- | arch/arm64/include/asm/hw_breakpoint.h | 137 |
2 files changed, 225 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h new file mode 100644 index 000000000000..7eaa0b302493 --- /dev/null +++ b/arch/arm64/include/asm/debug-monitors.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_DEBUG_MONITORS_H | ||
17 | #define __ASM_DEBUG_MONITORS_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | #define DBG_ESR_EVT(x) (((x) >> 27) & 0x7) | ||
22 | |||
23 | /* AArch64 */ | ||
24 | #define DBG_ESR_EVT_HWBP 0x0 | ||
25 | #define DBG_ESR_EVT_HWSS 0x1 | ||
26 | #define DBG_ESR_EVT_HWWP 0x2 | ||
27 | #define DBG_ESR_EVT_BRK 0x6 | ||
28 | |||
29 | enum debug_el { | ||
30 | DBG_ACTIVE_EL0 = 0, | ||
31 | DBG_ACTIVE_EL1, | ||
32 | }; | ||
33 | |||
34 | /* AArch32 */ | ||
35 | #define DBG_ESR_EVT_BKPT 0x4 | ||
36 | #define DBG_ESR_EVT_VECC 0x5 | ||
37 | |||
38 | #define AARCH32_BREAK_ARM 0x07f001f0 | ||
39 | #define AARCH32_BREAK_THUMB 0xde01 | ||
40 | #define AARCH32_BREAK_THUMB2_LO 0xf7f0 | ||
41 | #define AARCH32_BREAK_THUMB2_HI 0xa000 | ||
42 | |||
43 | #ifndef __ASSEMBLY__ | ||
44 | struct task_struct; | ||
45 | |||
46 | #define local_dbg_save(flags) \ | ||
47 | do { \ | ||
48 | typecheck(unsigned long, flags); \ | ||
49 | asm volatile( \ | ||
50 | "mrs %0, daif // local_dbg_save\n" \ | ||
51 | "msr daifset, #8" \ | ||
52 | : "=r" (flags) : : "memory"); \ | ||
53 | } while (0) | ||
54 | |||
55 | #define local_dbg_restore(flags) \ | ||
56 | do { \ | ||
57 | typecheck(unsigned long, flags); \ | ||
58 | asm volatile( \ | ||
59 | "msr daif, %0 // local_dbg_restore\n" \ | ||
60 | : : "r" (flags) : "memory"); \ | ||
61 | } while (0) | ||
62 | |||
63 | #define DBG_ARCH_ID_RESERVED 0 /* In case of ptrace ABI updates. */ | ||
64 | |||
65 | u8 debug_monitors_arch(void); | ||
66 | |||
67 | void enable_debug_monitors(enum debug_el el); | ||
68 | void disable_debug_monitors(enum debug_el el); | ||
69 | |||
70 | void user_rewind_single_step(struct task_struct *task); | ||
71 | void user_fastforward_single_step(struct task_struct *task); | ||
72 | |||
73 | void kernel_enable_single_step(struct pt_regs *regs); | ||
74 | void kernel_disable_single_step(void); | ||
75 | int kernel_active_single_step(void); | ||
76 | |||
77 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
78 | int reinstall_suspended_bps(struct pt_regs *regs); | ||
79 | #else | ||
80 | static inline int reinstall_suspended_bps(struct pt_regs *regs) | ||
81 | { | ||
82 | return -ENODEV; | ||
83 | } | ||
84 | #endif | ||
85 | |||
86 | #endif /* __ASSEMBLY */ | ||
87 | #endif /* __KERNEL__ */ | ||
88 | #endif /* __ASM_DEBUG_MONITORS_H */ | ||
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h new file mode 100644 index 000000000000..d064047612b1 --- /dev/null +++ b/arch/arm64/include/asm/hw_breakpoint.h | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 ARM Ltd. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #ifndef __ASM_HW_BREAKPOINT_H | ||
17 | #define __ASM_HW_BREAKPOINT_H | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | struct arch_hw_breakpoint_ctrl { | ||
22 | u32 __reserved : 19, | ||
23 | len : 8, | ||
24 | type : 2, | ||
25 | privilege : 2, | ||
26 | enabled : 1; | ||
27 | }; | ||
28 | |||
29 | struct arch_hw_breakpoint { | ||
30 | u64 address; | ||
31 | u64 trigger; | ||
32 | struct arch_hw_breakpoint_ctrl ctrl; | ||
33 | }; | ||
34 | |||
35 | static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl) | ||
36 | { | ||
37 | return (ctrl.len << 5) | (ctrl.type << 3) | (ctrl.privilege << 1) | | ||
38 | ctrl.enabled; | ||
39 | } | ||
40 | |||
41 | static inline void decode_ctrl_reg(u32 reg, | ||
42 | struct arch_hw_breakpoint_ctrl *ctrl) | ||
43 | { | ||
44 | ctrl->enabled = reg & 0x1; | ||
45 | reg >>= 1; | ||
46 | ctrl->privilege = reg & 0x3; | ||
47 | reg >>= 2; | ||
48 | ctrl->type = reg & 0x3; | ||
49 | reg >>= 2; | ||
50 | ctrl->len = reg & 0xff; | ||
51 | } | ||
52 | |||
53 | /* Breakpoint */ | ||
54 | #define ARM_BREAKPOINT_EXECUTE 0 | ||
55 | |||
56 | /* Watchpoints */ | ||
57 | #define ARM_BREAKPOINT_LOAD 1 | ||
58 | #define ARM_BREAKPOINT_STORE 2 | ||
59 | #define AARCH64_ESR_ACCESS_MASK (1 << 6) | ||
60 | |||
61 | /* Privilege Levels */ | ||
62 | #define AARCH64_BREAKPOINT_EL1 1 | ||
63 | #define AARCH64_BREAKPOINT_EL0 2 | ||
64 | |||
65 | /* Lengths */ | ||
66 | #define ARM_BREAKPOINT_LEN_1 0x1 | ||
67 | #define ARM_BREAKPOINT_LEN_2 0x3 | ||
68 | #define ARM_BREAKPOINT_LEN_4 0xf | ||
69 | #define ARM_BREAKPOINT_LEN_8 0xff | ||
70 | |||
71 | /* Kernel stepping */ | ||
72 | #define ARM_KERNEL_STEP_NONE 0 | ||
73 | #define ARM_KERNEL_STEP_ACTIVE 1 | ||
74 | #define ARM_KERNEL_STEP_SUSPEND 2 | ||
75 | |||
76 | /* | ||
77 | * Limits. | ||
78 | * Changing these will require modifications to the register accessors. | ||
79 | */ | ||
80 | #define ARM_MAX_BRP 16 | ||
81 | #define ARM_MAX_WRP 16 | ||
82 | #define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP) | ||
83 | |||
84 | /* Virtual debug register bases. */ | ||
85 | #define AARCH64_DBG_REG_BVR 0 | ||
86 | #define AARCH64_DBG_REG_BCR (AARCH64_DBG_REG_BVR + ARM_MAX_BRP) | ||
87 | #define AARCH64_DBG_REG_WVR (AARCH64_DBG_REG_BCR + ARM_MAX_BRP) | ||
88 | #define AARCH64_DBG_REG_WCR (AARCH64_DBG_REG_WVR + ARM_MAX_WRP) | ||
89 | |||
90 | /* Debug register names. */ | ||
91 | #define AARCH64_DBG_REG_NAME_BVR "bvr" | ||
92 | #define AARCH64_DBG_REG_NAME_BCR "bcr" | ||
93 | #define AARCH64_DBG_REG_NAME_WVR "wvr" | ||
94 | #define AARCH64_DBG_REG_NAME_WCR "wcr" | ||
95 | |||
96 | /* Accessor macros for the debug registers. */ | ||
97 | #define AARCH64_DBG_READ(N, REG, VAL) do {\ | ||
98 | asm volatile("mrs %0, dbg" REG #N "_el1" : "=r" (VAL));\ | ||
99 | } while (0) | ||
100 | |||
101 | #define AARCH64_DBG_WRITE(N, REG, VAL) do {\ | ||
102 | asm volatile("msr dbg" REG #N "_el1, %0" :: "r" (VAL));\ | ||
103 | } while (0) | ||
104 | |||
105 | struct task_struct; | ||
106 | struct notifier_block; | ||
107 | struct perf_event; | ||
108 | struct pmu; | ||
109 | |||
110 | extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, | ||
111 | int *gen_len, int *gen_type); | ||
112 | extern int arch_check_bp_in_kernelspace(struct perf_event *bp); | ||
113 | extern int arch_validate_hwbkpt_settings(struct perf_event *bp); | ||
114 | extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, | ||
115 | unsigned long val, void *data); | ||
116 | |||
117 | extern int arch_install_hw_breakpoint(struct perf_event *bp); | ||
118 | extern void arch_uninstall_hw_breakpoint(struct perf_event *bp); | ||
119 | extern void hw_breakpoint_pmu_read(struct perf_event *bp); | ||
120 | extern int hw_breakpoint_slots(int type); | ||
121 | |||
122 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
123 | extern void hw_breakpoint_thread_switch(struct task_struct *next); | ||
124 | extern void ptrace_hw_copy_thread(struct task_struct *task); | ||
125 | #else | ||
126 | static inline void hw_breakpoint_thread_switch(struct task_struct *next) | ||
127 | { | ||
128 | } | ||
129 | static inline void ptrace_hw_copy_thread(struct task_struct *task) | ||
130 | { | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | extern struct pmu perf_ops_bp; | ||
135 | |||
136 | #endif /* __KERNEL__ */ | ||
137 | #endif /* __ASM_BREAKPOINT_H */ | ||