linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Anna-Maria Gleixner <anna-maria@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	keescook@chromium.org, Christoph Hellwig <hch@lst.de>,
	John Stultz <john.stultz@linaro.org>,
	Anna-Maria Gleixner <anna-maria@linutronix.de>
Subject: [PATCH v4 01/36] timers: Use static keys for migrate_enable/nohz_active
Date: Thu, 21 Dec 2017 11:41:30 +0100	[thread overview]
Message-ID: <20171221104205.7269-2-anna-maria@linutronix.de> (raw)
In-Reply-To: <20171221104205.7269-1-anna-maria@linutronix.de>

From: Thomas Gleixner <tglx@linutronix.de>

The members migrate_enable and nohz_active in the timer/hrtimer per CPU
bases have been introduced to avoid accessing global variables for these
decisions.

Still that results in a (cache hot) load and conditional branch, which can
be avoided by using static keys.

Implement it with static keys and optimize for the most critical case of
high performance networking which tends to disable the timer migration
functionality.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
---
 include/linux/hrtimer.h     |  4 --
 kernel/time/hrtimer.c       | 17 +++------
 kernel/time/tick-internal.h | 19 ++++++----
 kernel/time/tick-sched.c    |  2 +-
 kernel/time/timer.c         | 91 +++++++++++++++++++++++----------------------
 5 files changed, 65 insertions(+), 68 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 012c37fdb688..79b2a8d29d8c 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -153,8 +153,6 @@ enum  hrtimer_base_type {
  * @cpu:		cpu number
  * @active_bases:	Bitfield to mark bases with active timers
  * @clock_was_set_seq:	Sequence counter of clock was set events
- * @migration_enabled:	The migration of hrtimers to other cpus is enabled
- * @nohz_active:	The nohz functionality is enabled
  * @expires_next:	absolute time of the next event which was scheduled
  *			via clock_set_next_event()
  * @next_timer:		Pointer to the first expiring timer
@@ -178,8 +176,6 @@ struct hrtimer_cpu_base {
 	unsigned int			cpu;
 	unsigned int			active_bases;
 	unsigned int			clock_was_set_seq;
-	bool				migration_enabled;
-	bool				nohz_active;
 #ifdef CONFIG_HIGH_RES_TIMERS
 	unsigned int			in_hrtirq	: 1,
 					hres_active	: 1,
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index d32520840fde..69d203d8b12d 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -178,23 +178,16 @@ hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base)
 #endif
 }
 
-#ifdef CONFIG_NO_HZ_COMMON
-static inline
-struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base,
-					 int pinned)
-{
-	if (pinned || !base->migration_enabled)
-		return base;
-	return &per_cpu(hrtimer_bases, get_nohz_timer_target());
-}
-#else
 static inline
 struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base,
 					 int pinned)
 {
+#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
+	if (static_branch_unlikely(&timers_migration_enabled) && !pinned)
+		return &per_cpu(hrtimer_bases, get_nohz_timer_target());
+#endif
 	return base;
 }
-#endif
 
 /*
  * We switch the timer base to a power-optimized selected CPU target,
@@ -969,7 +962,7 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
 		 * Kick to reschedule the next tick to handle the new timer
 		 * on dynticks target.
 		 */
