xtensa: optimize syscall helper functions

The original idea of the syscall helpers is to workaround
an issue where the compiler could not correctly model register
usage with inline functions. It was supposed to be only used
when there are more then 3 arguments to syscalls. However,
during the original MMU code development, the helper got
expanded to cover "less then 2 arguments syscalls" as a way
for debugging syscall handling code and was never removed.
So fix that now by limiting the helper for syscalls with
more than 3 arguments.

Moreover, instead of using one helper with 6 arguments, now
we have separate implementations for both 4 and 5 arguments
syscall helpers. Now the compiler does not have to generate
code to always handle 6 arguments which saves a few code bytes
as there is no need to pass extra zeroes as arguments.

This has been verified to work with xt-clang RI-2022.10.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2024-11-20 23:25:44 -08:00 committed by Anas Nashif
parent 4483b7ebb7
commit 42b209f816
3 changed files with 126 additions and 39 deletions

View file

@ -283,7 +283,7 @@ config XTENSA_SYSCALL_USE_HELPER
default y if "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "xt-clang"
depends on (XTENSA_MMU || XTENSA_MPU) && USERSPACE
help
Use syscall helpers for passing more then 3 arguments.
Use syscall helpers for passing more than 3 arguments.
This is a workaround for toolchains where they have
issue modeling register usage.

View file

