All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] entry: inline syscall enter/exit functions
@ 2023-12-05 13:30 Sven Schnelle
  2023-12-05 13:30 ` [PATCH 1/3] entry: move exit to usermode functions to header file Sven Schnelle
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Sven Schnelle @ 2023-12-05 13:30 UTC (permalink / raw)
  To: Thomas Gleixner, Peter Zijlstra, Andy Lutomirski
  Cc: linux-kernel, Heiko Carstens

Hi List,

looking into the performance of syscall entry/exit after s390 switched
to generic entry showed that there's quite some overhead calling some
of the entry/exit work functions even when there's nothing to do.
This patchset moves the entry and exit function to entry-common.h, so
non inlined code gets only called when there is some work pending.

I wrote a small program that just issues invalid syscalls in a loop.
On an s390 machine, this results in the following numbers:

without this series:

# ./syscall 1000000000
runtime: 94.886581s / per-syscall 9.488658e-08s

with this series:

./syscall 1000000000
runtime: 84.732391s / per-syscall 8.473239e-08s

so the time required for one syscall dropped from 94.8ns to
84.7ns, which is a drop of about 11%.

Sven Schnelle (3):
  entry: move exit to usermode functions to header file
  move enter_from_user_mode() to header file
  entry: move syscall_enter_from_user_mode() to header file

 include/linux/entry-common.h | 137 ++++++++++++++++++++++++++++++++-
 kernel/entry/common.c        | 145 ++---------------------------------
 2 files changed, 138 insertions(+), 144 deletions(-)

-- 
2.40.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] entry: move exit to usermode functions to header file
  2023-12-05 13:30 [PATCH 0/3] entry: inline syscall enter/exit functions Sven Schnelle
@ 2023-12-05 13:30 ` Sven Schnelle
  2023-12-15 19:09   ` Thomas Gleixner
  2023-12-05 13:30 ` [PATCH 2/3] move enter_from_user_mode() " Sven Schnelle
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Sven Schnelle @ 2023-12-05 13:30 UTC (permalink / raw)
  To: Thomas Gleixner, Peter Zijlstra, Andy Lutomirski
  Cc: linux-kernel, Heiko Carstens

To allow inlining, move exit_to_user_mode() and
exit_to_user_mode_loop() to common.h.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
---
 include/linux/entry-common.h | 95 +++++++++++++++++++++++++++++++++++-
 kernel/entry/common.c        | 89 +--------------------------------
 2 files changed, 96 insertions(+), 88 deletions(-)

diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
index d95ab85f96ba..f0f1a26dc638 100644
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -7,6 +7,10 @@
 #include <linux/syscalls.h>
 #include <linux/seccomp.h>
 #include <linux/sched.h>
+#include <linux/context_tracking.h>
+#include <linux/livepatch.h>
+#include <linux/resume_user_mode.h>
+#include <linux/tick.h>
 
 #include <asm/entry-common.h>
 
@@ -258,6 +262,85 @@ static __always_inline void arch_exit_to_user_mode(void) { }
  */
 void arch_do_signal_or_restart(struct pt_regs *regs);
 
+/**
+ * exit_to_user_mode_loop - do any pending work before leaving to user space
+ */
+static __always_inline unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
+							    unsigned long ti_work)
+{
+	/*
+	 * Before returning to user space ensure that all pending work
+	 * items have been completed.
+	 */
+	while (ti_work & EXIT_TO_USER_MODE_WORK) {
+
+		local_irq_enable_exit_to_user(ti_work);
+
+		if (ti_work & _TIF_NEED_RESCHED)
+			schedule();
+
+		if (ti_work & _TIF_UPROBE)
+			uprobe_notify_resume(regs);
+
+		if (ti_work & _TIF_PATCH_PENDING)
+			klp_update_patch_state(current);
+
+		if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
+			arch_do_signal_or_restart(regs);
+
+		if (ti_work & _TIF_NOTIFY_RESUME)
+			resume_user_mode_work(regs);
+
+		/* Architecture specific TIF work */
+		arch_exit_to_user_mode_work(regs, ti_work);
+
+		/*
+		 * Disable interrupts and reevaluate the work flags as they
+		 * might have changed while interrupts and preemption was
+		 * enabled above.
+		 */
+		local_irq_disable_exit_to_user();
+
+		/* Check if any of the above work has queued a deferred wakeup */
+		tick_nohz_user_enter_prepare();
+
+		ti_work = read_thread_flags();
+	}
+
+	/* Return the latest work state for arch_exit_to_user_mode() */
+	return ti_work;
+}
+
+/**
+ * exit_to_user_mode_prepare - call exit_to_user_mode_loop() if required
+ *
+ * 1) check that interrupts are disabled
+ * 2) call tick_nohz_user_enter_prepare()
+ * 3) call exit_to_user_mode_loop() if any flags from
+ *    EXIT_TO_USER_MODE_WORK are set
+ * 4) check that interrupts are still disabled
+ */
+static __always_inline void exit_to_user_mode_prepare(struct pt_regs *regs)
+{
+	unsigned long ti_work;
+
+	lockdep_assert_irqs_disabled();
+
+	/* Flush pending rcuog wakeup before the last need_resched() check */
+	tick_nohz_user_enter_prepare();
+
+	ti_work = read_thread_flags();
+	if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
+		ti_work = exit_to_user_mode_loop(regs, ti_work);
+
+	arch_exit_to_user_mode_prepare(regs, ti_work);
+
+	/* Ensure that kernel state is sane for a return to userspace */
+	kmap_assert_nomap();
+	lockdep_assert_irqs_disabled();
+	lockdep_sys_exit();
+}
+
 /**
  * exit_to_user_mode - Fixup state when exiting to user mode
  *
@@ -276,7 +359,17 @@ void arch_do_signal_or_restart(struct pt_regs *regs);
  * non-instrumentable.
  * The caller has to invoke syscall_exit_to_user_mode_work() before this.
  */
