Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'trace-rv-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull runtime verifier updates from Steven Rostedt:

- Adapt the ftracetest script to be run from a different folder

This uses the already existing OPT_TEST_DIR but extends it further to
run independent tests, then add an --rv flag to allow using the
script for testing RV (mostly) independently on ftrace.

- Add basic RV selftests in selftests/verification for more validations

Add more validations for available/enabled monitors and reactors.
This could have caught the bug introducing kernel panic solved above.
Tests use ftracetest.

- Convert react() function in reactor to use va_list directly

Use a central helper to handle the variadic arguments. Clean up
macros and mark functions as static.

- Add lockdep annotations to reactors to have lockdep complain of
errors

If the reactors are called from improper context. Useful to develop
new reactors. This highlights a warning in the panic reactor that is
related to the printk subsystem and not to RV.

- Convert core RV code to use lock guards and __free helpers

This completely removes goto statements.

- Fix compilation if !CONFIG_RV_REACTORS

Fix the warning by keeping LTL monitor variable as always static.

* tag 'trace-rv-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
rv: Fix compilation if !CONFIG_RV_REACTORS
rv: Convert to use __free
rv: Convert to use lock guard
rv: Add explicit lockdep context for reactors
rv: Make rv_reacting_on() static
rv: Pass va_list to reactors
selftests/verification: Add initial RV tests
selftest/ftrace: Generalise ftracetest to use with RV

