ltl_monitor.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /**
  3. * This file must be combined with the $(MODEL_NAME).h file generated by
  4. * tools/verification/rvgen.
  5. */
  6. #include <linux/args.h>
  7. #include <linux/rv.h>
  8. #include <linux/stringify.h>
  9. #include <linux/seq_buf.h>
  10. #include <rv/instrumentation.h>
  11. #include <trace/events/task.h>
  12. #include <trace/events/sched.h>
  13. #ifndef MONITOR_NAME
  14. #error "Please include $(MODEL_NAME).h generated by rvgen"
  15. #endif
  16. #define RV_MONITOR_NAME CONCATENATE(rv_, MONITOR_NAME)
  17. static struct rv_monitor RV_MONITOR_NAME;
  18. static int ltl_monitor_slot = RV_PER_TASK_MONITOR_INIT;
  19. static void ltl_atoms_fetch(struct task_struct *task, struct ltl_monitor *mon);
  20. static void ltl_atoms_init(struct task_struct *task, struct ltl_monitor *mon, bool task_creation);
  21. static struct ltl_monitor *ltl_get_monitor(struct task_struct *task)
  22. {
  23. return &task->rv[ltl_monitor_slot].ltl_mon;
  24. }
  25. static void ltl_task_init(struct task_struct *task, bool task_creation)
  26. {
  27. struct ltl_monitor *mon = ltl_get_monitor(task);
  28. memset(&mon->states, 0, sizeof(mon->states));
  29. for (int i = 0; i < LTL_NUM_ATOM; ++i)
  30. __set_bit(i, mon->unknown_atoms);
  31. ltl_atoms_init(task, mon, task_creation);
  32. ltl_atoms_fetch(task, mon);
  33. }
  34. static void handle_task_newtask(void *data, struct task_struct *task, u64 flags)
  35. {
  36. ltl_task_init(task, true);
  37. }
  38. static int ltl_monitor_init(void)
  39. {
  40. struct task_struct *g, *p;
  41. int ret, cpu;
  42. ret = rv_get_task_monitor_slot();
  43. if (ret < 0)
  44. return ret;
  45. ltl_monitor_slot = ret;
  46. rv_attach_trace_probe(name, task_newtask, handle_task_newtask);
  47. read_lock(&tasklist_lock);
  48. for_each_process_thread(g, p)
  49. ltl_task_init(p, false);
  50. for_each_present_cpu(cpu)
  51. ltl_task_init(idle_task(cpu), false);
  52. read_unlock(&tasklist_lock);
  53. return 0;
  54. }
  55. static void ltl_monitor_destroy(void)
  56. {
  57. rv_detach_trace_probe(name, task_newtask, handle_task_newtask);
  58. rv_put_task_monitor_slot(ltl_monitor_slot);
  59. ltl_monitor_slot = RV_PER_TASK_MONITOR_INIT;
  60. }
  61. static void ltl_illegal_state(struct task_struct *task, struct ltl_monitor *mon)
  62. {
  63. CONCATENATE(trace_error_, MONITOR_NAME)(task);
  64. rv_react(&RV_MONITOR_NAME, "rv: "__stringify(MONITOR_NAME)": %s[%d]: violation detected\n",
  65. task->comm, task->pid);
  66. }
  67. static void ltl_attempt_start(struct task_struct *task, struct ltl_monitor *mon)
  68. {
  69. if (rv_ltl_all_atoms_known(mon))
  70. ltl_start(task, mon);
  71. }
  72. static inline void ltl_atom_set(struct ltl_monitor *mon, enum ltl_atom atom, bool value)
  73. {
  74. __clear_bit(atom, mon->unknown_atoms);
  75. if (value)
  76. __set_bit(atom, mon->atoms);
  77. else
  78. __clear_bit(atom, mon->atoms);
  79. }
  80. static void
  81. ltl_trace_event(struct task_struct *task, struct ltl_monitor *mon, unsigned long *next_state)
  82. {
  83. const char *format_str = "%s";
  84. DECLARE_SEQ_BUF(atoms, 64);
  85. char states[32], next[32];
  86. int i;
  87. if (!CONCATENATE(CONCATENATE(trace_event_, MONITOR_NAME), _enabled)())
  88. return;
  89. snprintf(states, sizeof(states), "%*pbl", RV_MAX_BA_STATES, mon->states);
  90. snprintf(next, sizeof(next), "%*pbl", RV_MAX_BA_STATES, next_state);
  91. for (i = 0; i < LTL_NUM_ATOM; ++i) {
  92. if (test_bit(i, mon->atoms)) {
  93. seq_buf_printf(&atoms, format_str, ltl_atom_str(i));
  94. format_str = ",%s";
  95. }
  96. }
  97. CONCATENATE(trace_event_, MONITOR_NAME)(task, states, atoms.buffer, next);
  98. }
  99. static void ltl_validate(struct task_struct *task, struct ltl_monitor *mon)
  100. {
  101. DECLARE_BITMAP(next_states, RV_MAX_BA_STATES) = {0};
  102. if (!rv_ltl_valid_state(mon))
  103. return;
  104. for (unsigned int i = 0; i < RV_NUM_BA_STATES; ++i) {
  105. if (test_bit(i, mon->states))
  106. ltl_possible_next_states(mon, i, next_states);
  107. }
  108. ltl_trace_event(task, mon, next_states);
  109. memcpy(mon->states, next_states, sizeof(next_states));
  110. if (!rv_ltl_valid_state(mon))
  111. ltl_illegal_state(task, mon);
  112. }
  113. static void ltl_atom_update(struct task_struct *task, enum ltl_atom atom, bool value)
  114. {
  115. struct ltl_monitor *mon = ltl_get_monitor(task);
  116. ltl_atom_set(mon, atom, value);
  117. ltl_atoms_fetch(task, mon);
  118. if (!rv_ltl_valid_state(mon)) {
  119. ltl_attempt_start(task, mon);
  120. return;
  121. }
  122. ltl_validate(task, mon);
  123. }
  124. static void __maybe_unused ltl_atom_pulse(struct task_struct *task, enum ltl_atom atom, bool value)
  125. {
  126. struct ltl_monitor *mon = ltl_get_monitor(task);
  127. ltl_atom_update(task, atom, value);
  128. ltl_atom_set(mon, atom, !value);
  129. ltl_validate(task, mon);
  130. }