@ -12,7 +12,7 @@
#include <xtensa_internal.h>
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
uintptr_t xtensa_syscall_helper(uintptr_t arg1, uintptr_t arg2,
uintptr_t xtensa_syscall_helper_args_6(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t arg4,
uintptr_t arg5, uintptr_t arg6,
uintptr_t call_id)
@ -33,6 +33,101 @@ uintptr_t xtensa_syscall_helper(uintptr_t arg1, uintptr_t arg2,
return a2;
}
uintptr_t xtensa_syscall_helper_args_5(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t arg4,
uintptr_t arg5, uintptr_t call_id)
{
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
register uintptr_t a3 __asm__("%a3") = arg2;
register uintptr_t a4 __asm__("%a4") = arg3;
register uintptr_t a5 __asm__("%a5") = arg4;
register uintptr_t a8 __asm__("%a8") = arg5;
__asm__ volatile("syscall\n\t"
: "=r" (a2)
: "r" (a2), "r" (a6), "r" (a3), "r" (a4),
"r" (a5), "r" (a8)
: "memory");
return a2;
}
uintptr_t xtensa_syscall_helper_args_4(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t arg4,
uintptr_t call_id)
{
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
register uintptr_t a3 __asm__("%a3") = arg2;
register uintptr_t a4 __asm__("%a4") = arg3;
register uintptr_t a5 __asm__("%a5") = arg4;
__asm__ volatile("syscall\n\t"
: "=r" (a2)
: "r" (a2), "r" (a6), "r" (a3), "r" (a4),
"r" (a5)
: "memory");
return a2;
}
uintptr_t xtensa_syscall_helper_args_3(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t call_id)
{
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
register uintptr_t a3 __asm__("%a3") = arg2;
register uintptr_t a4 __asm__("%a4") = arg3;
__asm__ volatile("syscall\n\t"
: "=r" (a2)
: "r" (a2), "r" (a6), "r" (a3), "r" (a4)
: "memory");
return a2;
}
uintptr_t xtensa_syscall_helper_args_2(uintptr_t arg1, uintptr_t arg2,
uintptr_t call_id)
{
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
register uintptr_t a3 __asm__("%a3") = arg2;
__asm__ volatile("syscall\n\t"
: "=r" (a2)
: "r" (a2), "r" (a6), "r" (a3)
: "memory");
return a2;
}
uintptr_t xtensa_syscall_helper_args_1(uintptr_t arg1, uintptr_t call_id)
{
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
__asm__ volatile("syscall\n\t"
: "=r" (a2)
: "r" (a2), "r" (a6)
: "memory");
return a2;
}
uintptr_t xtensa_syscall_helper_args_0(uintptr_t call_id)
{
register uintptr_t a2 __asm__("%a2") = call_id;
__asm__ volatile("syscall\n\t"
: "=r" (a2)
: "r" (a2)
: "memory");
return a2;
}
#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER */
#if XCHAL_HAVE_THREADPTR == 0

View file

@ -31,11 +31,19 @@ extern "C" {
#endif
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
uintptr_t xtensa_syscall_helper(uintptr_t arg1, uintptr_t arg2,
uintptr_t xtensa_syscall_helper_args_6(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t arg4,
uintptr_t arg5, uintptr_t arg6,
uintptr_t call_id);
uintptr_t xtensa_syscall_helper_args_5(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t arg4,
uintptr_t arg5, uintptr_t call_id);
uintptr_t xtensa_syscall_helper_args_4(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t arg4,
uintptr_t call_id);
#define SYSINL ALWAYS_INLINE
#else
#define SYSINL inline
@ -50,13 +58,14 @@ uintptr_t xtensa_syscall_helper(uintptr_t arg1, uintptr_t arg2,
*
**/
static SYSINL uintptr_t arch_syscall_invoke6(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t arg4,
uintptr_t arg5, uintptr_t arg6,
uintptr_t call_id)
{
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
return xtensa_syscall_helper(arg1, arg2, arg3, arg4, arg5, arg6, call_id);
return xtensa_syscall_helper_args_6(arg1, arg2, arg3, arg4, arg5, arg6, call_id);
#else
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
@ -81,7 +90,7 @@ static SYSINL uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg5, uintptr_t call_id)
{
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
return xtensa_syscall_helper(arg1, arg2, arg3, arg4, arg5, 0, call_id);
return xtensa_syscall_helper_args_5(arg1, arg2, arg3, arg4, arg5, call_id);
#else
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
@ -105,7 +114,7 @@ static SYSINL uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2,
uintptr_t call_id)
{
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
return xtensa_syscall_helper(arg1, arg2, arg3, arg4, 0, 0, call_id);
return xtensa_syscall_helper_args_4(arg1, arg2, arg3, arg4, call_id);
#else
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
@ -123,12 +132,9 @@ static SYSINL uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2,
#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER */
}
static SYSINL uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
static inline uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3, uintptr_t call_id)
{
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
return xtensa_syscall_helper(arg1, arg2, arg3, 0, 0, 0, call_id);
#else
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
register uintptr_t a3 __asm__("%a3") = arg2;
@ -140,15 +146,11 @@ static SYSINL uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
: "memory");
return a2;
#endif /* CONFIG_XTENSA_SYSCALL_USE_HELPER */
}
static SYSINL uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2,
static inline uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2,
uintptr_t call_id)
{
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
return xtensa_syscall_helper(arg1, arg2, 0, 0, 0, 0, call_id);
#else
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
register uintptr_t a3 __asm__("%a3") = arg2;
@ -159,15 +161,10 @@ static SYSINL uintptr_t arch_syscall_invoke2(uintptr_t arg1, uintptr_t arg2,
: "memory");
return a2;
#endif
}
static SYSINL uintptr_t arch_syscall_invoke1(uintptr_t arg1,
uintptr_t call_id)
static inline uintptr_t arch_syscall_invoke1(uintptr_t arg1, uintptr_t call_id)
{
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
return xtensa_syscall_helper(arg1, 0, 0, 0, 0, 0, call_id);
#else
register uintptr_t a2 __asm__("%a2") = call_id;
register uintptr_t a6 __asm__("%a6") = arg1;
@ -177,14 +174,10 @@ static SYSINL uintptr_t arch_syscall_invoke1(uintptr_t arg1,
: "memory");
return a2;
#endif
}
static SYSINL uintptr_t arch_syscall_invoke0(uintptr_t call_id)
static inline uintptr_t arch_syscall_invoke0(uintptr_t call_id)
{
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
return xtensa_syscall_helper(0, 0, 0, 0, 0, 0, call_id);
#else
register uintptr_t a2 __asm__("%a2") = call_id;
__asm__ volatile("syscall\n\t"
@ -193,7 +186,6 @@ static SYSINL uintptr_t arch_syscall_invoke0(uintptr_t call_id)
: "memory");
return a2;
#endif
}
/*