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