public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
From: yushengjin <yushengjin@uniontech.com>
To: linux-arm-kernel@lists.infradead.org
Cc: catalin.marinas@arm.com, will@kernel.org, mark.rutland@arm.com,
	keescook@chromium.org, maz@kernel.org, joey.gouly@arm.com,
	yushengjin <yushengjin@uniontech.com>
Subject: [PATCH] arm64: syscall: Fixed the problem that local_daif_mask was called twice in a row when there was no _TIF_SYSCALL_WORK when the do_el0_svc call returned.
Date: Fri,  3 Dec 2021 20:17:54 +0800	[thread overview]
Message-ID: <20211203121754.8177-1-yushengjin@uniontech.com> (raw)

This commit f37099b6992a ("arm64: convert syscall trace logic to C") is
a patch that converts syscall trace to C. It was submitted to the v4.18
branch in 2018, but there is a small problem in the conversion process,
which is still there.

After calling disable_daif, the previous assembly code ret_fast_syscall
will directly call kernel_exit to exit the kernel state if there is no
_TIF_SYSCALL_WORK flag bit,Instead of calling  ret_to_user.But after
converting this assembly code into C,After checking the flag bit and
finding no _TIF_SYSCALL_WORK and it returns, ret_to_user will be called
unconditionally, and ret_to_user also has a code of disable_daif, which
will cause ret_to_user to be called twice in a row in this program execution
flow.

Although calling twice doesn't have much impact, I found that this disable_daif
code has some impact on the performance of arm64 machines.

Taking the gitpid test of "Unixbench syscall" as an example, we know that if
getpid is not specially optimized in C library, the performance of getpid
is almost the performance of system call.

The performance test after patching is as follows:

    ~/UnixBench$ ./pgms/syscall 10 g
    COUNT|83397768|1|lps
    ~/UnixBench$ ./pgms/syscall 10 g
    COUNT|83521095|1|lps

At the same time, I add a line of repeated code under XXX, similar to this
-----------------
local_daif_mask();
local_daif_mask();
-----------------
    ~/UnixBench$ ./pgms/syscall 10 g
    COUNT|78040911|1|lps
    ~/UnixBench$ ./pgms/syscall 10 g
    COUNT|78046938|1|lps

This shows that the operation of this daIf has a loss of performance,
Therefore, after fixing the problem of repeated calls twice, the performance
is as follows.

    ~/UnixBench$ ./pgms/syscall 10 g
    COUNT|93664649|1|lps
    ~/UnixBench$ ./pgms/syscall 10 g
    COUNT|94852639|1|lps

Signed-off-by: yushengjin <yushengjin@uniontech.com>
---
 arch/arm64/kernel/entry-common.c | 13 ++++++++++++-
 arch/arm64/kernel/syscall.c      |  1 +
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index f7408edf8571..99baf32b3e3d 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -141,6 +141,17 @@ static __always_inline void exit_to_user_mode(struct pt_regs *regs)
 	__exit_to_user_mode();
 }
 
+static __always_inline void el0_svc_exit_to_user_mode(struct pt_regs *regs)
+{
+	unsigned long flags;
+
+	flags = READ_ONCE(current_thread_info()->flags);
+	if (unlikely(flags & _TIF_WORK_MASK))
+		do_notify_resume(regs, flags);
+	mte_check_tfsr_exit();
+	__exit_to_user_mode();
+}
+
 asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
 {
 	exit_to_user_mode(regs);
@@ -601,7 +612,7 @@ static void noinstr el0_svc(struct pt_regs *regs)
 	enter_from_user_mode(regs);
 	cortex_a76_erratum_1463225_svc_handler();
 	do_el0_svc(regs);
-	exit_to_user_mode(regs);
+	el0_svc_exit_to_user_mode(regs);
 }
 
 static void noinstr el0_fpac(struct pt_regs *regs, unsigned long esr)
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index 50a0f1a38e84..4095786c85f1 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -156,6 +156,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 
 trace_exit:
 	syscall_trace_exit(regs);
+	local_daif_mask();
 }
 
 static inline void sve_user_discard(void)
-- 
2.20.1




_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

             reply	other threads:[~2021-12-03 12:20 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-03 12:17 yushengjin [this message]
2021-12-03 14:48 ` [PATCH] arm64: syscall: Fixed the problem that local_daif_mask was called twice in a row when there was no _TIF_SYSCALL_WORK when the do_el0_svc call returned Mark Rutland

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=20211203121754.8177-1-yushengjin@uniontech.com \
    --to=yushengjin@uniontech.com \
    --cc=catalin.marinas@arm.com \
    --cc=joey.gouly@arm.com \
    --cc=keescook@chromium.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=will@kernel.org \
    /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