xref: /openbmc/linux/include/rv/da_monitor.h (revision 360823a09426347ea8f232b0b0b5156d0aed0302)
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/bug.h>
17 #include <linux/sched.h>
18 
19 #ifdef CONFIG_RV_REACTORS
20 
21 #define DECLARE_RV_REACTING_HELPERS(name, type)							\
22 static char REACT_MSG_##name[1024];								\
23 												\
24 static inline char *format_react_msg_##name(type curr_state, type event)			\
25 {												\
26 	snprintf(REACT_MSG_##name, 1024,							\
27 		 "rv: monitor %s does not allow event %s on state %s\n",			\
28 		 #name,										\
29 		 model_get_event_name_##name(event),						\
30 		 model_get_state_name_##name(curr_state));					\
31 	return REACT_MSG_##name;								\
32 }												\
33 												\
34 static void cond_react_##name(char *msg)							\
35 {												\
36 	if (rv_##name.react)									\
37 		rv_##name.react(msg);								\
38 }												\
39 												\
40 static bool rv_reacting_on_##name(void)								\
41 {												\
42 	return rv_reacting_on();								\
43 }
44 
45 #else /* CONFIG_RV_REACTOR */
46 
47 #define DECLARE_RV_REACTING_HELPERS(name, type)							\
48 static inline char *format_react_msg_##name(type curr_state, type event)			\
49 {												\
50 	return NULL;										\
51 }												\
52 												\
53 static void cond_react_##name(char *msg)							\
54 {												\
55 	return;											\
56 }												\
57 												\
58 static bool rv_reacting_on_##name(void)								\
59 {												\
60 	return 0;										\
61 }
62 #endif
63 
64 /*
65  * Generic helpers for all types of deterministic automata monitors.
66  */
67 #define DECLARE_DA_MON_GENERIC_HELPERS(name, type)						\
68 												\
69 DECLARE_RV_REACTING_HELPERS(name, type)								\
70 												\
71 /*												\
72  * da_monitor_reset_##name - reset a monitor and setting it to init state			\
73  */												\
74 static inline void da_monitor_reset_##name(struct da_monitor *da_mon)				\
75 {												\
76 	da_mon->monitoring = 0;									\
77 	da_mon->curr_state = model_get_initial_state_##name();					\
78 }												\
79 												\
80 /*												\
81  * da_monitor_curr_state_##name - return the current state					\
82  */												\
83 static inline type da_monitor_curr_state_##name(struct da_monitor *da_mon)			\
84 {												\
85 	return da_mon->curr_state;								\
86 }												\
87 												\
88 /*												\
89  * da_monitor_set_state_##name - set the new current state					\
90  */												\
91 static inline void										\
92 da_monitor_set_state_##name(struct da_monitor *da_mon, enum states_##name state)		\
93 {												\
94 	da_mon->curr_state = state;								\
95 }												\
96 												\
97 /*												\
98  * da_monitor_start_##name - start monitoring							\
99  *												\
100  * The monitor will ignore all events until monitoring is set to true. This			\
101  * function needs to be called to tell the monitor to start monitoring.				\
102  */												\
103 static inline void da_monitor_start_##name(struct da_monitor *da_mon)				\
104 {												\
105 	da_mon->curr_state = model_get_initial_state_##name();					\
106 	da_mon->monitoring = 1;									\
107 }												\
108 												\
109 /*												\
110  * da_monitoring_##name - returns true if the monitor is processing events			\
111  */												\
112 static inline bool da_monitoring_##name(struct da_monitor *da_mon)				\
113 {												\
114 	return da_mon->monitoring;								\
115 }												\
116 												\
117 /*												\
118  * da_monitor_enabled_##name - checks if the monitor is enabled					\
119  */												\
120 static inline bool da_monitor_enabled_##name(void)						\
121 {												\
122 	/* global switch */									\
123 	if (unlikely(!rv_monitoring_on()))							\
124 		return 0;									\
125 												\
126 	/* monitor enabled */									\
127 	if (unlikely(!rv_##name.enabled))							\
128 		return 0;									\
129 												\
130 	return 1;										\
131 }												\
132 												\
133 /*												\
134  * da_monitor_handling_event_##name - checks if the monitor is ready to handle events		\
135  */												\
136 static inline bool da_monitor_handling_event_##name(struct da_monitor *da_mon)			\
137 {												\
138 												\
139 	if (!da_monitor_enabled_##name())							\
140 		return 0;									\
141 												\
142 	/* monitor is actually monitoring */							\
143 	if (unlikely(!da_monitoring_##name(da_mon)))						\
144 		return 0;									\
145 												\
146 	return 1;										\
147 }
148 
149 /*
150  * Event handler for implicit monitors. Implicit monitor is the one which the
151  * handler does not need to specify which da_monitor to manipulate. Examples
152  * of implicit monitor are the per_cpu or the global ones.
153  */
154 #define DECLARE_DA_MON_MODEL_HANDLER_IMPLICIT(name, type)					\
155 												\
156 static inline bool										\
157 da_event_##name(struct da_monitor *da_mon, enum events_##name event)				\
158 {												\
159 	type curr_state = da_monitor_curr_state_##name(da_mon);					\
160 	type next_state = model_get_next_state_##name(curr_state, event);			\
161 												\
162 	if (next_state != INVALID_STATE) {							\
163 		da_monitor_set_state_##name(da_mon, next_state);				\
164 												\
165 		trace_event_##name(model_get_state_name_##name(curr_state),			\
166 				   model_get_event_name_##name(event),				\
167 				   model_get_state_name_##name(next_state),			\
168 				   model_is_final_state_##name(next_state));			\
169 												\
170 		return true;									\
171 	}											\
172 												\
173 	if (rv_reacting_on_##name())								\
174 		cond_react_##name(format_react_msg_##name(curr_state, event));			\
175 												\
176 	trace_error_##name(model_get_state_name_##name(curr_state),				\
177 			   model_get_event_name_##name(event));					\
178 												\
179 	return false;										\
180 }												\
181 
182 /*
183  * Event handler for per_task monitors.
184  */
185 #define DECLARE_DA_MON_MODEL_HANDLER_PER_TASK(name, type)					\
186 												\
187 static inline bool da_event_##name(struct da_monitor *da_mon, struct task_struct *tsk,		\
188 				   enum events_##name event)					\
189 {												\
190 	type curr_state = da_monitor_curr_state_##name(da_mon);					\
191 	type next_state = model_get_next_state_##name(curr_state, event);			\
192 												\
193 	if (next_state != INVALID_STATE) {							\
194 		da_monitor_set_state_##name(da_mon, next_state);				\
195 												\
196 		trace_event_##name(tsk->pid,							\
197 				   model_get_state_name_##name(curr_state),			\
198 				   model_get_event_name_##name(event),				\
199 				   model_get_state_name_##name(next_state),			\
200 				   model_is_final_state_##name(next_state));			\
201 												\
202 		return true;									\
203 	}											\
204 												\
205 	if (rv_reacting_on_##name())								\
206 		cond_react_##name(format_react_msg_##name(curr_state, event));			\
207 												\
208 	trace_error_##name(tsk->pid,								\
209 			   model_get_state_name_##name(curr_state),				\
210 			   model_get_event_name_##name(event));					\
211 												\
212 	return false;										\
213 }
214 
215 /*
216  * Functions to define, init and get a global monitor.
217  */
218 #define DECLARE_DA_MON_INIT_GLOBAL(name, type)							\
219 												\
220 /*												\
221  * global monitor (a single variable)								\
222  */												\
223 static struct da_monitor da_mon_##name;								\
224 												\
225 /*												\
226  * da_get_monitor_##name - return the global monitor address					\
227  */												\
228 static struct da_monitor *da_get_monitor_##name(void)						\
229 {												\
230 	return &da_mon_##name;									\
231 }												\
232 												\
233 /*												\
234  * da_monitor_reset_all_##name - reset the single monitor					\
235  */												\
236 static void da_monitor_reset_all_##name(void)							\
237 {												\
238 	da_monitor_reset_##name(da_get_monitor_##name());					\
239 }												\
240 												\
241 /*												\
242  * da_monitor_init_##name - initialize a monitor						\
243  */												\
244 static inline int da_monitor_init_##name(void)							\
245 {												\
246 	da_monitor_reset_all_##name();								\
247 	return 0;										\
248 }												\
249 												\
250 /*												\
251  * da_monitor_destroy_##name - destroy the monitor						\
252  */												\
253 static inline void da_monitor_destroy_##name(void)						\
254 {												\
255 	return;											\
256 }
257 
258 /*
259  * Functions to define, init and get a per-cpu monitor.
260  */
261 #define DECLARE_DA_MON_INIT_PER_CPU(name, type)							\
262 												\
263 /*												\
264  * per-cpu monitor variables									\
265  */												\
266 static DEFINE_PER_CPU(struct da_monitor, da_mon_##name);					\
267 												\
268 /*												\
269  * da_get_monitor_##name - return current CPU monitor address					\
270  */												\
271 static struct da_monitor *da_get_monitor_##name(void)						\
272 {												\
273 	return this_cpu_ptr(&da_mon_##name);							\
274 }												\
275 												\
276 /*												\
277  * da_monitor_reset_all_##name - reset all CPUs' monitor					\
278  */												\
279 static void da_monitor_reset_all_##name(void)							\
280 {												\
281 	struct da_monitor *da_mon;								\
282 	int cpu;										\
283 	for_each_cpu(cpu, cpu_online_mask) {							\
284 		da_mon = per_cpu_ptr(&da_mon_##name, cpu);					\
285 		da_monitor_reset_##name(da_mon);						\
286 	}											\
287 }												\
288 												\
289 /*												\
290  * da_monitor_init_##name - initialize all CPUs' monitor					\
291  */												\
292 static inline int da_monitor_init_##name(void)							\
293 {												\
294 	da_monitor_reset_all_##name();								\
295 	return 0;										\
296 }												\
297 												\
298 /*												\
299  * da_monitor_destroy_##name - destroy the monitor						\
300  */												\
301 static inline void da_monitor_destroy_##name(void)						\
302 {												\
303 	return;											\
304 }
305 
306 /*
307  * Functions to define, init and get a per-task monitor.
308  */
309 #define DECLARE_DA_MON_INIT_PER_TASK(name, type)						\
310 												\
311 /*												\
312  * The per-task monitor is stored a vector in the task struct. This variable			\
313  * stores the position on the vector reserved for this monitor.					\
314  */												\
315 static int task_mon_slot_##name = RV_PER_TASK_MONITOR_INIT;					\
316 												\
317 /*												\
318  * da_get_monitor_##name - return the monitor in the allocated slot for tsk 			\
319  */												\
320 static inline struct da_monitor *da_get_monitor_##name(struct task_struct *tsk)			\
321 {												\
322 	return &tsk->rv[task_mon_slot_##name].da_mon;						\
323 }												\
324 												\
325 static void da_monitor_reset_all_##name(void)							\
326 {												\
327 	struct task_struct *g, *p;								\
328 	int cpu;										\
329 												\
330 	read_lock(&tasklist_lock);								\
331 	for_each_process_thread(g, p)								\
332 		da_monitor_reset_##name(da_get_monitor_##name(p));				\
333 	for_each_present_cpu(cpu)								\
334 		da_monitor_reset_##name(da_get_monitor_##name(idle_task(cpu)));			\
335 	read_unlock(&tasklist_lock);								\
336 }												\
337 												\
338 /*												\
339  * da_monitor_init_##name - initialize the per-task monitor					\
340  *												\
341  * Try to allocate a slot in the task's vector of monitors. If there				\
342  * is an available slot, use it and reset all task's monitor.					\
343  */												\
344 static int da_monitor_init_##name(void)								\
345 {												\
346 	int slot;										\
347 												\
348 	slot = rv_get_task_monitor_slot();							\
349 	if (slot < 0 || slot >= RV_PER_TASK_MONITOR_INIT)					\
350 		return slot;									\
351 												\
352 	task_mon_slot_##name = slot;								\
353 												\
354 	da_monitor_reset_all_##name();								\
355 	return 0;										\
356 }												\
357 												\
358 /*												\
359  * da_monitor_destroy_##name - return the allocated slot					\
360  */												\
361 static inline void da_monitor_destroy_##name(void)						\
362 {												\
363 	if (task_mon_slot_##name == RV_PER_TASK_MONITOR_INIT) {					\
364 		WARN_ONCE(1, "Disabling a disabled monitor: " #name);				\
365 		return;										\
366 	}											\
367 	rv_put_task_monitor_slot(task_mon_slot_##name);						\
368 	task_mon_slot_##name = RV_PER_TASK_MONITOR_INIT;					\
369 	return;											\
370 }
371 
372 /*
373  * Handle event for implicit monitor: da_get_monitor_##name() will figure out
374  * the monitor.
375  */
376 #define DECLARE_DA_MON_MONITOR_HANDLER_IMPLICIT(name, type)					\
377 												\
378 static inline void __da_handle_event_##name(struct da_monitor *da_mon,				\
379 					    enum events_##name event)				\
380 {												\
381 	bool retval;										\
382 												\
383 	retval = da_event_##name(da_mon, event);						\
384 	if (!retval)										\
385 		da_monitor_reset_##name(da_mon);						\
386 }												\
387 												\
388 /*												\
389  * da_handle_event_##name - handle an event							\
390  */												\
391 static inline void da_handle_event_##name(enum events_##name event)				\
392 {												\
393 	struct da_monitor *da_mon = da_get_monitor_##name();					\
394 	bool retval;										\
395 												\
396 	retval = da_monitor_handling_event_##name(da_mon);					\
397 	if (!retval)										\
398 		return;										\
399 												\
400 	__da_handle_event_##name(da_mon, event);						\
401 }												\
402 												\
403 /*												\
404  * da_handle_start_event_##name - start monitoring or handle event				\
405  *												\
406  * This function is used to notify the monitor that the system is returning			\
407  * to the initial state, so the monitor can start monitoring in the next event.			\
408  * Thus:											\
409  *												\
410  * If the monitor already started, handle the event.						\
411  * If the monitor did not start yet, start the monitor but skip the event.			\
412  */												\
413 static inline bool da_handle_start_event_##name(enum events_##name event)			\
414 {												\
415 	struct da_monitor *da_mon;								\
416 												\
417 	if (!da_monitor_enabled_##name())							\
418 		return 0;									\
419 												\
420 	da_mon = da_get_monitor_##name();							\
421 												\
422 	if (unlikely(!da_monitoring_##name(da_mon))) {						\
423 		da_monitor_start_##name(da_mon);						\
424 		return 0;									\
425 	}											\
426 												\
427 	__da_handle_event_##name(da_mon, event);						\
428 												\
429 	return 1;										\
430 }												\
431 												\
432 /*												\
433  * da_handle_start_run_event_##name - start monitoring and handle event				\
434  *												\
435  * This function is used to notify the monitor that the system is in the			\
436  * initial state, so the monitor can start monitoring and handling event.			\
437  */												\
438 static inline bool da_handle_start_run_event_##name(enum events_##name event)			\
439 {												\
440 	struct da_monitor *da_mon;								\
441 												\
442 	if (!da_monitor_enabled_##name())							\
443 		return 0;									\
444 												\
445 	da_mon = da_get_monitor_##name();							\
446 												\
447 	if (unlikely(!da_monitoring_##name(da_mon)))						\
448 		da_monitor_start_##name(da_mon);						\
449 												\
450 	__da_handle_event_##name(da_mon, event);						\
451 												\
452 	return 1;										\
453 }
454 
455 /*
456  * Handle event for per task.
457  */
458 #define DECLARE_DA_MON_MONITOR_HANDLER_PER_TASK(name, type)					\
459 												\
460 static inline void										\
461 __da_handle_event_##name(struct da_monitor *da_mon, struct task_struct *tsk,			\
462 			 enum events_##name event)						\
463 {												\
464 	bool retval;										\
465 												\
466 	retval = da_event_##name(da_mon, tsk, event);						\
467 	if (!retval)										\
468 		da_monitor_reset_##name(da_mon);						\
469 }												\
470 												\
471 /*												\
472  * da_handle_event_##name - handle an event							\
473  */												\
474 static inline void										\
475 da_handle_event_##name(struct task_struct *tsk, enum events_##name event)			\
476 {												\
477 	struct da_monitor *da_mon = da_get_monitor_##name(tsk);					\
478 	bool retval;										\
479 												\
480 	retval = da_monitor_handling_event_##name(da_mon);					\
481 	if (!retval)										\
482 		return;										\
483 												\
484 	__da_handle_event_##name(da_mon, tsk, event);						\
485 }												\
486 												\
487 /*												\
488  * da_handle_start_event_##name - start monitoring or handle event				\
489  *												\
490  * This function is used to notify the monitor that the system is returning			\
491  * to the initial state, so the monitor can start monitoring in the next event.			\
492  * Thus:											\
493  *												\
494  * If the monitor already started, handle the event.						\
495  * If the monitor did not start yet, start the monitor but skip the event.			\
496  */												\
497 static inline bool										\
498 da_handle_start_event_##name(struct task_struct *tsk, enum events_##name event)			\
499 {												\
500 	struct da_monitor *da_mon;								\
501 												\
502 	if (!da_monitor_enabled_##name())							\
503 		return 0;									\
504 												\
505 	da_mon = da_get_monitor_##name(tsk);							\
506 												\
507 	if (unlikely(!da_monitoring_##name(da_mon))) {						\
508 		da_monitor_start_##name(da_mon);						\
509 		return 0;									\
510 	}											\
511 												\
512 	__da_handle_event_##name(da_mon, tsk, event);						\
513 												\
514 	return 1;										\
515 }
516 
517 /*
518  * Entry point for the global monitor.
519  */
520 #define DECLARE_DA_MON_GLOBAL(name, type)							\
521 												\
522 DECLARE_AUTOMATA_HELPERS(name, type)								\
523 DECLARE_DA_MON_GENERIC_HELPERS(name, type)							\
524 DECLARE_DA_MON_MODEL_HANDLER_IMPLICIT(name, type)						\
525 DECLARE_DA_MON_INIT_GLOBAL(name, type)								\
526 DECLARE_DA_MON_MONITOR_HANDLER_IMPLICIT(name, type)
527 
528 /*
529  * Entry point for the per-cpu monitor.
530  */
531 #define DECLARE_DA_MON_PER_CPU(name, type)							\
532 												\
533 DECLARE_AUTOMATA_HELPERS(name, type)								\
534 DECLARE_DA_MON_GENERIC_HELPERS(name, type)							\
535 DECLARE_DA_MON_MODEL_HANDLER_IMPLICIT(name, type)						\
536 DECLARE_DA_MON_INIT_PER_CPU(name, type)								\
537 DECLARE_DA_MON_MONITOR_HANDLER_IMPLICIT(name, type)
538 
539 /*
540  * Entry point for the per-task monitor.
541  */
542 #define DECLARE_DA_MON_PER_TASK(name, type)							\
543 												\
544 DECLARE_AUTOMATA_HELPERS(name, type)								\
545 DECLARE_DA_MON_GENERIC_HELPERS(name, type)							\
546 DECLARE_DA_MON_MODEL_HANDLER_PER_TASK(name, type)						\
547 DECLARE_DA_MON_INIT_PER_TASK(name, type)							\
548 DECLARE_DA_MON_MONITOR_HANDLER_PER_TASK(name, type)
549