-		if (new_base->cpu_base->nohz_active)
+		if (is_timers_nohz_active())
 			wake_up_nohz_cpu(new_base->cpu_base->cpu);
 	} else {
 		hrtimer_reprogram(timer, new_base);
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index f8e1845aa464..4ac74dff59f0 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -150,14 +150,19 @@ static inline void tick_nohz_init(void) { }
 
 #ifdef CONFIG_NO_HZ_COMMON
 extern unsigned long tick_nohz_active;
-#else
+extern void timers_update_nohz(void);
+extern struct static_key_false timers_nohz_active;
+static inline bool is_timers_nohz_active(void)
+{
+	return static_branch_unlikely(&timers_nohz_active);
+}
+# ifdef CONFIG_SMP
+extern struct static_key_false timers_migration_enabled;
+# endif
+#else /* CONFIG_NO_HZ_COMMON */
+static inline void timers_update_nohz(void) { }
 #define tick_nohz_active (0)
-#endif
-
-#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
-extern void timers_update_migration(bool update_nohz);
-#else
-static inline void timers_update_migration(bool update_nohz) { }
+static inline bool is_timers_nohz_active(void) { return false; }
 #endif
 
 DECLARE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 99578f06c8d4..f371f25f3510 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -1079,7 +1079,7 @@ static inline void tick_nohz_activate(struct tick_sched *ts, int mode)
 	ts->nohz_mode = mode;
 	/* One update is enough */
 	if (!test_and_set_bit(0, &tick_nohz_active))
-		timers_update_migration(true);
+		timers_update_nohz();
 }
 
 /**
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index ffebcf878fba..1e2140a23044 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -200,8 +200,6 @@ struct timer_base {
 	unsigned long		clk;
 	unsigned long		next_expiry;
 	unsigned int		cpu;
-	bool			migration_enabled;
-	bool			nohz_active;
 	bool			is_idle;
 	bool			must_forward_clk;
 	DECLARE_BITMAP(pending_map, WHEEL_SIZE);
@@ -210,45 +208,59 @@ struct timer_base {
 
 static DEFINE_PER_CPU(struct timer_base, timer_bases[NR_BASES]);
 
-#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
+#ifdef CONFIG_NO_HZ_COMMON
+
+DEFINE_STATIC_KEY_FALSE(timers_nohz_active);
+static DEFINE_MUTEX(timer_keys_mutex);
+
+static void timer_update_keys(struct work_struct *work);
+static DECLARE_WORK(timer_update_work, timer_update_keys);
+
+#ifdef CONFIG_SMP
 unsigned int sysctl_timer_migration = 1;
 
-void timers_update_migration(bool update_nohz)
+DEFINE_STATIC_KEY_FALSE(timers_migration_enabled);
+
+static void timers_update_migration(void)
 {
 	bool on = sysctl_timer_migration && tick_nohz_active;
-	unsigned int cpu;
 
-	/* Avoid the loop, if nothing to update */
-	if (this_cpu_read(timer_bases[BASE_STD].migration_enabled) == on)
-		return;
+	if (on)
+		static_branch_enable(&timers_migration_enabled);
+	else
+		static_branch_disable(&timers_migration_enabled);
+}
+#else
+static inline void timers_update_migration(void) { }
+#endif /* !CONFIG_SMP */
 
-	for_each_possible_cpu(cpu) {
-		per_cpu(timer_bases[BASE_STD].migration_enabled, cpu) = on;
-		per_cpu(timer_bases[BASE_DEF].migration_enabled, cpu) = on;
-		per_cpu(hrtimer_bases.migration_enabled, cpu) = on;
-		if (!update_nohz)
-			continue;
-		per_cpu(timer_bases[BASE_STD].nohz_active, cpu) = true;
-		per_cpu(timer_bases[BASE_DEF].nohz_active, cpu) = true;
-		per_cpu(hrtimer_bases.nohz_active, cpu) = true;
-	}
+static void timer_update_keys(struct work_struct *work)
+{
+	mutex_lock(&timer_keys_mutex);
+	timers_update_migration();
+	static_branch_enable(&timers_nohz_active);
+	mutex_unlock(&timer_keys_mutex);
+}
+
+void timers_update_nohz(void)
+{
+	schedule_work(&timer_update_work);
 }
 
 int timer_migration_handler(struct ctl_table *table, int write,
 			    void __user *buffer, size_t *lenp,
 			    loff_t *ppos)
 {
-	static DEFINE_MUTEX(mutex);
 	int ret;
 
-	mutex_lock(&mutex);
+	mutex_lock(&timer_keys_mutex);
 	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
 	if (!ret && write)
-		timers_update_migration(false);
-	mutex_unlock(&mutex);
+		timers_update_migration();
+	mutex_unlock(&timer_keys_mutex);
 	return ret;
 }
