mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
rtla/osnoise: Trace IPI events when recording a trace file
IPIs can now be monitored and accounted by osnoise top. When that is the case, also record them when saving a trace file. To match what is being recorded by the tool for its own analysis, event filters are applied to the events recorded to the trace output. Signed-off-by: Valentin Schneider <vschneid@redhat.com> Link: https://lore.kernel.org/r/20260902123942.695822-9-vschneid@redhat.com Signed-off-by: Tomas Glozar <tglozar@redhat.com>
This commit is contained in:
parent
20e92ac8c1
commit
cf89b1086d
|
|
@ -228,7 +228,7 @@ int run_tool(struct tool_ops *ops, int argc, char *argv[])
|
|||
|
||||
if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
|
||||
params->end_actions.present[ACTION_TRACE_OUTPUT]) {
|
||||
tool->record = osnoise_init_trace_tool(ops->tracer);
|
||||
tool->record = osnoise_init_trace_tool(params, ops->tracer);
|
||||
if (!tool->record) {
|
||||
err_msg("Failed to enable the trace instance\n");
|
||||
goto out_free;
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ int osnoise_set_workload(struct osnoise_context *context, bool onoff);
|
|||
|
||||
void osnoise_destroy_tool(struct osnoise_tool *top);
|
||||
struct osnoise_tool *osnoise_init_tool(char *tool_name);
|
||||
struct osnoise_tool *osnoise_init_trace_tool(const char *tracer);
|
||||
struct osnoise_tool *osnoise_init_trace_tool(struct common_params *params, const char *tracer);
|
||||
bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record);
|
||||
int osnoise_set_stop_us(struct osnoise_context *context, long long stop_us);
|
||||
int osnoise_set_stop_total_us(struct osnoise_context *context,
|
||||
|
|
|
|||
|
|
@ -1222,10 +1222,56 @@ struct osnoise_tool *osnoise_init_tool(char *tool_name)
|
|||
return top;
|
||||
}
|
||||
|
||||
/*
|
||||
* osnoise_init_ipi_filters - Initialize event filtering for IPI events
|
||||
*/
|
||||
int osnoise_init_ipi_filters(struct osnoise_tool *tool,
|
||||
struct common_params *params,
|
||||
bool *filters_enabled)
|
||||
{
|
||||
char filter[MAX_PATH];
|
||||
int retval;
|
||||
/*
|
||||
* If tracing on a subset of possible CPUs, leverage the kernel filtering
|
||||
* infrastructure to only generate events on traced CPUs.
|
||||
* Older kernels (pre v6.6) may have the IPI events but not the ability
|
||||
* to filter them, so allow that to fail gracefully.
|
||||
*/
|
||||
|
||||
snprintf(filter, ARRAY_SIZE(filter), "cpu & CPUS{%s}\n", params->cpus);
|
||||
retval = tracefs_event_file_write(tool->trace.inst,
|
||||
"ipi", "ipi_send_cpu", "filter",
|
||||
filter);
|
||||
if (retval < 0) {
|
||||
debug_msg("Could not set ipi_send_cpu CPU filter\n");
|
||||
*filters_enabled = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
snprintf(filter, ARRAY_SIZE(filter), "cpumask & CPUS{%s}\n", params->cpus);
|
||||
retval = tracefs_event_file_write(tool->trace.inst,
|
||||
"ipi", "ipi_send_cpumask", "filter",
|
||||
filter);
|
||||
if (retval < 0) {
|
||||
/*
|
||||
* If we managed to set up the previous filter but not
|
||||
* this one, something's really wrong
|
||||
*/
|
||||
err_msg("Could not set ipi_send_cpumask CPU filter\n");
|
||||
*filters_enabled = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*filters_enabled = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* osnoise_init_trace_tool - init a tracer instance to trace osnoise events
|
||||
*/
|
||||
struct osnoise_tool *osnoise_init_trace_tool(const char *tracer)
|
||||
struct osnoise_tool *osnoise_init_trace_tool(struct common_params *params,
|
||||
const char *tracer)
|
||||
{
|
||||
struct osnoise_tool *trace;
|
||||
int retval;
|
||||
|
|
@ -1240,6 +1286,30 @@ struct osnoise_tool *osnoise_init_trace_tool(const char *tracer)
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
if (!params->ipi)
|
||||
goto done;
|
||||
|
||||
retval = tracefs_event_enable(trace->trace.inst, "ipi", "ipi_send_cpu");
|
||||
if (retval < 0 && !errno) {
|
||||
err_msg("Could not find ipi_send_cpu event\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
retval = tracefs_event_enable(trace->trace.inst, "ipi", "ipi_send_cpumask");
|
||||
if (retval < 0 && !errno) {
|
||||
err_msg("Could not find ipi_send_cpumask event\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (params->cpus) {
|
||||
bool unused;
|
||||
|
||||
retval = osnoise_init_ipi_filters(trace, params, &unused);
|
||||
if (retval < 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
done:
|
||||
retval = enable_tracer_by_name(trace->trace.inst, tracer);
|
||||
if (retval) {
|
||||
err_msg("Could not enable %s tracer for tracing\n", tracer);
|
||||
|
|
|
|||
|
|
@ -65,6 +65,10 @@ int osnoise_enable(struct osnoise_tool *tool);
|
|||
int osnoise_main(int argc, char **argv);
|
||||
int hwnoise_main(int argc, char **argv);
|
||||
|
||||
int osnoise_init_ipi_filters(struct osnoise_tool *tool,
|
||||
struct common_params *params,
|
||||
bool *filters_enabled);
|
||||
|
||||
extern struct tool_ops timerlat_top_ops, timerlat_hist_ops;
|
||||
extern struct tool_ops osnoise_top_ops, osnoise_hist_ops;
|
||||
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ osnoise_ipi_cpumask_handler(struct trace_seq *s, struct tep_record *record,
|
|||
*/
|
||||
struct osnoise_tool *osnoise_init_top(struct common_params *params)
|
||||
{
|
||||
bool ipi_filters_enabled = false;
|
||||
bool ipi_filters_enabled;
|
||||
struct osnoise_tool *tool;
|
||||
int retval;
|
||||
|
||||
|
|
@ -425,41 +425,11 @@ struct osnoise_tool *osnoise_init_top(struct common_params *params)
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* If tracing on a subset of possible CPUs, leverage the kernel filtering
|
||||
* infrastructure to only generate events on traced CPUs.
|
||||
* Older kernels (pre v6.6) may have the IPI events but not the ability
|
||||
* to filter them, so allow that to fail gracefully.
|
||||
*/
|
||||
if (params->cpus) {
|
||||
char filter[MAX_PATH];
|
||||
|
||||
snprintf(filter, ARRAY_SIZE(filter), "cpu & CPUS{%s}\n", params->cpus);
|
||||
retval = tracefs_event_file_write(tool->trace.inst,
|
||||
"ipi", "ipi_send_cpu", "filter",
|
||||
filter);
|
||||
if (retval < 0) {
|
||||
debug_msg("Could not set ipi_send_cpu CPU filter\n");
|
||||
goto no_filter;
|
||||
}
|
||||
|
||||
|
||||
snprintf(filter, ARRAY_SIZE(filter), "cpumask & CPUS{%s}\n", params->cpus);
|
||||
retval = tracefs_event_file_write(tool->trace.inst,
|
||||
"ipi", "ipi_send_cpumask", "filter",
|
||||
filter);
|
||||
if (retval < 0) {
|
||||
/*
|
||||
* If we managed to set up the previous filter but not
|
||||
* this one, something's really wrong
|
||||
*/
|
||||
err_msg("Could not set ipi_send_cpumask CPU filter\n");
|
||||
retval = osnoise_init_ipi_filters(tool, params, &ipi_filters_enabled);
|
||||
if (retval < 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
ipi_filters_enabled = true;
|
||||
}
|
||||
no_filter:
|
||||
|
||||
/*
|
||||
* If no filtering is available and we're tracing all CPUs, we can still
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user