xref: /linux/tools/verification/rvgen/tests/golden/test_ha/test_ha.c (revision 55ee4b931a7ffedc886175d265dd6e6d08fd4151)
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