diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-06 17:33:32 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-06 17:33:32 -0500 |
commit | 404a02cbd2ae8bf256a2fa1169bdfe86bb5ebb34 (patch) | |
tree | 99119edc53fdca73ed7586829b8ee736e09440b3 /arch/arm/kernel | |
parent | 28cdac6690cb113856293bf79b40de33dbd8f974 (diff) | |
parent | 1051b9f0f9eab8091fe3bf98320741adf36b4cfa (diff) |
Merge branch 'devel-stable' into devel
Conflicts:
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/clock.h
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/entry-header.S | 19 | ||||
-rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 543 | ||||
-rw-r--r-- | arch/arm/kernel/iwmmxt.S | 55 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event.c | 18 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_v6.c | 30 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_v7.c | 26 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event_xscale.c | 40 | ||||
-rw-r--r-- | arch/arm/kernel/pj4-cp0.c | 94 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 4 |
11 files changed, 538 insertions, 296 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7c33e6f29bc..185ee822c93 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -54,6 +54,7 @@ AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 | |||
54 | obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o | 54 | obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o |
55 | obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o | 55 | obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o |
56 | obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o | 56 | obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o |
57 | obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o | ||
57 | obj-$(CONFIG_IWMMXT) += iwmmxt.o | 58 | obj-$(CONFIG_IWMMXT) += iwmmxt.o |
58 | obj-$(CONFIG_CPU_HAS_PMU) += pmu.o | 59 | obj-$(CONFIG_CPU_HAS_PMU) += pmu.o |
59 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o | 60 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 27f64489c1c..2b46fea36c9 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -178,6 +178,7 @@ __dabt_svc: | |||
178 | @ | 178 | @ |
179 | @ set desired IRQ state, then call main handler | 179 | @ set desired IRQ state, then call main handler |
180 | @ | 180 | @ |
181 | debug_entry r1 | ||
181 | msr cpsr_c, r9 | 182 | msr cpsr_c, r9 |
182 | mov r2, sp | 183 | mov r2, sp |
183 | bl do_DataAbort | 184 | bl do_DataAbort |
@@ -304,6 +305,7 @@ __pabt_svc: | |||
304 | #else | 305 | #else |
305 | bl CPU_PABORT_HANDLER | 306 | bl CPU_PABORT_HANDLER |
306 | #endif | 307 | #endif |
308 | debug_entry r1 | ||
307 | msr cpsr_c, r9 @ Maybe enable interrupts | 309 | msr cpsr_c, r9 @ Maybe enable interrupts |
308 | mov r2, sp @ regs | 310 | mov r2, sp @ regs |
309 | bl do_PrefetchAbort @ call abort handler | 311 | bl do_PrefetchAbort @ call abort handler |
@@ -419,6 +421,7 @@ __dabt_usr: | |||
419 | @ | 421 | @ |
420 | @ IRQs on, then call the main handler | 422 | @ IRQs on, then call the main handler |
421 | @ | 423 | @ |
424 | debug_entry r1 | ||
422 | enable_irq | 425 | enable_irq |
423 | mov r2, sp | 426 | mov r2, sp |
424 | adr lr, BSYM(ret_from_exception) | 427 | adr lr, BSYM(ret_from_exception) |
@@ -683,6 +686,7 @@ __pabt_usr: | |||
683 | #else | 686 | #else |
684 | bl CPU_PABORT_HANDLER | 687 | bl CPU_PABORT_HANDLER |
685 | #endif | 688 | #endif |
689 | debug_entry r1 | ||
686 | enable_irq @ Enable interrupts | 690 | enable_irq @ Enable interrupts |
687 | mov r2, sp @ regs | 691 | mov r2, sp @ regs |
688 | bl do_PrefetchAbort @ call abort handler | 692 | bl do_PrefetchAbort @ call abort handler |
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index d93f976fb38..ae946490016 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S | |||
@@ -165,6 +165,25 @@ | |||
165 | .endm | 165 | .endm |
166 | #endif /* !CONFIG_THUMB2_KERNEL */ | 166 | #endif /* !CONFIG_THUMB2_KERNEL */ |
167 | 167 | ||
168 | @ | ||
169 | @ Debug exceptions are taken as prefetch or data aborts. | ||
170 | @ We must disable preemption during the handler so that | ||
171 | @ we can access the debug registers safely. | ||
172 | @ | ||
173 | .macro debug_entry, fsr | ||
174 | #if defined(CONFIG_HAVE_HW_BREAKPOINT) && defined(CONFIG_PREEMPT) | ||
175 | ldr r4, =0x40f @ mask out fsr.fs | ||
176 | and r5, r4, \fsr | ||
177 | cmp r5, #2 @ debug exception | ||
178 | bne 1f | ||
179 | get_thread_info r10 | ||
180 | ldr r6, [r10, #TI_PREEMPT] @ get preempt count | ||
181 | add r11, r6, #1 @ increment it | ||
182 | str r11, [r10, #TI_PREEMPT] | ||
183 | 1: | ||
184 | #endif | ||
185 | .endm | ||
186 | |||
168 | /* | 187 | /* |
169 | * These are the registers used in the syscall handler, and allow us to | 188 | * These are the registers used in the syscall handler, and allow us to |
170 | * have in theory up to 7 arguments to a function - r0 to r6. | 189 | * have in theory up to 7 arguments to a function - r0 to r6. |
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 21e3a4ab3b8..c9f3f046757 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #define pr_fmt(fmt) "hw-breakpoint: " fmt | 24 | #define pr_fmt(fmt) "hw-breakpoint: " fmt |
25 | 25 | ||
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/hardirq.h> | ||
27 | #include <linux/perf_event.h> | 28 | #include <linux/perf_event.h> |
28 | #include <linux/hw_breakpoint.h> | 29 | #include <linux/hw_breakpoint.h> |
29 | #include <linux/smp.h> | 30 | #include <linux/smp.h> |
@@ -44,6 +45,7 @@ static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]); | |||
44 | 45 | ||
45 | /* Number of BRP/WRP registers on this CPU. */ | 46 | /* Number of BRP/WRP registers on this CPU. */ |
46 | static int core_num_brps; | 47 | static int core_num_brps; |
48 | static int core_num_reserved_brps; | ||
47 | static int core_num_wrps; | 49 | static int core_num_wrps; |
48 | 50 | ||
49 | /* Debug architecture version. */ | 51 | /* Debug architecture version. */ |
@@ -52,87 +54,6 @@ static u8 debug_arch; | |||
52 | /* Maximum supported watchpoint length. */ | 54 | /* Maximum supported watchpoint length. */ |
53 | static u8 max_watchpoint_len; | 55 | static u8 max_watchpoint_len; |
54 | 56 | ||
55 | /* Determine number of BRP registers available. */ | ||
56 | static int get_num_brps(void) | ||
57 | { | ||
58 | u32 didr; | ||
59 | ARM_DBG_READ(c0, 0, didr); | ||
60 | return ((didr >> 24) & 0xf) + 1; | ||
61 | } | ||
62 | |||
63 | /* Determine number of WRP registers available. */ | ||
64 | static int get_num_wrps(void) | ||
65 | { | ||
66 | /* | ||
67 | * FIXME: When a watchpoint fires, the only way to work out which | ||
68 | * watchpoint it was is by disassembling the faulting instruction | ||
69 | * and working out the address of the memory access. | ||
70 | * | ||
71 | * Furthermore, we can only do this if the watchpoint was precise | ||
72 | * since imprecise watchpoints prevent us from calculating register | ||
73 | * based addresses. | ||
74 | * | ||
75 | * For the time being, we only report 1 watchpoint register so we | ||
76 | * always know which watchpoint fired. In the future we can either | ||
77 | * add a disassembler and address generation emulator, or we can | ||
78 | * insert a check to see if the DFAR is set on watchpoint exception | ||
79 | * entry [the ARM ARM states that the DFAR is UNKNOWN, but | ||
80 | * experience shows that it is set on some implementations]. | ||
81 | */ | ||
82 | |||
83 | #if 0 | ||
84 | u32 didr, wrps; | ||
85 | ARM_DBG_READ(c0, 0, didr); | ||
86 | return ((didr >> 28) & 0xf) + 1; | ||
87 | #endif | ||
88 | |||
89 | return 1; | ||
90 | } | ||
91 | |||
92 | int hw_breakpoint_slots(int type) | ||
93 | { | ||
94 | /* | ||
95 | * We can be called early, so don't rely on | ||
96 | * our static variables being initialised. | ||
97 | */ | ||
98 | switch (type) { | ||
99 | case TYPE_INST: | ||
100 | return get_num_brps(); | ||
101 | case TYPE_DATA: | ||
102 | return get_num_wrps(); | ||
103 | default: | ||
104 | pr_warning("unknown slot type: %d\n", type); | ||
105 | return 0; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | /* Determine debug architecture. */ | ||
110 | static u8 get_debug_arch(void) | ||
111 | { | ||
112 | u32 didr; | ||
113 | |||
114 | /* Do we implement the extended CPUID interface? */ | ||
115 | if (((read_cpuid_id() >> 16) & 0xf) != 0xf) { | ||
116 | pr_warning("CPUID feature registers not supported. " | ||
117 | "Assuming v6 debug is present.\n"); | ||
118 | return ARM_DEBUG_ARCH_V6; | ||
119 | } | ||
120 | |||
121 | ARM_DBG_READ(c0, 0, didr); | ||
122 | return (didr >> 16) & 0xf; | ||
123 | } | ||
124 | |||
125 | /* Does this core support mismatch breakpoints? */ | ||
126 | static int core_has_mismatch_bps(void) | ||
127 | { | ||
128 | return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1; | ||
129 | } | ||
130 | |||
131 | u8 arch_get_debug_arch(void) | ||
132 | { | ||
133 | return debug_arch; | ||
134 | } | ||
135 | |||
136 | #define READ_WB_REG_CASE(OP2, M, VAL) \ | 57 | #define READ_WB_REG_CASE(OP2, M, VAL) \ |
137 | case ((OP2 << 4) + M): \ | 58 | case ((OP2 << 4) + M): \ |
138 | ARM_DBG_READ(c ## M, OP2, VAL); \ | 59 | ARM_DBG_READ(c ## M, OP2, VAL); \ |
@@ -210,6 +131,94 @@ static void write_wb_reg(int n, u32 val) | |||
210 | isb(); | 131 | isb(); |
211 | } | 132 | } |
212 | 133 | ||
134 | /* Determine debug architecture. */ | ||
135 | static 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 | |||
150 | u8 arch_get_debug_arch(void) | ||
151 | { | ||
152 | return debug_arch; | ||
153 | } | ||
154 | |||
155 | /* Determine number of BRP register available. */ | ||
156 | static 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? */ | ||
164 | static 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. */ | ||
171 | static 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. */ | ||
206 | static 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. */ | ||
214 | static 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 | |||
213 | /* | 222 | /* |
214 | * In order to access the breakpoint/watchpoint control registers, | 223 | * In order to access the breakpoint/watchpoint control registers, |
215 | * we must be running in debug monitor mode. Unfortunately, we can | 224 | * we must be running in debug monitor mode. Unfortunately, we can |
@@ -230,8 +239,12 @@ static int enable_monitor_mode(void) | |||
230 | goto out; | 239 | goto out; |
231 | } | 240 | } |
232 | 241 | ||
242 | /* If monitor mode is already enabled, just return. */ | ||
243 | if (dscr & ARM_DSCR_MDBGEN) | ||
244 | goto out; | ||
245 | |||
233 | /* Write to the corresponding DSCR. */ | 246 | /* Write to the corresponding DSCR. */ |
234 | switch (debug_arch) { | 247 | switch (get_debug_arch()) { |
235 | case ARM_DEBUG_ARCH_V6: | 248 | case ARM_DEBUG_ARCH_V6: |
236 | case ARM_DEBUG_ARCH_V6_1: | 249 | case ARM_DEBUG_ARCH_V6_1: |
237 | ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN)); | 250 | ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN)); |
@@ -246,15 +259,30 @@ static int enable_monitor_mode(void) | |||
246 | 259 | ||
247 | /* Check that the write made it through. */ | 260 | /* Check that the write made it through. */ |
248 | ARM_DBG_READ(c1, 0, dscr); | 261 | ARM_DBG_READ(c1, 0, dscr); |
249 | if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN), | 262 | if (!(dscr & ARM_DSCR_MDBGEN)) |
250 | "failed to enable monitor mode.")) { | ||
251 | ret = -EPERM; | 263 | ret = -EPERM; |
252 | } | ||
253 | 264 | ||
254 | out: | 265 | out: |
255 | return ret; | 266 | return ret; |
256 | } | 267 | } |
257 | 268 | ||
269 | int hw_breakpoint_slots(int type) | ||
270 | { | ||
271 | /* | ||
272 | * We can be called early, so don't rely on | ||
273 | * our static variables being initialised. | ||
274 | */ | ||
275 | switch (type) { | ||
276 | case TYPE_INST: | ||
277 | return get_num_brps(); | ||
278 | case TYPE_DATA: | ||
279 | return get_num_wrps(); | ||
280 | default: | ||
281 | pr_warning("unknown slot type: %d\n", type); | ||
282 | return 0; | ||
283 | } | ||
284 | } | ||
285 | |||
258 | /* | 286 | /* |
259 | * Check if 8-bit byte-address select is available. | 287 | * Check if 8-bit byte-address select is available. |
260 | * This clobbers WRP 0. | 288 | * This clobbers WRP 0. |
@@ -268,9 +296,6 @@ static u8 get_max_wp_len(void) | |||
268 | if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14) | 296 | if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14) |
269 | goto out; | 297 | goto out; |
270 | 298 | ||
271 | if (enable_monitor_mode()) | ||
272 | goto out; | ||
273 | |||
274 | memset(&ctrl, 0, sizeof(ctrl)); | 299 | memset(&ctrl, 0, sizeof(ctrl)); |
275 | ctrl.len = ARM_BREAKPOINT_LEN_8; | 300 | ctrl.len = ARM_BREAKPOINT_LEN_8; |
276 | ctrl_reg = encode_ctrl_reg(ctrl); | 301 | ctrl_reg = encode_ctrl_reg(ctrl); |
@@ -290,23 +315,6 @@ u8 arch_get_max_wp_len(void) | |||
290 | } | 315 | } |
291 | 316 | ||
292 | /* | 317 | /* |
293 | * Handler for reactivating a suspended watchpoint when the single | ||
294 | * step `mismatch' breakpoint is triggered. | ||
295 | */ | ||
296 | static void wp_single_step_handler(struct perf_event *bp, int unused, | ||
297 | struct perf_sample_data *data, | ||
298 | struct pt_regs *regs) | ||
299 | { | ||
300 | perf_event_enable(counter_arch_bp(bp)->suspended_wp); | ||
301 | unregister_hw_breakpoint(bp); | ||
302 | } | ||
303 | |||
304 | static int bp_is_single_step(struct perf_event *bp) | ||
305 | { | ||
306 | return bp->overflow_handler == wp_single_step_handler; | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * Install a perf counter breakpoint. | 318 | * Install a perf counter breakpoint. |
311 | */ | 319 | */ |
312 | int arch_install_hw_breakpoint(struct perf_event *bp) | 320 | int arch_install_hw_breakpoint(struct perf_event *bp) |
@@ -314,30 +322,41 @@ int arch_install_hw_breakpoint(struct perf_event *bp) | |||
314 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | 322 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); |
315 | struct perf_event **slot, **slots; | 323 | struct perf_event **slot, **slots; |
316 | int i, max_slots, ctrl_base, val_base, ret = 0; | 324 | int i, max_slots, ctrl_base, val_base, ret = 0; |
325 | u32 addr, ctrl; | ||
317 | 326 | ||
318 | /* Ensure that we are in monitor mode and halting mode is disabled. */ | 327 | /* Ensure that we are in monitor mode and halting mode is disabled. */ |
319 | ret = enable_monitor_mode(); | 328 | ret = enable_monitor_mode(); |
320 | if (ret) | 329 | if (ret) |
321 | goto out; | 330 | goto out; |
322 | 331 | ||
332 | addr = info->address; | ||
333 | ctrl = encode_ctrl_reg(info->ctrl) | 0x1; | ||
334 | |||
323 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { | 335 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { |
324 | /* Breakpoint */ | 336 | /* Breakpoint */ |
325 | ctrl_base = ARM_BASE_BCR; | 337 | ctrl_base = ARM_BASE_BCR; |
326 | val_base = ARM_BASE_BVR; | 338 | val_base = ARM_BASE_BVR; |
327 | slots = __get_cpu_var(bp_on_reg); | 339 | slots = (struct perf_event **)__get_cpu_var(bp_on_reg); |
328 | max_slots = core_num_brps - 1; | 340 | max_slots = core_num_brps; |
329 | 341 | if (info->step_ctrl.enabled) { | |
330 | if (bp_is_single_step(bp)) { | 342 | /* Override the breakpoint data with the step data. */ |
331 | info->ctrl.mismatch = 1; | 343 | addr = info->trigger & ~0x3; |
332 | i = max_slots; | 344 | ctrl = encode_ctrl_reg(info->step_ctrl); |
333 | slots[i] = bp; | ||
334 | goto setup; | ||
335 | } | 345 | } |
336 | } else { | 346 | } else { |
337 | /* Watchpoint */ | 347 | /* Watchpoint */ |
338 | ctrl_base = ARM_BASE_WCR; | 348 | if (info->step_ctrl.enabled) { |
339 | val_base = ARM_BASE_WVR; | 349 | /* Install into the reserved breakpoint region. */ |
340 | slots = __get_cpu_var(wp_on_reg); | 350 | ctrl_base = ARM_BASE_BCR + core_num_brps; |
351 | val_base = ARM_BASE_BVR + core_num_brps; | ||
352 | /* Override the watchpoint data with the step data. */ | ||
353 | addr = info->trigger & ~0x3; | ||
354 | ctrl = encode_ctrl_reg(info->step_ctrl); | ||
355 | } else { | ||
356 | ctrl_base = ARM_BASE_WCR; | ||
357 | val_base = ARM_BASE_WVR; | ||
358 | } | ||
359 | slots = (struct perf_event **)__get_cpu_var(wp_on_reg); | ||
341 | max_slots = core_num_wrps; | 360 | max_slots = core_num_wrps; |
342 | } | 361 | } |
343 | 362 | ||
@@ -355,12 +374,11 @@ int arch_install_hw_breakpoint(struct perf_event *bp) | |||
355 | goto out; | 374 | goto out; |
356 | } | 375 | } |
357 | 376 | ||
358 | setup: | ||
359 | /* Setup the address register. */ | 377 | /* Setup the address register. */ |
360 | write_wb_reg(val_base + i, info->address); | 378 | write_wb_reg(val_base + i, addr); |
361 | 379 | ||
362 | /* Setup the control register. */ | 380 | /* Setup the control register. */ |
363 | write_wb_reg(ctrl_base + i, encode_ctrl_reg(info->ctrl) | 0x1); | 381 | write_wb_reg(ctrl_base + i, ctrl); |
364 | 382 | ||
365 | out: | 383 | out: |
366 | return ret; | 384 | return ret; |
@@ -375,18 +393,15 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp) | |||
375 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { | 393 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { |
376 | /* Breakpoint */ | 394 | /* Breakpoint */ |
377 | base = ARM_BASE_BCR; | 395 | base = ARM_BASE_BCR; |
378 | slots = __get_cpu_var(bp_on_reg); | 396 | slots = (struct perf_event **)__get_cpu_var(bp_on_reg); |
379 | max_slots = core_num_brps - 1; | 397 | max_slots = core_num_brps; |
380 | |||
381 | if (bp_is_single_step(bp)) { | ||
382 | i = max_slots; | ||
383 | slots[i] = NULL; | ||
384 | goto reset; | ||
385 | } | ||
386 | } else { | 398 | } else { |
387 | /* Watchpoint */ | 399 | /* Watchpoint */ |
388 | base = ARM_BASE_WCR; | 400 | if (info->step_ctrl.enabled) |
389 | slots = __get_cpu_var(wp_on_reg); | 401 | base = ARM_BASE_BCR + core_num_brps; |
402 | else | ||
403 | base = ARM_BASE_WCR; | ||
404 | slots = (struct perf_event **)__get_cpu_var(wp_on_reg); | ||
390 | max_slots = core_num_wrps; | 405 | max_slots = core_num_wrps; |
391 | } | 406 | } |
392 | 407 | ||
@@ -403,7 +418,6 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp) | |||
403 | if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) | 418 | if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) |
404 | return; | 419 | return; |
405 | 420 | ||
406 | reset: | ||
407 | /* Reset the control register. */ | 421 | /* Reset the control register. */ |
408 | write_wb_reg(base + i, 0); | 422 | write_wb_reg(base + i, 0); |
409 | } | 423 | } |
@@ -537,12 +551,23 @@ static int arch_build_bp_info(struct perf_event *bp) | |||
537 | return -EINVAL; | 551 | return -EINVAL; |
538 | } | 552 | } |
539 | 553 | ||
554 | /* | ||
555 | * Breakpoints must be of length 2 (thumb) or 4 (ARM) bytes. | ||
556 | * Watchpoints can be of length 1, 2, 4 or 8 bytes if supported | ||
557 | * by the hardware and must be aligned to the appropriate number of | ||
558 | * bytes. | ||
559 | */ | ||
560 | if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE && | ||
561 | info->ctrl.len != ARM_BREAKPOINT_LEN_2 && | ||
562 | info->ctrl.len != ARM_BREAKPOINT_LEN_4) | ||
563 | return -EINVAL; | ||
564 | |||
540 | /* Address */ | 565 | /* Address */ |
541 | info->address = bp->attr.bp_addr; | 566 | info->address = bp->attr.bp_addr; |
542 | 567 | ||
543 | /* Privilege */ | 568 | /* Privilege */ |
544 | info->ctrl.privilege = ARM_BREAKPOINT_USER; | 569 | info->ctrl.privilege = ARM_BREAKPOINT_USER; |
545 | if (arch_check_bp_in_kernelspace(bp) && !bp_is_single_step(bp)) | 570 | if (arch_check_bp_in_kernelspace(bp)) |
546 | info->ctrl.privilege |= ARM_BREAKPOINT_PRIV; | 571 | info->ctrl.privilege |= ARM_BREAKPOINT_PRIV; |
547 | 572 | ||
548 | /* Enabled? */ | 573 | /* Enabled? */ |
@@ -561,7 +586,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) | |||
561 | { | 586 | { |
562 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | 587 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); |
563 | int ret = 0; | 588 | int ret = 0; |
564 | u32 bytelen, max_len, offset, alignment_mask = 0x3; | 589 | u32 offset, alignment_mask = 0x3; |
565 | 590 | ||
566 | /* Build the arch_hw_breakpoint. */ | 591 | /* Build the arch_hw_breakpoint. */ |
567 | ret = arch_build_bp_info(bp); | 592 | ret = arch_build_bp_info(bp); |
@@ -571,84 +596,85 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) | |||
571 | /* Check address alignment. */ | 596 | /* Check address alignment. */ |
572 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) | 597 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) |
573 | alignment_mask = 0x7; | 598 | alignment_mask = 0x7; |
574 | if (info->address & alignment_mask) { | 599 | offset = info->address & alignment_mask; |
575 | /* | 600 | switch (offset) { |
576 | * Try to fix the alignment. This may result in a length | 601 | case 0: |
577 | * that is too large, so we must check for that. | 602 | /* Aligned */ |
578 | */ | 603 | break; |
579 | bytelen = get_hbp_len(info->ctrl.len); | 604 | case 1: |
580 | max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 : | 605 | /* Allow single byte watchpoint. */ |
581 | max_watchpoint_len; | 606 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) |
582 | 607 | break; | |
583 | if (max_len >= 8) | 608 | case 2: |
584 | offset = info->address & 0x7; | 609 | /* Allow halfword watchpoints and breakpoints. */ |
585 | else | 610 | if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) |
586 | offset = info->address & 0x3; | 611 | break; |
587 | 612 | default: | |
588 | if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) { | 613 | ret = -EINVAL; |
589 | ret = -EFBIG; | 614 | goto out; |
590 | goto out; | ||
591 | } | ||
592 | |||
593 | info->ctrl.len <<= offset; | ||
594 | info->address &= ~offset; | ||
595 | |||
596 | pr_debug("breakpoint alignment fixup: length = 0x%x, " | ||
597 | "address = 0x%x\n", info->ctrl.len, info->address); | ||
598 | } | 615 | } |
599 | 616 | ||
617 | info->address &= ~alignment_mask; | ||
618 | info->ctrl.len <<= offset; | ||
619 | |||
600 | /* | 620 | /* |
601 | * Currently we rely on an overflow handler to take | 621 | * Currently we rely on an overflow handler to take |
602 | * care of single-stepping the breakpoint when it fires. | 622 | * care of single-stepping the breakpoint when it fires. |
603 | * In the case of userspace breakpoints on a core with V7 debug, | 623 | * In the case of userspace breakpoints on a core with V7 debug, |
604 | * we can use the mismatch feature as a poor-man's hardware single-step. | 624 | * we can use the mismatch feature as a poor-man's hardware |
625 | * single-step, but this only works for per-task breakpoints. | ||
605 | */ | 626 | */ |
606 | if (WARN_ONCE(!bp->overflow_handler && | 627 | if (WARN_ONCE(!bp->overflow_handler && |
607 | (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()), | 628 | (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps() |
629 | || !bp->hw.bp_target), | ||
608 | "overflow handler required but none found")) { | 630 | "overflow handler required but none found")) { |
609 | ret = -EINVAL; | 631 | ret = -EINVAL; |
610 | goto out; | ||
611 | } | 632 | } |
612 | out: | 633 | out: |
613 | return ret; | 634 | return ret; |
614 | } | 635 | } |
615 | 636 | ||
616 | static void update_mismatch_flag(int idx, int flag) | 637 | /* |
638 | * Enable/disable single-stepping over the breakpoint bp at address addr. | ||
639 | */ | ||
640 | static void enable_single_step(struct perf_event *bp, u32 addr) | ||
617 | { | 641 | { |
618 | struct perf_event *bp = __get_cpu_var(bp_on_reg[idx]); | 642 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); |
619 | struct arch_hw_breakpoint *info; | ||
620 | |||
621 | if (bp == NULL) | ||
622 | return; | ||
623 | 643 | ||
624 | info = counter_arch_bp(bp); | 644 | arch_uninstall_hw_breakpoint(bp); |
645 | info->step_ctrl.mismatch = 1; | ||
646 | info->step_ctrl.len = ARM_BREAKPOINT_LEN_4; | ||
647 | info->step_ctrl.type = ARM_BREAKPOINT_EXECUTE; | ||
648 | info->step_ctrl.privilege = info->ctrl.privilege; | ||
649 | info->step_ctrl.enabled = 1; | ||
650 | info->trigger = addr; | ||
651 | arch_install_hw_breakpoint(bp); | ||
652 | } | ||
625 | 653 | ||
626 | /* Update the mismatch field to enter/exit `single-step' mode */ | 654 | static void disable_single_step(struct perf_event *bp) |
627 | if (!bp->overflow_handler && info->ctrl.mismatch != flag) { | 655 | { |
628 | info->ctrl.mismatch = flag; | 656 | arch_uninstall_hw_breakpoint(bp); |
629 | write_wb_reg(ARM_BASE_BCR + idx, encode_ctrl_reg(info->ctrl) | 0x1); | 657 | counter_arch_bp(bp)->step_ctrl.enabled = 0; |
630 | } | 658 | arch_install_hw_breakpoint(bp); |
631 | } | 659 | } |
632 | 660 | ||
633 | static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs) | 661 | static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs) |
634 | { | 662 | { |
635 | int i; | 663 | int i; |
636 | struct perf_event *bp, **slots = __get_cpu_var(wp_on_reg); | 664 | struct perf_event *wp, **slots; |
637 | struct arch_hw_breakpoint *info; | 665 | struct arch_hw_breakpoint *info; |
638 | struct perf_event_attr attr; | 666 | |
667 | slots = (struct perf_event **)__get_cpu_var(wp_on_reg); | ||
639 | 668 | ||
640 | /* Without a disassembler, we can only handle 1 watchpoint. */ | 669 | /* Without a disassembler, we can only handle 1 watchpoint. */ |
641 | BUG_ON(core_num_wrps > 1); | 670 | BUG_ON(core_num_wrps > 1); |
642 | 671 | ||
643 | hw_breakpoint_init(&attr); | ||
644 | attr.bp_addr = regs->ARM_pc & ~0x3; | ||
645 | attr.bp_len = HW_BREAKPOINT_LEN_4; | ||
646 | attr.bp_type = HW_BREAKPOINT_X; | ||
647 | |||
648 | for (i = 0; i < core_num_wrps; ++i) { | 672 | for (i = 0; i < core_num_wrps; ++i) { |
649 | rcu_read_lock(); | 673 | rcu_read_lock(); |
650 | 674 | ||
651 | if (slots[i] == NULL) { | 675 | wp = slots[i]; |
676 | |||
677 | if (wp == NULL) { | ||
652 | rcu_read_unlock(); | 678 | rcu_read_unlock(); |
653 | continue; | 679 | continue; |
654 | } | 680 | } |
@@ -658,24 +684,51 @@ static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs) | |||
658 | * single watchpoint, we can set the trigger to the lowest | 684 | * single watchpoint, we can set the trigger to the lowest |
659 | * possible faulting address. | 685 | * possible faulting address. |
660 | */ | 686 | */ |
661 | info = counter_arch_bp(slots[i]); | 687 | info = counter_arch_bp(wp); |
662 | info->trigger = slots[i]->attr.bp_addr; | 688 | info->trigger = wp->attr.bp_addr; |
663 | pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); | 689 | pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); |
664 | perf_bp_event(slots[i], regs); | 690 | perf_bp_event(wp, regs); |
665 | 691 | ||
666 | /* | 692 | /* |
667 | * If no overflow handler is present, insert a temporary | 693 | * If no overflow handler is present, insert a temporary |
668 | * mismatch breakpoint so we can single-step over the | 694 | * mismatch breakpoint so we can single-step over the |
669 | * watchpoint trigger. | 695 | * watchpoint trigger. |
670 | */ | 696 | */ |
671 | if (!slots[i]->overflow_handler) { | 697 | if (!wp->overflow_handler) |
672 | bp = register_user_hw_breakpoint(&attr, | 698 | enable_single_step(wp, instruction_pointer(regs)); |
673 | wp_single_step_handler, | 699 | |
674 | current); | 700 | rcu_read_unlock(); |
675 | counter_arch_bp(bp)->suspended_wp = slots[i]; | 701 | } |
676 | perf_event_disable(slots[i]); | 702 | } |
677 | } | ||
678 | 703 | ||
704 | static void watchpoint_single_step_handler(unsigned long pc) | ||
705 | { | ||
706 | int i; | ||
707 | struct perf_event *wp, **slots; | ||
708 | struct arch_hw_breakpoint *info; | ||
709 | |||
710 | slots = (struct perf_event **)__get_cpu_var(wp_on_reg); | ||
711 | |||
712 | for (i = 0; i < core_num_reserved_brps; ++i) { | ||
713 | rcu_read_lock(); | ||
714 | |||
715 | wp = slots[i]; | ||
716 | |||
717 | if (wp == NULL) | ||
718 | goto unlock; | ||
719 | |||
720 | info = counter_arch_bp(wp); | ||
721 | if (!info->step_ctrl.enabled) | ||
722 | goto unlock; | ||
723 | |||
724 | /* | ||
725 | * Restore the original watchpoint if we've completed the | ||
726 | * single-step. | ||
727 | */ | ||
728 | if (info->trigger != pc) | ||
729 | disable_single_step(wp); | ||
730 | |||
731 | unlock: | ||
679 | rcu_read_unlock(); | 732 | rcu_read_unlock(); |
680 | } | 733 | } |
681 | } | 734 | } |
@@ -683,62 +736,69 @@ static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs) | |||
683 | static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs) | 736 | static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs) |
684 | { | 737 | { |
685 | int i; | 738 | int i; |
686 | int mismatch; | ||
687 | u32 ctrl_reg, val, addr; | 739 | u32 ctrl_reg, val, addr; |
688 | struct perf_event *bp, **slots = __get_cpu_var(bp_on_reg); | 740 | struct perf_event *bp, **slots; |
689 | struct arch_hw_breakpoint *info; | 741 | struct arch_hw_breakpoint *info; |
690 | struct arch_hw_breakpoint_ctrl ctrl; | 742 | struct arch_hw_breakpoint_ctrl ctrl; |
691 | 743 | ||
744 | slots = (struct perf_event **)__get_cpu_var(bp_on_reg); | ||
745 | |||
692 | /* The exception entry code places the amended lr in the PC. */ | 746 | /* The exception entry code places the amended lr in the PC. */ |
693 | addr = regs->ARM_pc; | 747 | addr = regs->ARM_pc; |
694 | 748 | ||
749 | /* Check the currently installed breakpoints first. */ | ||
695 | for (i = 0; i < core_num_brps; ++i) { | 750 | for (i = 0; i < core_num_brps; ++i) { |
696 | rcu_read_lock(); | 751 | rcu_read_lock(); |
697 | 752 | ||
698 | bp = slots[i]; | 753 | bp = slots[i]; |
699 | 754 | ||
700 | if (bp == NULL) { | 755 | if (bp == NULL) |
701 | rcu_read_unlock(); | 756 | goto unlock; |
702 | continue; | ||
703 | } | ||
704 | 757 | ||
705 | mismatch = 0; | 758 | info = counter_arch_bp(bp); |
706 | 759 | ||
707 | /* Check if the breakpoint value matches. */ | 760 | /* Check if the breakpoint value matches. */ |
708 | val = read_wb_reg(ARM_BASE_BVR + i); | 761 | val = read_wb_reg(ARM_BASE_BVR + i); |
709 | if (val != (addr & ~0x3)) | 762 | if (val != (addr & ~0x3)) |
710 | goto unlock; | 763 | goto mismatch; |
711 | 764 | ||
712 | /* Possible match, check the byte address select to confirm. */ | 765 | /* Possible match, check the byte address select to confirm. */ |
713 | ctrl_reg = read_wb_reg(ARM_BASE_BCR + i); | 766 | ctrl_reg = read_wb_reg(ARM_BASE_BCR + i); |
714 | decode_ctrl_reg(ctrl_reg, &ctrl); | 767 | decode_ctrl_reg(ctrl_reg, &ctrl); |
715 | if ((1 << (addr & 0x3)) & ctrl.len) { | 768 | if ((1 << (addr & 0x3)) & ctrl.len) { |
716 | mismatch = 1; | ||
717 | info = counter_arch_bp(bp); | ||
718 | info->trigger = addr; | 769 | info->trigger = addr; |
719 | } | ||
720 | |||
721 | unlock: | ||
722 | if ((mismatch && !info->ctrl.mismatch) || bp_is_single_step(bp)) { | ||
723 | pr_debug("breakpoint fired: address = 0x%x\n", addr); | 770 | pr_debug("breakpoint fired: address = 0x%x\n", addr); |
724 | perf_bp_event(bp, regs); | 771 | perf_bp_event(bp, regs); |
772 | if (!bp->overflow_handler) | ||
773 | enable_single_step(bp, addr); | ||
774 | goto unlock; | ||
725 | } | 775 | } |
726 | 776 | ||
727 | update_mismatch_flag(i, mismatch); | 777 | mismatch: |
778 | /* If we're stepping a breakpoint, it can now be restored. */ | ||
779 | if (info->step_ctrl.enabled) | ||
780 | disable_single_step(bp); | ||
781 | unlock: | ||
728 | rcu_read_unlock(); | 782 | rcu_read_unlock(); |
729 | } | 783 | } |
784 | |||
785 | /* Handle any pending watchpoint single-step breakpoints. */ | ||
786 | watchpoint_single_step_handler(addr); | ||
730 | } | 787 | } |
731 | 788 | ||
732 | /* | 789 | /* |
733 | * Called from either the Data Abort Handler [watchpoint] or the | 790 | * Called from either the Data Abort Handler [watchpoint] or the |
734 | * Prefetch Abort Handler [breakpoint]. | 791 | * Prefetch Abort Handler [breakpoint] with preemption disabled. |
735 | */ | 792 | */ |
736 | static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, | 793 | static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, |
737 | struct pt_regs *regs) | 794 | struct pt_regs *regs) |
738 | { | 795 | { |
739 | int ret = 1; /* Unhandled fault. */ | 796 | int ret = 0; |
740 | u32 dscr; | 797 | u32 dscr; |
741 | 798 | ||
799 | /* We must be called with preemption disabled. */ | ||
800 | WARN_ON(preemptible()); | ||
801 | |||
742 | /* We only handle watchpoints and hardware breakpoints. */ | 802 | /* We only handle watchpoints and hardware breakpoints. */ |
743 | ARM_DBG_READ(c1, 0, dscr); | 803 | ARM_DBG_READ(c1, 0, dscr); |
744 | 804 | ||
@@ -753,25 +813,47 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, | |||
753 | watchpoint_handler(addr, regs); | 813 | watchpoint_handler(addr, regs); |
754 | break; | 814 | break; |
755 | default: | 815 | default: |
756 | goto out; | 816 | ret = 1; /* Unhandled fault. */ |
757 | } | 817 | } |
758 | 818 | ||
759 | ret = 0; | 819 | /* |
760 | out: | 820 | * Re-enable preemption after it was disabled in the |
821 | * low-level exception handling code. | ||
822 | */ | ||
823 | preempt_enable(); | ||
824 | |||
761 | return ret; | 825 | return ret; |
762 | } | 826 | } |
763 | 827 | ||
764 | /* | 828 | /* |
765 | * One-time initialisation. | 829 | * One-time initialisation. |
766 | */ | 830 | */ |
767 | static void __init reset_ctrl_regs(void *unused) | 831 | static void reset_ctrl_regs(void *unused) |
768 | { | 832 | { |
769 | int i; | 833 | int i; |
770 | 834 | ||
835 | /* | ||
836 | * v7 debug contains save and restore registers so that debug state | ||
837 | * can be maintained across low-power modes without leaving | ||
838 | * the debug logic powered up. It is IMPLEMENTATION DEFINED whether | ||
839 | * we can write to the debug registers out of reset, so we must | ||
840 | * unlock the OS Lock Access Register to avoid taking undefined | ||
841 | * instruction exceptions later on. | ||
842 | */ | ||
843 | if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) { | ||
844 | /* | ||
845 | * Unconditionally clear the lock by writing a value | ||
846 | * other than 0xC5ACCE55 to the access register. | ||
847 | */ | ||
848 | asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0)); | ||
849 | isb(); | ||
850 | } | ||
851 | |||
771 | if (enable_monitor_mode()) | 852 | if (enable_monitor_mode()) |
772 | return; | 853 | return; |
773 | 854 | ||
774 | for (i = 0; i < core_num_brps; ++i) { | 855 | /* We must also reset any reserved registers. */ |
856 | for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) { | ||
775 | write_wb_reg(ARM_BASE_BCR + i, 0UL); | 857 | write_wb_reg(ARM_BASE_BCR + i, 0UL); |
776 | write_wb_reg(ARM_BASE_BVR + i, 0UL); | 858 | write_wb_reg(ARM_BASE_BVR + i, 0UL); |
777 | } | 859 | } |
@@ -782,45 +864,57 @@ static void __init reset_ctrl_regs(void *unused) | |||
782 | } | 864 | } |
783 | } | 865 | } |
784 | 866 | ||
867 | static int __cpuinit dbg_reset_notify(struct notifier_block *self, | ||
868 | unsigned long action, void *cpu) | ||
869 | { | ||
870 | if (action == CPU_ONLINE) | ||
871 | smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1); | ||
872 | return NOTIFY_OK; | ||
873 | } | ||
874 | |||
875 | static struct notifier_block __cpuinitdata dbg_reset_nb = { | ||
876 | .notifier_call = dbg_reset_notify, | ||
877 | }; | ||
878 | |||
785 | static int __init arch_hw_breakpoint_init(void) | 879 | static int __init arch_hw_breakpoint_init(void) |
786 | { | 880 | { |
787 | int ret = 0; | ||
788 | u32 dscr; | 881 | u32 dscr; |
789 | 882 | ||
790 | debug_arch = get_debug_arch(); | 883 | debug_arch = get_debug_arch(); |
791 | 884 | ||
792 | if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) { | 885 | if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) { |
793 | pr_info("debug architecture 0x%x unsupported.\n", debug_arch); | 886 | pr_info("debug architecture 0x%x unsupported.\n", debug_arch); |
794 | ret = -ENODEV; | 887 | return 0; |
795 | goto out; | ||
796 | } | 888 | } |
797 | 889 | ||
798 | /* Determine how many BRPs/WRPs are available. */ | 890 | /* Determine how many BRPs/WRPs are available. */ |
799 | core_num_brps = get_num_brps(); | 891 | core_num_brps = get_num_brps(); |
892 | core_num_reserved_brps = get_num_reserved_brps(); | ||
800 | core_num_wrps = get_num_wrps(); | 893 | core_num_wrps = get_num_wrps(); |
801 | 894 | ||
802 | pr_info("found %d breakpoint and %d watchpoint registers.\n", | 895 | pr_info("found %d breakpoint and %d watchpoint registers.\n", |
803 | core_num_brps, core_num_wrps); | 896 | core_num_brps + core_num_reserved_brps, core_num_wrps); |
804 | 897 | ||
805 | if (core_has_mismatch_bps()) | 898 | if (core_num_reserved_brps) |
806 | pr_info("1 breakpoint reserved for watchpoint single-step.\n"); | 899 | pr_info("%d breakpoint(s) reserved for watchpoint " |
900 | "single-step.\n", core_num_reserved_brps); | ||
807 | 901 | ||
808 | ARM_DBG_READ(c1, 0, dscr); | 902 | ARM_DBG_READ(c1, 0, dscr); |
809 | if (dscr & ARM_DSCR_HDBGEN) { | 903 | if (dscr & ARM_DSCR_HDBGEN) { |
810 | pr_warning("halting debug mode enabled. Assuming maximum " | 904 | pr_warning("halting debug mode enabled. Assuming maximum " |
811 | "watchpoint size of 4 bytes."); | 905 | "watchpoint size of 4 bytes."); |
812 | } else { | 906 | } else { |
813 | /* Work out the maximum supported watchpoint length. */ | ||
814 | max_watchpoint_len = get_max_wp_len(); | ||
815 | pr_info("maximum watchpoint size is %u bytes.\n", | ||
816 | max_watchpoint_len); | ||
817 | |||
818 | /* | 907 | /* |
819 | * Reset the breakpoint resources. We assume that a halting | 908 | * Reset the breakpoint resources. We assume that a halting |
820 | * debugger will leave the world in a nice state for us. | 909 | * debugger will leave the world in a nice state for us. |
821 | */ | 910 | */ |
822 | smp_call_function(reset_ctrl_regs, NULL, 1); | 911 | smp_call_function(reset_ctrl_regs, NULL, 1); |
823 | reset_ctrl_regs(NULL); | 912 | reset_ctrl_regs(NULL); |
913 | |||
914 | /* Work out the maximum supported watchpoint length. */ | ||
915 | max_watchpoint_len = get_max_wp_len(); | ||
916 | pr_info("maximum watchpoint size is %u bytes.\n", | ||
917 | max_watchpoint_len); | ||
824 | } | 918 | } |
825 | 919 | ||
826 | /* Register debug fault handler. */ | 920 | /* Register debug fault handler. */ |
@@ -829,8 +923,9 @@ static int __init arch_hw_breakpoint_init(void) | |||
829 | hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT, | 923 | hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT, |
830 | "breakpoint debug exception"); | 924 | "breakpoint debug exception"); |
831 | 925 | ||
832 | out: | 926 | /* Register hotplug notifier. */ |
833 | return ret; | 927 | register_cpu_notifier(&dbg_reset_nb); |
928 | return 0; | ||
834 | } | 929 | } |
835 | arch_initcall(arch_hw_breakpoint_init); | 930 | arch_initcall(arch_hw_breakpoint_init); |
836 | 931 | ||
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index b63b528f22a..7fa3bb0d239 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S | |||
@@ -19,6 +19,14 @@ | |||
19 | #include <asm/thread_info.h> | 19 | #include <asm/thread_info.h> |
20 | #include <asm/asm-offsets.h> | 20 | #include <asm/asm-offsets.h> |
21 | 21 | ||
22 | #if defined(CONFIG_CPU_PJ4) | ||
23 | #define PJ4(code...) code | ||
24 | #define XSC(code...) | ||
25 | #else | ||
26 | #define PJ4(code...) | ||
27 | #define XSC(code...) code | ||
28 | #endif | ||
29 | |||
22 | #define MMX_WR0 (0x00) | 30 | #define MMX_WR0 (0x00) |
23 | #define MMX_WR1 (0x08) | 31 | #define MMX_WR1 (0x08) |
24 | #define MMX_WR2 (0x10) | 32 | #define MMX_WR2 (0x10) |
@@ -58,11 +66,17 @@ | |||
58 | 66 | ||
59 | ENTRY(iwmmxt_task_enable) | 67 | ENTRY(iwmmxt_task_enable) |
60 | 68 | ||
61 | mrc p15, 0, r2, c15, c1, 0 | 69 | XSC(mrc p15, 0, r2, c15, c1, 0) |
62 | tst r2, #0x3 @ CP0 and CP1 accessible? | 70 | PJ4(mrc p15, 0, r2, c1, c0, 2) |
71 | @ CP0 and CP1 accessible? | ||
72 | XSC(tst r2, #0x3) | ||
73 | PJ4(tst r2, #0xf) | ||
63 | movne pc, lr @ if so no business here | 74 | movne pc, lr @ if so no business here |
64 | orr r2, r2, #0x3 @ enable access to CP0 and CP1 | 75 | @ enable access to CP0 and CP1 |
65 | mcr p15, 0, r2, c15, c1, 0 | 76 | XSC(orr r2, r2, #0x3) |
77 | XSC(mcr p15, 0, r2, c15, c1, 0) | ||
78 | PJ4(orr r2, r2, #0xf) | ||
79 | PJ4(mcr p15, 0, r2, c1, c0, 2) | ||
66 | 80 | ||
67 | ldr r3, =concan_owner | 81 | ldr r3, =concan_owner |
68 | add r0, r10, #TI_IWMMXT_STATE @ get task Concan save area | 82 | add r0, r10, #TI_IWMMXT_STATE @ get task Concan save area |
@@ -179,17 +193,26 @@ ENTRY(iwmmxt_task_disable) | |||
179 | teqne r1, r2 @ or specified one? | 193 | teqne r1, r2 @ or specified one? |
180 | bne 1f @ no: quit | 194 | bne 1f @ no: quit |
181 | 195 | ||
182 | mrc p15, 0, r4, c15, c1, 0 | 196 | @ enable access to CP0 and CP1 |
183 | orr r4, r4, #0x3 @ enable access to CP0 and CP1 | 197 | XSC(mrc p15, 0, r4, c15, c1, 0) |
184 | mcr p15, 0, r4, c15, c1, 0 | 198 | XSC(orr r4, r4, #0xf) |
199 | XSC(mcr p15, 0, r4, c15, c1, 0) | ||
200 | PJ4(mrc p15, 0, r4, c1, c0, 2) | ||
201 | PJ4(orr r4, r4, #0x3) | ||
202 | PJ4(mcr p15, 0, r4, c1, c0, 2) | ||
203 | |||
185 | mov r0, #0 @ nothing to load | 204 | mov r0, #0 @ nothing to load |
186 | str r0, [r3] @ no more current owner | 205 | str r0, [r3] @ no more current owner |
187 | mrc p15, 0, r2, c2, c0, 0 | 206 | mrc p15, 0, r2, c2, c0, 0 |
188 | mov r2, r2 @ cpwait | 207 | mov r2, r2 @ cpwait |
189 | bl concan_save | 208 | bl concan_save |
190 | 209 | ||
191 | bic r4, r4, #0x3 @ disable access to CP0 and CP1 | 210 | @ disable access to CP0 and CP1 |
192 | mcr p15, 0, r4, c15, c1, 0 | 211 | XSC(bic r4, r4, #0x3) |
212 | XSC(mcr p15, 0, r4, c15, c1, 0) | ||
213 | PJ4(bic r4, r4, #0xf) | ||
214 | PJ4(mcr p15, 0, r4, c1, c0, 2) | ||
215 | |||
193 | mrc p15, 0, r2, c2, c0, 0 | 216 | mrc p15, 0, r2, c2, c0, 0 |
194 | mov r2, r2 @ cpwait | 217 | mov r2, r2 @ cpwait |
195 | 218 | ||
@@ -277,8 +300,11 @@ ENTRY(iwmmxt_task_restore) | |||
277 | */ | 300 | */ |
278 | ENTRY(iwmmxt_task_switch) | 301 | ENTRY(iwmmxt_task_switch) |
279 | 302 | ||
280 | mrc p15, 0, r1, c15, c1, 0 | 303 | XSC(mrc p15, 0, r1, c15, c1, 0) |
281 | tst r1, #0x3 @ CP0 and CP1 accessible? | 304 | PJ4(mrc p15, 0, r1, c1, c0, 2) |
305 | @ CP0 and CP1 accessible? | ||
306 | XSC(tst r1, #0x3) | ||
307 | PJ4(tst r1, #0xf) | ||
282 | bne 1f @ yes: block them for next task | 308 | bne 1f @ yes: block them for next task |
283 | 309 | ||
284 | ldr r2, =concan_owner | 310 | ldr r2, =concan_owner |
@@ -287,8 +313,11 @@ ENTRY(iwmmxt_task_switch) | |||
287 | teq r2, r3 @ next task owns it? | 313 | teq r2, r3 @ next task owns it? |
288 | movne pc, lr @ no: leave Concan disabled | 314 | movne pc, lr @ no: leave Concan disabled |
289 | 315 | ||
290 | 1: eor r1, r1, #3 @ flip Concan access | 316 | 1: @ flip Conan access |
291 | mcr p15, 0, r1, c15, c1, 0 | 317 | XSC(eor r1, r1, #0x3) |
318 | XSC(mcr p15, 0, r1, c15, c1, 0) | ||
319 | PJ4(eor r1, r1, #0xf) | ||
320 | PJ4(mcr p15, 0, r1, c1, c0, 2) | ||
292 | 321 | ||
293 | mrc p15, 0, r1, c2, c0, 0 | 322 | mrc p15, 0, r1, c2, c0, 0 |
294 | sub pc, lr, r1, lsr #32 @ cpwait and return | 323 | sub pc, lr, r1, lsr #32 @ cpwait and return |
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 421a4bb88fe..624e2a5de2b 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -32,7 +32,7 @@ static struct platform_device *pmu_device; | |||
32 | * Hardware lock to serialize accesses to PMU registers. Needed for the | 32 | * Hardware lock to serialize accesses to PMU registers. Needed for the |
33 | * read/modify/write sequences. | 33 | * read/modify/write sequences. |
34 | */ | 34 | */ |
35 | DEFINE_SPINLOCK(pmu_lock); | 35 | static DEFINE_RAW_SPINLOCK(pmu_lock); |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * ARMv6 supports a maximum of 3 events, starting from index 1. If we add | 38 | * ARMv6 supports a maximum of 3 events, starting from index 1. If we add |
@@ -65,7 +65,7 @@ struct cpu_hw_events { | |||
65 | */ | 65 | */ |
66 | unsigned long active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)]; | 66 | unsigned long active_mask[BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)]; |
67 | }; | 67 | }; |
68 | DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); | 68 | static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); |
69 | 69 | ||
70 | struct arm_pmu { | 70 | struct arm_pmu { |
71 | enum arm_perf_pmu_ids id; | 71 | enum arm_perf_pmu_ids id; |
@@ -673,17 +673,17 @@ arch_initcall(init_hw_perf_events); | |||
673 | * This code has been adapted from the ARM OProfile support. | 673 | * This code has been adapted from the ARM OProfile support. |
674 | */ | 674 | */ |
675 | struct frame_tail { | 675 | struct frame_tail { |
676 | struct frame_tail *fp; | 676 | struct frame_tail __user *fp; |
677 | unsigned long sp; | 677 | unsigned long sp; |
678 | unsigned long lr; | 678 | unsigned long lr; |
679 | } __attribute__((packed)); | 679 | } __attribute__((packed)); |
680 | 680 | ||
681 | /* | 681 | /* |
682 | * Get the return address for a single stackframe and return a pointer to the | 682 | * Get the return address for a single stackframe and return a pointer to the |
683 | * next frame tail. | 683 | * next frame tail. |
684 | */ | 684 | */ |
685 | static struct frame_tail * | 685 | static struct frame_tail __user * |
686 | user_backtrace(struct frame_tail *tail, | 686 | user_backtrace(struct frame_tail __user *tail, |
687 | struct perf_callchain_entry *entry) | 687 | struct perf_callchain_entry *entry) |
688 | { | 688 | { |
689 | struct frame_tail buftail; | 689 | struct frame_tail buftail; |
@@ -709,10 +709,10 @@ user_backtrace(struct frame_tail *tail, | |||
709 | void | 709 | void |
710 | perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) | 710 | perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) |
711 | { | 711 | { |
712 | struct frame_tail *tail; | 712 | struct frame_tail __user *tail; |
713 | 713 | ||
714 | 714 | ||
715 | tail = (struct frame_tail *)regs->ARM_fp - 1; | 715 | tail = (struct frame_tail __user *)regs->ARM_fp - 1; |
716 | 716 | ||
717 | while (tail && !((unsigned long)tail & 0x3)) | 717 | while (tail && !((unsigned long)tail & 0x3)) |
718 | tail = user_backtrace(tail, entry); | 718 | tail = user_backtrace(tail, entry); |
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index 7aeb07da907..c058bfc8532 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c | |||
@@ -400,7 +400,7 @@ armv6pmu_write_counter(int counter, | |||
400 | WARN_ONCE(1, "invalid counter number (%d)\n", counter); | 400 | WARN_ONCE(1, "invalid counter number (%d)\n", counter); |
401 | } | 401 | } |
402 | 402 | ||
403 | void | 403 | static void |
404 | armv6pmu_enable_event(struct hw_perf_event *hwc, | 404 | armv6pmu_enable_event(struct hw_perf_event *hwc, |
405 | int idx) | 405 | int idx) |
406 | { | 406 | { |
@@ -426,12 +426,12 @@ armv6pmu_enable_event(struct hw_perf_event *hwc, | |||
426 | * Mask out the current event and set the counter to count the event | 426 | * Mask out the current event and set the counter to count the event |
427 | * that we're interested in. | 427 | * that we're interested in. |
428 | */ | 428 | */ |
429 | spin_lock_irqsave(&pmu_lock, flags); | 429 | raw_spin_lock_irqsave(&pmu_lock, flags); |
430 | val = armv6_pmcr_read(); | 430 | val = armv6_pmcr_read(); |
431 | val &= ~mask; | 431 | val &= ~mask; |
432 | val |= evt; | 432 | val |= evt; |
433 | armv6_pmcr_write(val); | 433 | armv6_pmcr_write(val); |
434 | spin_unlock_irqrestore(&pmu_lock, flags); | 434 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
435 | } | 435 | } |
436 | 436 | ||
437 | static irqreturn_t | 437 | static irqreturn_t |
@@ -500,11 +500,11 @@ armv6pmu_start(void) | |||
500 | { | 500 | { |
501 | unsigned long flags, val; | 501 | unsigned long flags, val; |
502 | 502 | ||
503 | spin_lock_irqsave(&pmu_lock, flags); | 503 | raw_spin_lock_irqsave(&pmu_lock, flags); |
504 | val = armv6_pmcr_read(); | 504 | val = armv6_pmcr_read(); |
505 | val |= ARMV6_PMCR_ENABLE; | 505 | val |= ARMV6_PMCR_ENABLE; |
506 | armv6_pmcr_write(val); | 506 | armv6_pmcr_write(val); |
507 | spin_unlock_irqrestore(&pmu_lock, flags); | 507 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
508 | } | 508 | } |
509 | 509 | ||
510 | static void | 510 | static void |
@@ -512,11 +512,11 @@ armv6pmu_stop(void) | |||
512 | { | 512 | { |
513 | unsigned long flags, val; | 513 | unsigned long flags, val; |
514 | 514 | ||
515 | spin_lock_irqsave(&pmu_lock, flags); | 515 | raw_spin_lock_irqsave(&pmu_lock, flags); |
516 | val = armv6_pmcr_read(); | 516 | val = armv6_pmcr_read(); |
517 | val &= ~ARMV6_PMCR_ENABLE; | 517 | val &= ~ARMV6_PMCR_ENABLE; |
518 | armv6_pmcr_write(val); | 518 | armv6_pmcr_write(val); |
519 | spin_unlock_irqrestore(&pmu_lock, flags); | 519 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
520 | } | 520 | } |
521 | 521 | ||
522 | static int | 522 | static int |
@@ -570,12 +570,12 @@ armv6pmu_disable_event(struct hw_perf_event *hwc, | |||
570 | * of ETM bus signal assertion cycles. The external reporting should | 570 | * of ETM bus signal assertion cycles. The external reporting should |
571 | * be disabled and so this should never increment. | 571 | * be disabled and so this should never increment. |
572 | */ | 572 | */ |
573 | spin_lock_irqsave(&pmu_lock, flags); | 573 | raw_spin_lock_irqsave(&pmu_lock, flags); |
574 | val = armv6_pmcr_read(); | 574 | val = armv6_pmcr_read(); |
575 | val &= ~mask; | 575 | val &= ~mask; |
576 | val |= evt; | 576 | val |= evt; |
577 | armv6_pmcr_write(val); | 577 | armv6_pmcr_write(val); |
578 | spin_unlock_irqrestore(&pmu_lock, flags); | 578 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
579 | } | 579 | } |
580 | 580 | ||
581 | static void | 581 | static void |
@@ -599,12 +599,12 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc, | |||
599 | * Unlike UP ARMv6, we don't have a way of stopping the counters. We | 599 | * Unlike UP ARMv6, we don't have a way of stopping the counters. We |
600 | * simply disable the interrupt reporting. | 600 | * simply disable the interrupt reporting. |
601 | */ | 601 | */ |
602 | spin_lock_irqsave(&pmu_lock, flags); | 602 | raw_spin_lock_irqsave(&pmu_lock, flags); |
603 | val = armv6_pmcr_read(); | 603 | val = armv6_pmcr_read(); |
604 | val &= ~mask; | 604 | val &= ~mask; |
605 | val |= evt; | 605 | val |= evt; |
606 | armv6_pmcr_write(val); | 606 | armv6_pmcr_write(val); |
607 | spin_unlock_irqrestore(&pmu_lock, flags); | 607 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
608 | } | 608 | } |
609 | 609 | ||
610 | static const struct arm_pmu armv6pmu = { | 610 | static const struct arm_pmu armv6pmu = { |
@@ -625,7 +625,7 @@ static const struct arm_pmu armv6pmu = { | |||
625 | .max_period = (1LLU << 32) - 1, | 625 | .max_period = (1LLU << 32) - 1, |
626 | }; | 626 | }; |
627 | 627 | ||
628 | const struct arm_pmu *__init armv6pmu_init(void) | 628 | static const struct arm_pmu *__init armv6pmu_init(void) |
629 | { | 629 | { |
630 | return &armv6pmu; | 630 | return &armv6pmu; |
631 | } | 631 | } |
@@ -655,17 +655,17 @@ static const struct arm_pmu armv6mpcore_pmu = { | |||
655 | .max_period = (1LLU << 32) - 1, | 655 | .max_period = (1LLU << 32) - 1, |
656 | }; | 656 | }; |
657 | 657 | ||
658 | const struct arm_pmu *__init armv6mpcore_pmu_init(void) | 658 | static const struct arm_pmu *__init armv6mpcore_pmu_init(void) |
659 | { | 659 | { |
660 | return &armv6mpcore_pmu; | 660 | return &armv6mpcore_pmu; |
661 | } | 661 | } |
662 | #else | 662 | #else |
663 | const struct arm_pmu *__init armv6pmu_init(void) | 663 | static const struct arm_pmu *__init armv6pmu_init(void) |
664 | { | 664 | { |
665 | return NULL; | 665 | return NULL; |
666 | } | 666 | } |
667 | 667 | ||
668 | const struct arm_pmu *__init armv6mpcore_pmu_init(void) | 668 | static const struct arm_pmu *__init armv6mpcore_pmu_init(void) |
669 | { | 669 | { |
670 | return NULL; | 670 | return NULL; |
671 | } | 671 | } |
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 4d0423969df..2e1402556fa 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c | |||
@@ -681,7 +681,7 @@ static void armv7_pmnc_dump_regs(void) | |||
681 | } | 681 | } |
682 | #endif | 682 | #endif |
683 | 683 | ||
684 | void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) | 684 | static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) |
685 | { | 685 | { |
686 | unsigned long flags; | 686 | unsigned long flags; |
687 | 687 | ||
@@ -689,7 +689,7 @@ void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) | |||
689 | * Enable counter and interrupt, and set the counter to count | 689 | * Enable counter and interrupt, and set the counter to count |
690 | * the event that we're interested in. | 690 | * the event that we're interested in. |
691 | */ | 691 | */ |
692 | spin_lock_irqsave(&pmu_lock, flags); | 692 | raw_spin_lock_irqsave(&pmu_lock, flags); |
693 | 693 | ||
694 | /* | 694 | /* |
695 | * Disable counter | 695 | * Disable counter |
@@ -713,7 +713,7 @@ void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) | |||
713 | */ | 713 | */ |
714 | armv7_pmnc_enable_counter(idx); | 714 | armv7_pmnc_enable_counter(idx); |
715 | 715 | ||
716 | spin_unlock_irqrestore(&pmu_lock, flags); | 716 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
717 | } | 717 | } |
718 | 718 | ||
719 | static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) | 719 | static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) |
@@ -723,7 +723,7 @@ static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) | |||
723 | /* | 723 | /* |
724 | * Disable counter and interrupt | 724 | * Disable counter and interrupt |
725 | */ | 725 | */ |
726 | spin_lock_irqsave(&pmu_lock, flags); | 726 | raw_spin_lock_irqsave(&pmu_lock, flags); |
727 | 727 | ||
728 | /* | 728 | /* |
729 | * Disable counter | 729 | * Disable counter |
@@ -735,7 +735,7 @@ static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) | |||
735 | */ | 735 | */ |
736 | armv7_pmnc_disable_intens(idx); | 736 | armv7_pmnc_disable_intens(idx); |
737 | 737 | ||
738 | spin_unlock_irqrestore(&pmu_lock, flags); | 738 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
739 | } | 739 | } |
740 | 740 | ||
741 | static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) | 741 | static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) |
@@ -805,20 +805,20 @@ static void armv7pmu_start(void) | |||
805 | { | 805 | { |
806 | unsigned long flags; | 806 | unsigned long flags; |
807 | 807 | ||
808 | spin_lock_irqsave(&pmu_lock, flags); | 808 | raw_spin_lock_irqsave(&pmu_lock, flags); |
809 | /* Enable all counters */ | 809 | /* Enable all counters */ |
810 | armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E); | 810 | armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E); |
811 | spin_unlock_irqrestore(&pmu_lock, flags); | 811 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
812 | } | 812 | } |
813 | 813 | ||
814 | static void armv7pmu_stop(void) | 814 | static void armv7pmu_stop(void) |
815 | { | 815 | { |
816 | unsigned long flags; | 816 | unsigned long flags; |
817 | 817 | ||
818 | spin_lock_irqsave(&pmu_lock, flags); | 818 | raw_spin_lock_irqsave(&pmu_lock, flags); |
819 | /* Disable all counters */ | 819 | /* Disable all counters */ |
820 | armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E); | 820 | armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E); |
821 | spin_unlock_irqrestore(&pmu_lock, flags); | 821 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
822 | } | 822 | } |
823 | 823 | ||
824 | static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc, | 824 | static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc, |
@@ -874,7 +874,7 @@ static u32 __init armv7_reset_read_pmnc(void) | |||
874 | return nb_cnt + 1; | 874 | return nb_cnt + 1; |
875 | } | 875 | } |
876 | 876 | ||
877 | const struct arm_pmu *__init armv7_a8_pmu_init(void) | 877 | static const struct arm_pmu *__init armv7_a8_pmu_init(void) |
878 | { | 878 | { |
879 | armv7pmu.id = ARM_PERF_PMU_ID_CA8; | 879 | armv7pmu.id = ARM_PERF_PMU_ID_CA8; |
880 | armv7pmu.name = "ARMv7 Cortex-A8"; | 880 | armv7pmu.name = "ARMv7 Cortex-A8"; |
@@ -884,7 +884,7 @@ const struct arm_pmu *__init armv7_a8_pmu_init(void) | |||
884 | return &armv7pmu; | 884 | return &armv7pmu; |
885 | } | 885 | } |
886 | 886 | ||
887 | const struct arm_pmu *__init armv7_a9_pmu_init(void) | 887 | static const struct arm_pmu *__init armv7_a9_pmu_init(void) |
888 | { | 888 | { |
889 | armv7pmu.id = ARM_PERF_PMU_ID_CA9; | 889 | armv7pmu.id = ARM_PERF_PMU_ID_CA9; |
890 | armv7pmu.name = "ARMv7 Cortex-A9"; | 890 | armv7pmu.name = "ARMv7 Cortex-A9"; |
@@ -894,12 +894,12 @@ const struct arm_pmu *__init armv7_a9_pmu_init(void) | |||
894 | return &armv7pmu; | 894 | return &armv7pmu; |
895 | } | 895 | } |
896 | #else | 896 | #else |
897 | const struct arm_pmu *__init armv7_a8_pmu_init(void) | 897 | static const struct arm_pmu *__init armv7_a8_pmu_init(void) |
898 | { | 898 | { |
899 | return NULL; | 899 | return NULL; |
900 | } | 900 | } |
901 | 901 | ||
902 | const struct arm_pmu *__init armv7_a9_pmu_init(void) | 902 | static const struct arm_pmu *__init armv7_a9_pmu_init(void) |
903 | { | 903 | { |
904 | return NULL; | 904 | return NULL; |
905 | } | 905 | } |
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index 4e9592789d4..28cd3b025bc 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c | |||
@@ -291,12 +291,12 @@ xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx) | |||
291 | return; | 291 | return; |
292 | } | 292 | } |
293 | 293 | ||
294 | spin_lock_irqsave(&pmu_lock, flags); | 294 | raw_spin_lock_irqsave(&pmu_lock, flags); |
295 | val = xscale1pmu_read_pmnc(); | 295 | val = xscale1pmu_read_pmnc(); |
296 | val &= ~mask; | 296 | val &= ~mask; |
297 | val |= evt; | 297 | val |= evt; |
298 | xscale1pmu_write_pmnc(val); | 298 | xscale1pmu_write_pmnc(val); |
299 | spin_unlock_irqrestore(&pmu_lock, flags); | 299 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
300 | } | 300 | } |
301 | 301 | ||
302 | static void | 302 | static void |
@@ -322,12 +322,12 @@ xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx) | |||
322 | return; | 322 | return; |
323 | } | 323 | } |
324 | 324 | ||
325 | spin_lock_irqsave(&pmu_lock, flags); | 325 | raw_spin_lock_irqsave(&pmu_lock, flags); |
326 | val = xscale1pmu_read_pmnc(); | 326 | val = xscale1pmu_read_pmnc(); |
327 | val &= ~mask; | 327 | val &= ~mask; |
328 | val |= evt; | 328 | val |= evt; |
329 | xscale1pmu_write_pmnc(val); | 329 | xscale1pmu_write_pmnc(val); |
330 | spin_unlock_irqrestore(&pmu_lock, flags); | 330 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
331 | } | 331 | } |
332 | 332 | ||
333 | static int | 333 | static int |
@@ -355,11 +355,11 @@ xscale1pmu_start(void) | |||
355 | { | 355 | { |
356 | unsigned long flags, val; | 356 | unsigned long flags, val; |
357 | 357 | ||
358 | spin_lock_irqsave(&pmu_lock, flags); | 358 | raw_spin_lock_irqsave(&pmu_lock, flags); |
359 | val = xscale1pmu_read_pmnc(); | 359 | val = xscale1pmu_read_pmnc(); |
360 | val |= XSCALE_PMU_ENABLE; | 360 | val |= XSCALE_PMU_ENABLE; |
361 | xscale1pmu_write_pmnc(val); | 361 | xscale1pmu_write_pmnc(val); |
362 | spin_unlock_irqrestore(&pmu_lock, flags); | 362 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
363 | } | 363 | } |
364 | 364 | ||
365 | static void | 365 | static void |
@@ -367,11 +367,11 @@ xscale1pmu_stop(void) | |||
367 | { | 367 | { |
368 | unsigned long flags, val; | 368 | unsigned long flags, val; |
369 | 369 | ||
370 | spin_lock_irqsave(&pmu_lock, flags); | 370 | raw_spin_lock_irqsave(&pmu_lock, flags); |
371 | val = xscale1pmu_read_pmnc(); | 371 | val = xscale1pmu_read_pmnc(); |
372 | val &= ~XSCALE_PMU_ENABLE; | 372 | val &= ~XSCALE_PMU_ENABLE; |
373 | xscale1pmu_write_pmnc(val); | 373 | xscale1pmu_write_pmnc(val); |
374 | spin_unlock_irqrestore(&pmu_lock, flags); | 374 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
375 | } | 375 | } |
376 | 376 | ||
377 | static inline u32 | 377 | static inline u32 |
@@ -428,7 +428,7 @@ static const struct arm_pmu xscale1pmu = { | |||
428 | .max_period = (1LLU << 32) - 1, | 428 | .max_period = (1LLU << 32) - 1, |
429 | }; | 429 | }; |
430 | 430 | ||
431 | const struct arm_pmu *__init xscale1pmu_init(void) | 431 | static const struct arm_pmu *__init xscale1pmu_init(void) |
432 | { | 432 | { |
433 | return &xscale1pmu; | 433 | return &xscale1pmu; |
434 | } | 434 | } |
@@ -635,10 +635,10 @@ xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx) | |||
635 | return; | 635 | return; |
636 | } | 636 | } |
637 | 637 | ||
638 | spin_lock_irqsave(&pmu_lock, flags); | 638 | raw_spin_lock_irqsave(&pmu_lock, flags); |
639 | xscale2pmu_write_event_select(evtsel); | 639 | xscale2pmu_write_event_select(evtsel); |
640 | xscale2pmu_write_int_enable(ien); | 640 | xscale2pmu_write_int_enable(ien); |
641 | spin_unlock_irqrestore(&pmu_lock, flags); | 641 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
642 | } | 642 | } |
643 | 643 | ||
644 | static void | 644 | static void |
@@ -678,10 +678,10 @@ xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx) | |||
678 | return; | 678 | return; |
679 | } | 679 | } |
680 | 680 | ||
681 | spin_lock_irqsave(&pmu_lock, flags); | 681 | raw_spin_lock_irqsave(&pmu_lock, flags); |
682 | xscale2pmu_write_event_select(evtsel); | 682 | xscale2pmu_write_event_select(evtsel); |
683 | xscale2pmu_write_int_enable(ien); | 683 | xscale2pmu_write_int_enable(ien); |
684 | spin_unlock_irqrestore(&pmu_lock, flags); | 684 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
685 | } | 685 | } |
686 | 686 | ||
687 | static int | 687 | static int |
@@ -705,11 +705,11 @@ xscale2pmu_start(void) | |||
705 | { | 705 | { |
706 | unsigned long flags, val; | 706 | unsigned long flags, val; |
707 | 707 | ||
708 | spin_lock_irqsave(&pmu_lock, flags); | 708 | raw_spin_lock_irqsave(&pmu_lock, flags); |
709 | val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64; | 709 | val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64; |
710 | val |= XSCALE_PMU_ENABLE; | 710 | val |= XSCALE_PMU_ENABLE; |
711 | xscale2pmu_write_pmnc(val); | 711 | xscale2pmu_write_pmnc(val); |
712 | spin_unlock_irqrestore(&pmu_lock, flags); | 712 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
713 | } | 713 | } |
714 | 714 | ||
715 | static void | 715 | static void |
@@ -717,11 +717,11 @@ xscale2pmu_stop(void) | |||
717 | { | 717 | { |
718 | unsigned long flags, val; | 718 | unsigned long flags, val; |
719 | 719 | ||
720 | spin_lock_irqsave(&pmu_lock, flags); | 720 | raw_spin_lock_irqsave(&pmu_lock, flags); |
721 | val = xscale2pmu_read_pmnc(); | 721 | val = xscale2pmu_read_pmnc(); |
722 | val &= ~XSCALE_PMU_ENABLE; | 722 | val &= ~XSCALE_PMU_ENABLE; |
723 | xscale2pmu_write_pmnc(val); | 723 | xscale2pmu_write_pmnc(val); |
724 | spin_unlock_irqrestore(&pmu_lock, flags); | 724 | raw_spin_unlock_irqrestore(&pmu_lock, flags); |
725 | } | 725 | } |
726 | 726 | ||
727 | static inline u32 | 727 | static inline u32 |
@@ -790,17 +790,17 @@ static const struct arm_pmu xscale2pmu = { | |||
790 | .max_period = (1LLU << 32) - 1, | 790 | .max_period = (1LLU << 32) - 1, |
791 | }; | 791 | }; |
792 | 792 | ||
793 | const struct arm_pmu *__init xscale2pmu_init(void) | 793 | static const struct arm_pmu *__init xscale2pmu_init(void) |
794 | { | 794 | { |
795 | return &xscale2pmu; | 795 | return &xscale2pmu; |
796 | } | 796 | } |
797 | #else | 797 | #else |
798 | const struct arm_pmu *__init xscale1pmu_init(void) | 798 | static const struct arm_pmu *__init xscale1pmu_init(void) |
799 | { | 799 | { |
800 | return NULL; | 800 | return NULL; |
801 | } | 801 | } |
802 | 802 | ||
803 | const struct arm_pmu *__init xscale2pmu_init(void) | 803 | static const struct arm_pmu *__init xscale2pmu_init(void) |
804 | { | 804 | { |
805 | return NULL; | 805 | return NULL; |
806 | } | 806 | } |
diff --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c new file mode 100644 index 00000000000..a4b1b0748fd --- /dev/null +++ b/arch/arm/kernel/pj4-cp0.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/pj4-cp0.c | ||
3 | * | ||
4 | * PJ4 iWMMXt coprocessor context switching and handling | ||
5 | * | ||
6 | * Copyright (c) 2010 Marvell International Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/signal.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <asm/thread_notify.h> | ||
21 | |||
22 | static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) | ||
23 | { | ||
24 | struct thread_info *thread = t; | ||
25 | |||
26 | switch (cmd) { | ||
27 | case THREAD_NOTIFY_FLUSH: | ||
28 | /* | ||
29 | * flush_thread() zeroes thread->fpstate, so no need | ||
30 | * to do anything here. | ||
31 | * | ||
32 | * FALLTHROUGH: Ensure we don't try to overwrite our newly | ||
33 | * initialised state information on the first fault. | ||
34 | */ | ||
35 | |||
36 | case THREAD_NOTIFY_EXIT: | ||
37 | iwmmxt_task_release(thread); | ||
38 | break; | ||
39 | |||
40 | case THREAD_NOTIFY_SWITCH: | ||
41 | iwmmxt_task_switch(thread); | ||
42 | break; | ||
43 | } | ||
44 | |||
45 | return NOTIFY_DONE; | ||
46 | } | ||
47 | |||
48 | static struct notifier_block iwmmxt_notifier_block = { | ||
49 | .notifier_call = iwmmxt_do, | ||
50 | }; | ||
51 | |||
52 | |||
53 | static u32 __init pj4_cp_access_read(void) | ||
54 | { | ||
55 | u32 value; | ||
56 | |||
57 | __asm__ __volatile__ ( | ||
58 | "mrc p15, 0, %0, c1, c0, 2\n\t" | ||
59 | : "=r" (value)); | ||
60 | return value; | ||
61 | } | ||
62 | |||
63 | static void __init pj4_cp_access_write(u32 value) | ||
64 | { | ||
65 | u32 temp; | ||
66 | |||
67 | __asm__ __volatile__ ( | ||
68 | "mcr p15, 0, %1, c1, c0, 2\n\t" | ||
69 | "mrc p15, 0, %0, c1, c0, 2\n\t" | ||
70 | "mov %0, %0\n\t" | ||
71 | "sub pc, pc, #4\n\t" | ||
72 | : "=r" (temp) : "r" (value)); | ||
73 | } | ||
74 | |||
75 | |||
76 | /* | ||
77 | * Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy | ||
78 | * switch code handle iWMMXt context switching. | ||
79 | */ | ||
80 | static int __init pj4_cp0_init(void) | ||
81 | { | ||
82 | u32 cp_access; | ||
83 | |||
84 | cp_access = pj4_cp_access_read() & ~0xf; | ||
85 | pj4_cp_access_write(cp_access); | ||
86 | |||
87 | printk(KERN_INFO "PJ4 iWMMXt coprocessor enabled.\n"); | ||
88 | elf_hwcap |= HWCAP_IWMMXT; | ||
89 | thread_register_notifier(&iwmmxt_notifier_block); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | late_initcall(pj4_cp0_init); | ||
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 3e97483abcf..19c6816db61 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -1060,8 +1060,8 @@ static int ptrace_sethbpregs(struct task_struct *tsk, long num, | |||
1060 | goto out; | 1060 | goto out; |
1061 | 1061 | ||
1062 | if ((gen_type & implied_type) != gen_type) { | 1062 | if ((gen_type & implied_type) != gen_type) { |
1063 | ret = -EINVAL; | 1063 | ret = -EINVAL; |
1064 | goto out; | 1064 | goto out; |
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | attr.bp_len = gen_len; | 1067 | attr.bp_len = gen_len; |