0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/irqflags.h>
0021 #include <linux/kallsyms.h>
0022 #include <linux/notifier.h>
0023 #include <linux/kprobes.h>
0024 #include <linux/kdebug.h>
0025 #include <linux/kernel.h>
0026 #include <linux/module.h>
0027 #include <linux/percpu.h>
0028 #include <linux/sched.h>
0029 #include <linux/init.h>
0030 #include <linux/slab.h>
0031 #include <linux/list.h>
0032 #include <linux/cpu.h>
0033 #include <linux/smp.h>
0034 #include <linux/bug.h>
0035
0036 #include <linux/hw_breakpoint.h>
0037
0038
0039
0040 struct bp_cpuinfo {
0041
0042 unsigned int cpu_pinned;
0043
0044 unsigned int *tsk_pinned;
0045
0046 unsigned int flexible;
0047 };
0048
0049 static DEFINE_PER_CPU(struct bp_cpuinfo, bp_cpuinfo[TYPE_MAX]);
0050 static int nr_slots[TYPE_MAX];
0051
0052 static struct bp_cpuinfo *get_bp_info(int cpu, enum bp_type_idx type)
0053 {
0054 return per_cpu_ptr(bp_cpuinfo + type, cpu);
0055 }
0056
0057
0058 static LIST_HEAD(bp_task_head);
0059
0060 static int constraints_initialized;
0061
0062
0063 struct bp_busy_slots {
0064 unsigned int pinned;
0065 unsigned int flexible;
0066 };
0067
0068
0069 static DEFINE_MUTEX(nr_bp_mutex);
0070
0071 __weak int hw_breakpoint_weight(struct perf_event *bp)
0072 {
0073 return 1;
0074 }
0075
0076 static inline enum bp_type_idx find_slot_idx(u64 bp_type)
0077 {
0078 if (bp_type & HW_BREAKPOINT_RW)
0079 return TYPE_DATA;
0080
0081 return TYPE_INST;
0082 }
0083
0084
0085
0086
0087
0088 static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type)
0089 {
0090 unsigned int *tsk_pinned = get_bp_info(cpu, type)->tsk_pinned;
0091 int i;
0092
0093 for (i = nr_slots[type] - 1; i >= 0; i--) {
0094 if (tsk_pinned[i] > 0)
0095 return i + 1;
0096 }
0097
0098 return 0;
0099 }
0100
0101
0102
0103
0104
0105 static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type)
0106 {
0107 struct task_struct *tsk = bp->hw.target;
0108 struct perf_event *iter;
0109 int count = 0;
0110
0111 list_for_each_entry(iter, &bp_task_head, hw.bp_list) {
0112 if (iter->hw.target == tsk &&
0113 find_slot_idx(iter->attr.bp_type) == type &&
0114 (iter->cpu < 0 || cpu == iter->cpu))
0115 count += hw_breakpoint_weight(iter);
0116 }
0117
0118 return count;
0119 }
0120
0121 static const struct cpumask *cpumask_of_bp(struct perf_event *bp)
0122 {
0123 if (bp->cpu >= 0)
0124 return cpumask_of(bp->cpu);
0125 return cpu_possible_mask;
0126 }
0127
0128
0129
0130
0131
0132 static void
0133 fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
0134 enum bp_type_idx type)
0135 {
0136 const struct cpumask *cpumask = cpumask_of_bp(bp);
0137 int cpu;
0138
0139 for_each_cpu(cpu, cpumask) {
0140 struct bp_cpuinfo *info = get_bp_info(cpu, type);
0141 int nr;
0142
0143 nr = info->cpu_pinned;
0144 if (!bp->hw.target)
0145 nr += max_task_bp_pinned(cpu, type);
0146 else
0147 nr += task_bp_pinned(cpu, bp, type);
0148
0149 if (nr > slots->pinned)
0150 slots->pinned = nr;
0151
0152 nr = info->flexible;
0153 if (nr > slots->flexible)
0154 slots->flexible = nr;
0155 }
0156 }
0157
0158
0159
0160
0161
0162
0163 static void
0164 fetch_this_slot(struct bp_busy_slots *slots, int weight)
0165 {
0166 slots->pinned += weight;
0167 }
0168
0169
0170
0171
0172 static void toggle_bp_task_slot(struct perf_event *bp, int cpu,
0173 enum bp_type_idx type, int weight)
0174 {
0175 unsigned int *tsk_pinned = get_bp_info(cpu, type)->tsk_pinned;
0176 int old_idx, new_idx;
0177
0178 old_idx = task_bp_pinned(cpu, bp, type) - 1;
0179 new_idx = old_idx + weight;
0180
0181 if (old_idx >= 0)
0182 tsk_pinned[old_idx]--;
0183 if (new_idx >= 0)
0184 tsk_pinned[new_idx]++;
0185 }
0186
0187
0188
0189
0190 static void
0191 toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type,
0192 int weight)
0193 {
0194 const struct cpumask *cpumask = cpumask_of_bp(bp);
0195 int cpu;
0196
0197 if (!enable)
0198 weight = -weight;
0199
0200
0201 if (!bp->hw.target) {
0202 get_bp_info(bp->cpu, type)->cpu_pinned += weight;
0203 return;
0204 }
0205
0206
0207 for_each_cpu(cpu, cpumask)
0208 toggle_bp_task_slot(bp, cpu, type, weight);
0209
0210 if (enable)
0211 list_add_tail(&bp->hw.bp_list, &bp_task_head);
0212 else
0213 list_del(&bp->hw.bp_list);
0214 }
0215
0216 __weak int arch_reserve_bp_slot(struct perf_event *bp)
0217 {
0218 return 0;
0219 }
0220
0221 __weak void arch_release_bp_slot(struct perf_event *bp)
0222 {
0223 }
0224
0225
0226
0227
0228 __weak void arch_unregister_hw_breakpoint(struct perf_event *bp)
0229 {
0230
0231
0232
0233
0234 }
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 static int __reserve_bp_slot(struct perf_event *bp, u64 bp_type)
0278 {
0279 struct bp_busy_slots slots = {0};
0280 enum bp_type_idx type;
0281 int weight;
0282 int ret;
0283
0284
0285 if (!constraints_initialized)
0286 return -ENOMEM;
0287
0288
0289 if (bp_type == HW_BREAKPOINT_EMPTY ||
0290 bp_type == HW_BREAKPOINT_INVALID)
0291 return -EINVAL;
0292
0293 type = find_slot_idx(bp_type);
0294 weight = hw_breakpoint_weight(bp);
0295
0296 fetch_bp_busy_slots(&slots, bp, type);
0297
0298
0299
0300
0301 fetch_this_slot(&slots, weight);
0302
0303
0304 if (slots.pinned + (!!slots.flexible) > nr_slots[type])
0305 return -ENOSPC;
0306
0307 ret = arch_reserve_bp_slot(bp);
0308 if (ret)
0309 return ret;
0310
0311 toggle_bp_slot(bp, true, type, weight);
0312
0313 return 0;
0314 }
0315
0316 int reserve_bp_slot(struct perf_event *bp)
0317 {
0318 int ret;
0319
0320 mutex_lock(&nr_bp_mutex);
0321
0322 ret = __reserve_bp_slot(bp, bp->attr.bp_type);
0323
0324 mutex_unlock(&nr_bp_mutex);
0325
0326 return ret;
0327 }
0328
0329 static void __release_bp_slot(struct perf_event *bp, u64 bp_type)
0330 {
0331 enum bp_type_idx type;
0332 int weight;
0333
0334 arch_release_bp_slot(bp);
0335
0336 type = find_slot_idx(bp_type);
0337 weight = hw_breakpoint_weight(bp);
0338 toggle_bp_slot(bp, false, type, weight);
0339 }
0340
0341 void release_bp_slot(struct perf_event *bp)
0342 {
0343 mutex_lock(&nr_bp_mutex);
0344
0345 arch_unregister_hw_breakpoint(bp);
0346 __release_bp_slot(bp, bp->attr.bp_type);
0347
0348 mutex_unlock(&nr_bp_mutex);
0349 }
0350
0351 static int __modify_bp_slot(struct perf_event *bp, u64 old_type, u64 new_type)
0352 {
0353 int err;
0354
0355 __release_bp_slot(bp, old_type);
0356
0357 err = __reserve_bp_slot(bp, new_type);
0358 if (err) {
0359
0360
0361
0362
0363
0364
0365
0366
0367 WARN_ON(__reserve_bp_slot(bp, old_type));
0368 }
0369
0370 return err;
0371 }
0372
0373 static int modify_bp_slot(struct perf_event *bp, u64 old_type, u64 new_type)
0374 {
0375 int ret;
0376
0377 mutex_lock(&nr_bp_mutex);
0378 ret = __modify_bp_slot(bp, old_type, new_type);
0379 mutex_unlock(&nr_bp_mutex);
0380 return ret;
0381 }
0382
0383
0384
0385
0386
0387
0388 int dbg_reserve_bp_slot(struct perf_event *bp)
0389 {
0390 if (mutex_is_locked(&nr_bp_mutex))
0391 return -1;
0392
0393 return __reserve_bp_slot(bp, bp->attr.bp_type);
0394 }
0395
0396 int dbg_release_bp_slot(struct perf_event *bp)
0397 {
0398 if (mutex_is_locked(&nr_bp_mutex))
0399 return -1;
0400
0401 __release_bp_slot(bp, bp->attr.bp_type);
0402
0403 return 0;
0404 }
0405
0406 static int hw_breakpoint_parse(struct perf_event *bp,
0407 const struct perf_event_attr *attr,
0408 struct arch_hw_breakpoint *hw)
0409 {
0410 int err;
0411
0412 err = hw_breakpoint_arch_parse(bp, attr, hw);
0413 if (err)
0414 return err;
0415
0416 if (arch_check_bp_in_kernelspace(hw)) {
0417 if (attr->exclude_kernel)
0418 return -EINVAL;
0419
0420
0421
0422
0423 if (!capable(CAP_SYS_ADMIN))
0424 return -EPERM;
0425 }
0426
0427 return 0;
0428 }
0429
0430 int register_perf_hw_breakpoint(struct perf_event *bp)
0431 {
0432 struct arch_hw_breakpoint hw = { };
0433 int err;
0434
0435 err = reserve_bp_slot(bp);
0436 if (err)
0437 return err;
0438
0439 err = hw_breakpoint_parse(bp, &bp->attr, &hw);
0440 if (err) {
0441 release_bp_slot(bp);
0442 return err;
0443 }
0444
0445 bp->hw.info = hw;
0446
0447 return 0;
0448 }
0449
0450
0451
0452
0453
0454
0455
0456
0457 struct perf_event *
0458 register_user_hw_breakpoint(struct perf_event_attr *attr,
0459 perf_overflow_handler_t triggered,
0460 void *context,
0461 struct task_struct *tsk)
0462 {
0463 return perf_event_create_kernel_counter(attr, -1, tsk, triggered,
0464 context);
0465 }
0466 EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);
0467
0468 static void hw_breakpoint_copy_attr(struct perf_event_attr *to,
0469 struct perf_event_attr *from)
0470 {
0471 to->bp_addr = from->bp_addr;
0472 to->bp_type = from->bp_type;
0473 to->bp_len = from->bp_len;
0474 to->disabled = from->disabled;
0475 }
0476
0477 int
0478 modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *attr,
0479 bool check)
0480 {
0481 struct arch_hw_breakpoint hw = { };
0482 int err;
0483
0484 err = hw_breakpoint_parse(bp, attr, &hw);
0485 if (err)
0486 return err;
0487
0488 if (check) {
0489 struct perf_event_attr old_attr;
0490
0491 old_attr = bp->attr;
0492 hw_breakpoint_copy_attr(&old_attr, attr);
0493 if (memcmp(&old_attr, attr, sizeof(*attr)))
0494 return -EINVAL;
0495 }
0496
0497 if (bp->attr.bp_type != attr->bp_type) {
0498 err = modify_bp_slot(bp, bp->attr.bp_type, attr->bp_type);
0499 if (err)
0500 return err;
0501 }
0502
0503 hw_breakpoint_copy_attr(&bp->attr, attr);
0504 bp->hw.info = hw;
0505
0506 return 0;
0507 }
0508
0509
0510
0511
0512
0513
0514 int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr)
0515 {
0516 int err;
0517
0518
0519
0520
0521
0522
0523
0524 if (irqs_disabled() && bp->ctx && bp->ctx->task == current)
0525 perf_event_disable_local(bp);
0526 else
0527 perf_event_disable(bp);
0528
0529 err = modify_user_hw_breakpoint_check(bp, attr, false);
0530
0531 if (!bp->attr.disabled)
0532 perf_event_enable(bp);
0533
0534 return err;
0535 }
0536 EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint);
0537
0538
0539
0540
0541
0542 void unregister_hw_breakpoint(struct perf_event *bp)
0543 {
0544 if (!bp)
0545 return;
0546 perf_event_release_kernel(bp);
0547 }
0548 EXPORT_SYMBOL_GPL(unregister_hw_breakpoint);
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558 struct perf_event * __percpu *
0559 register_wide_hw_breakpoint(struct perf_event_attr *attr,
0560 perf_overflow_handler_t triggered,
0561 void *context)
0562 {
0563 struct perf_event * __percpu *cpu_events, *bp;
0564 long err = 0;
0565 int cpu;
0566
0567 cpu_events = alloc_percpu(typeof(*cpu_events));
0568 if (!cpu_events)
0569 return (void __percpu __force *)ERR_PTR(-ENOMEM);
0570
0571 cpus_read_lock();
0572 for_each_online_cpu(cpu) {
0573 bp = perf_event_create_kernel_counter(attr, cpu, NULL,
0574 triggered, context);
0575 if (IS_ERR(bp)) {
0576 err = PTR_ERR(bp);
0577 break;
0578 }
0579
0580 per_cpu(*cpu_events, cpu) = bp;
0581 }
0582 cpus_read_unlock();
0583
0584 if (likely(!err))
0585 return cpu_events;
0586
0587 unregister_wide_hw_breakpoint(cpu_events);
0588 return (void __percpu __force *)ERR_PTR(err);
0589 }
0590 EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
0591
0592
0593
0594
0595
0596 void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events)
0597 {
0598 int cpu;
0599
0600 for_each_possible_cpu(cpu)
0601 unregister_hw_breakpoint(per_cpu(*cpu_events, cpu));
0602
0603 free_percpu(cpu_events);
0604 }
0605 EXPORT_SYMBOL_GPL(unregister_wide_hw_breakpoint);
0606
0607 static struct notifier_block hw_breakpoint_exceptions_nb = {
0608 .notifier_call = hw_breakpoint_exceptions_notify,
0609
0610 .priority = 0x7fffffff
0611 };
0612
0613 static void bp_perf_event_destroy(struct perf_event *event)
0614 {
0615 release_bp_slot(event);
0616 }
0617
0618 static int hw_breakpoint_event_init(struct perf_event *bp)
0619 {
0620 int err;
0621
0622 if (bp->attr.type != PERF_TYPE_BREAKPOINT)
0623 return -ENOENT;
0624
0625
0626
0627
0628 if (has_branch_stack(bp))
0629 return -EOPNOTSUPP;
0630
0631 err = register_perf_hw_breakpoint(bp);
0632 if (err)
0633 return err;
0634
0635 bp->destroy = bp_perf_event_destroy;
0636
0637 return 0;
0638 }
0639
0640 static int hw_breakpoint_add(struct perf_event *bp, int flags)
0641 {
0642 if (!(flags & PERF_EF_START))
0643 bp->hw.state = PERF_HES_STOPPED;
0644
0645 if (is_sampling_event(bp)) {
0646 bp->hw.last_period = bp->hw.sample_period;
0647 perf_swevent_set_period(bp);
0648 }
0649
0650 return arch_install_hw_breakpoint(bp);
0651 }
0652
0653 static void hw_breakpoint_del(struct perf_event *bp, int flags)
0654 {
0655 arch_uninstall_hw_breakpoint(bp);
0656 }
0657
0658 static void hw_breakpoint_start(struct perf_event *bp, int flags)
0659 {
0660 bp->hw.state = 0;
0661 }
0662
0663 static void hw_breakpoint_stop(struct perf_event *bp, int flags)
0664 {
0665 bp->hw.state = PERF_HES_STOPPED;
0666 }
0667
0668 static struct pmu perf_breakpoint = {
0669 .task_ctx_nr = perf_sw_context,
0670
0671 .event_init = hw_breakpoint_event_init,
0672 .add = hw_breakpoint_add,
0673 .del = hw_breakpoint_del,
0674 .start = hw_breakpoint_start,
0675 .stop = hw_breakpoint_stop,
0676 .read = hw_breakpoint_pmu_read,
0677 };
0678
0679 int __init init_hw_breakpoint(void)
0680 {
0681 int cpu, err_cpu;
0682 int i;
0683
0684 for (i = 0; i < TYPE_MAX; i++)
0685 nr_slots[i] = hw_breakpoint_slots(i);
0686
0687 for_each_possible_cpu(cpu) {
0688 for (i = 0; i < TYPE_MAX; i++) {
0689 struct bp_cpuinfo *info = get_bp_info(cpu, i);
0690
0691 info->tsk_pinned = kcalloc(nr_slots[i], sizeof(int),
0692 GFP_KERNEL);
0693 if (!info->tsk_pinned)
0694 goto err_alloc;
0695 }
0696 }
0697
0698 constraints_initialized = 1;
0699
0700 perf_pmu_register(&perf_breakpoint, "breakpoint", PERF_TYPE_BREAKPOINT);
0701
0702 return register_die_notifier(&hw_breakpoint_exceptions_nb);
0703
0704 err_alloc:
0705 for_each_possible_cpu(err_cpu) {
0706 for (i = 0; i < TYPE_MAX; i++)
0707 kfree(get_bp_info(err_cpu, i)->tsk_pinned);
0708 if (err_cpu == cpu)
0709 break;
0710 }
0711
0712 return -ENOMEM;
0713 }
0714
0715