-void exit_to_user_mode(void);
+static __always_inline void exit_to_user_mode(void)
+{
+	instrumentation_begin();
+	trace_hardirqs_on_prepare();
+	lockdep_hardirqs_on_prepare();
+	instrumentation_end();
+
+	user_enter_irqoff();
+	arch_exit_to_user_mode();
+	lockdep_hardirqs_on(CALLER_ADDR0);
+}
 
 /**
  * syscall_exit_to_user_mode_work - Handle work before returning to user mode
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index d7ee4bc3f2ba..6ba2bcfbe32c 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -123,94 +123,9 @@ noinstr void syscall_enter_from_user_mode_prepare(struct pt_regs *regs)
 	instrumentation_end();
 }
 
-/* See comment for exit_to_user_mode() in entry-common.h */
-static __always_inline void __exit_to_user_mode(void)
-{
-	instrumentation_begin();
-	trace_hardirqs_on_prepare();
-	lockdep_hardirqs_on_prepare();
-	instrumentation_end();
-
-	user_enter_irqoff();
-	arch_exit_to_user_mode();
-	lockdep_hardirqs_on(CALLER_ADDR0);
-}
-
-void noinstr exit_to_user_mode(void)
-{
-	__exit_to_user_mode();
-}
-
 /* Workaround to allow gradual conversion of architecture code */
 void __weak arch_do_signal_or_restart(struct pt_regs *regs) { }
 
