From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.linutronix.de (146.0.238.70:993) by crypto-ml.lab.linutronix.de with IMAP4-SSL for ; 12 Jan 2019 01:39:08 -0000 Received: from mga18.intel.com ([134.134.136.126]) by Galois.linutronix.de with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1gi87V-0002Kj-VY for speck@linutronix.de; Sat, 12 Jan 2019 02:29:54 +0100 From: Andi Kleen Subject: [MODERATED] [PATCH v4 19/28] MDSv4 14 Date: Fri, 11 Jan 2019 17:29:32 -0800 Message-Id: In-Reply-To: References: In-Reply-To: References: Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit MIME-Version: 1.0 To: speck@linutronix.de Cc: Andi Kleen List-ID: By default we assume tasklets might touch user data and schedule a cpu clear on next kernel exit. Add new interfaces to allow audited tasklets to opt-out. Signed-off-by: Andi Kleen --- include/linux/interrupt.h | 16 +++++++++++++++- kernel/softirq.c | 25 +++++++++++++++++++------ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 291b7fee3afe..81b852fb5ecf 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -571,11 +571,22 @@ struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data } #define DECLARE_TASKLET_DISABLED(name, func, data) \ struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data } +#define DECLARE_TASKLET_NOUSER(name, func, data) \ +struct tasklet_struct name = { NULL, TASKLET_NO_USER, ATOMIC_INIT(0), func, data } + +#define DECLARE_TASKLET_DISABLED_NOUSER(name, func, data) \ +struct tasklet_struct name = { NULL, TASKLET_NO_USER, ATOMIC_INIT(1), func, data } enum { TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */ - TASKLET_STATE_RUN /* Tasklet is running (SMP only) */ + TASKLET_STATE_RUN, /* Tasklet is running (SMP only) */ + + /* + * Set this flag when the tasklet is known to not touch user data, + * so doesn't need extra CPU state clearing. + */ + TASKLET_NO_USER = 1 << 5, }; #ifdef CONFIG_SMP @@ -639,6 +650,9 @@ extern void tasklet_kill(struct tasklet_struct *t); extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu); extern void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); +extern void tasklet_init_flags(struct tasklet_struct *t, + void (*func)(unsigned long), unsigned long data, + unsigned flags); struct tasklet_hrtimer { struct hrtimer timer; diff --git a/kernel/softirq.c b/kernel/softirq.c index d28813306b2c..fdd4e3be3db7 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -26,6 +26,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -522,6 +523,8 @@ static void tasklet_action_common(struct softirq_action *a, BUG(); t->func(t->data); tasklet_unlock(t); + if (!(t->state & TASKLET_NO_USER)) + lazy_clear_cpu(); continue; } tasklet_unlock(t); @@ -546,15 +549,23 @@ static __latent_entropy void tasklet_hi_action(struct softirq_action *a) tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ); } -void tasklet_init(struct tasklet_struct *t, - void (*func)(unsigned long), unsigned long data) +void tasklet_init_flags(struct tasklet_struct *t, + void (*func)(unsigned long), unsigned long data, + unsigned flags) { t->next = NULL; - t->state = 0; + t->state = flags; atomic_set(&t->count, 0); t->func = func; t->data = data; } +EXPORT_SYMBOL(tasklet_init_flags); + +void tasklet_init(struct tasklet_struct *t, + void (*func)(unsigned long), unsigned long data) +{ + tasklet_init_flags(t, func, data, 0); +} EXPORT_SYMBOL(tasklet_init); void tasklet_kill(struct tasklet_struct *t) @@ -609,7 +620,8 @@ static void __tasklet_hrtimer_trampoline(unsigned long data) * @ttimer: tasklet_hrtimer which is initialized * @function: hrtimer callback function which gets called from softirq context * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME) - * @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL) + * @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL), + * HRTIMER_MODE_NO_USER */ void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer, enum hrtimer_restart (*function)(struct hrtimer *), @@ -617,8 +629,9 @@ void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer, { hrtimer_init(&ttimer->timer, which_clock, mode); ttimer->timer.function = __hrtimer_tasklet_trampoline; - tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline, - (unsigned long)ttimer); + tasklet_init_flags(&ttimer->tasklet, __tasklet_hrtimer_trampoline, + (unsigned long)ttimer, + (mode & HRTIMER_MODE_NO_USER) ? TASKLET_NO_USER : 0); ttimer->function = function; } EXPORT_SYMBOL_GPL(tasklet_hrtimer_init); -- 2.17.2