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