-static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
-					    unsigned long ti_work)
-{
-	/*
-	 * Before returning to user space ensure that all pending work
-	 * items have been completed.
-	 */
-	while (ti_work & EXIT_TO_USER_MODE_WORK) {
-
-		local_irq_enable_exit_to_user(ti_work);
-
-		if (ti_work & _TIF_NEED_RESCHED)
-			schedule();
-
-		if (ti_work & _TIF_UPROBE)
-			uprobe_notify_resume(regs);
-
-		if (ti_work & _TIF_PATCH_PENDING)
-			klp_update_patch_state(current);
-
-		if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
-			arch_do_signal_or_restart(regs);
-
-		if (ti_work & _TIF_NOTIFY_RESUME)
-			resume_user_mode_work(regs);
-
-		/* Architecture specific TIF work */
-		arch_exit_to_user_mode_work(regs, ti_work);
-
-		/*
-		 * Disable interrupts and reevaluate the work flags as they
-		 * might have changed while interrupts and preemption was
-		 * enabled above.
-		 */
-		local_irq_disable_exit_to_user();
-
-		/* Check if any of the above work has queued a deferred wakeup */
-		tick_nohz_user_enter_prepare();
-
-		ti_work = read_thread_flags();
-	}
-
-	/* Return the latest work state for arch_exit_to_user_mode() */
-	return ti_work;
-}
-
-static void exit_to_user_mode_prepare(struct pt_regs *regs)
-{
-	unsigned long ti_work;
-
-	lockdep_assert_irqs_disabled();
-
-	/* Flush pending rcuog wakeup before the last need_resched() check */
-	tick_nohz_user_enter_prepare();
-
-	ti_work = read_thread_flags();
-	if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
-		ti_work = exit_to_user_mode_loop(regs, ti_work);
-
-	arch_exit_to_user_mode_prepare(regs, ti_work);
-
-	/* Ensure that kernel state is sane for a return to userspace */
-	kmap_assert_nomap();
-	lockdep_assert_irqs_disabled();
-	lockdep_sys_exit();
-}
-
 /*
  * If SYSCALL_EMU is set, then the only reason to report is when
  * SINGLESTEP is set (i.e. PTRACE_SYSEMU_SINGLESTEP).  This syscall
@@ -295,7 +210,7 @@ __visible noinstr void syscall_exit_to_user_mode(struct pt_regs *regs)
 	instrumentation_begin();
 	__syscall_exit_to_user_mode_work(regs);
 	instrumentation_end();
-	__exit_to_user_mode();
+	exit_to_user_mode();
 }
 
 noinstr void irqentry_enter_from_user_mode(struct pt_regs *regs)
@@ -308,7 +223,7 @@ noinstr void irqentry_exit_to_user_mode(struct pt_regs *regs)
 	instrumentation_begin();
 	exit_to_user_mode_prepare(regs);
 	instrumentation_end();
-	__exit_to_user_mode();
+	exit_to_user_mode();
 }
 
 noinstr irqentry_state_t irqentry_enter(struct pt_regs *regs)
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] move enter_from_user_mode() to header file
  2023-12-05 13:30 [PATCH 0/3] entry: inline syscall enter/exit functions Sven Schnelle
  2023-12-05 13:30 ` [PATCH 1/3] entry: move exit to usermode functions to header file Sven Schnelle
@ 2023-12-05 13:30 ` Sven Schnelle
  2023-12-05 13:30 ` [PATCH 3/3] entry: move syscall_enter_from_user_mode() " Sven Schnelle
  2023-12-06 11:02 ` [PATCH 0/3] entry: inline syscall enter/exit functions Peter Zijlstra
  3 siblings, 0 replies; 10+ messages in thread
From: Sven Schnelle @ 2023-12-05 13:30 UTC (permalink / raw)
  To: Thomas Gleixner, Peter Zijlstra, Andy Lutomirski
  Cc: linux-kernel, Heiko Carstens

To allow inlining of enter_from_user_mode(), move it to common.h.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
---
 include/linux/entry-common.h | 15 ++++++++++++++-
 kernel/entry/common.c        | 26 +++-----------------------
 2 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
index f0f1a26dc638..e2c62d111318 100644
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -11,6 +11,7 @@
 #include <linux/livepatch.h>
 #include <linux/resume_user_mode.h>
 #include <linux/tick.h>
+#include <linux/kmsan.h>
 
 #include <asm/entry-common.h>
 
@@ -102,7 +103,19 @@ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs) {}
  * done between establishing state and enabling interrupts. The caller must
  * enable interrupts before invoking syscall_enter_from_user_mode_work().
  */
