1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/ftrace.h> 3 #include <linux/tracepoint.h> 4 #include <linux/kernel.h> 5 #include <linux/module.h> 6 #include <linux/init.h> 7 #include <linux/rv.h> 8 #include <rv/instrumentation.h> 9 10 #define MODULE_NAME "test_ha_kunit" 11 12 /* 13 * XXX: include required tracepoint headers, e.g., 14 * #include <trace/events/sched.h> 15 */ 16 #include <rv_trace.h> 17 18 /* 19 * This is the self-generated part of the monitor. Generally, there is no need 20 * to touch this section. 21 */ 22 #define RV_MON_TYPE RV_MON_PER_TASK 23 /* XXX: If the monitor has several instances, consider HA_TIMER_WHEEL */ 24 #define HA_TIMER_TYPE HA_TIMER_HRTIMER 25 #include "test_ha_kunit.h" 26 #include <rv/ha_monitor.h> 27 28 /* 29 * This is the instrumentation part of the monitor. 30 * 31 * This is the section where manual work is required. Here the kernel events 32 * are translated into model's event. 33 * 34 */ 35 #define BAR_NS(ha_mon) /* XXX: what is BAR_NS(ha_mon)? */ 36 37 #define FOO_NS /* XXX: what is FOO_NS? */ 38 39 static inline u64 bar_ns(struct ha_monitor *ha_mon) 40 { 41 return /* XXX: what is bar_ns(ha_mon)? */; 42 } 43 44 static u64 foo_ns = /* XXX: default value */; 45 module_param(foo_ns, ullong, 0644); 46 47 /* 48 * These functions define how to read and reset the environment variable. 49 * 50 * Common environment variables like ns-based and jiffy-based clocks have 51 * pre-define getters and resetters you can use. The parser can infer the type 52 * of the environment variable if you supply a measure unit in the constraint. 53 * If you define your own functions, make sure to add appropriate memory 54 * barriers if required. 55 * Some environment variables don't require a storage as they read a system 56 * state (e.g. preemption count). Those variables are never reset, so we don't 57 * define a reset function on monitors only relying on this type of variables. 58 */ 59 static u64 ha_get_env(struct ha_monitor *ha_mon, enum envs_test_ha_kunit env, u64 time_ns) 60 { 61 if (env == clk_test_ha_kunit) 62 return ha_get_clk_ns(ha_mon, env, time_ns); 63 else if (env == env1_test_ha_kunit) 64 return /* XXX: how do I read env1? */ 65 else if (env == env2_test_ha_kunit) 66 return /* XXX: how do I read env2? */ 67 return ENV_INVALID_VALUE; 68 } 69 70 static void ha_reset_env(struct ha_monitor *ha_mon, enum envs_test_ha_kunit env, u64 time_ns) 71 { 72 if (env == clk_test_ha_kunit) 73 ha_reset_clk_ns(ha_mon, env, time_ns); 74 } 75 76 /* 77 * These functions are used to validate state transitions. 78 * 79 * They are generated by parsing the model, there is usually no need to change them. 80 * If the monitor requires a timer, there are functions responsible to arm it when 81 * the next state has a constraint, cancel it in any other case and to check 82 * that it didn't expire before the callback run. Transitions to the same state 83 * without a reset never affect timers. 84 */ 85 static inline bool ha_verify_invariants(struct ha_monitor *ha_mon, 86 enum states curr_state, enum events event, 87 enum states next_state, u64 time_ns) 88 { 89 if (curr_state == S0_test_ha_kunit) 90 return ha_check_invariant_ns(ha_mon, clk_test_ha_kunit, time_ns, bar_ns(ha_mon)); 91 else if (curr_state == S2_test_ha_kunit) 92 return ha_check_invariant_ns(ha_mon, clk_test_ha_kunit, time_ns, BAR_NS(ha_mon)); 93 return true; 94 } 95 96 static inline bool ha_verify_guards(struct ha_monitor *ha_mon, 97 enum states curr_state, enum events event, 98 enum states next_state, u64 time_ns) 99 { 100 bool res = true; 101 102 if (curr_state == S0_test_ha_kunit && event == event0_test_ha_kunit) 103 ha_reset_env(ha_mon, clk_test_ha_kunit, time_ns); 104 else if (curr_state == S0_test_ha_kunit && event == event1_test_ha_kunit) 105 ha_reset_env(ha_mon, clk_test_ha_kunit, time_ns); 106 else if (curr_state == S1_test_ha_kunit && event == event0_test_ha_kunit) 107 ha_reset_env(ha_mon, clk_test_ha_kunit, time_ns); 108 else if (curr_state == S1_test_ha_kunit && event == event2_test_ha_kunit) { 109 res = ha_get_env(ha_mon, env1_test_ha_kunit, time_ns) == 0ull; 110 ha_reset_env(ha_mon, clk_test_ha_kunit, time_ns); 111 } else if (curr_state == S2_test_ha_kunit && event == event1_test_ha_kunit) 112 res = ha_monitor_env_invalid(ha_mon, clk_test_ha_kunit) || 113 ha_get_env(ha_mon, clk_test_ha_kunit, time_ns) < foo_ns; 114 else if (curr_state == S3_test_ha_kunit && event == event0_test_ha_kunit) 115 res = ha_monitor_env_invalid(ha_mon, clk_test_ha_kunit) || 116 (ha_get_env(ha_mon, clk_test_ha_kunit, time_ns) < FOO_NS && 117 ha_get_env(ha_mon, env2_test_ha_kunit, time_ns) == 0ull); 118 else if (curr_state == S3_test_ha_kunit && event == event1_test_ha_kunit) { 119 res = ha_monitor_env_invalid(ha_mon, clk_test_ha_kunit) || 120 (ha_get_env(ha_mon, clk_test_ha_kunit, time_ns) < 5000ull && 121 ha_get_env(ha_mon, env1_test_ha_kunit, time_ns) == 1ull); 122 ha_reset_env(ha_mon, clk_test_ha_kunit, time_ns); 123 } 124 return res; 125 } 126 127 static inline void ha_setup_invariants(struct ha_monitor *ha_mon, 128 enum states curr_state, enum events event, 129 enum states next_state, u64 time_ns) 130 { 131 if (next_state == curr_state && event != event0_test_ha_kunit) 132 return; 133 if (next_state == S0_test_ha_kunit) 134 ha_start_timer_ns(ha_mon, clk_test_ha_kunit, bar_ns(ha_mon), time_ns); 135 else if (next_state == S2_test_ha_kunit) 136 ha_start_timer_ns(ha_mon, clk_test_ha_kunit, BAR_NS(ha_mon), time_ns); 137 else if (curr_state == S0_test_ha_kunit) 138 ha_cancel_timer(ha_mon); 139 else if (curr_state == S2_test_ha_kunit) 140 ha_cancel_timer(ha_mon); 141 } 142 143 static bool ha_verify_constraint(struct ha_monitor *ha_mon, 144 enum states curr_state, enum events event, 145 enum states next_state, u64 time_ns) 146 { 147 if (!ha_verify_invariants(ha_mon, curr_state, event, next_state, time_ns)) 148 return false; 149 150 if (!ha_verify_guards(ha_mon, curr_state, event, next_state, time_ns)) 151 return false; 152 153 ha_setup_invariants(ha_mon, curr_state, event, next_state, time_ns); 154 155 return true; 156 } 157 158 static void handle_event0(void *data, /* XXX: fill header */) 159 { 160 /* XXX: validate that this event always leads to the initial state */ 161 struct task_struct *p = /* XXX: how do I get p? */; 162 da_handle_start_event(p, event0_test_ha_kunit); 163 } 164 165 static void handle_event1(void *data, /* XXX: fill header */) 166 { 167 struct task_struct *p = /* XXX: how do I get p? */; 168 da_handle_event(p, event1_test_ha_kunit); 169 } 170 171 static void handle_event2(void *data, /* XXX: fill header */) 172 { 173 struct task_struct *p = /* XXX: how do I get p? */; 174 da_handle_event(p, event2_test_ha_kunit); 175 } 176 177 static int enable_test_ha_kunit(void) 178 { 179 int retval; 180 181 retval = ha_monitor_init(); 182 if (retval) 183 return retval; 184 185 rv_attach_trace_probe("test_ha_kunit", /* XXX: tracepoint */, handle_event0); 186 rv_attach_trace_probe("test_ha_kunit", /* XXX: tracepoint */, handle_event1); 187 rv_attach_trace_probe("test_ha_kunit", /* XXX: tracepoint */, handle_event2); 188 189 return 0; 190 } 191 192 static void disable_test_ha_kunit(void) 193 { 194 rv_this.enabled = 0; 195 196 rv_detach_trace_probe("test_ha_kunit", /* XXX: tracepoint */, handle_event0); 197 rv_detach_trace_probe("test_ha_kunit", /* XXX: tracepoint */, handle_event1); 198 rv_detach_trace_probe("test_ha_kunit", /* XXX: tracepoint */, handle_event2); 199 200 ha_monitor_destroy(); 201 } 202 203 /* 204 * This is the monitor register section. 205 */ 206 static struct rv_monitor rv_this = { 207 .name = "test_ha_kunit", 208 .description = "auto-generated", 209 .enable = enable_test_ha_kunit, 210 .disable = disable_test_ha_kunit, 211 .reset = da_monitor_reset_all, 212 .enabled = 0, 213 }; 214 215 static int __init register_test_ha_kunit(void) 216 { 217 return rv_register_monitor(&rv_this, NULL); 218 } 219 220 static void __exit unregister_test_ha_kunit(void) 221 { 222 rv_unregister_monitor(&rv_this); 223 } 224 225 module_init(register_test_ha_kunit); 226 module_exit(unregister_test_ha_kunit); 227 228 MODULE_LICENSE("GPL"); 229 MODULE_AUTHOR("rvgen: auto-generated"); 230 MODULE_DESCRIPTION("test_ha_kunit: auto-generated"); 231 232 #if IS_ENABLED(CONFIG_RV_MONITORS_KUNIT_TEST) 233 #include <kunit/visibility.h> 234 #include "test_ha_kunit_kunit.h" 235 236 const struct rv_test_ha_kunit_ops rv_test_ha_kunit_ops = { 237 .mon = RV_MON_OPS_INIT(), 238 .handle_event0 = handle_event0, 239 .handle_event1 = handle_event1, 240 .handle_event2 = handle_event2, 241 }; 242 EXPORT_SYMBOL_IF_KUNIT(rv_test_ha_kunit_ops); 243 #endif 244