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 ; 24 Feb 2019 15:11:38 -0000 Received: from mga02.intel.com ([134.134.136.20]) by Galois.linutronix.de with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1gxvO0-0001Tj-At for speck@linutronix.de; Sun, 24 Feb 2019 16:08:13 +0100 From: Andi Kleen Subject: [MODERATED] [PATCH v6 19/43] MDSv6 Date: Sun, 24 Feb 2019 07:07:25 -0800 Message-Id: In-Reply-To: References: In-Reply-To: References: To: speck@linutronix.de Cc: Andi Kleen List-ID: From: Andi Kleen Subject: mds: Support cpu clear after tasklets tasklets run asynchronously to user processes. Most tasklets don't touch user data, but some do. Add a per tasklet flag to request CPU clearing after the tasklet executes. Later patches will use this to mark tasklets that need it. 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 0f8ddb7ba09b..df795f2f5f34 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -572,11 +572,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_USERDATA(name, func, data) \ +struct tasklet_struct name = { NULL, TASKLET_USER_DATA, ATOMIC_INIT(0), func, data } + +#define DECLARE_TASKLET_USERDATA_DISABLED(name, func, data) \ +struct tasklet_struct name = { NULL, TASKLET_USER_DATA, 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 touch user data, + * so needs extra CPU state clearing. + */ + TASKLET_USER_DATA = 1 << 5, }; #ifdef CONFIG_SMP @@ -640,6 +651,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..b2d348cc8b2e 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_USER_DATA) + 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_USER_DATA) ? TASKLET_USER_DATA : 0); ttimer->function = function; } EXPORT_SYMBOL_GPL(tasklet_hrtimer_init); -- 2.17.2