16d60f896SDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0
26d60f896SDaniel Bristot de Oliveira /*
36d60f896SDaniel Bristot de Oliveira  * in kernel monitor support: allows rv to control in-kernel monitors.
46d60f896SDaniel Bristot de Oliveira  *
56d60f896SDaniel Bristot de Oliveira  * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
66d60f896SDaniel Bristot de Oliveira  */
76d60f896SDaniel Bristot de Oliveira #include <getopt.h>
86d60f896SDaniel Bristot de Oliveira #include <stdlib.h>
96d60f896SDaniel Bristot de Oliveira #include <string.h>
106d60f896SDaniel Bristot de Oliveira #include <errno.h>
116d60f896SDaniel Bristot de Oliveira #include <unistd.h>
126d60f896SDaniel Bristot de Oliveira 
136d60f896SDaniel Bristot de Oliveira #include <trace.h>
146d60f896SDaniel Bristot de Oliveira #include <utils.h>
156d60f896SDaniel Bristot de Oliveira #include <rv.h>
166d60f896SDaniel Bristot de Oliveira 
176d60f896SDaniel Bristot de Oliveira static int config_has_id;
186d60f896SDaniel Bristot de Oliveira static int config_my_pid;
196d60f896SDaniel Bristot de Oliveira static int config_trace;
206d60f896SDaniel Bristot de Oliveira 
216d60f896SDaniel Bristot de Oliveira static char *config_initial_reactor;
226d60f896SDaniel Bristot de Oliveira static char *config_reactor;
236d60f896SDaniel Bristot de Oliveira 
246d60f896SDaniel Bristot de Oliveira /*
256d60f896SDaniel Bristot de Oliveira  * __ikm_read_enable - reads monitor's enable status
266d60f896SDaniel Bristot de Oliveira  *
276d60f896SDaniel Bristot de Oliveira  * __does not log errors.
286d60f896SDaniel Bristot de Oliveira  *
296d60f896SDaniel Bristot de Oliveira  * Returns the current status, or -1 if the monitor does not exist,
306d60f896SDaniel Bristot de Oliveira  * __hence not logging errors.
316d60f896SDaniel Bristot de Oliveira  */
__ikm_read_enable(char * monitor_name)326d60f896SDaniel Bristot de Oliveira static int __ikm_read_enable(char *monitor_name)
336d60f896SDaniel Bristot de Oliveira {
346d60f896SDaniel Bristot de Oliveira 	char path[MAX_PATH];
356d60f896SDaniel Bristot de Oliveira 	long long enabled;
366d60f896SDaniel Bristot de Oliveira 	int retval;
376d60f896SDaniel Bristot de Oliveira 
386d60f896SDaniel Bristot de Oliveira 	snprintf(path, MAX_PATH, "rv/monitors/%s/enable", monitor_name);
396d60f896SDaniel Bristot de Oliveira 
406d60f896SDaniel Bristot de Oliveira 	retval = tracefs_instance_file_read_number(NULL, path, &enabled);
416d60f896SDaniel Bristot de Oliveira 	if (retval < 0)
426d60f896SDaniel Bristot de Oliveira 		return -1;
436d60f896SDaniel Bristot de Oliveira 
446d60f896SDaniel Bristot de Oliveira 	return enabled;
456d60f896SDaniel Bristot de Oliveira }
466d60f896SDaniel Bristot de Oliveira 
476d60f896SDaniel Bristot de Oliveira /*
486d60f896SDaniel Bristot de Oliveira  * ikm_read_enable - reads monitor's enable status
496d60f896SDaniel Bristot de Oliveira  *
506d60f896SDaniel Bristot de Oliveira  * Returns the current status, or -1 on error.
516d60f896SDaniel Bristot de Oliveira  */
ikm_read_enable(char * monitor_name)526d60f896SDaniel Bristot de Oliveira static int ikm_read_enable(char *monitor_name)
536d60f896SDaniel Bristot de Oliveira {
546d60f896SDaniel Bristot de Oliveira 	int enabled;
556d60f896SDaniel Bristot de Oliveira 
566d60f896SDaniel Bristot de Oliveira 	enabled = __ikm_read_enable(monitor_name);
576d60f896SDaniel Bristot de Oliveira 	if (enabled < 0) {
586d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: fail read enabled: %d\n", enabled);
596d60f896SDaniel Bristot de Oliveira 		return -1;
606d60f896SDaniel Bristot de Oliveira 	}
616d60f896SDaniel Bristot de Oliveira 
626d60f896SDaniel Bristot de Oliveira 	debug_msg("ikm: read enabled: %d\n", enabled);
636d60f896SDaniel Bristot de Oliveira 
646d60f896SDaniel Bristot de Oliveira 	return enabled;
656d60f896SDaniel Bristot de Oliveira }
666d60f896SDaniel Bristot de Oliveira 
676d60f896SDaniel Bristot de Oliveira /*
686d60f896SDaniel Bristot de Oliveira  * ikm_write_enable - write to the monitor's enable file
696d60f896SDaniel Bristot de Oliveira  *
706d60f896SDaniel Bristot de Oliveira  * Return the number of bytes written, -1 on error.
716d60f896SDaniel Bristot de Oliveira  */
ikm_write_enable(char * monitor_name,char * enable_disable)726d60f896SDaniel Bristot de Oliveira static int ikm_write_enable(char *monitor_name, char *enable_disable)
736d60f896SDaniel Bristot de Oliveira {
746d60f896SDaniel Bristot de Oliveira 	char path[MAX_PATH];
756d60f896SDaniel Bristot de Oliveira 	int retval;
766d60f896SDaniel Bristot de Oliveira 
776d60f896SDaniel Bristot de Oliveira 	debug_msg("ikm: writing enabled: %s\n", enable_disable);
786d60f896SDaniel Bristot de Oliveira 
796d60f896SDaniel Bristot de Oliveira 	snprintf(path, MAX_PATH, "rv/monitors/%s/enable", monitor_name);
806d60f896SDaniel Bristot de Oliveira 	retval = tracefs_instance_file_write(NULL, path, enable_disable);
816d60f896SDaniel Bristot de Oliveira 	if (retval < strlen(enable_disable)) {
826d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: writing enabled: %s\n", enable_disable);
836d60f896SDaniel Bristot de Oliveira 		return -1;
846d60f896SDaniel Bristot de Oliveira 	}
856d60f896SDaniel Bristot de Oliveira 
866d60f896SDaniel Bristot de Oliveira 	return retval;
876d60f896SDaniel Bristot de Oliveira }
886d60f896SDaniel Bristot de Oliveira 
896d60f896SDaniel Bristot de Oliveira /*
906d60f896SDaniel Bristot de Oliveira  * ikm_enable - enable a monitor
916d60f896SDaniel Bristot de Oliveira  *
926d60f896SDaniel Bristot de Oliveira  * Returns -1 on failure. Success otherwise.
936d60f896SDaniel Bristot de Oliveira  */
ikm_enable(char * monitor_name)946d60f896SDaniel Bristot de Oliveira static int ikm_enable(char *monitor_name)
956d60f896SDaniel Bristot de Oliveira {
966d60f896SDaniel Bristot de Oliveira 	return ikm_write_enable(monitor_name, "1");
976d60f896SDaniel Bristot de Oliveira }
986d60f896SDaniel Bristot de Oliveira 
996d60f896SDaniel Bristot de Oliveira /*
1006d60f896SDaniel Bristot de Oliveira  * ikm_disable - disable a monitor
1016d60f896SDaniel Bristot de Oliveira  *
1026d60f896SDaniel Bristot de Oliveira  * Returns -1 on failure. Success otherwise.
1036d60f896SDaniel Bristot de Oliveira  */
ikm_disable(char * monitor_name)1046d60f896SDaniel Bristot de Oliveira static int ikm_disable(char *monitor_name)
1056d60f896SDaniel Bristot de Oliveira {
1066d60f896SDaniel Bristot de Oliveira 	return ikm_write_enable(monitor_name, "0");
1076d60f896SDaniel Bristot de Oliveira }
1086d60f896SDaniel Bristot de Oliveira 
1096d60f896SDaniel Bristot de Oliveira /*
1106d60f896SDaniel Bristot de Oliveira  * ikm_read_desc - read monitors' description
1116d60f896SDaniel Bristot de Oliveira  *
1126d60f896SDaniel Bristot de Oliveira  * Return a dynamically allocated string with the monitor's
1136d60f896SDaniel Bristot de Oliveira  * description, NULL otherwise.
1146d60f896SDaniel Bristot de Oliveira  */
ikm_read_desc(char * monitor_name)1156d60f896SDaniel Bristot de Oliveira static char *ikm_read_desc(char *monitor_name)
1166d60f896SDaniel Bristot de Oliveira {
1176d60f896SDaniel Bristot de Oliveira 	char path[MAX_PATH];
1186d60f896SDaniel Bristot de Oliveira 	char *desc;
1196d60f896SDaniel Bristot de Oliveira 
1206d60f896SDaniel Bristot de Oliveira 	snprintf(path, MAX_PATH, "rv/monitors/%s/desc", monitor_name);
1216d60f896SDaniel Bristot de Oliveira 	desc = tracefs_instance_file_read(NULL, path, NULL);
1226d60f896SDaniel Bristot de Oliveira 	if (!desc) {
1236d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: error reading monitor %s desc\n", monitor_name);
1246d60f896SDaniel Bristot de Oliveira 		return NULL;
1256d60f896SDaniel Bristot de Oliveira 	}
1266d60f896SDaniel Bristot de Oliveira 
1276d60f896SDaniel Bristot de Oliveira 	*strstr(desc, "\n") = '\0';
1286d60f896SDaniel Bristot de Oliveira 
1296d60f896SDaniel Bristot de Oliveira 	return desc;
1306d60f896SDaniel Bristot de Oliveira }
1316d60f896SDaniel Bristot de Oliveira 
1326d60f896SDaniel Bristot de Oliveira /*
1336d60f896SDaniel Bristot de Oliveira  * ikm_fill_monitor_definition - fill monitor's definition
1346d60f896SDaniel Bristot de Oliveira  *
1356d60f896SDaniel Bristot de Oliveira  * Returns -1 on error, 0 otherwise.
1366d60f896SDaniel Bristot de Oliveira  */
ikm_fill_monitor_definition(char * name,struct monitor * ikm)1376d60f896SDaniel Bristot de Oliveira static int ikm_fill_monitor_definition(char *name, struct monitor *ikm)
1386d60f896SDaniel Bristot de Oliveira {
1396d60f896SDaniel Bristot de Oliveira 	int enabled;
1406d60f896SDaniel Bristot de Oliveira 	char *desc;
1416d60f896SDaniel Bristot de Oliveira 
1426d60f896SDaniel Bristot de Oliveira 	enabled = ikm_read_enable(name);
1436d60f896SDaniel Bristot de Oliveira 	if (enabled < 0) {
1446d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: monitor %s fail to read enable file, bug?\n", name);
1456d60f896SDaniel Bristot de Oliveira 		return -1;
1466d60f896SDaniel Bristot de Oliveira 	}
1476d60f896SDaniel Bristot de Oliveira 
1486d60f896SDaniel Bristot de Oliveira 	desc = ikm_read_desc(name);
1496d60f896SDaniel Bristot de Oliveira 	if (!desc) {
1506d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: monitor %s does not have desc file, bug?\n", name);
1516d60f896SDaniel Bristot de Oliveira 		return -1;
1526d60f896SDaniel Bristot de Oliveira 	}
1536d60f896SDaniel Bristot de Oliveira 
1546d60f896SDaniel Bristot de Oliveira 	strncpy(ikm->name, name, MAX_DA_NAME_LEN);
1556d60f896SDaniel Bristot de Oliveira 	ikm->enabled = enabled;
1566d60f896SDaniel Bristot de Oliveira 	strncpy(ikm->desc, desc, MAX_DESCRIPTION);
1576d60f896SDaniel Bristot de Oliveira 
1586d60f896SDaniel Bristot de Oliveira 	free(desc);
1596d60f896SDaniel Bristot de Oliveira 
1606d60f896SDaniel Bristot de Oliveira 	return 0;
1616d60f896SDaniel Bristot de Oliveira }
1626d60f896SDaniel Bristot de Oliveira 
1636d60f896SDaniel Bristot de Oliveira /*
1646d60f896SDaniel Bristot de Oliveira  * ikm_write_reactor - switch the reactor to *reactor
1656d60f896SDaniel Bristot de Oliveira  *
1666d60f896SDaniel Bristot de Oliveira  * Return the number or characters written, -1 on error.
1676d60f896SDaniel Bristot de Oliveira  */
ikm_write_reactor(char * monitor_name,char * reactor)1686d60f896SDaniel Bristot de Oliveira static int ikm_write_reactor(char *monitor_name, char *reactor)
1696d60f896SDaniel Bristot de Oliveira {
1706d60f896SDaniel Bristot de Oliveira 	char path[MAX_PATH];
1716d60f896SDaniel Bristot de Oliveira 	int retval;
1726d60f896SDaniel Bristot de Oliveira 
1736d60f896SDaniel Bristot de Oliveira 	snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name);
1746d60f896SDaniel Bristot de Oliveira 	retval = tracefs_instance_file_write(NULL, path, reactor);
1756d60f896SDaniel Bristot de Oliveira 	debug_msg("ikm: write \"%s\" reactors: %d\n", reactor, retval);
1766d60f896SDaniel Bristot de Oliveira 
1776d60f896SDaniel Bristot de Oliveira 	return retval;
1786d60f896SDaniel Bristot de Oliveira }
1796d60f896SDaniel Bristot de Oliveira 
1806d60f896SDaniel Bristot de Oliveira /*
1816d60f896SDaniel Bristot de Oliveira  * ikm_read_reactor - read the reactors file
1826d60f896SDaniel Bristot de Oliveira  *
1836d60f896SDaniel Bristot de Oliveira  * Returns a dynamically allocated string with monitor's
1846d60f896SDaniel Bristot de Oliveira  * available reactors, or NULL on error.
1856d60f896SDaniel Bristot de Oliveira  */
ikm_read_reactor(char * monitor_name)1866d60f896SDaniel Bristot de Oliveira static char *ikm_read_reactor(char *monitor_name)
1876d60f896SDaniel Bristot de Oliveira {
1886d60f896SDaniel Bristot de Oliveira 	char path[MAX_PATH];
1896d60f896SDaniel Bristot de Oliveira 	char *reactors;
1906d60f896SDaniel Bristot de Oliveira 
1916d60f896SDaniel Bristot de Oliveira 	snprintf(path, MAX_PATH, "rv/monitors/%s/reactors", monitor_name);
1926d60f896SDaniel Bristot de Oliveira 	reactors = tracefs_instance_file_read(NULL, path, NULL);
1936d60f896SDaniel Bristot de Oliveira 	if (!reactors) {
1946d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: fail reading monitor's %s reactors file\n", monitor_name);
1956d60f896SDaniel Bristot de Oliveira 		return NULL;
1966d60f896SDaniel Bristot de Oliveira 	}
1976d60f896SDaniel Bristot de Oliveira 
1986d60f896SDaniel Bristot de Oliveira 	return reactors;
1996d60f896SDaniel Bristot de Oliveira }
2006d60f896SDaniel Bristot de Oliveira 
2016d60f896SDaniel Bristot de Oliveira /*
2026d60f896SDaniel Bristot de Oliveira  * ikm_get_current_reactor - get the current enabled reactor
2036d60f896SDaniel Bristot de Oliveira  *
2046d60f896SDaniel Bristot de Oliveira  * Reads the reactors file and find the currently enabled
2056d60f896SDaniel Bristot de Oliveira  * [reactor].
2066d60f896SDaniel Bristot de Oliveira  *
2076d60f896SDaniel Bristot de Oliveira  * Returns a dynamically allocated memory with the current
2086d60f896SDaniel Bristot de Oliveira  * reactor. NULL otherwise.
2096d60f896SDaniel Bristot de Oliveira  */
ikm_get_current_reactor(char * monitor_name)2106d60f896SDaniel Bristot de Oliveira static char *ikm_get_current_reactor(char *monitor_name)
2116d60f896SDaniel Bristot de Oliveira {
2126d60f896SDaniel Bristot de Oliveira 	char *reactors = ikm_read_reactor(monitor_name);
213*2863f8cfSDaniel Bristot de Oliveira 	char *curr_reactor = NULL;
2146d60f896SDaniel Bristot de Oliveira 	char *start;
2156d60f896SDaniel Bristot de Oliveira 	char *end;
2166d60f896SDaniel Bristot de Oliveira 
2176d60f896SDaniel Bristot de Oliveira 	if (!reactors)
2186d60f896SDaniel Bristot de Oliveira 		return NULL;
2196d60f896SDaniel Bristot de Oliveira 
2206d60f896SDaniel Bristot de Oliveira 	start = strstr(reactors, "[");
2216d60f896SDaniel Bristot de Oliveira 	if (!start)
2226d60f896SDaniel Bristot de Oliveira 		goto out_free;
2236d60f896SDaniel Bristot de Oliveira 
2246d60f896SDaniel Bristot de Oliveira 	start++;
2256d60f896SDaniel Bristot de Oliveira 
2266d60f896SDaniel Bristot de Oliveira 	end = strstr(start, "]");
2276d60f896SDaniel Bristot de Oliveira 	if (!end)
2286d60f896SDaniel Bristot de Oliveira 		goto out_free;
2296d60f896SDaniel Bristot de Oliveira 
2306d60f896SDaniel Bristot de Oliveira 	*end = '\0';
2316d60f896SDaniel Bristot de Oliveira 
2326d60f896SDaniel Bristot de Oliveira 	curr_reactor = calloc(strlen(start) + 1, sizeof(char));
2336d60f896SDaniel Bristot de Oliveira 	if (!curr_reactor)
2346d60f896SDaniel Bristot de Oliveira 		goto out_free;
2356d60f896SDaniel Bristot de Oliveira 
2366d60f896SDaniel Bristot de Oliveira 	strncpy(curr_reactor, start, strlen(start));
2376d60f896SDaniel Bristot de Oliveira 	debug_msg("ikm: read current reactor %s\n", curr_reactor);
2386d60f896SDaniel Bristot de Oliveira 
2396d60f896SDaniel Bristot de Oliveira out_free:
2406d60f896SDaniel Bristot de Oliveira 	free(reactors);
2416d60f896SDaniel Bristot de Oliveira 
2426d60f896SDaniel Bristot de Oliveira 	return curr_reactor;
2436d60f896SDaniel Bristot de Oliveira }
2446d60f896SDaniel Bristot de Oliveira 
ikm_has_id(char * monitor_name)2456d60f896SDaniel Bristot de Oliveira static int ikm_has_id(char *monitor_name)
2466d60f896SDaniel Bristot de Oliveira {
2476d60f896SDaniel Bristot de Oliveira 	char path[MAX_PATH];
2486d60f896SDaniel Bristot de Oliveira 	char *format;
2496d60f896SDaniel Bristot de Oliveira 	int has_id;
2506d60f896SDaniel Bristot de Oliveira 
2516d60f896SDaniel Bristot de Oliveira 	snprintf(path, MAX_PATH, "events/rv/event_%s/format", monitor_name);
2526d60f896SDaniel Bristot de Oliveira 	format = tracefs_instance_file_read(NULL, path, NULL);
2536d60f896SDaniel Bristot de Oliveira 	if (!format) {
2546d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: fail reading monitor's %s format event file\n", monitor_name);
2556d60f896SDaniel Bristot de Oliveira 		return -1;
2566d60f896SDaniel Bristot de Oliveira 	}
2576d60f896SDaniel Bristot de Oliveira 
2586d60f896SDaniel Bristot de Oliveira 	/* print fmt: "%d: %s x %s -> %s %s", REC->id, ... */
2596d60f896SDaniel Bristot de Oliveira 	has_id = !!strstr(format, "REC->id");
2606d60f896SDaniel Bristot de Oliveira 
2616d60f896SDaniel Bristot de Oliveira 	debug_msg("ikm: monitor %s has id: %s\n", monitor_name, has_id ? "yes" : "no");
2626d60f896SDaniel Bristot de Oliveira 
2636d60f896SDaniel Bristot de Oliveira 	free(format);
2646d60f896SDaniel Bristot de Oliveira 
2656d60f896SDaniel Bristot de Oliveira 	return has_id;
2666d60f896SDaniel Bristot de Oliveira }
2676d60f896SDaniel Bristot de Oliveira 
2686d60f896SDaniel Bristot de Oliveira /**
2696d60f896SDaniel Bristot de Oliveira  * ikm_list_monitors - list all available monitors
2706d60f896SDaniel Bristot de Oliveira  *
2716d60f896SDaniel Bristot de Oliveira  * Returns 0 on success, -1 otherwise.
2726d60f896SDaniel Bristot de Oliveira  */
ikm_list_monitors(void)2736d60f896SDaniel Bristot de Oliveira int ikm_list_monitors(void)
2746d60f896SDaniel Bristot de Oliveira {
2756d60f896SDaniel Bristot de Oliveira 	char *available_monitors;
2766d60f896SDaniel Bristot de Oliveira 	struct monitor ikm;
2776d60f896SDaniel Bristot de Oliveira 	char *curr, *next;
2786d60f896SDaniel Bristot de Oliveira 	int retval;
2796d60f896SDaniel Bristot de Oliveira 
2806d60f896SDaniel Bristot de Oliveira 	available_monitors = tracefs_instance_file_read(NULL, "rv/available_monitors", NULL);
2816d60f896SDaniel Bristot de Oliveira 
2826d60f896SDaniel Bristot de Oliveira 	if (!available_monitors) {
2836d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: available monitors is not available, is CONFIG_RV enabled?\n");
2846d60f896SDaniel Bristot de Oliveira 		return -1;
2856d60f896SDaniel Bristot de Oliveira 	}
2866d60f896SDaniel Bristot de Oliveira 
2876d60f896SDaniel Bristot de Oliveira 	curr = available_monitors;
2886d60f896SDaniel Bristot de Oliveira 	do {
2896d60f896SDaniel Bristot de Oliveira 		next = strstr(curr, "\n");
2906d60f896SDaniel Bristot de Oliveira 		*next = '\0';
2916d60f896SDaniel Bristot de Oliveira 
2926d60f896SDaniel Bristot de Oliveira 		retval = ikm_fill_monitor_definition(curr, &ikm);
2936d60f896SDaniel Bristot de Oliveira 		if (retval)
2946d60f896SDaniel Bristot de Oliveira 			err_msg("ikm: error reading %d in kernel monitor, skipping\n", curr);
2956d60f896SDaniel Bristot de Oliveira 
2966d60f896SDaniel Bristot de Oliveira 		printf("%-24s %s %s\n", ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF]");
2976d60f896SDaniel Bristot de Oliveira 		curr = ++next;
2986d60f896SDaniel Bristot de Oliveira 
2996d60f896SDaniel Bristot de Oliveira 	} while (strlen(curr));
3006d60f896SDaniel Bristot de Oliveira 
3016d60f896SDaniel Bristot de Oliveira 	free(available_monitors);
3026d60f896SDaniel Bristot de Oliveira 
3036d60f896SDaniel Bristot de Oliveira 	return 0;
3046d60f896SDaniel Bristot de Oliveira }
3056d60f896SDaniel Bristot de Oliveira 
ikm_print_header(struct trace_seq * s)3066d60f896SDaniel Bristot de Oliveira static void ikm_print_header(struct trace_seq *s)
3076d60f896SDaniel Bristot de Oliveira {
3086d60f896SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%16s-%-8s %5s %5s ", "<TASK>", "PID", "[CPU]", "TYPE");
3096d60f896SDaniel Bristot de Oliveira 	if (config_has_id)
3106d60f896SDaniel Bristot de Oliveira 		trace_seq_printf(s, "%8s ", "ID");
3116d60f896SDaniel Bristot de Oliveira 
3126d60f896SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n",
3136d60f896SDaniel Bristot de Oliveira 			 "STATE",
3146d60f896SDaniel Bristot de Oliveira 			 "EVENT",
3156d60f896SDaniel Bristot de Oliveira 			 "NEXT_STATE",
3166d60f896SDaniel Bristot de Oliveira 			 "FINAL");
3176d60f896SDaniel Bristot de Oliveira 
3186d60f896SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%16s %-8s %5s %5s ", " | ", " | ", " | ", " | ");
3196d60f896SDaniel Bristot de Oliveira 
3206d60f896SDaniel Bristot de Oliveira 	if (config_has_id)
3216d60f896SDaniel Bristot de Oliveira 		trace_seq_printf(s, "%8s ", " | ");
3226d60f896SDaniel Bristot de Oliveira 
3236d60f896SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%24s   %-24s    %-24s %s\n",
3246d60f896SDaniel Bristot de Oliveira 			 " | ",
3256d60f896SDaniel Bristot de Oliveira 			 " | ",
3266d60f896SDaniel Bristot de Oliveira 			 " | ",
3276d60f896SDaniel Bristot de Oliveira 			 "|");
3286d60f896SDaniel Bristot de Oliveira 
3296d60f896SDaniel Bristot de Oliveira }
3306d60f896SDaniel Bristot de Oliveira 
3316d60f896SDaniel Bristot de Oliveira /*
3326d60f896SDaniel Bristot de Oliveira  * ikm_event_handler - callback to handle event events
3336d60f896SDaniel Bristot de Oliveira  *
3346d60f896SDaniel Bristot de Oliveira  * Called any time a rv:"monitor"_event events is generated.
3356d60f896SDaniel Bristot de Oliveira  * It parses and print event.
3366d60f896SDaniel Bristot de Oliveira  */
3376d60f896SDaniel Bristot de Oliveira static int
ikm_event_handler(struct trace_seq * s,struct tep_record * record,struct tep_event * trace_event,void * context)3386d60f896SDaniel Bristot de Oliveira ikm_event_handler(struct trace_seq *s, struct tep_record *record,
3396d60f896SDaniel Bristot de Oliveira 		  struct tep_event *trace_event, void *context)
3406d60f896SDaniel Bristot de Oliveira {
3416d60f896SDaniel Bristot de Oliveira 	/* if needed: struct trace_instance *inst = context; */
3426d60f896SDaniel Bristot de Oliveira 	char *state, *event, *next_state;
3436d60f896SDaniel Bristot de Oliveira 	unsigned long long final_state;
3446d60f896SDaniel Bristot de Oliveira 	unsigned long long pid;
3456d60f896SDaniel Bristot de Oliveira 	unsigned long long id;
3466d60f896SDaniel Bristot de Oliveira 	int cpu = record->cpu;
3476d60f896SDaniel Bristot de Oliveira 	int val;
3486d60f896SDaniel Bristot de Oliveira 
3496d60f896SDaniel Bristot de Oliveira 	if (config_has_id)
3506d60f896SDaniel Bristot de Oliveira 		tep_get_field_val(s, trace_event, "id", record, &id, 1);
3516d60f896SDaniel Bristot de Oliveira 
3526d60f896SDaniel Bristot de Oliveira 	tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1);
3536d60f896SDaniel Bristot de Oliveira 
3546d60f896SDaniel Bristot de Oliveira 	if (config_has_id && (config_my_pid == id))
3556d60f896SDaniel Bristot de Oliveira 		return 0;
3566d60f896SDaniel Bristot de Oliveira 	else if (config_my_pid && (config_my_pid == pid))
3576d60f896SDaniel Bristot de Oliveira 		return 0;
3586d60f896SDaniel Bristot de Oliveira 
3596d60f896SDaniel Bristot de Oliveira 	tep_print_event(trace_event->tep, s, record, "%16s-%-8d ", TEP_PRINT_COMM, TEP_PRINT_PID);
3606d60f896SDaniel Bristot de Oliveira 
3616d60f896SDaniel Bristot de Oliveira 	trace_seq_printf(s, "[%.3d] event ", cpu);
3626d60f896SDaniel Bristot de Oliveira 
3636d60f896SDaniel Bristot de Oliveira 	if (config_has_id)
3646d60f896SDaniel Bristot de Oliveira 		trace_seq_printf(s, "%8llu ", id);
3656d60f896SDaniel Bristot de Oliveira 
3666d60f896SDaniel Bristot de Oliveira 	state = tep_get_field_raw(s, trace_event, "state", record, &val, 0);
3676d60f896SDaniel Bristot de Oliveira 	event = tep_get_field_raw(s, trace_event, "event", record, &val, 0);
3686d60f896SDaniel Bristot de Oliveira 	next_state = tep_get_field_raw(s, trace_event, "next_state", record, &val, 0);
3696d60f896SDaniel Bristot de Oliveira 	tep_get_field_val(s, trace_event, "final_state", record, &final_state, 1);
3706d60f896SDaniel Bristot de Oliveira 
3716d60f896SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%24s x %-24s -> %-24s %s\n",
3726d60f896SDaniel Bristot de Oliveira 			 state,
3736d60f896SDaniel Bristot de Oliveira 			 event,
3746d60f896SDaniel Bristot de Oliveira 			 next_state,
3756d60f896SDaniel Bristot de Oliveira 			 final_state ? "Y" : "N");
3766d60f896SDaniel Bristot de Oliveira 
3776d60f896SDaniel Bristot de Oliveira 	trace_seq_do_printf(s);
3786d60f896SDaniel Bristot de Oliveira 	trace_seq_reset(s);
3796d60f896SDaniel Bristot de Oliveira 
3806d60f896SDaniel Bristot de Oliveira 	return 0;
3816d60f896SDaniel Bristot de Oliveira }
3826d60f896SDaniel Bristot de Oliveira 
3836d60f896SDaniel Bristot de Oliveira /*
3846d60f896SDaniel Bristot de Oliveira  * ikm_error_handler - callback to handle error events
3856d60f896SDaniel Bristot de Oliveira  *
3866d60f896SDaniel Bristot de Oliveira  * Called any time a rv:"monitor"_errors events is generated.
3876d60f896SDaniel Bristot de Oliveira  * It parses and print event.
3886d60f896SDaniel Bristot de Oliveira  */
3896d60f896SDaniel Bristot de Oliveira static int
ikm_error_handler(struct trace_seq * s,struct tep_record * record,struct tep_event * trace_event,void * context)3906d60f896SDaniel Bristot de Oliveira ikm_error_handler(struct trace_seq *s, struct tep_record *record,
3916d60f896SDaniel Bristot de Oliveira 		  struct tep_event *trace_event, void *context)
3926d60f896SDaniel Bristot de Oliveira {
3936d60f896SDaniel Bristot de Oliveira 	unsigned long long pid, id;
3946d60f896SDaniel Bristot de Oliveira 	int cpu = record->cpu;
3956d60f896SDaniel Bristot de Oliveira 	char *state, *event;
3966d60f896SDaniel Bristot de Oliveira 	int val;
3976d60f896SDaniel Bristot de Oliveira 
3986d60f896SDaniel Bristot de Oliveira 	if (config_has_id)
3996d60f896SDaniel Bristot de Oliveira 		tep_get_field_val(s, trace_event, "id", record, &id, 1);
4006d60f896SDaniel Bristot de Oliveira 
4016d60f896SDaniel Bristot de Oliveira 	tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1);
4026d60f896SDaniel Bristot de Oliveira 
4036d60f896SDaniel Bristot de Oliveira 	if (config_has_id && config_my_pid == id)
4046d60f896SDaniel Bristot de Oliveira 		return 0;
4056d60f896SDaniel Bristot de Oliveira 	else if (config_my_pid == pid)
4066d60f896SDaniel Bristot de Oliveira 		return 0;
4076d60f896SDaniel Bristot de Oliveira 
4086d60f896SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%8lld [%03d] error ", pid, cpu);
4096d60f896SDaniel Bristot de Oliveira 
4106d60f896SDaniel Bristot de Oliveira 	if (config_has_id)
4116d60f896SDaniel Bristot de Oliveira 		trace_seq_printf(s, "%8llu ", id);
4126d60f896SDaniel Bristot de Oliveira 
4136d60f896SDaniel Bristot de Oliveira 	state = tep_get_field_raw(s, trace_event, "state", record, &val, 0);
4146d60f896SDaniel Bristot de Oliveira 	event = tep_get_field_raw(s, trace_event, "event", record, &val, 0);
4156d60f896SDaniel Bristot de Oliveira 
4166d60f896SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%24s x %s\n", state, event);
4176d60f896SDaniel Bristot de Oliveira 
4186d60f896SDaniel Bristot de Oliveira 	trace_seq_do_printf(s);
4196d60f896SDaniel Bristot de Oliveira 	trace_seq_reset(s);
4206d60f896SDaniel Bristot de Oliveira 
4216d60f896SDaniel Bristot de Oliveira 	return 0;
4226d60f896SDaniel Bristot de Oliveira }
4236d60f896SDaniel Bristot de Oliveira 
4246d60f896SDaniel Bristot de Oliveira /*
4256d60f896SDaniel Bristot de Oliveira  * ikm_setup_trace_instance - set up a tracing instance to collect data
4266d60f896SDaniel Bristot de Oliveira  *
4276d60f896SDaniel Bristot de Oliveira  * Create a trace instance, enable rv: events and enable the trace.
4286d60f896SDaniel Bristot de Oliveira  *
4296d60f896SDaniel Bristot de Oliveira  * Returns the trace_instance * with all set, NULL otherwise.
4306d60f896SDaniel Bristot de Oliveira  */
ikm_setup_trace_instance(char * monitor_name)4316d60f896SDaniel Bristot de Oliveira static struct trace_instance *ikm_setup_trace_instance(char *monitor_name)
4326d60f896SDaniel Bristot de Oliveira {
4336d60f896SDaniel Bristot de Oliveira 	char event[MAX_DA_NAME_LEN + 7]; /* max(error_,event_) + '0' = 7 */
4346d60f896SDaniel Bristot de Oliveira 	struct trace_instance *inst;
4356d60f896SDaniel Bristot de Oliveira 	int retval;
4366d60f896SDaniel Bristot de Oliveira 
4376d60f896SDaniel Bristot de Oliveira 	if (!config_trace)
4386d60f896SDaniel Bristot de Oliveira 		return NULL;
4396d60f896SDaniel Bristot de Oliveira 
4406d60f896SDaniel Bristot de Oliveira 	config_has_id = ikm_has_id(monitor_name);
4416d60f896SDaniel Bristot de Oliveira 	if (config_has_id < 0) {
4426d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: failed to read monitor %s event format\n", monitor_name);
4436d60f896SDaniel Bristot de Oliveira 		goto out_err;
4446d60f896SDaniel Bristot de Oliveira 	}
4456d60f896SDaniel Bristot de Oliveira 
4466d60f896SDaniel Bristot de Oliveira 	/* alloc data */
4476d60f896SDaniel Bristot de Oliveira 	inst = calloc(1, sizeof(*inst));
4486d60f896SDaniel Bristot de Oliveira 	if (!inst) {
4496d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: failed to allocate trace instance");
4506d60f896SDaniel Bristot de Oliveira 		goto out_err;
4516d60f896SDaniel Bristot de Oliveira 	}
4526d60f896SDaniel Bristot de Oliveira 
4536d60f896SDaniel Bristot de Oliveira 	retval = trace_instance_init(inst, monitor_name);
4546d60f896SDaniel Bristot de Oliveira 	if (retval)
4556d60f896SDaniel Bristot de Oliveira 		goto out_free;
4566d60f896SDaniel Bristot de Oliveira 
4576d60f896SDaniel Bristot de Oliveira 	/* enable events */
4586d60f896SDaniel Bristot de Oliveira 	snprintf(event, sizeof(event), "event_%s", monitor_name);
4596d60f896SDaniel Bristot de Oliveira 	retval = tracefs_event_enable(inst->inst, "rv",  event);
4606d60f896SDaniel Bristot de Oliveira 	if (retval)
4616d60f896SDaniel Bristot de Oliveira 		goto out_inst;
4626d60f896SDaniel Bristot de Oliveira 
4636d60f896SDaniel Bristot de Oliveira 	tep_register_event_handler(inst->tep, -1, "rv", event,
4646d60f896SDaniel Bristot de Oliveira 				   ikm_event_handler, NULL);
4656d60f896SDaniel Bristot de Oliveira 
4666d60f896SDaniel Bristot de Oliveira 	snprintf(event, sizeof(event), "error_%s", monitor_name);
4676d60f896SDaniel Bristot de Oliveira 	retval = tracefs_event_enable(inst->inst, "rv", event);
4686d60f896SDaniel Bristot de Oliveira 	if (retval)
4696d60f896SDaniel Bristot de Oliveira 		goto out_inst;
4706d60f896SDaniel Bristot de Oliveira 
4716d60f896SDaniel Bristot de Oliveira 	tep_register_event_handler(inst->tep, -1, "rv", event,
4726d60f896SDaniel Bristot de Oliveira 				   ikm_error_handler, NULL);
4736d60f896SDaniel Bristot de Oliveira 
4746d60f896SDaniel Bristot de Oliveira 	/* ready to enable */
4756d60f896SDaniel Bristot de Oliveira 	tracefs_trace_on(inst->inst);
4766d60f896SDaniel Bristot de Oliveira 
4776d60f896SDaniel Bristot de Oliveira 	return inst;
4786d60f896SDaniel Bristot de Oliveira 
4796d60f896SDaniel Bristot de Oliveira out_inst:
4806d60f896SDaniel Bristot de Oliveira 	trace_instance_destroy(inst);
4816d60f896SDaniel Bristot de Oliveira out_free:
4826d60f896SDaniel Bristot de Oliveira 	free(inst);
4836d60f896SDaniel Bristot de Oliveira out_err:
4846d60f896SDaniel Bristot de Oliveira 	return NULL;
4856d60f896SDaniel Bristot de Oliveira }
4866d60f896SDaniel Bristot de Oliveira 
4876d60f896SDaniel Bristot de Oliveira /**
4886d60f896SDaniel Bristot de Oliveira  * ikm_destroy_trace_instance - destroy a previously created instance
4896d60f896SDaniel Bristot de Oliveira  */
ikm_destroy_trace_instance(struct trace_instance * inst)4906d60f896SDaniel Bristot de Oliveira static void ikm_destroy_trace_instance(struct trace_instance *inst)
4916d60f896SDaniel Bristot de Oliveira {
4926d60f896SDaniel Bristot de Oliveira 	if (!inst)
4936d60f896SDaniel Bristot de Oliveira 		return;
4946d60f896SDaniel Bristot de Oliveira 
4956d60f896SDaniel Bristot de Oliveira 	trace_instance_destroy(inst);
4966d60f896SDaniel Bristot de Oliveira 	free(inst);
4976d60f896SDaniel Bristot de Oliveira }
4986d60f896SDaniel Bristot de Oliveira 
4996d60f896SDaniel Bristot de Oliveira /*
5006d60f896SDaniel Bristot de Oliveira  * ikm_usage_print_reactors - print all available reactors, one per line.
5016d60f896SDaniel Bristot de Oliveira  */
ikm_usage_print_reactors(void)5026d60f896SDaniel Bristot de Oliveira static void ikm_usage_print_reactors(void)
5036d60f896SDaniel Bristot de Oliveira {
5046d60f896SDaniel Bristot de Oliveira 	char *reactors = tracefs_instance_file_read(NULL, "rv/available_reactors", NULL);
5056d60f896SDaniel Bristot de Oliveira 	char *start, *end;
5066d60f896SDaniel Bristot de Oliveira 
5076d60f896SDaniel Bristot de Oliveira 	if (!reactors)
5086d60f896SDaniel Bristot de Oliveira 		return;
5096d60f896SDaniel Bristot de Oliveira 
5106d60f896SDaniel Bristot de Oliveira 	fprintf(stderr, "  available reactors:");
5116d60f896SDaniel Bristot de Oliveira 
5126d60f896SDaniel Bristot de Oliveira 	start = reactors;
5136d60f896SDaniel Bristot de Oliveira 	end = strstr(start, "\n");
5146d60f896SDaniel Bristot de Oliveira 
5156d60f896SDaniel Bristot de Oliveira 	while (end) {
5166d60f896SDaniel Bristot de Oliveira 		*end = '\0';
5176d60f896SDaniel Bristot de Oliveira 
5186d60f896SDaniel Bristot de Oliveira 		fprintf(stderr, " %s", start);
5196d60f896SDaniel Bristot de Oliveira 
5206d60f896SDaniel Bristot de Oliveira 		start = ++end;
5216d60f896SDaniel Bristot de Oliveira 		end = strstr(start, "\n");
522a37380efSzhang songyi 	}
5236d60f896SDaniel Bristot de Oliveira 
5246d60f896SDaniel Bristot de Oliveira 	fprintf(stderr, "\n");
5256d60f896SDaniel Bristot de Oliveira }
5266d60f896SDaniel Bristot de Oliveira /*
5276d60f896SDaniel Bristot de Oliveira  * ikm_usage - print usage
5286d60f896SDaniel Bristot de Oliveira  */
ikm_usage(int exit_val,char * monitor_name,const char * fmt,...)5296d60f896SDaniel Bristot de Oliveira static void ikm_usage(int exit_val, char *monitor_name, const char *fmt, ...)
5306d60f896SDaniel Bristot de Oliveira {
5316d60f896SDaniel Bristot de Oliveira 
5326d60f896SDaniel Bristot de Oliveira 	char message[1024];
5336d60f896SDaniel Bristot de Oliveira 	va_list ap;
5346d60f896SDaniel Bristot de Oliveira 	int i;
5356d60f896SDaniel Bristot de Oliveira 
5366d60f896SDaniel Bristot de Oliveira 	static const char *const usage[] = {
5376d60f896SDaniel Bristot de Oliveira 		"",
5386d60f896SDaniel Bristot de Oliveira 		"	-h/--help: print this menu and the reactor list",
5396d60f896SDaniel Bristot de Oliveira 		"	-r/--reactor 'reactor': enables the 'reactor'",
5406d60f896SDaniel Bristot de Oliveira 		"	-s/--self: when tracing (-t), also trace rv command",
5416d60f896SDaniel Bristot de Oliveira 		"	-t/--trace: trace monitor's event",
5426d60f896SDaniel Bristot de Oliveira 		"	-v/--verbose: print debug messages",
5436d60f896SDaniel Bristot de Oliveira 		"",
5446d60f896SDaniel Bristot de Oliveira 		NULL,
5456d60f896SDaniel Bristot de Oliveira 	};
5466d60f896SDaniel Bristot de Oliveira 
5476d60f896SDaniel Bristot de Oliveira 	va_start(ap, fmt);
5486d60f896SDaniel Bristot de Oliveira 	vsnprintf(message, sizeof(message), fmt, ap);
5496d60f896SDaniel Bristot de Oliveira 	va_end(ap);
5506d60f896SDaniel Bristot de Oliveira 
5516d60f896SDaniel Bristot de Oliveira 	fprintf(stderr, "  %s\n", message);
5526d60f896SDaniel Bristot de Oliveira 
5536d60f896SDaniel Bristot de Oliveira 	fprintf(stderr, "\n  usage: rv mon %s [-h] [-q] [-r reactor] [-s] [-v]", monitor_name);
5546d60f896SDaniel Bristot de Oliveira 
5556d60f896SDaniel Bristot de Oliveira 	for (i = 0; usage[i]; i++)
5566d60f896SDaniel Bristot de Oliveira 		fprintf(stderr, "%s\n", usage[i]);
5576d60f896SDaniel Bristot de Oliveira 
5586d60f896SDaniel Bristot de Oliveira 	ikm_usage_print_reactors();
5596d60f896SDaniel Bristot de Oliveira 	exit(exit_val);
5606d60f896SDaniel Bristot de Oliveira }
5616d60f896SDaniel Bristot de Oliveira 
5626d60f896SDaniel Bristot de Oliveira /*
5636d60f896SDaniel Bristot de Oliveira  * parse_arguments - parse arguments and set config
5646d60f896SDaniel Bristot de Oliveira  */
parse_arguments(char * monitor_name,int argc,char ** argv)5656d60f896SDaniel Bristot de Oliveira static int parse_arguments(char *monitor_name, int argc, char **argv)
5666d60f896SDaniel Bristot de Oliveira {
5676d60f896SDaniel Bristot de Oliveira 	int c, retval;
5686d60f896SDaniel Bristot de Oliveira 
5696d60f896SDaniel Bristot de Oliveira 	config_my_pid = getpid();
5706d60f896SDaniel Bristot de Oliveira 
5716d60f896SDaniel Bristot de Oliveira 	while (1) {
5726d60f896SDaniel Bristot de Oliveira 		static struct option long_options[] = {
5736d60f896SDaniel Bristot de Oliveira 			{"help",		no_argument,		0, 'h'},
5746d60f896SDaniel Bristot de Oliveira 			{"reactor",		required_argument,	0, 'r'},
5756d60f896SDaniel Bristot de Oliveira 			{"self",		no_argument,		0, 's'},
5766d60f896SDaniel Bristot de Oliveira 			{"trace",		no_argument,		0, 't'},
5776d60f896SDaniel Bristot de Oliveira 			{"verbose",		no_argument,		0, 'v'},
5786d60f896SDaniel Bristot de Oliveira 			{0, 0, 0, 0}
5796d60f896SDaniel Bristot de Oliveira 		};
5806d60f896SDaniel Bristot de Oliveira 
5816d60f896SDaniel Bristot de Oliveira 		/* getopt_long stores the option index here. */
5826d60f896SDaniel Bristot de Oliveira 		int option_index = 0;
5836d60f896SDaniel Bristot de Oliveira 
5846d60f896SDaniel Bristot de Oliveira 		c = getopt_long(argc, argv, "hr:stv", long_options, &option_index);
5856d60f896SDaniel Bristot de Oliveira 
5866d60f896SDaniel Bristot de Oliveira 		/* detect the end of the options. */
5876d60f896SDaniel Bristot de Oliveira 		if (c == -1)
5886d60f896SDaniel Bristot de Oliveira 			break;
5896d60f896SDaniel Bristot de Oliveira 
5906d60f896SDaniel Bristot de Oliveira 		switch (c) {
5916d60f896SDaniel Bristot de Oliveira 		case 'h':
5926d60f896SDaniel Bristot de Oliveira 			ikm_usage(0, monitor_name, "help:");
5936d60f896SDaniel Bristot de Oliveira 			break;
5946d60f896SDaniel Bristot de Oliveira 		case 'r':
5956d60f896SDaniel Bristot de Oliveira 			config_reactor = optarg;
5966d60f896SDaniel Bristot de Oliveira 			break;
5976d60f896SDaniel Bristot de Oliveira 		case 's':
5986d60f896SDaniel Bristot de Oliveira 			config_my_pid = 0;
5996d60f896SDaniel Bristot de Oliveira 			break;
6006d60f896SDaniel Bristot de Oliveira 		case 't':
6016d60f896SDaniel Bristot de Oliveira 			config_trace = 1;
6026d60f896SDaniel Bristot de Oliveira 			break;
6036d60f896SDaniel Bristot de Oliveira 		case 'v':
6046d60f896SDaniel Bristot de Oliveira 			config_debug = 1;
6056d60f896SDaniel Bristot de Oliveira 			break;
6066d60f896SDaniel Bristot de Oliveira 		}
6076d60f896SDaniel Bristot de Oliveira 	}
6086d60f896SDaniel Bristot de Oliveira 
6096d60f896SDaniel Bristot de Oliveira 	if (config_reactor) {
6106d60f896SDaniel Bristot de Oliveira 		config_initial_reactor = ikm_get_current_reactor(monitor_name);
6116d60f896SDaniel Bristot de Oliveira 		if (!config_initial_reactor)
6126d60f896SDaniel Bristot de Oliveira 			ikm_usage(1, monitor_name,
6136d60f896SDaniel Bristot de Oliveira 				  "ikm: failed to read current reactor, are reactors enabled?");
6146d60f896SDaniel Bristot de Oliveira 
6156d60f896SDaniel Bristot de Oliveira 		retval = ikm_write_reactor(monitor_name, config_reactor);
6166d60f896SDaniel Bristot de Oliveira 		if (retval <= 0)
6176d60f896SDaniel Bristot de Oliveira 			ikm_usage(1, monitor_name,
6186d60f896SDaniel Bristot de Oliveira 				  "ikm: failed to set %s reactor, is it available?",
6196d60f896SDaniel Bristot de Oliveira 				  config_reactor);
6206d60f896SDaniel Bristot de Oliveira 	}
6216d60f896SDaniel Bristot de Oliveira 
6226d60f896SDaniel Bristot de Oliveira 	debug_msg("ikm: my pid is %d\n", config_my_pid);
6236d60f896SDaniel Bristot de Oliveira 
6246d60f896SDaniel Bristot de Oliveira 	return 0;
6256d60f896SDaniel Bristot de Oliveira }
6266d60f896SDaniel Bristot de Oliveira 
6276d60f896SDaniel Bristot de Oliveira /**
6286d60f896SDaniel Bristot de Oliveira  * ikm_run_monitor - apply configs and run the monitor
6296d60f896SDaniel Bristot de Oliveira  *
6306d60f896SDaniel Bristot de Oliveira  * Returns 1 if a monitor was found an executed, 0 if no
6316d60f896SDaniel Bristot de Oliveira  * monitors were found, or -1 on error.
6326d60f896SDaniel Bristot de Oliveira  */
ikm_run_monitor(char * monitor_name,int argc,char ** argv)6336d60f896SDaniel Bristot de Oliveira int ikm_run_monitor(char *monitor_name, int argc, char **argv)
6346d60f896SDaniel Bristot de Oliveira {
6356d60f896SDaniel Bristot de Oliveira 	struct trace_instance *inst = NULL;
6366d60f896SDaniel Bristot de Oliveira 	int retval;
6376d60f896SDaniel Bristot de Oliveira 
6386d60f896SDaniel Bristot de Oliveira 	/*
6396d60f896SDaniel Bristot de Oliveira 	 * Check if monitor exists by seeing it is enabled.
6406d60f896SDaniel Bristot de Oliveira 	 */
6416d60f896SDaniel Bristot de Oliveira 	retval = __ikm_read_enable(monitor_name);
6426d60f896SDaniel Bristot de Oliveira 	if (retval < 0)
6436d60f896SDaniel Bristot de Oliveira 		return 0;
6446d60f896SDaniel Bristot de Oliveira 
6456d60f896SDaniel Bristot de Oliveira 	if (retval) {
6466d60f896SDaniel Bristot de Oliveira 		err_msg("ikm: monitor %s (in-kernel) is already enabled\n", monitor_name);
6476d60f896SDaniel Bristot de Oliveira 		return -1;
6486d60f896SDaniel Bristot de Oliveira 	}
6496d60f896SDaniel Bristot de Oliveira 
6506d60f896SDaniel Bristot de Oliveira 	/* we should be good to go */
6516d60f896SDaniel Bristot de Oliveira 	retval = parse_arguments(monitor_name, argc, argv);
6526d60f896SDaniel Bristot de Oliveira 	if (retval)
6536d60f896SDaniel Bristot de Oliveira 		ikm_usage(1, monitor_name, "ikm: failed parsing arguments");
6546d60f896SDaniel Bristot de Oliveira 
6556d60f896SDaniel Bristot de Oliveira 	if (config_trace) {
6566d60f896SDaniel Bristot de Oliveira 		inst = ikm_setup_trace_instance(monitor_name);
6576d60f896SDaniel Bristot de Oliveira 		if (!inst)
6586d60f896SDaniel Bristot de Oliveira 			return -1;
6596d60f896SDaniel Bristot de Oliveira 	}
6606d60f896SDaniel Bristot de Oliveira 
6616d60f896SDaniel Bristot de Oliveira 	retval = ikm_enable(monitor_name);
6626d60f896SDaniel Bristot de Oliveira 	if (retval < 0)
6636d60f896SDaniel Bristot de Oliveira 		goto out_free_instance;
6646d60f896SDaniel Bristot de Oliveira 
6656d60f896SDaniel Bristot de Oliveira 	if (config_trace)
6666d60f896SDaniel Bristot de Oliveira 		ikm_print_header(inst->seq);
6676d60f896SDaniel Bristot de Oliveira 
6686d60f896SDaniel Bristot de Oliveira 	while (!should_stop()) {
6696d60f896SDaniel Bristot de Oliveira 		if (config_trace) {
6706d60f896SDaniel Bristot de Oliveira 			retval = tracefs_iterate_raw_events(inst->tep,
6716d60f896SDaniel Bristot de Oliveira 							    inst->inst,
6726d60f896SDaniel Bristot de Oliveira 							    NULL,
6736d60f896SDaniel Bristot de Oliveira 							    0,
6746d60f896SDaniel Bristot de Oliveira 							    collect_registered_events,
6756d60f896SDaniel Bristot de Oliveira 							    inst);
6766d60f896SDaniel Bristot de Oliveira 			if (retval) {
6776d60f896SDaniel Bristot de Oliveira 				err_msg("ikm: error reading trace buffer\n");
6786d60f896SDaniel Bristot de Oliveira 				break;
6796d60f896SDaniel Bristot de Oliveira 			}
6806d60f896SDaniel Bristot de Oliveira 		}
6816d60f896SDaniel Bristot de Oliveira 
6826d60f896SDaniel Bristot de Oliveira 		sleep(1);
6836d60f896SDaniel Bristot de Oliveira 	}
6846d60f896SDaniel Bristot de Oliveira 
6856d60f896SDaniel Bristot de Oliveira 	ikm_disable(monitor_name);
6866d60f896SDaniel Bristot de Oliveira 	ikm_destroy_trace_instance(inst);
6876d60f896SDaniel Bristot de Oliveira 
6886d60f896SDaniel Bristot de Oliveira 	if (config_reactor && config_initial_reactor)
6896d60f896SDaniel Bristot de Oliveira 		ikm_write_reactor(monitor_name, config_initial_reactor);
6906d60f896SDaniel Bristot de Oliveira 
6916d60f896SDaniel Bristot de Oliveira 	return 1;
6926d60f896SDaniel Bristot de Oliveira 
6936d60f896SDaniel Bristot de Oliveira out_free_instance:
6946d60f896SDaniel Bristot de Oliveira 	ikm_destroy_trace_instance(inst);
6956d60f896SDaniel Bristot de Oliveira 	if (config_reactor && config_initial_reactor)
6966d60f896SDaniel Bristot de Oliveira 		ikm_write_reactor(monitor_name, config_initial_reactor);
6976d60f896SDaniel Bristot de Oliveira 	return -1;
6986d60f896SDaniel Bristot de Oliveira }
699