xref: /linux/tools/verification/rvgen/tests/golden/test_ha/test_ha.c (revision 55ee4b931a7ffedc886175d265dd6e6d08fd4151)
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"
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.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 env, u64 time_ns)
60 {
61 	if (env == clk_test_ha)
62 		return ha_get_clk_ns(ha_mon, env, time_ns);
63 	else if (env == env1_test_ha)
64 		return /* XXX: how do I read env1? */
65 	else if (env == env2_test_ha)
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 env, u64 time_ns)
71 {
72 	if (env == clk_test_ha)
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)
90 		return ha_check_invariant_ns(ha_mon, clk_test_ha, time_ns, bar_ns(ha_mon));
91 	else if (curr_state == S2_test_ha)
92 		return ha_check_invariant_ns(ha_mon, clk_test_ha, 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 && event == event0_test_ha)
103 		ha_reset_env(ha_mon, clk_test_ha, time_ns);
104 	else if (curr_state == S0_test_ha && event == event1_test_ha)
105 		ha_reset_env(ha_mon, clk_test_ha, time_ns);
106 	else if (curr_state == S1_test_ha && event == event0_test_ha)
107 		ha_reset_env(ha_mon, clk_test_ha, time_ns);
108 	else if (curr_state == S1_test_ha && event == event2_test_ha) {
109 		res = ha_get_env(ha_mon, env1_test_ha, time_ns) == 0ull;
110 		ha_reset_env(ha_mon, clk_test_ha, time_ns);
111 	} else if (curr_state == S2_test_ha && event == event1_test_ha)
112 		res = ha_monitor_env_invalid(ha_mon, clk_test_ha) ||
113 		      ha_get_env(ha_mon, clk_test_ha, time_ns) < foo_ns;
114 	else if (curr_state == S3_test_ha && event == event0_test_ha)
115 		res = ha_monitor_env_invalid(ha_mon, clk_test_ha) ||
116 		      (ha_get_env(ha_mon, clk_test_ha, time_ns) < FOO_NS &&
117 		      ha_get_env(ha_mon, env2_test_ha, time_ns) == 0ull);
118 	else if (curr_state == S3_test_ha && event == event1_test_ha) {
119 		res = ha_monitor_env_invalid(ha_mon, clk_test_ha) ||
120 		      (ha_get_env(ha_mon, clk_test_ha, time_ns) < 5000ull &&
121 		      ha_get_env(ha_mon, env1_test_ha, time_ns) == 1ull);
122 		ha_reset_env(ha_mon, clk_test_ha, 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)
132 		return;
133 	if (next_state == S0_test_ha)
134 		ha_start_timer_ns(ha_mon, clk_test_ha, bar_ns(ha_mon), time_ns);
135 	else if (next_state == S2_test_ha)
136 		ha_start_timer_ns(ha_mon, clk_test_ha, BAR_NS(ha_mon), time_ns);
137 	else if (curr_state == S0_test_ha)
138 		ha_cancel_timer(ha_mon);
139 	else if (curr_state == S2_test_ha)
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);
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);
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);
175 }
176 
177 static int enable_test_ha(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", /* XXX: tracepoint */, handle_event0);
186 	rv_attach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event1);
187 	rv_attach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event2);
188 
189 	return 0;
190 }
191 
192 static void disable_test_ha(void)
193 {
194 	rv_this.enabled = 0;
195 
196 	rv_detach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event0);
197 	rv_detach_trace_probe("test_ha", /* XXX: tracepoint */, handle_event1);
198 	rv_detach_trace_probe("test_ha", /* 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",
208 	.description = "auto-generated",
209 	.enable = enable_test_ha,
210 	.disable = disable_test_ha,
211 	.reset = da_monitor_reset_all,
212 	.enabled = 0,
213 };
214 
215 static int __init register_test_ha(void)
216 {
217 	return rv_register_monitor(&rv_this, NULL);
218 }
219 
220 static void __exit unregister_test_ha(void)
221 {
222 	rv_unregister_monitor(&rv_this);
223 }
224 
225 module_init(register_test_ha);
226 module_exit(unregister_test_ha);
227 
228 MODULE_LICENSE("GPL");
229 MODULE_AUTHOR("rvgen: auto-generated");
230 MODULE_DESCRIPTION("test_ha: auto-generated");
231