xref: /linux/include/rv/da_monitor.h (revision 30984ccf31b7f0678fad05a22e06bb9f6014c1ce)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
4  *
5  * Deterministic automata (DA) monitor functions, to be used together
6  * with automata models in C generated by the dot2k tool.
7  *
8  * The dot2k tool is available at tools/verification/dot2k/
9  *
10  * For further information, see:
11  *   Documentation/trace/rv/da_monitor_synthesis.rst
12  */
13 
14 #include <rv/automata.h>
15 #include <linux/rv.h>
16 #include <linux/stringify.h>
17 #include <linux/bug.h>
18 #include <linux/sched.h>
19 
20 static struct rv_monitor rv_this;
21 
22 /*
23  * Generic helpers for all types of deterministic automata monitors.
24  */
25 #define DECLARE_DA_MON_GENERIC_HELPERS(name, type)
26 
27 static void react(type curr_state, type event)
28 {
29 	rv_react(&rv_this,
30 		 "rv: monitor %s does not allow event %s on state %s\n",
31 		 __stringify(MONITOR_NAME),
32 		 model_get_event_name(event),
33 		 model_get_state_name(curr_state));
34 }
35 
36 /*
37  * da_monitor_reset - reset a monitor and setting it to init state
38  */
39 static inline void da_monitor_reset(struct da_monitor *da_mon)
40 {
41 	da_mon->monitoring = 0;
42 	da_mon->curr_state = model_get_initial_state();
43 }
44 
45 /*
46  * da_monitor_start - start monitoring
47  *
48  * The monitor will ignore all events until monitoring is set to true. This
49  * function needs to be called to tell the monitor to start monitoring.
50  */
51 static inline void da_monitor_start(struct da_monitor *da_mon)
52 {
53 	da_mon->curr_state = model_get_initial_state();
54 	da_mon->monitoring = 1;
55 }
56 
57 /*
58  * da_monitoring - returns true if the monitor is processing events
59  */
60 static inline bool da_monitoring(struct da_monitor *da_mon)
61 {
62 	return da_mon->monitoring;
63 }
64 
65 /*
66  * da_monitor_enabled - checks if the monitor is enabled
67  */
68 static inline bool da_monitor_enabled(void)
69 {
70 	/* global switch */
71 	if (unlikely(!rv_monitoring_on()))
72 		return 0;
73 
74 	/* monitor enabled */
75 	if (unlikely(!rv_this.enabled))
76 		return 0;
77 
78 	return 1;
79 }
80 
81 /*
82  * da_monitor_handling_event - checks if the monitor is ready to handle events
83  */
84 static inline bool da_monitor_handling_event(struct da_monitor *da_mon)
85 {
86 
87 	if (!da_monitor_enabled())
88 		return 0;
89 
90 	/* monitor is actually monitoring */
91 	if (unlikely(!da_monitoring(da_mon)))
92 		return 0;
93 
94 	return 1;
95 }
96 
97 /*
98  * Event handler for implicit monitors. Implicit monitor is the one which the
99  * handler does not need to specify which da_monitor to manipulate. Examples
100  * of implicit monitor are the per_cpu or the global ones.
101  *
102  * Retry in case there is a race between getting and setting the next state,
103  * warn and reset the monitor if it runs out of retries. The monitor should be
104  * able to handle various orders.
105  */
106 #if RV_MON_TYPE == RV_MON_GLOBAL || RV_MON_TYPE == RV_MON_PER_CPU
107 
108 static inline bool
109 da_event(struct da_monitor *da_mon, enum events event)
110 {
111 	enum states curr_state, next_state;
112 
113 	curr_state = READ_ONCE(da_mon->curr_state);
114 	for (int i = 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) {
115 		next_state = model_get_next_state(curr_state, event);
116 		if (next_state == INVALID_STATE) {
117 			react(curr_state, event);
118 			CONCATENATE(trace_error_, MONITOR_NAME)(model_get_state_name(curr_state),
119 					   model_get_event_name(event));
120 			return false;
121 		}
122 		if (likely(try_cmpxchg(&da_mon->curr_state, &curr_state, next_state))) {
123 			CONCATENATE(trace_event_, MONITOR_NAME)(model_get_state_name(curr_state),
124 					   model_get_event_name(event),
125 					   model_get_state_name(next_state),
126 					   model_is_final_state(next_state));
127 			return true;
128 		}
129 	}
130 
131 	trace_rv_retries_error(__stringify(MONITOR_NAME), model_get_event_name(event));
132 	pr_warn("rv: " __stringify(MAX_DA_RETRY_RACING_EVENTS)
133 		" retries reached for event %s, resetting monitor %s",
134 		model_get_event_name(event), __stringify(MONITOR_NAME));
135 	return false;
136 }
137 
138 /*
139  * Event handler for per_task monitors.
140  *
141  * Retry in case there is a race between getting and setting the next state,
142  * warn and reset the monitor if it runs out of retries. The monitor should be
143  * able to handle various orders.
144  */
145 #elif RV_MON_TYPE == RV_MON_PER_TASK
146 
147 static inline bool da_event(struct da_monitor *da_mon, struct task_struct *tsk,
148 				   enum events event)
149 {
150 	enum states curr_state, next_state;
151 
152 	curr_state = READ_ONCE(da_mon->curr_state);
153 	for (int i = 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) {
154 		next_state = model_get_next_state(curr_state, event);
155 		if (next_state == INVALID_STATE) {
156 			react(curr_state, event);
157 			CONCATENATE(trace_error_, MONITOR_NAME)(tsk->pid,
158 					   model_get_state_name(curr_state),
159 					   model_get_event_name(event));
160 			return false;
161 		}
162 		if (likely(try_cmpxchg(&da_mon->curr_state, &curr_state, next_state))) {
163 			CONCATENATE(trace_event_, MONITOR_NAME)(tsk->pid,
164 					   model_get_state_name(curr_state),
165 					   model_get_event_name(event),
166 					   model_get_state_name(next_state),
167 					   model_is_final_state(next_state));
168 			return true;
169 		}
170 	}
171 
172 	trace_rv_retries_error(__stringify(MONITOR_NAME), model_get_event_name(event));
173 	pr_warn("rv: " __stringify(MAX_DA_RETRY_RACING_EVENTS)
174 		" retries reached for event %s, resetting monitor %s",
175 		model_get_event_name(event), __stringify(MONITOR_NAME));
176 	return false;
177 }
178 #endif
179 
180 /*
181  * Functions to define, init and get a global monitor.
182  */
183 #if RV_MON_TYPE == RV_MON_GLOBAL
184 
185 /*
186  * global monitor (a single variable)
187  */
188 static struct da_monitor da_mon_this;
189 
190 /*
191  * da_get_monitor - return the global monitor address
192  */
193 static struct da_monitor *da_get_monitor(void)
194 {
195 	return &da_mon_this;
196 }
197 
198 /*
199  * da_monitor_reset_all - reset the single monitor
200  */
201 static void da_monitor_reset_all(void)
202 {
203 	da_monitor_reset(da_get_monitor());
204 }
205 
206 /*
207  * da_monitor_init - initialize a monitor
208  */
209 static inline int da_monitor_init(void)
210 {
211 	da_monitor_reset_all();
212 	return 0;
213 }
214 
215 /*
216  * da_monitor_destroy - destroy the monitor
217  */
218 static inline void da_monitor_destroy(void)
219 {
220 	return;
221 }
222 
223 /*
224  * Functions to define, init and get a per-cpu monitor.
225  */
226 #elif RV_MON_TYPE == RV_MON_PER_CPU
227 
228 /*
229  * per-cpu monitor variables
230  */
231 static DEFINE_PER_CPU(struct da_monitor, da_mon_this);
232 
233 /*
234  * da_get_monitor - return current CPU monitor address
235  */
236 static struct da_monitor *da_get_monitor(void)
237 {
238 	return this_cpu_ptr(&da_mon_this);
239 }
240 
241 /*
242  * da_monitor_reset_all - reset all CPUs' monitor
243  */
244 static void da_monitor_reset_all(void)
245 {
246 	struct da_monitor *da_mon;
247 	int cpu;
248 	for_each_cpu(cpu, cpu_online_mask) {
249 		da_mon = per_cpu_ptr(&da_mon_this, cpu);
250 		da_monitor_reset(da_mon);
251 	}
252 }
253 
254 /*
255  * da_monitor_init - initialize all CPUs' monitor
256  */
257 static inline int da_monitor_init(void)
258 {
259 	da_monitor_reset_all();
260 	return 0;
261 }
262 
263 /*
264  * da_monitor_destroy - destroy the monitor
265  */
266 static inline void da_monitor_destroy(void)
267 {
268 	return;
269 }
270 
271 /*
272  * Functions to define, init and get a per-task monitor.
273  */
274 #elif RV_MON_TYPE == RV_MON_PER_TASK
275 
276 /*
277  * The per-task monitor is stored a vector in the task struct. This variable
278  * stores the position on the vector reserved for this monitor.
279  */
280 static int task_mon_slot = RV_PER_TASK_MONITOR_INIT;
281 
282 /*
283  * da_get_monitor - return the monitor in the allocated slot for tsk
284  */
285 static inline struct da_monitor *da_get_monitor(struct task_struct *tsk)
286 {
287 	return &tsk->rv[task_mon_slot].da_mon;
288 }
289 
290 static void da_monitor_reset_all(void)
291 {
292 	struct task_struct *g, *p;
293 	int cpu;
294 
295 	read_lock(&tasklist_lock);
296 	for_each_process_thread(g, p)
297 		da_monitor_reset(da_get_monitor(p));
298 	for_each_present_cpu(cpu)
299 		da_monitor_reset(da_get_monitor(idle_task(cpu)));
300 	read_unlock(&tasklist_lock);
301 }
302 
303 /*
304  * da_monitor_init - initialize the per-task monitor
305  *
306  * Try to allocate a slot in the task's vector of monitors. If there
307  * is an available slot, use it and reset all task's monitor.
308  */
309 static int da_monitor_init(void)
310 {
311 	int slot;
312 
313 	slot = rv_get_task_monitor_slot();
314 	if (slot < 0 || slot >= RV_PER_TASK_MONITOR_INIT)
315 		return slot;
316 
317 	task_mon_slot = slot;
318 
319 	da_monitor_reset_all();
320 	return 0;
321 }
322 
323 /*
324  * da_monitor_destroy - return the allocated slot
325  */
326 static inline void da_monitor_destroy(void)
327 {
328 	if (task_mon_slot == RV_PER_TASK_MONITOR_INIT) {
329 		WARN_ONCE(1, "Disabling a disabled monitor: " __stringify(MONITOR_NAME));
330 		return;
331 	}
332 	rv_put_task_monitor_slot(task_mon_slot);
333 	task_mon_slot = RV_PER_TASK_MONITOR_INIT;
334 	return;
335 }
336 #endif
337 
338 /*
339  * Handle event for implicit monitor: da_get_monitor() will figure out
340  * the monitor.
341  */
342 #if RV_MON_TYPE == RV_MON_GLOBAL || RV_MON_TYPE == RV_MON_PER_CPU
343 
344 static inline void __da_handle_event(struct da_monitor *da_mon,
345 					    enum events event)
346 {
347 	bool retval;
348 
349 	retval = da_event(da_mon, event);
350 	if (!retval)
351 		da_monitor_reset(da_mon);
352 }
353 
354 /*
355  * da_handle_event - handle an event
356  */
357 static inline void da_handle_event(enum events event)
358 {
359 	struct da_monitor *da_mon = da_get_monitor();
360 	bool retval;
361 
362 	retval = da_monitor_handling_event(da_mon);
363 	if (!retval)
364 		return;
365 
366 	__da_handle_event(da_mon, event);
367 }
368 
369 /*
370  * da_handle_start_event - start monitoring or handle event
371  *
372  * This function is used to notify the monitor that the system is returning
373  * to the initial state, so the monitor can start monitoring in the next event.
374  * Thus:
375  *
376  * If the monitor already started, handle the event.
377  * If the monitor did not start yet, start the monitor but skip the event.
378  */
379 static inline bool da_handle_start_event(enum events event)
380 {
381 	struct da_monitor *da_mon;
382 
383 	if (!da_monitor_enabled())
384 		return 0;
385 
386 	da_mon = da_get_monitor();
387 
388 	if (unlikely(!da_monitoring(da_mon))) {
389 		da_monitor_start(da_mon);
390 		return 0;
391 	}
392 
393 	__da_handle_event(da_mon, event);
394 
395 	return 1;
396 }
397 
398 /*
399  * da_handle_start_run_event - start monitoring and handle event
400  *
401  * This function is used to notify the monitor that the system is in the
402  * initial state, so the monitor can start monitoring and handling event.
403  */
404 static inline bool da_handle_start_run_event(enum events event)
405 {
406 	struct da_monitor *da_mon;
407 
408 	if (!da_monitor_enabled())
409 		return 0;
410 
411 	da_mon = da_get_monitor();
412 
413 	if (unlikely(!da_monitoring(da_mon)))
414 		da_monitor_start(da_mon);
415 
416 	__da_handle_event(da_mon, event);
417 
418 	return 1;
419 }
420 
421 /*
422  * Handle event for per task.
423  */
424 #elif RV_MON_TYPE == RV_MON_PER_TASK
425 
426 static inline void
427 __da_handle_event(struct da_monitor *da_mon, struct task_struct *tsk,
428 			 enum events event)
429 {
430 	bool retval;
431 
432 	retval = da_event(da_mon, tsk, event);
433 	if (!retval)
434 		da_monitor_reset(da_mon);
435 }
436 
437 /*
438  * da_handle_event - handle an event
439  */
440 static inline void
441 da_handle_event(struct task_struct *tsk, enum events event)
442 {
443 	struct da_monitor *da_mon = da_get_monitor(tsk);
444 	bool retval;
445 
446 	retval = da_monitor_handling_event(da_mon);
447 	if (!retval)
448 		return;
449 
450 	__da_handle_event(da_mon, tsk, event);
451 }
452 
453 /*
454  * da_handle_start_event - start monitoring or handle event
455  *
456  * This function is used to notify the monitor that the system is returning
457  * to the initial state, so the monitor can start monitoring in the next event.
458  * Thus:
459  *
460  * If the monitor already started, handle the event.
461  * If the monitor did not start yet, start the monitor but skip the event.
462  */
463 static inline bool
464 da_handle_start_event(struct task_struct *tsk, enum events event)
465 {
466 	struct da_monitor *da_mon;
467 
468 	if (!da_monitor_enabled())
469 		return 0;
470 
471 	da_mon = da_get_monitor(tsk);
472 
473 	if (unlikely(!da_monitoring(da_mon))) {
474 		da_monitor_start(da_mon);
475 		return 0;
476 	}
477 
478 	__da_handle_event(da_mon, tsk, event);
479 
480 	return 1;
481 }
482 
483 /*
484  * da_handle_start_run_event - start monitoring and handle event
485  *
486  * This function is used to notify the monitor that the system is in the
487  * initial state, so the monitor can start monitoring and handling event.
488  */
489 static inline bool
490 da_handle_start_run_event(struct task_struct *tsk, enum events event)
491 {
492 	struct da_monitor *da_mon;
493 
494 	if (!da_monitor_enabled())
495 		return 0;
496 
497 	da_mon = da_get_monitor(tsk);
498 
499 	if (unlikely(!da_monitoring(da_mon)))
500 		da_monitor_start(da_mon);
501 
502 	__da_handle_event(da_mon, tsk, event);
503 
504 	return 1;
505 }
506 #endif
507 
508 /*
509  * Entry point for the global monitor.
510  */
511 #define DECLARE_DA_MON_GLOBAL(name, type)
512 
513 /*
514  * Entry point for the per-cpu monitor.
515  */
516 #define DECLARE_DA_MON_PER_CPU(name, type)
517 
518 /*
519  * Entry point for the per-task monitor.
520  */
521 #define DECLARE_DA_MON_PER_TASK(name, type)
522