aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2011-08-02 08:01:17 -0400
committerWill Deacon <will.deacon@arm.com>2011-08-31 05:42:48 -0400
commitc512de955f0982aafa49d3f00d5643052a6790e5 (patch)
tree5bf3d463211f174ccf724e82be07cdf800b3168d /arch/arm/kernel/hw_breakpoint.c
parentb5d5b8f98641edac6641af9e19e933083ade603b (diff)
ARM: hw_breakpoint: reserve one breakpoint for watchpoint stepping
The current hw_breakpoint code on ARM reserves 1 breakpoint for each watchpoint that is available. Since debug architectures prior to 7.1 are restricted to 1 watchpoint anyway, only one breakpoint was ever reserved. This patch changes the reservation strategy so that a single breakpoint is reserved, regardless of the number of watchpoints. This is in preparation for multiple-watchpoint support on debug architectures from 7.1 onwards. Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/kernel/hw_breakpoint.c')
-rw-r--r--arch/arm/kernel/hw_breakpoint.c63
1 files changed, 24 insertions, 39 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index b6ddbfaae52..156b8af1357 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -45,7 +45,6 @@ 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;
49static int core_num_wrps; 48static int core_num_wrps;
50 49
51/* Debug architecture version. */ 50/* Debug architecture version. */
@@ -160,7 +159,15 @@ static int debug_arch_supported(void)
160 arch >= ARM_DEBUG_ARCH_V7_1; 159 arch >= ARM_DEBUG_ARCH_V7_1;
161} 160}
162 161
163/* Determine number of BRP register available. */ 162/* Determine number of WRP registers available. */
163static int get_num_wrp_resources(void)
164{
165 u32 didr;
166 ARM_DBG_READ(c0, 0, didr);
167 return ((didr >> 28) & 0xf) + 1;
168}
169
170/* Determine number of BRP registers available. */
164static int get_num_brp_resources(void) 171static int get_num_brp_resources(void)
165{ 172{
166 u32 didr; 173 u32 didr;
@@ -179,9 +186,10 @@ static int core_has_mismatch_brps(void)
179static int get_num_wrps(void) 186static int get_num_wrps(void)
180{ 187{
181 /* 188 /*
182 * FIXME: When a watchpoint fires, the only way to work out which 189 * On debug architectures prior to 7.1, when a watchpoint fires, the
183 * watchpoint it was is by disassembling the faulting instruction 190 * only way to work out which watchpoint it was is by disassembling
184 * and working out the address of the memory access. 191 * the faulting instruction and working out the address of the memory
192 * access.
185 * 193 *
186 * Furthermore, we can only do this if the watchpoint was precise 194 * Furthermore, we can only do this if the watchpoint was precise
187 * since imprecise watchpoints prevent us from calculating register 195 * since imprecise watchpoints prevent us from calculating register
@@ -195,36 +203,17 @@ static int get_num_wrps(void)
195 * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows 203 * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
196 * that it is set on some implementations]. 204 * that it is set on some implementations].
197 */ 205 */
206 if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1)
207 return 1;
198 208
199#if 0 209 return get_num_wrp_resources();
200 int wrps;
201 u32 didr;
202 ARM_DBG_READ(c0, 0, didr);
203 wrps = ((didr >> 28) & 0xf) + 1;
204#endif
205 int wrps = 1;
206
207 if (core_has_mismatch_brps() && wrps >= get_num_brp_resources())
208 wrps = get_num_brp_resources() - 1;
209
210 return wrps;
211}
212
213/* We reserve one breakpoint for each watchpoint. */
214static int get_num_reserved_brps(void)
215{
216 if (core_has_mismatch_brps())
217 return get_num_wrps();
218 return 0;
219} 210}
220 211
221/* Determine number of usable BRPs available. */ 212/* Determine number of usable BRPs available. */
222static int get_num_brps(void) 213static int get_num_brps(void)
223{ 214{
224 int brps = get_num_brp_resources(); 215 int brps = get_num_brp_resources();
225 if (core_has_mismatch_brps()) 216 return core_has_mismatch_brps() ? brps - 1 : brps;
226 brps -= get_num_reserved_brps();
227 return brps;
228} 217}
229 218
230/* 219/*
@@ -721,7 +710,7 @@ static void watchpoint_single_step_handler(unsigned long pc)
721 710
722 slots = (struct perf_event **)__get_cpu_var(wp_on_reg); 711 slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
723 712
724 for (i = 0; i < core_num_reserved_brps; ++i) { 713 for (i = 0; i < core_num_wrps; ++i) {
725 rcu_read_lock(); 714 rcu_read_lock();
726 715
727 wp = slots[i]; 716 wp = slots[i];
@@ -840,7 +829,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
840 */ 829 */
841static void reset_ctrl_regs(void *info) 830static void reset_ctrl_regs(void *info)
842{ 831{
843 int i, err = 0, cpu = smp_processor_id(); 832 int i, raw_num_brps, err = 0, cpu = smp_processor_id();
844 u32 dbg_power; 833 u32 dbg_power;
845 cpumask_t *cpumask = info; 834 cpumask_t *cpumask = info;
846 835
@@ -896,7 +885,8 @@ static void reset_ctrl_regs(void *info)
896 return; 885 return;
897 886
898 /* We must also reset any reserved registers. */ 887 /* We must also reset any reserved registers. */
899 for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) { 888 raw_num_brps = get_num_brp_resources();
889 for (i = 0; i < raw_num_brps; ++i) {
900 write_wb_reg(ARM_BASE_BCR + i, 0UL); 890 write_wb_reg(ARM_BASE_BCR + i, 0UL);
901 write_wb_reg(ARM_BASE_BVR + i, 0UL); 891 write_wb_reg(ARM_BASE_BVR + i, 0UL);
902 } 892 }
@@ -933,15 +923,11 @@ static int __init arch_hw_breakpoint_init(void)
933 923
934 /* Determine how many BRPs/WRPs are available. */ 924 /* Determine how many BRPs/WRPs are available. */
935 core_num_brps = get_num_brps(); 925 core_num_brps = get_num_brps();
936 core_num_reserved_brps = get_num_reserved_brps();
937 core_num_wrps = get_num_wrps(); 926 core_num_wrps = get_num_wrps();
938 927
939 pr_info("found %d breakpoint and %d watchpoint registers.\n", 928 pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n",
940 core_num_brps + core_num_reserved_brps, core_num_wrps); 929 core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
941 930 "", core_num_wrps);
942 if (core_num_reserved_brps)
943 pr_info("%d breakpoint(s) reserved for watchpoint "
944 "single-step.\n", core_num_reserved_brps);
945 931
946 /* 932 /*
947 * Reset the breakpoint resources. We assume that a halting 933 * Reset the breakpoint resources. We assume that a halting
@@ -950,7 +936,6 @@ static int __init arch_hw_breakpoint_init(void)
950 on_each_cpu(reset_ctrl_regs, &cpumask, 1); 936 on_each_cpu(reset_ctrl_regs, &cpumask, 1);
951 if (!cpumask_empty(&cpumask)) { 937 if (!cpumask_empty(&cpumask)) {
952 core_num_brps = 0; 938 core_num_brps = 0;
953 core_num_reserved_brps = 0;
954 core_num_wrps = 0; 939 core_num_wrps = 0;
955 return 0; 940 return 0;
956 } 941 }