+384 -173
+1
MAINTAINERS
··· 22700 22700 F: include/linux/rv.h 22701 22701 F: include/rv/ 22702 22702 F: kernel/trace/rv/ 22703 + F: tools/testing/selftests/verification/ 22703 22704 F: tools/verification/ 22704 22705 22705 22706 RUST
+6 -5
include/linux/rv.h
··· 88 88 struct rv_reactor { 89 89 const char *name; 90 90 const char *description; 91 - __printf(1, 2) void (*react)(const char *msg, ...); 91 + __printf(1, 0) void (*react)(const char *msg, va_list args); 92 92 struct list_head list; 93 93 }; 94 94 #endif ··· 102 102 void (*reset)(void); 103 103 #ifdef CONFIG_RV_REACTORS 104 104 struct rv_reactor *reactor; 105 - __printf(1, 2) void (*react)(const char *msg, ...); 105 + __printf(1, 0) void (*react)(const char *msg, va_list args); 106 106 #endif 107 107 struct list_head list; 108 108 struct rv_monitor *parent; ··· 116 116 void rv_put_task_monitor_slot(int slot); 117 117 118 118 #ifdef CONFIG_RV_REACTORS 119 - bool rv_reacting_on(void); 120 119 int rv_unregister_reactor(struct rv_reactor *reactor); 121 120 int rv_register_reactor(struct rv_reactor *reactor); 121 + __printf(2, 3) 122 + void rv_react(struct rv_monitor *monitor, const char *msg, ...); 122 123 #else 123 - static inline bool rv_reacting_on(void) 124 + __printf(2, 3) 125 + static inline void rv_react(struct rv_monitor *monitor, const char *msg, ...) 124 126 { 125 - return false; 126 127 } 127 128 #endif /* CONFIG_RV_REACTORS */ 128 129
+10 -25
include/rv/da_monitor.h
··· 16 16 #include <linux/bug.h> 17 17 #include <linux/sched.h> 18 18 19 - #ifdef CONFIG_RV_REACTORS 20 - 21 - #define DECLARE_RV_REACTING_HELPERS(name, type) \ 22 - static void cond_react_##name(type curr_state, type event) \ 23 - { \ 24 - if (!rv_reacting_on() || !rv_##name.react) \ 25 - return; \ 26 - rv_##name.react("rv: monitor %s does not allow event %s on state %s\n", \ 27 - #name, \ 28 - model_get_event_name_##name(event), \ 29 - model_get_state_name_##name(curr_state)); \ 30 - } 31 - 32 - #else /* CONFIG_RV_REACTOR */ 33 - 34 - #define DECLARE_RV_REACTING_HELPERS(name, type) \ 35 - static void cond_react_##name(type curr_state, type event) \ 36 - { \ 37 - return; \ 38 - } 39 - #endif 40 - 41 19 /* 42 20 * Generic helpers for all types of deterministic automata monitors. 43 21 */ 44 22 #define DECLARE_DA_MON_GENERIC_HELPERS(name, type) \ 45 23 \ 46 - DECLARE_RV_REACTING_HELPERS(name, type) \ 24 + static void react_##name(type curr_state, type event) \ 25 + { \ 26 + rv_react(&rv_##name, \ 27 + "rv: monitor %s does not allow event %s on state %s\n", \ 28 + #name, \ 29 + model_get_event_name_##name(event), \ 30 + model_get_state_name_##name(curr_state)); \ 31 + } \ 47 32 \ 48 33 /* \ 49 34 * da_monitor_reset_##name - reset a monitor and setting it to init state \ ··· 111 126 for (int i = 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) { \ 112 127 next_state = model_get_next_state_##name(curr_state, event); \ 113 128 if (next_state == INVALID_STATE) { \ 114 - cond_react_##name(curr_state, event); \ 129 + react_##name(curr_state, event); \ 115 130 trace_error_##name(model_get_state_name_##name(curr_state), \ 116 131 model_get_event_name_##name(event)); \ 117 132 return false; \ ··· 150 165 for (int i = 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) { \ 151 166 next_state = model_get_next_state_##name(curr_state, event); \ 152 167 if (next_state == INVALID_STATE) { \ 153 - cond_react_##name(curr_state, event); \ 168 + react_##name(curr_state, event); \ 154 169 trace_error_##name(tsk->pid, \ 155 170 model_get_state_name_##name(curr_state), \ 156 171 model_get_event_name_##name(event)); \
+2 -15
include/rv/ltl_monitor.h
··· 16 16 #error "Please include $(MODEL_NAME).h generated by rvgen" 17 17 #endif 18 18 19 - #ifdef CONFIG_RV_REACTORS 20 19 #define RV_MONITOR_NAME CONCATENATE(rv_, MONITOR_NAME) 21 20 static struct rv_monitor RV_MONITOR_NAME; 22 - 23 - static void rv_cond_react(struct task_struct *task) 24 - { 25 - if (!rv_reacting_on() || !RV_MONITOR_NAME.react) 26 - return; 27 - RV_MONITOR_NAME.react("rv: "__stringify(MONITOR_NAME)": %s[%d]: violation detected\n", 28 - task->comm, task->pid); 29 - } 30 - #else 31 - static void rv_cond_react(struct task_struct *task) 32 - { 33 - } 34 - #endif 35 21 36 22 static int ltl_monitor_slot = RV_PER_TASK_MONITOR_INIT; 37 23 ··· 84 98 static void ltl_illegal_state(struct task_struct *task, struct ltl_monitor *mon) 85 99 { 86 100 CONCATENATE(trace_error_, MONITOR_NAME)(task); 87 - rv_cond_react(task); 101 + rv_react(&RV_MONITOR_NAME, "rv: "__stringify(MONITOR_NAME)": %s[%d]: violation detected\n", 102 + task->comm, task->pid); 88 103 } 89 104 90 105 static void ltl_attempt_start(struct task_struct *task, struct ltl_monitor *mon)
+1 -5
kernel/trace/rv/reactor_panic.c
··· 13 13 #include <linux/init.h> 14 14 #include <linux/rv.h> 15 15 16 - __printf(1, 2) static void rv_panic_reaction(const char *msg, ...) 16 + __printf(1, 0) static void rv_panic_reaction(const char *msg, va_list args) 17 17 { 18 - va_list args; 19 - 20 - va_start(args, msg); 21 18 vpanic(msg, args); 22 - va_end(args); 23 19 } 24 20 25 21 static struct rv_reactor rv_panic = {
+1 -5
kernel/trace/rv/reactor_printk.c
··· 12 12 #include <linux/init.h> 13 13 #include <linux/rv.h> 14 14 15 - __printf(1, 2) static void rv_printk_reaction(const char *msg, ...) 15 + __printf(1, 0) static void rv_printk_reaction(const char *msg, va_list args) 16 16 { 17 - va_list args; 18 - 19 - va_start(args, msg); 20 17 vprintk_deferred(msg, args); 21 - va_end(args); 22 18 } 23 19 24 20 static struct rv_reactor rv_printk = {
+39 -63
kernel/trace/rv/rv.c
··· 375 375 if (retval) 376 376 return retval; 377 377 378 - mutex_lock(&rv_interface_lock); 378 + guard(mutex)(&rv_interface_lock); 379 379 380 380 if (val) 381 381 retval = rv_enable_monitor(mon); 382 382 else 383 383 retval = rv_disable_monitor(mon); 384 - 385 - mutex_unlock(&rv_interface_lock); 386 384 387 385 return retval ? : count; 388 386 } ··· 420 422 static int create_monitor_dir(struct rv_monitor *mon, struct rv_monitor *parent) 421 423 { 422 424 struct dentry *root = parent ? parent->root_d : get_monitors_root(); 423 - const char *name = mon->name; 425 + struct dentry *dir __free(rv_remove) = rv_create_dir(mon->name, root); 424 426 struct dentry *tmp; 425 427 int retval; 426 428 427 - mon->root_d = rv_create_dir(name, root); 428 - if (!mon->root_d) 429 + if (!dir) 429 430 return -ENOMEM; 430 431 431 - tmp = rv_create_file("enable", RV_MODE_WRITE, mon->root_d, mon, &interface_enable_fops); 432 - if (!tmp) { 433 - retval = -ENOMEM; 434 - goto out_remove_root; 435 - } 432 + tmp = rv_create_file("enable", RV_MODE_WRITE, dir, mon, &interface_enable_fops); 433 + if (!tmp) 434 + return -ENOMEM; 436 435 437 - tmp = rv_create_file("desc", RV_MODE_READ, mon->root_d, mon, &interface_desc_fops); 438 - if (!tmp) { 439 - retval = -ENOMEM; 440 - goto out_remove_root; 441 - } 436 + tmp = rv_create_file("desc", RV_MODE_READ, dir, mon, &interface_desc_fops); 437 + if (!tmp) 438 + return -ENOMEM; 442 439 443 - retval = reactor_populate_monitor(mon); 440 + retval = reactor_populate_monitor(mon, dir); 444 441 if (retval) 445 - goto out_remove_root; 442 + return retval; 446 443 444 + mon->root_d = no_free_ptr(dir); 447 445 return 0; 448 - 449 - out_remove_root: 450 - rv_remove(mon->root_d); 451 - return retval; 452 446 } 453 447 454 448 /* ··· 558 568 struct rv_monitor *mon; 559 569 int enabled = 0; 560 570 561 - mutex_lock(&rv_interface_lock); 571 + guard(mutex)(&rv_interface_lock); 562 572 563 573 list_for_each_entry(mon, &rv_monitors_list, list) 564 574 enabled += __rv_disable_monitor(mon, false); ··· 571 581 */ 572 582 tracepoint_synchronize_unregister(); 573 583 } 574 - 575 - mutex_unlock(&rv_interface_lock); 576 584 } 577 585 578 586 static int enabled_monitors_open(struct inode *inode, struct file *file) ··· 611 623 if (!len) 612 624 return count; 613 625 614 - mutex_lock(&rv_interface_lock); 626 + guard(mutex)(&rv_interface_lock); 615 627 616 628 retval = -EINVAL; 617 629 ··· 632 644 else 633 645 retval = rv_disable_monitor(mon); 634 646 635 - if (!retval) 636 - retval = count; 637 - 638 - break; 647 + if (retval) 648 + return retval; 649 + return count; 639 650 } 640 651 641 - mutex_unlock(&rv_interface_lock); 642 652 return retval; 643 653 } 644 654 ··· 723 737 if (retval) 724 738 return retval; 725 739 726 - mutex_lock(&rv_interface_lock); 740 + guard(mutex)(&rv_interface_lock); 727 741 728 742 if (val) 729 743 turn_monitoring_on_with_reset(); ··· 735 749 * before returning to user-space. 736 750 */ 737 751 tracepoint_synchronize_unregister(); 738 - 739 - mutex_unlock(&rv_interface_lock); 740 752 741 753 return count; 742 754 } ··· 768 784 return -EINVAL; 769 785 } 770 786 771 - mutex_lock(&rv_interface_lock); 787 + guard(mutex)(&rv_interface_lock); 772 788 773 789 list_for_each_entry(r, &rv_monitors_list, list) { 774 790 if (strcmp(monitor->name, r->name) == 0) { 775 791 pr_info("Monitor %s is already registered\n", monitor->name); 776 - retval = -EEXIST; 777 - goto out_unlock; 792 + return -EEXIST; 778 793 } 779 794 } 780 795 781 796 if (parent && rv_is_nested_monitor(parent)) { 782 797 pr_info("Parent monitor %s is already nested, cannot nest further\n", 783 798 parent->name); 784 - retval = -EINVAL; 785 - goto out_unlock; 799 + return -EINVAL; 786 800 } 787 801 788 802 monitor->parent = parent; 789 803 790 804 retval = create_monitor_dir(monitor, parent); 791 805 if (retval) 792 - goto out_unlock; 806 + return retval; 793 807 794 808 /* keep children close to the parent for easier visualisation */ 795 809 if (parent) ··· 795 813 else 796 814 list_add_tail(&monitor->list, &rv_monitors_list); 797 815 798 - out_unlock: 799 - mutex_unlock(&rv_interface_lock); 800 - return retval; 816 + return 0; 801 817 } 802 818 803 819 /** ··· 806 826 */ 807 827 int rv_unregister_monitor(struct rv_monitor *monitor) 808 828 { 809 - mutex_lock(&rv_interface_lock); 829 + guard(mutex)(&rv_interface_lock); 810 830 811 831 rv_disable_monitor(monitor); 812 832 list_del(&monitor->list); 813 833 destroy_monitor_dir(monitor); 814 834 815 - mutex_unlock(&rv_interface_lock); 816 835 return 0; 817 836 } 818 837 ··· 819 840 { 820 841 struct dentry *tmp; 821 842 int retval; 843 + struct dentry *root_dir __free(rv_remove) = rv_create_dir("rv", NULL); 822 844 823 - rv_root.root_dir = rv_create_dir("rv", NULL); 824 - if (!rv_root.root_dir) 825 - goto out_err; 845 + if (!root_dir) 846 + return 1; 826 847 827 - rv_root.monitors_dir = rv_create_dir("monitors", rv_root.root_dir); 848 + rv_root.monitors_dir = rv_create_dir("monitors", root_dir); 828 849 if (!rv_root.monitors_dir) 829 - goto out_err; 850 + return 1; 830 851 831 - tmp = rv_create_file("available_monitors", RV_MODE_READ, rv_root.root_dir, NULL, 852 + tmp = rv_create_file("available_monitors", RV_MODE_READ, root_dir, NULL, 832 853 &available_monitors_ops); 833 854 if (!tmp) 834 - goto out_err; 855 + return 1; 835 856 836 - tmp = rv_create_file("enabled_monitors", RV_MODE_WRITE, rv_root.root_dir, NULL, 857 + tmp = rv_create_file("enabled_monitors", RV_MODE_WRITE, root_dir, NULL, 837 858 &enabled_monitors_ops); 838 859 if (!tmp) 839 - goto out_err; 860 + return 1; 840 861 841 - tmp = rv_create_file("monitoring_on", RV_MODE_WRITE, rv_root.root_dir, NULL, 862 + tmp = rv_create_file("monitoring_on", RV_MODE_WRITE, root_dir, NULL, 842 863 &monitoring_on_fops); 843 864 if (!tmp) 844 - goto out_err; 845 - retval = init_rv_reactors(rv_root.root_dir); 865 + return 1; 866 + retval = init_rv_reactors(root_dir); 846 867 if (retval) 847 - goto out_err; 868 + return 1; 848 869 849 870 turn_monitoring_on(); 850 871 851 - return 0; 872 + rv_root.root_dir = no_free_ptr(root_dir); 852 873 853 - out_err: 854 - rv_remove(rv_root.root_dir); 855 - printk(KERN_ERR "RV: Error while creating the RV interface\n"); 856 - return 1; 874 + return 0; 857 875 }
+4 -2
kernel/trace/rv/rv.h
··· 17 17 #define rv_create_file tracefs_create_file 18 18 #define rv_remove tracefs_remove 19 19 20 + DEFINE_FREE(rv_remove, struct dentry *, if (_T) rv_remove(_T)); 21 + 20 22 #define MAX_RV_MONITOR_NAME_SIZE 32 21 23 #define MAX_RV_REACTOR_NAME_SIZE 32 22 24 ··· 32 30 bool rv_is_nested_monitor(struct rv_monitor *mon); 33 31 34 32 #ifdef CONFIG_RV_REACTORS 35 - int reactor_populate_monitor(struct rv_monitor *mon); 33 + int reactor_populate_monitor(struct rv_monitor *mon, struct dentry *root); 36 34 int init_rv_reactors(struct dentry *root_dir); 37 35 #else 38 - static inline int reactor_populate_monitor(struct rv_monitor *mon) 36 + static inline int reactor_populate_monitor(struct rv_monitor *mon, struct dentry *root) 39 37 { 40 38 return 0; 41 39 }
+40 -38
kernel/trace/rv/rv_reactors.c
··· 61 61 * printk 62 62 */ 63 63 64 + #include <linux/lockdep.h> 64 65 #include <linux/slab.h> 65 66 66 67 #include "rv.h" ··· 233 232 seq_f = file->private_data; 234 233 mon = seq_f->private; 235 234 236 - mutex_lock(&rv_interface_lock); 237 - 238 - retval = -EINVAL; 235 + guard(mutex)(&rv_interface_lock); 239 236 240 237 list_for_each_entry(reactor, &rv_reactors_list, list) { 241 238 if (strcmp(ptr, reactor->name) != 0) ··· 241 242 242 243 monitor_swap_reactors(mon, reactor); 243 244 244 - retval = count; 245 - break; 245 + return count; 246 246 } 247 247 248 - mutex_unlock(&rv_interface_lock); 249 - 250 - return retval; 248 + return -EINVAL; 251 249 } 252 250 253 251 /* ··· 305 309 */ 306 310 int rv_register_reactor(struct rv_reactor *reactor) 307 311 { 308 - int retval = 0; 309 - 310 312 if (strlen(reactor->name) >= MAX_RV_REACTOR_NAME_SIZE) { 311 313 pr_info("Reactor %s has a name longer than %d\n", 312 314 reactor->name, MAX_RV_MONITOR_NAME_SIZE); 313 315 return -EINVAL; 314 316 } 315 317 316 - mutex_lock(&rv_interface_lock); 317 - retval = __rv_register_reactor(reactor); 318 - mutex_unlock(&rv_interface_lock); 319 - return retval; 318 + guard(mutex)(&rv_interface_lock); 319 + return __rv_register_reactor(reactor); 320 320 } 321 321 322 322 /** ··· 323 331 */ 324 332 int rv_unregister_reactor(struct rv_reactor *reactor) 325 333 { 326 - mutex_lock(&rv_interface_lock); 334 + guard(mutex)(&rv_interface_lock); 327 335 list_del(&reactor->list); 328 - mutex_unlock(&rv_interface_lock); 329 336 return 0; 330 337 } 331 338 ··· 338 347 * 339 348 * Returns 1 if on, 0 otherwise. 340 349 */ 341 - bool rv_reacting_on(void) 350 + static bool rv_reacting_on(void) 342 351 { 343 352 /* Ensures that concurrent monitors read consistent reacting_on */ 344 353 smp_rmb(); ··· 380 389 if (retval) 381 390 return retval; 382 391 383 - mutex_lock(&rv_interface_lock); 392 + guard(mutex)(&rv_interface_lock); 384 393 385 394 if (val) 386 395 turn_reacting_on(); ··· 392 401 * before returning to user-space. 393 402 */ 394 403 tracepoint_synchronize_unregister(); 395 - 396 - mutex_unlock(&rv_interface_lock); 397 404 398 405 return count; 399 406 } ··· 405 416 /** 406 417 * reactor_populate_monitor - creates per monitor reactors file 407 418 * @mon: The monitor. 419 + * @root: The directory of the monitor. 408 420 * 409 421 * Returns 0 if successful, error otherwise. 410 422 */ 411 - int reactor_populate_monitor(struct rv_monitor *mon) 423 + int reactor_populate_monitor(struct rv_monitor *mon, struct dentry *root) 412 424 { 413 425 struct dentry *tmp; 414 426 415 - tmp = rv_create_file("reactors", RV_MODE_WRITE, mon->root_d, mon, &monitor_reactors_ops); 427 + tmp = rv_create_file("reactors", RV_MODE_WRITE, root, mon, &monitor_reactors_ops); 416 428 if (!tmp) 417 429 return -ENOMEM; 418 430 ··· 428 438 /* 429 439 * Nop reactor register 430 440 */ 431 - __printf(1, 2) static void rv_nop_reaction(const char *msg, ...) 441 + __printf(1, 0) static void rv_nop_reaction(const char *msg, va_list args) 432 442 { 433 443 } 434 444 ··· 440 450 441 451 int init_rv_reactors(struct dentry *root_dir) 442 452 { 443 - struct dentry *available, *reacting; 444 453 int retval; 445 454 446 - available = rv_create_file("available_reactors", RV_MODE_READ, root_dir, NULL, 447 - &available_reactors_ops); 448 - if (!available) 449 - goto out_err; 455 + struct dentry *available __free(rv_remove) = 456 + rv_create_file("available_reactors", RV_MODE_READ, root_dir, 457 + NULL, &available_reactors_ops); 450 458 451 - reacting = rv_create_file("reacting_on", RV_MODE_WRITE, root_dir, NULL, &reacting_on_fops); 452 - if (!reacting) 453 - goto rm_available; 459 + struct dentry *reacting __free(rv_remove) = 460 + rv_create_file("reacting_on", RV_MODE_WRITE, root_dir, NULL, &reacting_on_fops); 461 + 462 + if (!reacting || !available) 463 + return -ENOMEM; 454 464 455 465 retval = __rv_register_reactor(&rv_nop); 456 466 if (retval) 457 - goto rm_reacting; 467 + return retval; 458 468 459 469 turn_reacting_on(); 460 470 471 + retain_and_null_ptr(available); 472 + retain_and_null_ptr(reacting); 461 473 return 0; 474 + } 462 475 463 - rm_reacting: 464 - rv_remove(reacting); 465 - rm_available: 466 - rv_remove(available); 467 - out_err: 468 - return -ENOMEM; 476 + void rv_react(struct rv_monitor *monitor, const char *msg, ...) 477 + { 478 + static DEFINE_WAIT_OVERRIDE_MAP(rv_react_map, LD_WAIT_FREE); 479 + va_list args; 480 + 481 + if (!rv_reacting_on() || !monitor->react) 482 + return; 483 + 484 + va_start(args, msg); 485 + 486 + lock_map_acquire_try(&rv_react_map); 487 + monitor->react(msg, args); 488 + lock_map_release(&rv_react_map); 489 + 490 + va_end(args); 469 491 }
+2 -1
kernel/trace/trace.c
··· 10969 10969 tracer_init_tracefs_work_func(NULL); 10970 10970 } 10971 10971 10972 - rv_init_interface(); 10972 + if (rv_init_interface()) 10973 + pr_err("RV: Error while creating the RV interface\n"); 10973 10974 10974 10975 return 0; 10975 10976 }
+24 -10
tools/testing/selftests/ftrace/ftracetest
··· 22 22 echo " -d|--debug Debug mode (trace all shell commands)" 23 23 echo " -l|--logdir <dir> Save logs on the <dir>" 24 24 echo " If <dir> is -, all logs output in console only" 25 + echo " --rv Run RV selftests instead of ftrace ones" 25 26 exit $1 26 27 } 27 28 ··· 134 133 LINK_PTR= 135 134 shift 2 136 135 ;; 136 + --rv) 137 + RV_TEST=1 138 + shift 1 139 + ;; 137 140 *.tc) 138 141 if [ -f "$1" ]; then 139 142 OPT_TEST_CASES="$OPT_TEST_CASES `abspath $1`" ··· 157 152 ;; 158 153 esac 159 154 done 160 - if [ ! -z "$OPT_TEST_CASES" ]; then 155 + if [ -n "$OPT_TEST_CASES" ]; then 161 156 TEST_CASES=$OPT_TEST_CASES 157 + fi 158 + if [ -n "$OPT_TEST_DIR" -a -f "$OPT_TEST_DIR"/test.d/functions ]; then 159 + TOP_DIR=$OPT_TEST_DIR 160 + TEST_DIR=$TOP_DIR/test.d 162 161 fi 163 162 } 164 163 ··· 199 190 TOP_DIR=`absdir $0` 200 191 TEST_DIR=$TOP_DIR/test.d 201 192 TEST_CASES=`find_testcases $TEST_DIR` 202 - LOG_TOP_DIR=$TOP_DIR/logs 203 - LOG_DATE=`date +%Y%m%d-%H%M%S` 204 - LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/ 205 - LINK_PTR=$LOG_TOP_DIR/latest 206 193 KEEP_LOG=0 207 194 KTAP=0 208 195 DEBUG=0 ··· 206 201 UNSUPPORTED_RESULT=0 207 202 UNRESOLVED_RESULT=0 208 203 STOP_FAILURE=0 204 + RV_TEST=0 209 205 # Parse command-line options 210 206 parse_opts $* 211 207 208 + LOG_TOP_DIR=$TOP_DIR/logs 209 + LOG_DATE=`date +%Y%m%d-%H%M%S` 210 + LOG_DIR=$LOG_TOP_DIR/$LOG_DATE/ 211 + LINK_PTR=$LOG_TOP_DIR/latest 212 + 212 213 [ $DEBUG -ne 0 ] && set -x 213 214 214 - # Verify parameters 215 - if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then 216 - errexit "No ftrace directory found" 215 + if [ $RV_TEST -ne 0 ]; then 216 + TRACING_DIR=$TRACING_DIR/rv 217 + if [ ! -d "$TRACING_DIR" ]; then 218 + err_ret=$err_skip 219 + errexit "rv is not configured in this kernel" 220 + fi 217 221 fi 218 222 219 223 # Preparing logs ··· 433 419 __run_test() { # testfile 434 420 # setup PID and PPID, $$ is not updated. 435 421 (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x; 436 - checkreq $1; initialize_ftrace; . $1) 422 + checkreq $1; initialize_system; . $1) 437 423 [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID 438 424 } 439 425 ··· 510 496 exit 1 511 497 fi 512 498 done 513 - (cd $TRACING_DIR; finish_ftrace) # for cleanup 499 + (cd $TRACING_DIR; finish_system) # for cleanup 514 500 515 501 prlog "" 516 502 prlog "# of passed: " `echo $PASSED_CASES | wc -w`
+1 -1
tools/testing/selftests/ftrace/test.d/00basic/mount_options.tc
··· 28 28 local mount_point="$1" 29 29 30 30 # Need to make sure the mount isn't busy so that we can umount it 31 - (cd $mount_point; finish_ftrace;) 31 + (cd $mount_point; finish_system;) 32 32 33 33 cleanup 34 34 }
+3 -3
tools/testing/selftests/ftrace/test.d/functions
··· 104 104 done 105 105 } 106 106 107 - initialize_ftrace() { # Reset ftrace to initial-state 107 + initialize_system() { # Reset ftrace to initial-state 108 108 # As the initial state, ftrace will be set to nop tracer, 109 109 # no events, no triggers, no filters, no function filters, 110 110 # no probes, and tracing on. ··· 134 134 enable_tracing 135 135 } 136 136 137 - finish_ftrace() { 138 - initialize_ftrace 137 + finish_system() { 138 + initialize_system 139 139 # And recover it to default. 140 140 [ -f options/pause-on-trace ] && echo 0 > options/pause-on-trace 141 141 }
+2
tools/testing/selftests/verification/.gitignore
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + logs
+8
tools/testing/selftests/verification/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + all: 3 + 4 + TEST_PROGS := verificationtest-ktap 5 + TEST_FILES := test.d settings 6 + EXTRA_CLEAN := $(OUTPUT)/logs/* 7 + 8 + include ../lib.mk
+1
tools/testing/selftests/verification/config
··· 1 + CONFIG_RV=y
+1
tools/testing/selftests/verification/settings
··· 1 + timeout=0
+39
tools/testing/selftests/verification/test.d/functions
··· 1 + check_requires() { # Check required files, monitors and reactors 2 + for i in "$@" ; do 3 + p=${i%:program} 4 + m=${i%:monitor} 5 + r=${i%:reactor} 6 + if [ $p != $i ]; then 7 + if ! which $p ; then 8 + echo "Required program $p is not found." 9 + exit_unresolved 10 + fi 11 + elif [ $m != $i ]; then 12 + if ! grep -wq $m available_monitors ; then 13 + echo "Required monitor $m is not configured." 14 + exit_unsupported 15 + fi 16 + elif [ $r != $i ]; then 17 + if ! grep -wq $r available_reactors ; then 18 + echo "Required reactor $r is not configured." 19 + exit_unsupported 20 + fi 21 + elif [ ! -e $i ]; then 22 + echo "Required feature interface $i doesn't exist." 23 + exit_unsupported 24 + fi 25 + done 26 + } 27 + 28 + initialize_system() { # Reset RV to initial-state 29 + echo > enabled_monitors 30 + for m in monitors/*; do 31 + echo nop > $m/reactors || true 32 + done 33 + echo 1 > monitoring_on 34 + echo 1 > reacting_on || true 35 + } 36 + 37 + finish_system() { 38 + initialize_system 39 + }
+75
tools/testing/selftests/verification/test.d/rv_monitor_enable_disable.tc
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0-or-later 3 + # description: Test monitor enable/disable 4 + 5 + test_simple_monitor() { 6 + local monitor="$1" 7 + local prefix="$2" # nested monitors 8 + 9 + echo 1 > "monitors/$prefix$monitor/enable" 10 + grep -q "$monitor$" enabled_monitors 11 + 12 + echo 0 > "monitors/$prefix$monitor/enable" 13 + ! grep -q "$monitor$" enabled_monitors 14 + 15 + echo "$monitor" >> enabled_monitors 16 + grep -q 1 "monitors/$prefix$monitor/enable" 17 + 18 + echo "!$monitor" >> enabled_monitors 19 + grep -q 0 "monitors/$prefix$monitor/enable" 20 + } 21 + 22 + test_container_monitor() { 23 + local monitor="$1" 24 + local nested 25 + 26 + echo 1 > "monitors/$monitor/enable" 27 + grep -q "^$monitor$" enabled_monitors 28 + 29 + for nested_dir in "monitors/$monitor"/*; do 30 + [ -d "$nested_dir" ] || continue 31 + nested=$(basename "$nested_dir") 32 + grep -q "^$monitor:$nested$" enabled_monitors 33 + done 34 + test -n "$nested" 35 + 36 + echo 0 > "monitors/$monitor/enable" 37 + ! grep -q "^$monitor$" enabled_monitors 38 + 39 + for nested_dir in "monitors/$monitor"/*; do 40 + [ -d "$nested_dir" ] || continue 41 + nested=$(basename "$nested_dir") 42 + ! grep -q "^$monitor:$nested$" enabled_monitors 43 + done 44 + 45 + echo "$monitor" >> enabled_monitors 46 + grep -q 1 "monitors/$monitor/enable" 47 + 48 + for nested_dir in "monitors/$monitor"/*; do 49 + [ -d "$nested_dir" ] || continue 50 + nested=$(basename "$nested_dir") 51 + grep -q "^$monitor:$nested$" enabled_monitors 52 + done 53 + 54 + echo "!$monitor" >> enabled_monitors 55 + grep -q 0 "monitors/$monitor/enable" 56 + 57 + for nested_dir in "monitors/$monitor"/*; do 58 + [ -d "$nested_dir" ] || continue 59 + nested=$(basename "$nested_dir") 60 + test_simple_monitor "$nested" "$monitor/" 61 + done 62 + } 63 + 64 + for monitor_dir in monitors/*; do 65 + monitor=$(basename "$monitor_dir") 66 + 67 + if find "$monitor_dir" -mindepth 1 -type d | grep -q .; then 68 + test_container_monitor "$monitor" 69 + else 70 + test_simple_monitor "$monitor" 71 + fi 72 + done 73 + 74 + ! echo non_existent_monitor > enabled_monitors 75 + ! grep -q "^non_existent_monitor$" enabled_monitors
+68
tools/testing/selftests/verification/test.d/rv_monitor_reactor.tc
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0-or-later 3 + # description: Test monitor reactor setting 4 + # requires: available_reactors 5 + 6 + test_monitor_reactor() { 7 + local monitor="$1" 8 + local prefix="$2" # nested monitors 9 + 10 + while read -r reactor; do 11 + [ "$reactor" = nop ] && continue 12 + 13 + echo "$reactor" > "monitors/$prefix$monitor/reactors" 14 + grep -q "\\[$reactor\\]" "monitors/$prefix$monitor/reactors" 15 + done < available_reactors 16 + 17 + echo nop > "monitors/$prefix$monitor/reactors" 18 + grep -q "\\[nop\\]" "monitors/$prefix$monitor/reactors" 19 + } 20 + 21 + test_container_monitor() { 22 + local monitor="$1" 23 + local nested 24 + 25 + while read -r reactor; do 26 + [ "$reactor" = nop ] && continue 27 + 28 + echo "$reactor" > "monitors/$monitor/reactors" 29 + grep -q "\\[$reactor\\]" "monitors/$monitor/reactors" 30 + 31 + for nested_dir in "monitors/$monitor"/*; do 32 + [ -d "$nested_dir" ] || continue 33 + nested=$(basename "$nested_dir") 34 + grep -q "\\[$reactor\\]" "monitors/$monitor/$nested/reactors" 35 + done 36 + done < available_reactors 37 + test -n "$nested" 38 + 39 + echo nop > "monitors/$monitor/reactors" 40 + grep -q "\\[nop\\]" "monitors/$monitor/reactors" 41 + 42 + for nested_dir in "monitors/$monitor"/*; do 43 + [ -d "$nested_dir" ] || continue 44 + nested=$(basename "$nested_dir") 45 + grep -q "\\[nop\\]" "monitors/$monitor/$nested/reactors" 46 + done 47 + 48 + for nested_dir in "monitors/$monitor"/*; do 49 + [ -d "$nested_dir" ] || continue 50 + nested=$(basename "$nested_dir") 51 + test_monitor_reactor "$nested" "$monitor/" 52 + done 53 + } 54 + 55 + for monitor_dir in monitors/*; do 56 + monitor=$(basename "$monitor_dir") 57 + 58 + if find "$monitor_dir" -mindepth 1 -type d | grep -q .; then 59 + test_container_monitor "$monitor" 60 + else 61 + test_monitor_reactor "$monitor" 62 + fi 63 + done 64 + 65 + monitor=$(ls /sys/kernel/tracing/rv/monitors -1 | head -n 1) 66 + test -f "monitors/$monitor/reactors" 67 + ! echo non_existent_reactor > "monitors/$monitor/reactors" 68 + ! grep -q "\\[non_existent_reactor\\]" "monitors/$monitor/reactors"
+18
tools/testing/selftests/verification/test.d/rv_monitors_available.tc
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0-or-later 3 + # description: Check available monitors 4 + 5 + for monitor_dir in monitors/*; do 6 + monitor=$(basename "$monitor_dir") 7 + 8 + grep -q "^$monitor$" available_monitors 9 + grep -q . "$monitor_dir"/desc 10 + 11 + for nested_dir in "$monitor_dir"/*; do 12 + [ -d "$nested_dir" ] || continue 13 + nested=$(basename "$nested_dir") 14 + 15 + grep -q "^$monitor:$nested$" available_monitors 16 + grep -q . "$nested_dir"/desc 17 + done 18 + done
+30
tools/testing/selftests/verification/test.d/rv_wwnr_printk.tc
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0-or-later 3 + # description: Test wwnr monitor with printk reactor 4 + # requires: available_reactors wwnr:monitor printk:reactor stress-ng:program 5 + 6 + load() { # returns true if there was a reaction 7 + local lines_before num 8 + num=$((($(nproc) + 1) / 2)) 9 + lines_before=$(dmesg | wc -l) 10 + stress-ng --cpu-sched "$num" --timer "$num" -t 5 -q 11 + dmesg | tail -n $((lines_before + 1)) | grep -q "rv: monitor wwnr does not allow event" 12 + } 13 + 14 + echo 1 > monitors/wwnr/enable 15 + echo printk > monitors/wwnr/reactors 16 + 17 + load 18 + 19 + echo 0 > monitoring_on 20 + ! load 21 + echo 1 > monitoring_on 22 + 23 + load 24 + 25 + echo 0 > reacting_on 26 + ! load 27 + echo 1 > reacting_on 28 + 29 + echo nop > monitors/wwnr/reactors 30 + echo 0 > monitors/wwnr/enable
+8
tools/testing/selftests/verification/verificationtest-ktap
··· 1 + #!/bin/sh -e 2 + # SPDX-License-Identifier: GPL-2.0-only 3 + # 4 + # ftracetest-ktap: Wrapper to integrate ftracetest with the kselftest runner 5 + # 6 + # Copyright (C) Arm Ltd., 2023 7 + 8 + ../ftrace/ftracetest -K -v --rv ../verification