-#endif
+#endif /* NO_HZ_COMMON */
 
 static unsigned long round_jiffies_common(unsigned long j, int cpu,
 		bool force_up)
@@ -534,7 +546,7 @@ __internal_add_timer(struct timer_base *base, struct timer_list *timer)
 static void
 trigger_dyntick_cpu(struct timer_base *base, struct timer_list *timer)
 {
-	if (!IS_ENABLED(CONFIG_NO_HZ_COMMON) || !base->nohz_active)
+	if (!is_timers_nohz_active())
 		return;
 
 	/*
@@ -826,7 +838,7 @@ static inline struct timer_base *get_timer_cpu_base(u32 tflags, u32 cpu)
 	 * If the timer is deferrable and nohz is active then we need to use
 	 * the deferrable base.
 	 */
-	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active &&
+	if (is_timers_nohz_active() &&
 	    (tflags & TIMER_DEFERRABLE))
 		base = per_cpu_ptr(&timer_bases[BASE_DEF], cpu);
 	return base;
@@ -840,7 +852,7 @@ static inline struct timer_base *get_timer_this_cpu_base(u32 tflags)
 	 * If the timer is deferrable and nohz is active then we need to use
 	 * the deferrable base.
 	 */
-	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active &&
+	if (is_timers_nohz_active() &&
 	    (tflags & TIMER_DEFERRABLE))
 		base = this_cpu_ptr(&timer_bases[BASE_DEF]);
 	return base;
@@ -851,21 +863,20 @@ static inline struct timer_base *get_timer_base(u32 tflags)
 	return get_timer_cpu_base(tflags, tflags & TIMER_CPUMASK);
 }
 
