0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 #include <linux/kernel.h>
0142 #include <linux/module.h>
0143 #include <linux/init.h>
0144 #include <linux/slab.h>
0145
0146 #ifdef CONFIG_DA_MON_EVENTS
0147 #define CREATE_TRACE_POINTS
0148 #include <trace/events/rv.h>
0149 #endif
0150
0151 #include "rv.h"
0152
0153 DEFINE_MUTEX(rv_interface_lock);
0154
0155 static struct rv_interface rv_root;
0156
0157 struct dentry *get_monitors_root(void)
0158 {
0159 return rv_root.monitors_dir;
0160 }
0161
0162
0163
0164
0165 static LIST_HEAD(rv_monitors_list);
0166
0167 static int task_monitor_count;
0168 static bool task_monitor_slots[RV_PER_TASK_MONITORS];
0169
0170 int rv_get_task_monitor_slot(void)
0171 {
0172 int i;
0173
0174 lockdep_assert_held(&rv_interface_lock);
0175
0176 if (task_monitor_count == RV_PER_TASK_MONITORS)
0177 return -EBUSY;
0178
0179 task_monitor_count++;
0180
0181 for (i = 0; i < RV_PER_TASK_MONITORS; i++) {
0182 if (task_monitor_slots[i] == false) {
0183 task_monitor_slots[i] = true;
0184 return i;
0185 }
0186 }
0187
0188 WARN_ONCE(1, "RV task_monitor_count and slots are out of sync\n");
0189
0190 return -EINVAL;
0191 }
0192
0193 void rv_put_task_monitor_slot(int slot)
0194 {
0195 lockdep_assert_held(&rv_interface_lock);
0196
0197 if (slot < 0 || slot >= RV_PER_TASK_MONITORS) {
0198 WARN_ONCE(1, "RV releasing an invalid slot!: %d\n", slot);
0199 return;
0200 }
0201
0202 WARN_ONCE(!task_monitor_slots[slot], "RV releasing unused task_monitor_slots: %d\n",
0203 slot);
0204
0205 task_monitor_count--;
0206 task_monitor_slots[slot] = false;
0207 }
0208
0209
0210
0211
0212 static ssize_t monitor_enable_read_data(struct file *filp, char __user *user_buf, size_t count,
0213 loff_t *ppos)
0214 {
0215 struct rv_monitor_def *mdef = filp->private_data;
0216 const char *buff;
0217
0218 buff = mdef->monitor->enabled ? "1\n" : "0\n";
0219
0220 return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff)+1);
0221 }
0222
0223
0224
0225
0226 static int __rv_disable_monitor(struct rv_monitor_def *mdef, bool sync)
0227 {
0228 lockdep_assert_held(&rv_interface_lock);
0229
0230 if (mdef->monitor->enabled) {
0231 mdef->monitor->enabled = 0;
0232 mdef->monitor->disable();
0233
0234
0235
0236
0237
0238
0239 if (sync)
0240 tracepoint_synchronize_unregister();
0241 return 1;
0242 }
0243 return 0;
0244 }
0245
0246
0247
0248
0249
0250
0251 int rv_disable_monitor(struct rv_monitor_def *mdef)
0252 {
0253 __rv_disable_monitor(mdef, true);
0254 return 0;
0255 }
0256
0257
0258
0259
0260
0261
0262 int rv_enable_monitor(struct rv_monitor_def *mdef)
0263 {
0264 int retval;
0265
0266 lockdep_assert_held(&rv_interface_lock);
0267
0268 if (mdef->monitor->enabled)
0269 return 0;
0270
0271 retval = mdef->monitor->enable();
0272
0273 if (!retval)
0274 mdef->monitor->enabled = 1;
0275
0276 return retval;
0277 }
0278
0279
0280
0281
0282 static ssize_t monitor_enable_write_data(struct file *filp, const char __user *user_buf,
0283 size_t count, loff_t *ppos)
0284 {
0285 struct rv_monitor_def *mdef = filp->private_data;
0286 int retval;
0287 bool val;
0288
0289 retval = kstrtobool_from_user(user_buf, count, &val);
0290 if (retval)
0291 return retval;
0292
0293 retval = count;
0294
0295 mutex_lock(&rv_interface_lock);
0296
0297 if (val)
0298 retval = rv_enable_monitor(mdef);
0299 else
0300 retval = rv_disable_monitor(mdef);
0301
0302 mutex_unlock(&rv_interface_lock);
0303
0304 return retval ? : count;
0305 }
0306
0307 static const struct file_operations interface_enable_fops = {
0308 .open = simple_open,
0309 .llseek = no_llseek,
0310 .write = monitor_enable_write_data,
0311 .read = monitor_enable_read_data,
0312 };
0313
0314
0315
0316
0317 static ssize_t monitor_desc_read_data(struct file *filp, char __user *user_buf, size_t count,
0318 loff_t *ppos)
0319 {
0320 struct rv_monitor_def *mdef = filp->private_data;
0321 char buff[256];
0322
0323 memset(buff, 0, sizeof(buff));
0324
0325 snprintf(buff, sizeof(buff), "%s\n", mdef->monitor->description);
0326
0327 return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff) + 1);
0328 }
0329
0330 static const struct file_operations interface_desc_fops = {
0331 .open = simple_open,
0332 .llseek = no_llseek,
0333 .read = monitor_desc_read_data,
0334 };
0335
0336
0337
0338
0339
0340
0341 static int create_monitor_dir(struct rv_monitor_def *mdef)
0342 {
0343 struct dentry *root = get_monitors_root();
0344 const char *name = mdef->monitor->name;
0345 struct dentry *tmp;
0346 int retval;
0347
0348 mdef->root_d = rv_create_dir(name, root);
0349 if (!mdef->root_d)
0350 return -ENOMEM;
0351
0352 tmp = rv_create_file("enable", RV_MODE_WRITE, mdef->root_d, mdef, &interface_enable_fops);
0353 if (!tmp) {
0354 retval = -ENOMEM;
0355 goto out_remove_root;
0356 }
0357
0358 tmp = rv_create_file("desc", RV_MODE_READ, mdef->root_d, mdef, &interface_desc_fops);
0359 if (!tmp) {
0360 retval = -ENOMEM;
0361 goto out_remove_root;
0362 }
0363
0364 retval = reactor_populate_monitor(mdef);
0365 if (retval)
0366 goto out_remove_root;
0367
0368 return 0;
0369
0370 out_remove_root:
0371 rv_remove(mdef->root_d);
0372 return retval;
0373 }
0374
0375
0376
0377
0378 static int monitors_show(struct seq_file *m, void *p)
0379 {
0380 struct rv_monitor_def *mon_def = p;
0381
0382 seq_printf(m, "%s\n", mon_def->monitor->name);
0383 return 0;
0384 }
0385
0386
0387
0388
0389
0390 static void monitors_stop(struct seq_file *m, void *p)
0391 {
0392 mutex_unlock(&rv_interface_lock);
0393 }
0394
0395
0396
0397
0398 static void *available_monitors_start(struct seq_file *m, loff_t *pos)
0399 {
0400 mutex_lock(&rv_interface_lock);
0401 return seq_list_start(&rv_monitors_list, *pos);
0402 }
0403
0404 static void *available_monitors_next(struct seq_file *m, void *p, loff_t *pos)
0405 {
0406 return seq_list_next(p, &rv_monitors_list, pos);
0407 }
0408
0409
0410
0411
0412 static void *enabled_monitors_next(struct seq_file *m, void *p, loff_t *pos)
0413 {
0414 struct rv_monitor_def *m_def = p;
0415
0416 (*pos)++;
0417
0418 list_for_each_entry_continue(m_def, &rv_monitors_list, list) {
0419 if (m_def->monitor->enabled)
0420 return m_def;
0421 }
0422
0423 return NULL;
0424 }
0425
0426 static void *enabled_monitors_start(struct seq_file *m, loff_t *pos)
0427 {
0428 struct rv_monitor_def *m_def;
0429 loff_t l;
0430
0431 mutex_lock(&rv_interface_lock);
0432
0433 if (list_empty(&rv_monitors_list))
0434 return NULL;
0435
0436 m_def = list_entry(&rv_monitors_list, struct rv_monitor_def, list);
0437
0438 for (l = 0; l <= *pos; ) {
0439 m_def = enabled_monitors_next(m, m_def, &l);
0440 if (!m_def)
0441 break;
0442 }
0443
0444 return m_def;
0445 }
0446
0447
0448
0449
0450 static const struct seq_operations available_monitors_seq_ops = {
0451 .start = available_monitors_start,
0452 .next = available_monitors_next,
0453 .stop = monitors_stop,
0454 .show = monitors_show
0455 };
0456
0457 static const struct seq_operations enabled_monitors_seq_ops = {
0458 .start = enabled_monitors_start,
0459 .next = enabled_monitors_next,
0460 .stop = monitors_stop,
0461 .show = monitors_show
0462 };
0463
0464
0465
0466
0467 static int available_monitors_open(struct inode *inode, struct file *file)
0468 {
0469 return seq_open(file, &available_monitors_seq_ops);
0470 };
0471
0472 static const struct file_operations available_monitors_ops = {
0473 .open = available_monitors_open,
0474 .read = seq_read,
0475 .llseek = seq_lseek,
0476 .release = seq_release
0477 };
0478
0479
0480
0481
0482 static void disable_all_monitors(void)
0483 {
0484 struct rv_monitor_def *mdef;
0485 int enabled = 0;
0486
0487 mutex_lock(&rv_interface_lock);
0488
0489 list_for_each_entry(mdef, &rv_monitors_list, list)
0490 enabled += __rv_disable_monitor(mdef, false);
0491
0492 if (enabled) {
0493
0494
0495
0496
0497
0498 tracepoint_synchronize_unregister();
0499 }
0500
0501 mutex_unlock(&rv_interface_lock);
0502 }
0503
0504 static int enabled_monitors_open(struct inode *inode, struct file *file)
0505 {
0506 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
0507 disable_all_monitors();
0508
0509 return seq_open(file, &enabled_monitors_seq_ops);
0510 };
0511
0512 static ssize_t enabled_monitors_write(struct file *filp, const char __user *user_buf,
0513 size_t count, loff_t *ppos)
0514 {
0515 char buff[MAX_RV_MONITOR_NAME_SIZE + 2];
0516 struct rv_monitor_def *mdef;
0517 int retval = -EINVAL;
0518 bool enable = true;
0519 char *ptr = buff;
0520 int len;
0521
0522 if (count < 1 || count > MAX_RV_MONITOR_NAME_SIZE + 1)
0523 return -EINVAL;
0524
0525 memset(buff, 0, sizeof(buff));
0526
0527 retval = simple_write_to_buffer(buff, sizeof(buff) - 1, ppos, user_buf, count);
0528 if (retval < 0)
0529 return -EFAULT;
0530
0531 ptr = strim(buff);
0532
0533 if (ptr[0] == '!') {
0534 enable = false;
0535 ptr++;
0536 }
0537
0538 len = strlen(ptr);
0539 if (!len)
0540 return count;
0541
0542 mutex_lock(&rv_interface_lock);
0543
0544 retval = -EINVAL;
0545
0546 list_for_each_entry(mdef, &rv_monitors_list, list) {
0547 if (strcmp(ptr, mdef->monitor->name) != 0)
0548 continue;
0549
0550
0551
0552
0553 if (enable)
0554 retval = rv_enable_monitor(mdef);
0555 else
0556 retval = rv_disable_monitor(mdef);
0557
0558 if (!retval)
0559 retval = count;
0560
0561 break;
0562 }
0563
0564 mutex_unlock(&rv_interface_lock);
0565 return retval;
0566 }
0567
0568 static const struct file_operations enabled_monitors_ops = {
0569 .open = enabled_monitors_open,
0570 .read = seq_read,
0571 .write = enabled_monitors_write,
0572 .llseek = seq_lseek,
0573 .release = seq_release,
0574 };
0575
0576
0577
0578
0579 static bool __read_mostly monitoring_on;
0580
0581
0582
0583
0584
0585
0586 bool rv_monitoring_on(void)
0587 {
0588
0589 smp_rmb();
0590 return READ_ONCE(monitoring_on);
0591 }
0592
0593
0594
0595
0596 static ssize_t monitoring_on_read_data(struct file *filp, char __user *user_buf,
0597 size_t count, loff_t *ppos)
0598 {
0599 const char *buff;
0600
0601 buff = rv_monitoring_on() ? "1\n" : "0\n";
0602
0603 return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff) + 1);
0604 }
0605
0606 static void turn_monitoring_off(void)
0607 {
0608 WRITE_ONCE(monitoring_on, false);
0609
0610 smp_wmb();
0611 }
0612
0613 static void reset_all_monitors(void)
0614 {
0615 struct rv_monitor_def *mdef;
0616
0617 list_for_each_entry(mdef, &rv_monitors_list, list) {
0618 if (mdef->monitor->enabled)
0619 mdef->monitor->reset();
0620 }
0621 }
0622
0623 static void turn_monitoring_on(void)
0624 {
0625 WRITE_ONCE(monitoring_on, true);
0626
0627 smp_wmb();
0628 }
0629
0630 static void turn_monitoring_on_with_reset(void)
0631 {
0632 lockdep_assert_held(&rv_interface_lock);
0633
0634 if (rv_monitoring_on())
0635 return;
0636
0637
0638
0639
0640
0641
0642
0643 reset_all_monitors();
0644 turn_monitoring_on();
0645 }
0646
0647 static ssize_t monitoring_on_write_data(struct file *filp, const char __user *user_buf,
0648 size_t count, loff_t *ppos)
0649 {
0650 int retval;
0651 bool val;
0652
0653 retval = kstrtobool_from_user(user_buf, count, &val);
0654 if (retval)
0655 return retval;
0656
0657 mutex_lock(&rv_interface_lock);
0658
0659 if (val)
0660 turn_monitoring_on_with_reset();
0661 else
0662 turn_monitoring_off();
0663
0664
0665
0666
0667
0668 tracepoint_synchronize_unregister();
0669
0670 mutex_unlock(&rv_interface_lock);
0671
0672 return count;
0673 }
0674
0675 static const struct file_operations monitoring_on_fops = {
0676 .open = simple_open,
0677 .llseek = no_llseek,
0678 .write = monitoring_on_write_data,
0679 .read = monitoring_on_read_data,
0680 };
0681
0682 static void destroy_monitor_dir(struct rv_monitor_def *mdef)
0683 {
0684 reactor_cleanup_monitor(mdef);
0685 rv_remove(mdef->root_d);
0686 }
0687
0688
0689
0690
0691
0692
0693
0694 int rv_register_monitor(struct rv_monitor *monitor)
0695 {
0696 struct rv_monitor_def *r;
0697 int retval = 0;
0698
0699 if (strlen(monitor->name) >= MAX_RV_MONITOR_NAME_SIZE) {
0700 pr_info("Monitor %s has a name longer than %d\n", monitor->name,
0701 MAX_RV_MONITOR_NAME_SIZE);
0702 return -1;
0703 }
0704
0705 mutex_lock(&rv_interface_lock);
0706
0707 list_for_each_entry(r, &rv_monitors_list, list) {
0708 if (strcmp(monitor->name, r->monitor->name) == 0) {
0709 pr_info("Monitor %s is already registered\n", monitor->name);
0710 retval = -1;
0711 goto out_unlock;
0712 }
0713 }
0714
0715 r = kzalloc(sizeof(struct rv_monitor_def), GFP_KERNEL);
0716 if (!r) {
0717 retval = -ENOMEM;
0718 goto out_unlock;
0719 }
0720
0721 r->monitor = monitor;
0722
0723 retval = create_monitor_dir(r);
0724 if (retval) {
0725 kfree(r);
0726 goto out_unlock;
0727 }
0728
0729 list_add_tail(&r->list, &rv_monitors_list);
0730
0731 out_unlock:
0732 mutex_unlock(&rv_interface_lock);
0733 return retval;
0734 }
0735
0736
0737
0738
0739
0740
0741
0742 int rv_unregister_monitor(struct rv_monitor *monitor)
0743 {
0744 struct rv_monitor_def *ptr, *next;
0745
0746 mutex_lock(&rv_interface_lock);
0747
0748 list_for_each_entry_safe(ptr, next, &rv_monitors_list, list) {
0749 if (strcmp(monitor->name, ptr->monitor->name) == 0) {
0750 rv_disable_monitor(ptr);
0751 list_del(&ptr->list);
0752 destroy_monitor_dir(ptr);
0753 }
0754 }
0755
0756 mutex_unlock(&rv_interface_lock);
0757 return 0;
0758 }
0759
0760 int __init rv_init_interface(void)
0761 {
0762 struct dentry *tmp;
0763 int retval;
0764
0765 rv_root.root_dir = rv_create_dir("rv", NULL);
0766 if (!rv_root.root_dir)
0767 goto out_err;
0768
0769 rv_root.monitors_dir = rv_create_dir("monitors", rv_root.root_dir);
0770 if (!rv_root.monitors_dir)
0771 goto out_err;
0772
0773 tmp = rv_create_file("available_monitors", RV_MODE_READ, rv_root.root_dir, NULL,
0774 &available_monitors_ops);
0775 if (!tmp)
0776 goto out_err;
0777
0778 tmp = rv_create_file("enabled_monitors", RV_MODE_WRITE, rv_root.root_dir, NULL,
0779 &enabled_monitors_ops);
0780 if (!tmp)
0781 goto out_err;
0782
0783 tmp = rv_create_file("monitoring_on", RV_MODE_WRITE, rv_root.root_dir, NULL,
0784 &monitoring_on_fops);
0785 if (!tmp)
0786 goto out_err;
0787 retval = init_rv_reactors(rv_root.root_dir);
0788 if (retval)
0789 goto out_err;
0790
0791 turn_monitoring_on();
0792
0793 return 0;
0794
0795 out_err:
0796 rv_remove(rv_root.root_dir);
0797 printk(KERN_ERR "RV: Error while creating the RV interface\n");
0798 return 1;
0799 }