-void enter_from_user_mode(struct pt_regs *regs);
+static __always_inline void enter_from_user_mode(struct pt_regs *regs)
+{
+	arch_enter_from_user_mode(regs);
+	lockdep_hardirqs_off(CALLER_ADDR0);
+
+	CT_WARN_ON(__ct_state() != CONTEXT_USER);
+	user_exit_irqoff();
+
+	instrumentation_begin();
+	kmsan_unpoison_entry_regs(regs);
+	trace_hardirqs_off_finish();
+	instrumentation_end();
+}
 
 /**
  * syscall_enter_from_user_mode_prepare - Establish state and enable interrupts
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index 6ba2bcfbe32c..90b995facd7a 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -15,26 +15,6 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
-/* See comment for enter_from_user_mode() in entry-common.h */
-static __always_inline void __enter_from_user_mode(struct pt_regs *regs)
-{
-	arch_enter_from_user_mode(regs);
-	lockdep_hardirqs_off(CALLER_ADDR0);
-
-	CT_WARN_ON(__ct_state() != CONTEXT_USER);
-	user_exit_irqoff();
-
-	instrumentation_begin();
-	kmsan_unpoison_entry_regs(regs);
-	trace_hardirqs_off_finish();
-	instrumentation_end();
-}
-
-void noinstr enter_from_user_mode(struct pt_regs *regs)
-{
-	__enter_from_user_mode(regs);
-}
-
 static inline void syscall_enter_audit(struct pt_regs *regs, long syscall)
 {
 	if (unlikely(audit_context())) {
@@ -105,7 +85,7 @@ noinstr long syscall_enter_from_user_mode(struct pt_regs *regs, long syscall)
 {
 	long ret;
 
-	__enter_from_user_mode(regs);
+	enter_from_user_mode(regs);
 
 	instrumentation_begin();
 	local_irq_enable();
@@ -117,7 +97,7 @@ noinstr long syscall_enter_from_user_mode(struct pt_regs *regs, long syscall)
 
 noinstr void syscall_enter_from_user_mode_prepare(struct pt_regs *regs)
 {
-	__enter_from_user_mode(regs);
+	enter_from_user_mode(regs);
 	instrumentation_begin();
 	local_irq_enable();
 	instrumentation_end();
@@ -215,7 +195,7 @@ __visible noinstr void syscall_exit_to_user_mode(struct pt_regs *regs)
 
 noinstr void irqentry_enter_from_user_mode(struct pt_regs *regs)
 {
-	__enter_from_user_mode(regs);
+	enter_from_user_mode(regs);
 }
 
 noinstr void irqentry_exit_to_user_mode(struct pt_regs *regs)
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] entry: move syscall_enter_from_user_mode() to header file
  2023-12-05 13:30 [PATCH 0/3] entry: inline syscall enter/exit functions Sven Schnelle
  2023-12-05 13:30 ` [PATCH 1/3] entry: move exit to usermode functions to header file Sven Schnelle
  2023-12-05 13:30 ` [PATCH 2/3] move enter_from_user_mode() " Sven Schnelle
@ 2023-12-05 13:30 ` Sven Schnelle
  2023-12-06 11:02 ` [PATCH 0/3] entry: inline syscall enter/exit functions Peter Zijlstra
  3 siblings, 0 replies; 10+ messages in thread
From: Sven Schnelle @ 2023-12-05 13:30 UTC (permalink / raw)
  To: Thomas Gleixner, Peter Zijlstra, Andy Lutomirski
  Cc: linux-kernel, Heiko Carstens

To allow inlining of syscall_enter_from_user_mode(), move it
to the entry-common.h header file.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
---
 include/linux/entry-common.h | 27 +++++++++++++++++++++++++--
 kernel/entry/common.c        | 32 +-------------------------------
 2 files changed, 26 insertions(+), 33 deletions(-)

diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
index e2c62d111318..ed26d626d587 100644
--- a/include/linux/entry-common.h
+++ b/include/linux/entry-common.h
@@ -134,6 +134,9 @@ static __always_inline void enter_from_user_mode(struct pt_regs *regs)
  */
 void syscall_enter_from_user_mode_prepare(struct pt_regs *regs);
 
+long syscall_trace_enter(struct pt_regs *regs, long syscall,
+			 unsigned long work);
+
 /**
  * syscall_enter_from_user_mode_work - Check and handle work before invoking
  *				       a syscall
@@ -157,7 +160,15 @@ void syscall_enter_from_user_mode_prepare(struct pt_regs *regs);
  *     ptrace_report_syscall_entry(), __secure_computing(), trace_sys_enter()
  *  2) Invocation of audit_syscall_entry()
  */
-long syscall_enter_from_user_mode_work(struct pt_regs *regs, long syscall);
+static __always_inline long syscall_enter_from_user_mode_work(struct pt_regs *regs, long syscall)
+{
+	unsigned long work = READ_ONCE(current_thread_info()->syscall_work);
+
+	if (work & SYSCALL_WORK_ENTER)
+		syscall = syscall_trace_enter(regs, syscall, work);
+
+	return syscall;
+}
 
 /**
  * syscall_enter_from_user_mode - Establish state and check and handle work
@@ -176,7 +187,19 @@ long syscall_enter_from_user_mode_work(struct pt_regs *regs, long syscall);
  * Returns: The original or a modified syscall number. See
  * syscall_enter_from_user_mode_work() for further explanation.
  */
-long syscall_enter_from_user_mode(struct pt_regs *regs, long syscall);
+static __always_inline long syscall_enter_from_user_mode(struct pt_regs *regs, long syscall)
+{
+	long ret;
+
+	enter_from_user_mode(regs);
+
+	instrumentation_begin();
+	local_irq_enable();
+	ret = syscall_enter_from_user_mode_work(regs, syscall);
+	instrumentation_end();
+
+	return ret;
+}
 
 /**
  * local_irq_enable_exit_to_user - Exit to user variant of local_irq_enable()
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index 90b995facd7a..dde4a9c1f9f3 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -25,7 +25,7 @@ static inline void syscall_enter_audit(struct pt_regs *regs, long syscall)
 	}
 }
 
-static long syscall_trace_enter(struct pt_regs *regs, long syscall,
+long syscall_trace_enter(struct pt_regs *regs, long syscall,
 				unsigned long work)
 {
 	long ret = 0;
@@ -65,36 +65,6 @@ static long syscall_trace_enter(struct pt_regs *regs, long syscall,
 	return ret ? : syscall;
 }
 
-static __always_inline long
-__syscall_enter_from_user_work(struct pt_regs *regs, long syscall)
-{
-	unsigned long work = READ_ONCE(current_thread_info()->syscall_work);
-
-	if (work & SYSCALL_WORK_ENTER)
-		syscall = syscall_trace_enter(regs, syscall, work);
-
-	return syscall;
-}
-
-long syscall_enter_from_user_mode_work(struct pt_regs *regs, long syscall)
-{
-	return __syscall_enter_from_user_work(regs, syscall);
-}
-
-noinstr long syscall_enter_from_user_mode(struct pt_regs *regs, long syscall)
-{
-	long ret;
-
-	enter_from_user_mode(regs);
-
-	instrumentation_begin();
-	local_irq_enable();
-	ret = __syscall_enter_from_user_work(regs, syscall);
-	instrumentation_end();
-
-	return ret;
-}
-
 noinstr void syscall_enter_from_user_mode_prepare(struct pt_regs *regs)
 {
 	enter_from_user_mode(regs);
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] entry: inline syscall enter/exit functions
  2023-12-05 13:30 [PATCH 0/3] entry: inline syscall enter/exit functions Sven Schnelle
                   ` (2 preceding siblings ...)
  2023-12-05 13:30 ` [PATCH 3/3] entry: move syscall_enter_from_user_mode() " Sven Schnelle
@ 2023-12-06 11:02 ` Peter Zijlstra
  2023-12-14  8:24   ` Sven Schnelle
  3 siblings, 1 reply; 10+ messages in thread
From: Peter Zijlstra @ 2023-12-06 11:02 UTC (permalink / raw)
  To: Sven Schnelle
  Cc: Thomas Gleixner, Andy Lutomirski, linux-kernel, Heiko Carstens

On Tue, Dec 05, 2023 at 02:30:12PM +0100, Sven Schnelle wrote:
> Hi List,
> 
> looking into the performance of syscall entry/exit after s390 switched
> to generic entry showed that there's quite some overhead calling some
> of the entry/exit work functions even when there's nothing to do.
> This patchset moves the entry and exit function to entry-common.h, so
> non inlined code gets only called when there is some work pending.

So per that logic you wouldn't need to inline exit_to_user_mode_loop()
for example, that's only called when there is a EXIT_TO_USER_MODE_WORK
bit set.

That is, I'm just being pedantic here and pointing out that your
justification doesn't cover the extent of the changes.

> I wrote a small program that just issues invalid syscalls in a loop.
> On an s390 machine, this results in the following numbers:
> 
> without this series:
> 
> # ./syscall 1000000000
> runtime: 94.886581s / per-syscall 9.488658e-08s
> 
> with this series:
> 
> ./syscall 1000000000
> runtime: 84.732391s / per-syscall 8.473239e-08s
> 
> so the time required for one syscall dropped from 94.8ns to
> 84.7ns, which is a drop of about 11%.

That is obviously very nice, and I don't immediately see anything wrong
with moving the lot to header based inlines.

Thomas?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] entry: inline syscall enter/exit functions
  2023-12-06 11:02 ` [PATCH 0/3] entry: inline syscall enter/exit functions Peter Zijlstra
@ 2023-12-14  8:24   ` Sven Schnelle
  2023-12-15 19:06     ` Thomas Gleixner
  0 siblings, 1 reply; 10+ messages in thread
From: Sven Schnelle @ 2023-12-14  8:24 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Peter Zijlstra, Andy Lutomirski, linux-kernel, Heiko Carstens

Peter Zijlstra <peterz@infradead.org> writes:

> On Tue, Dec 05, 2023 at 02:30:12PM +0100, Sven Schnelle wrote:
>> Hi List,
>> 
>> looking into the performance of syscall entry/exit after s390 switched
>> to generic entry showed that there's quite some overhead calling some
>> of the entry/exit work functions even when there's nothing to do.
>> This patchset moves the entry and exit function to entry-common.h, so
>> non inlined code gets only called when there is some work pending.
>
> So per that logic you wouldn't need to inline exit_to_user_mode_loop()
> for example, that's only called when there is a EXIT_TO_USER_MODE_WORK
> bit set.
>
> That is, I'm just being pedantic here and pointing out that your
> justification doesn't cover the extent of the changes.
>
>> I wrote a small program that just issues invalid syscalls in a loop.
>> On an s390 machine, this results in the following numbers:
>> 
>> without this series:
>> 
>> # ./syscall 1000000000
>> runtime: 94.886581s / per-syscall 9.488658e-08s
>> 
>> with this series:
>> 
>> ./syscall 1000000000
>> runtime: 84.732391s / per-syscall 8.473239e-08s
>> 
>> so the time required for one syscall dropped from 94.8ns to
>> 84.7ns, which is a drop of about 11%.
>
> That is obviously very nice, and I don't immediately see anything wrong
> with moving the lot to header based inlines.
>
> Thomas?

Thomas, any opinion on this change?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] entry: inline syscall enter/exit functions
  2023-12-14  8:24   ` Sven Schnelle
@ 2023-12-15 19:06     ` Thomas Gleixner
  0 siblings, 0 replies; 10+ messages in thread
From: Thomas Gleixner @ 2023-12-15 19:06 UTC (permalink / raw)
  To: Sven Schnelle
  Cc: Peter Zijlstra, Andy Lutomirski, linux-kernel, Heiko Carstens

On Thu, Dec 14 2023 at 09:24, Sven Schnelle wrote:
> Peter Zijlstra <peterz@infradead.org> writes:
>>> so the time required for one syscall dropped from 94.8ns to
>>> 84.7ns, which is a drop of about 11%.
>>
>> That is obviously very nice, and I don't immediately see anything wrong
>> with moving the lot to header based inlines.
>>
>> Thomas?

No objections in principle. Let me look at the lot

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] entry: move exit to usermode functions to header file
  2023-12-05 13:30 ` [PATCH 1/3] entry: move exit to usermode functions to header file Sven Schnelle
@ 2023-12-15 19:09   ` Thomas Gleixner
  2023-12-18  7:46     ` Sven Schnelle
  0 siblings, 1 reply; 10+ messages in thread
From: Thomas Gleixner @ 2023-12-15 19:09 UTC (permalink / raw)
  To: Sven Schnelle, Peter Zijlstra, Andy Lutomirski
  Cc: linux-kernel, Heiko Carstens

On Tue, Dec 05 2023 at 14:30, Sven Schnelle wrote:
> +/**
> + * exit_to_user_mode_loop - do any pending work before leaving to user space
> + */
> +static __always_inline unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
> +							    unsigned long ti_work)
> +{
> +	/*
> +	 * Before returning to user space ensure that all pending work
> +	 * items have been completed.
> +	 */
> +	while (ti_work & EXIT_TO_USER_MODE_WORK) {
> +
> +		local_irq_enable_exit_to_user(ti_work);
> +
> +		if (ti_work & _TIF_NEED_RESCHED)
> +			schedule();
> +
> +		if (ti_work & _TIF_UPROBE)
> +			uprobe_notify_resume(regs);
> +
> +		if (ti_work & _TIF_PATCH_PENDING)
> +			klp_update_patch_state(current);
> +
> +		if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
> +			arch_do_signal_or_restart(regs);
> +
> +		if (ti_work & _TIF_NOTIFY_RESUME)
> +			resume_user_mode_work(regs);
> +
> +		/* Architecture specific TIF work */
> +		arch_exit_to_user_mode_work(regs, ti_work);
> +
> +		/*
> +		 * Disable interrupts and reevaluate the work flags as they
> +		 * might have changed while interrupts and preemption was
> +		 * enabled above.
> +		 */
> +		local_irq_disable_exit_to_user();
> +
> +		/* Check if any of the above work has queued a deferred wakeup */
> +		tick_nohz_user_enter_prepare();
> +
> +		ti_work = read_thread_flags();
> +	}
> +
> +	/* Return the latest work state for arch_exit_to_user_mode() */
> +	return ti_work;
> +}

I'm not really sure about this part. exit_to_user_mode_loop() is the
slowpath when a TIF work flag is set. I can see the benefit on the
fastpath functions which are way smaller.

Thanks,

        tglx


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] entry: move exit to usermode functions to header file
  2023-12-15 19:09   ` Thomas Gleixner
@ 2023-12-18  7:46     ` Sven Schnelle
  0 siblings, 0 replies; 10+ messages in thread
From: Sven Schnelle @ 2023-12-18  7:46 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Peter Zijlstra, Andy Lutomirski, linux-kernel, Heiko Carstens

Hi Thomas,

Thomas Gleixner <tglx@linutronix.de> writes:

> On Tue, Dec 05 2023 at 14:30, Sven Schnelle wrote:
>> +/**
>> + * exit_to_user_mode_loop - do any pending work before leaving to user space
>> + */
>> +static __always_inline unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
>> +							    unsigned long ti_work)
>> +{
>> +	/*
>> +	 * Before returning to user space ensure that all pending work
>> +	 * items have been completed.
>> +	 */
>> +	while (ti_work & EXIT_TO_USER_MODE_WORK) {
>> +
>> +		local_irq_enable_exit_to_user(ti_work);
>> +
>> +		if (ti_work & _TIF_NEED_RESCHED)
>> +			schedule();
>> +
>> +		if (ti_work & _TIF_UPROBE)
>> +			uprobe_notify_resume(regs);
>> +
>> +		if (ti_work & _TIF_PATCH_PENDING)
>> +			klp_update_patch_state(current);
>> +
>> +		if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
>> +			arch_do_signal_or_restart(regs);
>> +
>> +		if (ti_work & _TIF_NOTIFY_RESUME)
>> +			resume_user_mode_work(regs);
>> +
>> +		/* Architecture specific TIF work */
>> +		arch_exit_to_user_mode_work(regs, ti_work);
>> +
>> +		/*
>> +		 * Disable interrupts and reevaluate the work flags as they
>> +		 * might have changed while interrupts and preemption was
>> +		 * enabled above.
>> +		 */
>> +		local_irq_disable_exit_to_user();
>> +
>> +		/* Check if any of the above work has queued a deferred wakeup */
>> +		tick_nohz_user_enter_prepare();
>> +
>> +		ti_work = read_thread_flags();
>> +	}
>> +
>> +	/* Return the latest work state for arch_exit_to_user_mode() */
>> +	return ti_work;
>> +}
>
> I'm not really sure about this part. exit_to_user_mode_loop() is the
> slowpath when a TIF work flag is set. I can see the benefit on the
> fastpath functions which are way smaller.

