aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2010-11-28 10:09:36 -0500
committerWill Deacon <will.deacon@arm.com>2010-12-06 06:55:56 -0500
commit0017ff42ac37ff6aeb87d0b006c5d32b9a39f5fc (patch)
treeee68bfe2ece2e7223e0802431a1cddd54157d4a2 /arch/arm/kernel
parent7e20269647169e7ea08a62bdc4979a3ba32e615c (diff)
ARM: hw_breakpoint: don't advertise reserved breakpoints
To permit handling of watchpoint exceptions without signalling a debugger, it is necessary to reserve breakpoint registers for in-kernel use only. This patch ensures that we record and subtract the number of reserved breakpoints from the number of usable breakpoint registers that we advertise to userspace via the ptrace API. Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/hw_breakpoint.c206
1 files changed, 117 insertions, 89 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index eeba38008032..b16c4568cb01 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -45,6 +45,7 @@ static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
45 45
46/* Number of BRP/WRP registers on this CPU. */ 46/* Number of BRP/WRP registers on this CPU. */
47static int core_num_brps; 47static int core_num_brps;
48static int core_num_reserved_brps;
48static int core_num_wrps; 49static int core_num_wrps;
49 50
50/* Debug architecture version. */ 51/* Debug architecture version. */
@@ -53,87 +54,6 @@ static u8 debug_arch;
53/* Maximum supported watchpoint length. */ 54/* Maximum supported watchpoint length. */
54static u8 max_watchpoint_len; 55static u8 max_watchpoint_len;
55 56
56/* Determine number of BRP registers available. */
57static int get_num_brps(void)
58{
59 u32 didr;
60 ARM_DBG_READ(c0, 0, didr);
61 return ((didr >> 24) & 0xf) + 1;
62}
63
64/* Determine number of WRP registers available. */
65static int get_num_wrps(void)
66{
67 /*
68 * FIXME: When a watchpoint fires, the only way to work out which
69 * watchpoint it was is by disassembling the faulting instruction
70 * and working out the address of the memory access.
71 *
72 * Furthermore, we can only do this if the watchpoint was precise
73 * since imprecise watchpoints prevent us from calculating register
74 * based addresses.
75 *
76 * For the time being, we only report 1 watchpoint register so we
77 * always know which watchpoint fired. In the future we can either
78 * add a disassembler and address generation emulator, or we can
79 * insert a check to see if the DFAR is set on watchpoint exception
80 * entry [the ARM ARM states that the DFAR is UNKNOWN, but
81 * experience shows that it is set on some implementations].
82 */
83
84#if 0
85 u32 didr, wrps;
86 ARM_DBG_READ(c0, 0, didr);
87 return ((didr >> 28) & 0xf) + 1;
88#endif
89
90 return 1;
91}
92
93int hw_breakpoint_slots(int type)
94{
95 /*
96 * We can be called early, so don't rely on
97 * our static variables being initialised.
98 */
99 switch (type) {
100 case TYPE_INST:
101 return get_num_brps();
102 case TYPE_DATA:
103 return get_num_wrps();
104 default:
105 pr_warning("unknown slot type: %d\n", type);
106 return 0;
107 }
108}
109
110/* Determine debug architecture. */
111static u8 get_debug_arch(void)
112{
113 u32 didr;
114
115 /* Do we implement the extended CPUID interface? */
116 if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
117 pr_warning("CPUID feature registers not supported. "
118 "Assuming v6 debug is present.\n");
119 return ARM_DEBUG_ARCH_V6;
120 }
121
122 ARM_DBG_READ(c0, 0, didr);
123 return (didr >> 16) & 0xf;
124}
125
126/* Does this core support mismatch breakpoints? */
127static int core_has_mismatch_bps(void)
128{
129 return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1;
130}
131
132u8 arch_get_debug_arch(void)
133{
134 return debug_arch;
135}
136
137#define READ_WB_REG_CASE(OP2, M, VAL) \ 57#define READ_WB_REG_CASE(OP2, M, VAL) \
138 case ((OP2 << 4) + M): \ 58 case ((OP2 << 4) + M): \
139 ARM_DBG_READ(c ## M, OP2, VAL); \ 59 ARM_DBG_READ(c ## M, OP2, VAL); \
@@ -211,6 +131,111 @@ static void write_wb_reg(int n, u32 val)
211 isb(); 131 isb();
212} 132}
213 133
134/* Determine debug architecture. */
135static u8 get_debug_arch(void)
136{
137 u32 didr;
138
139 /* Do we implement the extended CPUID interface? */
140 if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
141 pr_warning("CPUID feature registers not supported. "
142 "Assuming v6 debug is present.\n");
143 return ARM_DEBUG_ARCH_V6;
144 }
145
146 ARM_DBG_READ(c0, 0, didr);
147 return (didr >> 16) & 0xf;
148}
149
150u8 arch_get_debug_arch(void)
151{
152 return debug_arch;
153}
154
155/* Determine number of BRP register available. */
156static int get_num_brp_resources(void)
157{
158 u32 didr;
159 ARM_DBG_READ(c0, 0, didr);
160 return ((didr >> 24) & 0xf) + 1;
161}
162
163/* Does this core support mismatch breakpoints? */
164static int core_has_mismatch_brps(void)
165{
166 return (get_debug_arch() >= ARM_DEBUG_ARCH_V7_ECP14 &&
167 get_num_brp_resources() > 1);
168}
169
170/* Determine number of usable WRPs available. */
171static int get_num_wrps(void)
172{
173 /*
174 * FIXME: When a watchpoint fires, the only way to work out which
175 * watchpoint it was is by disassembling the faulting instruction
176 * and working out the address of the memory access.
177 *
178 * Furthermore, we can only do this if the watchpoint was precise
179 * since imprecise watchpoints prevent us from calculating register
180 * based addresses.
181 *
182 * Providing we have more than 1 breakpoint register, we only report
183 * a single watchpoint register for the time being. This way, we always
184 * know which watchpoint fired. In the future we can either add a
185 * disassembler and address generation emulator, or we can insert a
186 * check to see if the DFAR is set on watchpoint exception entry
187 * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
188 * that it is set on some implementations].
189 */
190
191#if 0
192 int wrps;
193 u32 didr;
194 ARM_DBG_READ(c0, 0, didr);
195 wrps = ((didr >> 28) & 0xf) + 1;
196#endif
197 int wrps = 1;
198
199 if (core_has_mismatch_brps() && wrps >= get_num_brp_resources())
200 wrps = get_num_brp_resources() - 1;
201
202 return wrps;
203}
204
205/* We reserve one breakpoint for each watchpoint. */
206static int get_num_reserved_brps(void)
207{
208 if (core_has_mismatch_brps())
209 return get_num_wrps();
210 return 0;
211}
212
213/* Determine number of usable BRPs available. */
214static int get_num_brps(void)
215{
216 int brps = get_num_brp_resources();
217 if (core_has_mismatch_brps())
218 brps -= get_num_reserved_brps();
219 return brps;
220}
221
222int hw_breakpoint_slots(int type)
223{
224 /*
225 * We can be called early, so don't rely on
226 * our static variables being initialised.
227 */
228 switch (type) {
229 case TYPE_INST:
230 return get_num_brps();
231 case TYPE_DATA:
232 return get_num_wrps();
233 default:
234 pr_warning("unknown slot type: %d\n", type);
235 return 0;
236 }
237}
238
214/* 239/*
215 * In order to access the breakpoint/watchpoint control registers, 240 * In order to access the breakpoint/watchpoint control registers,
216 * we must be running in debug monitor mode. Unfortunately, we can 241 * we must be running in debug monitor mode. Unfortunately, we can
@@ -326,7 +351,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
326 ctrl_base = ARM_BASE_BCR; 351 ctrl_base = ARM_BASE_BCR;
327 val_base = ARM_BASE_BVR; 352 val_base = ARM_BASE_BVR;
328 slots = __get_cpu_var(bp_on_reg); 353 slots = __get_cpu_var(bp_on_reg);
329 max_slots = core_num_brps - 1; 354 max_slots = core_num_brps;
330 355
331 if (bp_is_single_step(bp)) { 356 if (bp_is_single_step(bp)) {
332 info->ctrl.mismatch = 1; 357 info->ctrl.mismatch = 1;
@@ -377,7 +402,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
377 /* Breakpoint */ 402 /* Breakpoint */
378 base = ARM_BASE_BCR; 403 base = ARM_BASE_BCR;
379 slots = __get_cpu_var(bp_on_reg); 404 slots = __get_cpu_var(bp_on_reg);
380 max_slots = core_num_brps - 1; 405 max_slots = core_num_brps;
381 406
382 if (bp_is_single_step(bp)) { 407 if (bp_is_single_step(bp)) {
383 i = max_slots; 408 i = max_slots;
@@ -611,7 +636,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
611 * we can use the mismatch feature as a poor-man's hardware single-step. 636 * we can use the mismatch feature as a poor-man's hardware single-step.
612 */ 637 */
613 if (WARN_ONCE(!bp->overflow_handler && 638 if (WARN_ONCE(!bp->overflow_handler &&
614 (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()), 639 (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()),
615 "overflow handler required but none found")) { 640 "overflow handler required but none found")) {
616 ret = -EINVAL; 641 ret = -EINVAL;
617 } 642 }
@@ -698,7 +723,7 @@ static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
698 /* The exception entry code places the amended lr in the PC. */ 723 /* The exception entry code places the amended lr in the PC. */
699 addr = regs->ARM_pc; 724 addr = regs->ARM_pc;
700 725
701 for (i = 0; i < core_num_brps; ++i) { 726 for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
702 rcu_read_lock(); 727 rcu_read_lock();
703 728
704 bp = slots[i]; 729 bp = slots[i];
@@ -801,7 +826,8 @@ static void reset_ctrl_regs(void *unused)
801 if (enable_monitor_mode()) 826 if (enable_monitor_mode())
802 return; 827 return;
803 828
804 for (i = 0; i < core_num_brps; ++i) { 829 /* We must also reset any reserved registers. */
830 for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
805 write_wb_reg(ARM_BASE_BCR + i, 0UL); 831 write_wb_reg(ARM_BASE_BCR + i, 0UL);
806 write_wb_reg(ARM_BASE_BVR + i, 0UL); 832 write_wb_reg(ARM_BASE_BVR + i, 0UL);
807 } 833 }
@@ -839,13 +865,15 @@ static int __init arch_hw_breakpoint_init(void)
839 865
840 /* Determine how many BRPs/WRPs are available. */ 866 /* Determine how many BRPs/WRPs are available. */
841 core_num_brps = get_num_brps(); 867 core_num_brps = get_num_brps();
868 core_num_reserved_brps = get_num_reserved_brps();
842 core_num_wrps = get_num_wrps(); 869 core_num_wrps = get_num_wrps();
843 870
844 pr_info("found %d breakpoint and %d watchpoint registers.\n", 871 pr_info("found %d breakpoint and %d watchpoint registers.\n",
845 core_num_brps, core_num_wrps); 872 core_num_brps + core_num_reserved_brps, core_num_wrps);
846 873
847 if (core_has_mismatch_bps()) 874 if (core_num_reserved_brps)
848 pr_info("1 breakpoint reserved for watchpoint single-step.\n"); 875 pr_info("%d breakpoint(s) reserved for watchpoint "
876 "single-step.\n", core_num_reserved_brps);
849 877
850 ARM_DBG_READ(c1, 0, dscr); 878 ARM_DBG_READ(c1, 0, dscr);
851 if (dscr & ARM_DSCR_HDBGEN) { 879 if (dscr & ARM_DSCR_HDBGEN) {