-#ifdef CONFIG_NO_HZ_COMMON
 static inline struct timer_base *
 get_target_base(struct timer_base *base, unsigned tflags)
 {
-#ifdef CONFIG_SMP
-	if ((tflags & TIMER_PINNED) || !base->migration_enabled)
-		return get_timer_this_cpu_base(tflags);
-	return get_timer_cpu_base(tflags, get_nohz_timer_target());
-#else
-	return get_timer_this_cpu_base(tflags);
+#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
+	if (static_branch_unlikely(&timers_migration_enabled) &&
+	    !(tflags & TIMER_PINNED))
+		return get_timer_cpu_base(tflags, get_nohz_timer_target());
 #endif
+	return get_timer_this_cpu_base(tflags);
 }
 
 static inline void forward_timer_base(struct timer_base *base)
 {
+#ifdef CONFIG_NO_HZ_COMMON
 	unsigned long jnow;
 
 	/*
@@ -889,16 +900,8 @@ static inline void forward_timer_base(struct timer_base *base)
 		base->clk = jnow;
 	else
 		base->clk = base->next_expiry;
-}
-#else
-static inline struct timer_base *
-get_target_base(struct timer_base *base, unsigned tflags)
-{
-	return get_timer_this_cpu_base(tflags);
-}
-
-static inline void forward_timer_base(struct timer_base *base) { }
 #endif
+}
 
 
 /*
@@ -1684,7 +1687,7 @@ static __latent_entropy void run_timer_softirq(struct softirq_action *h)
 	base->must_forward_clk = false;
 
 	__run_timers(base);
-	if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active)
+	if (is_timers_nohz_active())
 		__run_timers(this_cpu_ptr(&timer_bases[BASE_DEF]));
 }
 
@@ -1698,7 +1701,7 @@ void run_local_timers(void)
 	hrtimer_run_queues();
 	/* Raise the softirq only if required. */
 	if (time_before(jiffies, base->clk)) {
-		if (!IS_ENABLED(CONFIG_NO_HZ_COMMON) || !base->nohz_active)
+		if (!is_timers_nohz_active())
 			return;
 		/* CPU is awake, so check the deferrable base. */
 		base++;
-- 
2.11.0

  reply	other threads:[~2017-12-21 10:47 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-21 10:41 [PATCH v4 00/36] hrtimer: Provide softirq context hrtimers Anna-Maria Gleixner
2017-12-21 10:41 ` Anna-Maria Gleixner [this message]
2017-12-22 15:45   ` [PATCH v5 01/36] timers: Use static keys for migrate_enable/nohz_active Sebastian Andrzej Siewior
2018-01-14 22:13     ` Thomas Gleixner
2018-01-14 22:30       ` [PATCH v6 " Thomas Gleixner
2018-01-11  4:25   ` [PATCH v4 " Frederic Weisbecker
2018-01-16  3:40   ` [tip:timers/core] hrtimer: Optimize the hrtimer code by using static keys for migration_enable/nohz_active tip-bot for Thomas Gleixner
2017-12-21 10:41 ` [PATCH v4 02/36] hrtimer: Correct blantanly wrong comment Anna-Maria Gleixner
2018-01-11 18:28   ` Frederic Weisbecker
2018-01-16  1:02   ` Ingo Molnar
2018-01-16  3:40   ` [tip:timers/core] hrtimer: Correct blatantly incorrect comment tip-bot for Thomas Gleixner
2017-12-21 10:41 ` [PATCH v4 03/36] hrtimer: Fix kerneldoc for struct hrtimer_cpu_base Anna-Maria Gleixner
2018-01-16  3:41   ` [tip:timers/core] hrtimer: Fix kerneldoc syntax for 'struct hrtimer_cpu_base' tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 04/36] hrtimer: Cleanup clock argument in schedule_hrtimeout_range_clock() Anna-Maria Gleixner
2018-01-16  3:41   ` [tip:timers/core] hrtimer: Clean up the 'int clock' parameter of schedule_hrtimeout_range_clock() tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 05/36] hrtimer: Fix hrtimer function description Anna-Maria Gleixner
2018-01-16  3:42   ` [tip:timers/core] hrtimer: Fix hrtimer_start[_range_ns]() function descriptions tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 06/36] hrtimer: Ensure POSIX compliance (relative CLOCK_REALTIME hrtimers) Anna-Maria Gleixner
2018-01-16  3:42   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 07/36] hrtimer: Cleanup hrtimer_mode enum Anna-Maria Gleixner
2018-01-16  3:43   ` [tip:timers/core] hrtimer: Clean up 'enum hrtimer_mode' tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 08/36] tracing/hrtimer: Take all clock bases and modes into account Anna-Maria Gleixner
2018-01-16  3:43   ` [tip:timers/core] tracing/hrtimer: Fix tracing bugs by taking " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 09/36] tracing/hrtimer: Print hrtimer mode in hrtimer_start tracepoint Anna-Maria Gleixner
2018-01-16  3:43   ` [tip:timers/core] tracing/hrtimer: Print the hrtimer mode in the 'hrtimer_start' tracepoint tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 10/36] hrtimer: Switch for loop to _ffs() evaluation Anna-Maria Gleixner
2018-01-16  3:44   ` [tip:timers/core] hrtimer: Switch 'for' " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 11/36] hrtimer: Store running timer in hrtimer_clock_base Anna-Maria Gleixner
2018-01-16  3:44   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 12/36] hrtimer: Make room in struct hrtimer_cpu_base Anna-Maria Gleixner
2018-01-16  3:45   ` [tip:timers/core] hrtimer: Make room in 'struct hrtimer_cpu_base' tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 13/36] hrtimer: Reduce conditional code (hres_active) Anna-Maria Gleixner
2018-01-16  3:45   ` [tip:timers/core] hrtimer: Make the hrtimer_cpu_base::hres_active field unconditional, to simplify the code tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 14/36] hrtimer: Use accesor functions instead of direct access Anna-Maria Gleixner
2018-01-16  3:46   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 15/36] hrtimer: Make the remote enqueue check unconditional Anna-Maria Gleixner
2018-01-16  3:46   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 16/36] hrtimer: Make hrtimer_cpu_base.next_timer handling unconditional Anna-Maria Gleixner
2018-01-16  3:46   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 17/36] hrtimer: Make hrtimer_reprogramm() unconditional Anna-Maria Gleixner
2018-01-16  3:47   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 18/36] hrtimer: Make hrtimer_force_reprogramm() unconditionally available Anna-Maria Gleixner
2018-01-16  3:47   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 19/36] hrtimer: Unify handling of hrtimer remove Anna-Maria Gleixner
2018-01-16  3:48   ` [tip:timers/core] hrtimer: Unify hrtimer removal handling tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 20/36] hrtimer: Unify handling of remote enqueue Anna-Maria Gleixner
2018-01-16  3:48   ` [tip:timers/core] hrtimer: Unify remote enqueue handling tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 21/36] hrtimer: Make remote enqueue decision less restrictive Anna-Maria Gleixner
2018-01-16  3:49   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 22/36] hrtimer: Remove base argument from hrtimer_reprogram() Anna-Maria Gleixner
2018-01-16  3:49   ` [tip:timers/core] hrtimer: Remove the 'base' parameter " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 23/36] hrtimer: Split hrtimer_start_range_ns() Anna-Maria Gleixner
2018-01-16  3:49   ` [tip:timers/core] hrtimer: Factor out __hrtimer_start_range_ns() tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 24/36] hrtimer: Split __hrtimer_get_next_event() Anna-Maria Gleixner
2018-01-16  3:50   ` [tip:timers/core] hrtimer: Factor out __hrtimer_next_event_base() tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 25/36] hrtimer: Use irqsave/irqrestore around __run_hrtimer() Anna-Maria Gleixner
2018-01-16  3:50   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 26/36] hrtimer: Add clock bases and hrtimer mode for soft irq context Anna-Maria Gleixner
2018-01-16  3:51   ` [tip:timers/core] hrtimer: Add clock bases and hrtimer mode for softirq context tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 27/36] hrtimer: Prepare handling of hard and softirq based hrtimers Anna-Maria Gleixner
2018-01-16  3:51   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 28/36] hrtimer: Implement support for " Anna-Maria Gleixner
2018-01-16 10:22   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 29/36] hrtimer: Implement SOFT/HARD clock base selection Anna-Maria Gleixner
2018-01-16 10:22   ` [tip:timers/core] " tip-bot for Anna-Maria Gleixner
2017-12-21 10:41 ` [PATCH v4 30/36] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer Anna-Maria Gleixner
2017-12-21 10:42 ` [PATCH v4 31/36] mac80211_hwsim: Replace hrtimer tasklet with softirq hrtimer Anna-Maria Gleixner
2018-01-04 15:12   ` Johannes Berg
2018-01-04 15:18     ` Thomas Gleixner
2017-12-21 10:42 ` [PATCH v4 32/36] xfrm: " Anna-Maria Gleixner
2017-12-21 10:42 ` [PATCH v4 33/36] softirq: Remove tasklet_hrtimer Anna-Maria Gleixner
2017-12-21 10:42 ` [PATCH v4 34/36] ALSA/dummy: Replace tasklet with softirq hrtimer Anna-Maria Gleixner
2018-01-16 10:23   ` [tip:timers/core] " tip-bot for Thomas Gleixner
2017-12-21 10:42 ` [PATCH v4 35/36] usb/gadget/NCM: " Anna-Maria Gleixner
2018-01-16 10:23   ` [tip:timers/core] " tip-bot for Thomas Gleixner
2017-12-21 10:42 ` [PATCH v4 36/36] net/mvpp2: " Anna-Maria Gleixner
2018-01-16  1:39 ` [PATCH v4 00/36] hrtimer: Provide softirq context hrtimers Ingo Molnar
2018-01-16  2:03   ` Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171221104205.7269-2-anna-maria@linutronix.de \
    --to=anna-maria@linutronix.de \
    --cc=hch@lst.de \
    --cc=john.stultz@linaro.org \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).