[RFC] arm64: syscall: add syscall inline

Guo Hui guohui at uniontech.com
Wed Jun 14 18:23:12 PDT 2023


I will introduce the advantages of syscall inline from the following four points:

1. Performance: syscall inline can improve syscall performance by about 2%.
2. Historical commit:

    f37099b6992a0b81 ("arm64: convert syscall trace logic to C")

    The purpose of this commit is to facilitate the operation of trace flags,
    so increasing the function call level is not the purpose.
3. The size of the kernel vmlinux file increases:
    1408B, about 1K, which can be ignored.
4. Instruction layout and jumps: reduced jumps, more conducive to CPU cache,
    and should be more beneficial to scenarios where system calls are frequently used.

Current instruction layout:
the base address of el0_svc_common is smaller than the base address of el0_svc_handler,
so it needs to jump backward every time in el0_svc_handler
    ---------------------
    |   el0_svc_common  |
    ---------------------
    |   el0_svc_handler |
    ---------------------

Instruction layout after syscall inline: el0_svc_handler contains el0_svc_common,
so all instructions are executed in order, reducing jumps
    ---------------------
    |   el0_svc_handler |
    ---------------------
    |   el0_svc_common  |
    ---------------------

If only the function el0_svc_common is inlined, but not the function invoke_syscall,
the instruction layout will become as follows, and the function invoke_syscall still needs to jump,
so both the function el0_svc_common and the function invoke_syscall need to be inlined
    ---------------------
    |    invoke_syscall |
    ---------------------
    |   el0_svc_handler |
    ---------------------

Based on the above analysis, I think syscall inline should be better,
but I am not sure if I have considered it thoroughly.
Please give me some suggestions, thank you very much.

Signed-off-by: Guo Hui <guohui at uniontech.com>
---
 arch/arm64/kernel/syscall.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index da84cf855c44..1403cfb83b84 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -38,7 +38,7 @@ static long __invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn)
 	return syscall_fn(regs);
 }
 
-static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
+static __always_inline void invoke_syscall(struct pt_regs *regs, unsigned int scno,
 			   unsigned int sc_nr,
 			   const syscall_fn_t syscall_table[])
 {
@@ -78,7 +78,7 @@ static inline bool has_syscall_work(unsigned long flags)
 int syscall_trace_enter(struct pt_regs *regs);
 void syscall_trace_exit(struct pt_regs *regs);
 
-static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
+static __always_inline void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
 			   const syscall_fn_t syscall_table[])
 {
 	unsigned long flags = read_thread_flags();
-- 
2.20.1




More information about the linux-arm-kernel mailing list