diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index c0aad38a993d..5c7974b7f27d 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -82,6 +82,7 @@ extern unsigned int sysctl_preemptoff_tracing_threshold_ns; #endif #if defined(CONFIG_PREEMPTIRQ_EVENTS) && defined(CONFIG_IRQSOFF_TRACER) extern unsigned int sysctl_irqsoff_tracing_threshold_ns; +extern unsigned int sysctl_irqsoff_dmesg_output_enabled; #endif enum sched_tunable_scaling { diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 45380ac22a51..4deb2310c63b 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -141,6 +141,8 @@ static int ten_thousand = 10000; #ifdef CONFIG_PERF_EVENTS static int six_hundred_forty_kb = 640 * 1024; #endif +static unsigned int __maybe_unused half_million = 500000; +static unsigned int __maybe_unused one_hundred_million = 100000000; #ifdef CONFIG_SCHED_WALT static int neg_three = -3; static int three = 3; @@ -355,6 +357,15 @@ static struct ctl_table kern_table[] = { .data = &sysctl_irqsoff_tracing_threshold_ns, .maxlen = sizeof(unsigned int), .mode = 0644, + .proc_handler = proc_douintvec_minmax, + .extra1 = &half_million, + .extra2 = &one_hundred_million, + }, + { + .procname = "irqsoff_dmesg_output_enabled", + .data = &sysctl_irqsoff_dmesg_output_enabled, + .maxlen = sizeof(unsigned int), + .mode = 0644, .proc_handler = proc_dointvec, }, #endif diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index bd251354be5d..46b6b1ae6257 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -608,11 +608,16 @@ static void irqsoff_tracer_stop(struct trace_array *tr) #ifdef CONFIG_IRQSOFF_TRACER #ifdef CONFIG_PREEMPTIRQ_EVENTS +#define IRQSOFF_SENTINEL 0x0fffDEAD /* * irqsoff stack tracing threshold in ns. - * default: 1ms + * default: 5ms */ -unsigned int sysctl_irqsoff_tracing_threshold_ns = 1000000UL; +unsigned int sysctl_irqsoff_tracing_threshold_ns = 5000000UL; +/* + * Enable irqsoff tracing to dmesg + */ +unsigned int sysctl_irqsoff_dmesg_output_enabled; struct irqsoff_store { u64 ts; @@ -637,9 +642,14 @@ void tracer_hardirqs_on(unsigned long a0, unsigned long a1) delta = sched_clock() - is->ts; if (!is_idle_task(current) && - delta > sysctl_irqsoff_tracing_threshold_ns) + delta > sysctl_irqsoff_tracing_threshold_ns) { trace_irqs_disable(delta, is->caddr[0], is->caddr[1], is->caddr[2], is->caddr[3]); + if (sysctl_irqsoff_dmesg_output_enabled == IRQSOFF_SENTINEL) + printk_deferred(KERN_ERR "D=%llu C:(%ps<-%ps<-%ps<-%ps)\n", + delta, is->caddr[0], is->caddr[1], + is->caddr[2], is->caddr[3]); + } is->ts = 0; lockdep_on(); #endif /* CONFIG_PREEMPTIRQ_EVENTS */