Indeed, the main performance improvement comes from inlining the small
functions. As Peter mentioned the same, i sent out a v2 which doesn't
move exit_to_user_mode_loop().

Thanks!
Sven

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] entry: move exit to usermode functions to header file
@ 2023-12-13 19:48 kernel test robot
  0 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2023-12-13 19:48 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp, Dan Carpenter

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20231205133015.752543-2-svens@linux.ibm.com>
References: <20231205133015.752543-2-svens@linux.ibm.com>
TO: Sven Schnelle <svens@linux.ibm.com>
TO: Thomas Gleixner <tglx@linutronix.de>
TO: Peter Zijlstra <peterz@infradead.org>
TO: Andy Lutomirski <luto@kernel.org>
CC: linux-kernel@vger.kernel.org
CC: Heiko Carstens <hca@linux.ibm.com>

Hi Sven,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tip/core/entry]
[also build test WARNING on linus/master v6.7-rc5 next-20231213]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Sven-Schnelle/entry-move-exit-to-usermode-functions-to-header-file/20231205-213501
base:   tip/core/entry
patch link:    https://lore.kernel.org/r/20231205133015.752543-2-svens%40linux.ibm.com
patch subject: [PATCH 1/3] entry: move exit to usermode functions to header file
:::::: branch date: 8 days ago
:::::: commit date: 8 days ago
config: riscv-randconfig-r071-20231211 (https://download.01.org/0day-ci/archive/20231214/202312140345.y20Pgw79-lkp@intel.com/config)
compiler: riscv64-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20231214/202312140345.y20Pgw79-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>
| Closes: https://lore.kernel.org/r/202312140345.y20Pgw79-lkp@intel.com/

smatch warnings:
include/linux/entry-common.h:285 exit_to_user_mode_loop() warn: bitwise AND condition is false here

vim +285 include/linux/entry-common.h

a9f3a74a29af09 Thomas Gleixner 2020-07-22  264  
f682d70e117d9c Sven Schnelle   2023-12-05  265  /**
f682d70e117d9c Sven Schnelle   2023-12-05  266   * exit_to_user_mode_loop - do any pending work before leaving to user space
f682d70e117d9c Sven Schnelle   2023-12-05  267   */
f682d70e117d9c Sven Schnelle   2023-12-05  268  static __always_inline unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
f682d70e117d9c Sven Schnelle   2023-12-05  269  							    unsigned long ti_work)
f682d70e117d9c Sven Schnelle   2023-12-05  270  {
f682d70e117d9c Sven Schnelle   2023-12-05  271  	/*
f682d70e117d9c Sven Schnelle   2023-12-05  272  	 * Before returning to user space ensure that all pending work
f682d70e117d9c Sven Schnelle   2023-12-05  273  	 * items have been completed.
f682d70e117d9c Sven Schnelle   2023-12-05  274  	 */
f682d70e117d9c Sven Schnelle   2023-12-05  275  	while (ti_work & EXIT_TO_USER_MODE_WORK) {
f682d70e117d9c Sven Schnelle   2023-12-05  276  
f682d70e117d9c Sven Schnelle   2023-12-05  277  		local_irq_enable_exit_to_user(ti_work);
f682d70e117d9c Sven Schnelle   2023-12-05  278  
f682d70e117d9c Sven Schnelle   2023-12-05  279  		if (ti_work & _TIF_NEED_RESCHED)
f682d70e117d9c Sven Schnelle   2023-12-05  280  			schedule();
f682d70e117d9c Sven Schnelle   2023-12-05  281  
f682d70e117d9c Sven Schnelle   2023-12-05  282  		if (ti_work & _TIF_UPROBE)
f682d70e117d9c Sven Schnelle   2023-12-05  283  			uprobe_notify_resume(regs);
f682d70e117d9c Sven Schnelle   2023-12-05  284  
f682d70e117d9c Sven Schnelle   2023-12-05 @285  		if (ti_work & _TIF_PATCH_PENDING)
f682d70e117d9c Sven Schnelle   2023-12-05  286  			klp_update_patch_state(current);
f682d70e117d9c Sven Schnelle   2023-12-05  287  
f682d70e117d9c Sven Schnelle   2023-12-05  288  		if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
f682d70e117d9c Sven Schnelle   2023-12-05  289  			arch_do_signal_or_restart(regs);
f682d70e117d9c Sven Schnelle   2023-12-05  290  
f682d70e117d9c Sven Schnelle   2023-12-05  291  		if (ti_work & _TIF_NOTIFY_RESUME)
f682d70e117d9c Sven Schnelle   2023-12-05  292  			resume_user_mode_work(regs);
f682d70e117d9c Sven Schnelle   2023-12-05  293  
f682d70e117d9c Sven Schnelle   2023-12-05  294  		/* Architecture specific TIF work */
f682d70e117d9c Sven Schnelle   2023-12-05  295  		arch_exit_to_user_mode_work(regs, ti_work);
f682d70e117d9c Sven Schnelle   2023-12-05  296  
f682d70e117d9c Sven Schnelle   2023-12-05  297  		/*
f682d70e117d9c Sven Schnelle   2023-12-05  298  		 * Disable interrupts and reevaluate the work flags as they
f682d70e117d9c Sven Schnelle   2023-12-05  299  		 * might have changed while interrupts and preemption was
f682d70e117d9c Sven Schnelle   2023-12-05  300  		 * enabled above.
f682d70e117d9c Sven Schnelle   2023-12-05  301  		 */
f682d70e117d9c Sven Schnelle   2023-12-05  302  		local_irq_disable_exit_to_user();
f682d70e117d9c Sven Schnelle   2023-12-05  303  
f682d70e117d9c Sven Schnelle   2023-12-05  304  		/* Check if any of the above work has queued a deferred wakeup */
f682d70e117d9c Sven Schnelle   2023-12-05  305  		tick_nohz_user_enter_prepare();
f682d70e117d9c Sven Schnelle   2023-12-05  306  
f682d70e117d9c Sven Schnelle   2023-12-05  307  		ti_work = read_thread_flags();
f682d70e117d9c Sven Schnelle   2023-12-05  308  	}
f682d70e117d9c Sven Schnelle   2023-12-05  309  
f682d70e117d9c Sven Schnelle   2023-12-05  310  	/* Return the latest work state for arch_exit_to_user_mode() */
f682d70e117d9c Sven Schnelle   2023-12-05  311  	return ti_work;
f682d70e117d9c Sven Schnelle   2023-12-05  312  }
f682d70e117d9c Sven Schnelle   2023-12-05  313  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-12-18  7:46 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-05 13:30 [PATCH 0/3] entry: inline syscall enter/exit functions Sven Schnelle
2023-12-05 13:30 ` [PATCH 1/3] entry: move exit to usermode functions to header file Sven Schnelle
2023-12-15 19:09   ` Thomas Gleixner
2023-12-18  7:46     ` Sven Schnelle
2023-12-05 13:30 ` [PATCH 2/3] move enter_from_user_mode() " Sven Schnelle
2023-12-05 13:30 ` [PATCH 3/3] entry: move syscall_enter_from_user_mode() " Sven Schnelle
2023-12-06 11:02 ` [PATCH 0/3] entry: inline syscall enter/exit functions Peter Zijlstra
2023-12-14  8:24   ` Sven Schnelle
2023-12-15 19:06     ` Thomas Gleixner
2023-12-13 19:48 [PATCH 1/3] entry: move exit to usermode functions to header file kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.