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:
parent
4483b7ebb7
commit
42b209f816
3 changed files with 126 additions and 39 deletions
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
#include <xtensa_internal.h>
|
||||
|
||||
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
|
||||
uintptr_t xtensa_syscall_helper(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_6(uintptr_t arg1, uintptr_t arg2,
|
||||
uintptr_t arg3, uintptr_t arg4,
|
||||
uintptr_t arg5, uintptr_t arg6,
|
||||
uintptr_t call_id)
|
||||
{
|
||||
register uintptr_t a2 __asm__("%a2") = call_id;
|
||||
register uintptr_t a6 __asm__("%a6") = arg1;
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -31,10 +31,18 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_XTENSA_SYSCALL_USE_HELPER
|
||||
uintptr_t xtensa_syscall_helper(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_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
|
||||
|
|
@ -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;
|
||||
|
|
@ -77,11 +86,11 @@ static SYSINL uintptr_t arch_syscall_invoke6(uintptr_t arg1, uintptr_t arg2,
|
|||
}
|
||||
|
||||
static SYSINL uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2,
|
||||
uintptr_t arg3, uintptr_t arg4,
|
||||
uintptr_t arg5, uintptr_t call_id)
|
||||
uintptr_t arg3, uintptr_t arg4,
|
||||
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;
|
||||
|
|
@ -101,11 +110,11 @@ static SYSINL uintptr_t arch_syscall_invoke5(uintptr_t arg1, uintptr_t arg2,
|
|||
}
|
||||
|
||||
static SYSINL uintptr_t arch_syscall_invoke4(uintptr_t arg1, uintptr_t arg2,
|
||||
uintptr_t arg3, uintptr_t arg4,
|
||||
uintptr_t call_id)
|
||||
uintptr_t arg3, uintptr_t arg4,
|
||||
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,
|
||||
uintptr_t arg3, uintptr_t call_id)
|
||||
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,
|
||||
uintptr_t call_id)
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue