Commit f31477a4 authored by Jan Kiszka's avatar Jan Kiszka
Browse files

lib/cobalt: arm64: Rework syscall wrappers



Converting them into inline functions helps to avoid clobbering of w8.
Without this, the compiler may squeeze function calls between the setup
of __scno in w8 and the actually submission of the syscall. Seen with
the smokey y2038 testcase.
Signed-off-by: Jan Kiszka's avatarJan Kiszka <jan.kiszka@siemens.com>
parent 98543980
/*
* Copyright (C) 2015 Philippe Gerum <rpm@xenomai.org>.
* Copyright (C) Siemens AG, 2021
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -22,76 +23,82 @@
#include <errno.h>
#include <cobalt/uapi/syscall.h>
#define __emit_asmdecl0 \
register unsigned int __scno __asm__ ("w8"); \
register unsigned long __res __asm__ ("x0")
#define __emit_asmdecl1 \
__emit_asmdecl0; register unsigned long __x0 __asm__ ("x0")
#define __emit_asmdecl2 \
__emit_asmdecl1; register unsigned long __x1 __asm__ ("x1")
#define __emit_asmdecl3 \
__emit_asmdecl2; register unsigned long __x2 __asm__ ("x2")
#define __emit_asmdecl4 \
__emit_asmdecl3; register unsigned long __x3 __asm__ ("x3")
#define __emit_asmdecl5 \
__emit_asmdecl4; register unsigned long __x4 __asm__ ("x4")
#define __load_asminput0(__op) \
__scno = (unsigned int)__xn_syscode(__op)
#define __load_asminput1(__op, __a1) \
__load_asminput0(__op); \
__x0 = (unsigned long)(__a1)
#define __load_asminput2(__op, __a1, __a2) \
__load_asminput1(__op, __a1); \
__x1 = (unsigned long)(__a2)
#define __load_asminput3(__op, __a1, __a2, __a3) \
__load_asminput2(__op, __a1, __a2); \
__x2 = (unsigned long)(__a3)
#define __load_asminput4(__op, __a1, __a2, __a3, __a4) \
__load_asminput3(__op, __a1, __a2, __a3); \
__x3 = (unsigned long)(__a4)
#define __load_asminput5(__op, __a1, __a2, __a3, __a4, __a5) \
__load_asminput4(__op, __a1, __a2, __a3, __a4); \
__x4 = (unsigned long)(__a5)
#define __xn_syscall_args0
#define __xn_syscall_args1 , unsigned long __a1
#define __xn_syscall_args2 __xn_syscall_args1, unsigned long __a2
#define __xn_syscall_args3 __xn_syscall_args2, unsigned long __a3
#define __xn_syscall_args4 __xn_syscall_args3, unsigned long __a4
#define __xn_syscall_args5 __xn_syscall_args4, unsigned long __a5
#define __emit_syscall0(__args...) \
register unsigned int __scno __asm__("w8") = __xn_syscode(__op); \
register unsigned long __res __asm__("x0"); \
__asm__ __volatile__ ( \
"svc 0;\n\t" \
: "=r" (__res) \
: "r" (__scno), ##__args \
: "cc", "memory"); \
__res
#define __emit_syscall1(__a1, __args...) \
return __res
#define __emit_syscall1(__args...) \
register unsigned long __x0 __asm__("x0") = __a1; \
__emit_syscall0("r" (__x0), ##__args)
#define __emit_syscall2(__a1, __a2, __args...) \
__emit_syscall1(__a1, "r" (__x1), ##__args)
#define __emit_syscall3(__a1, __a2, __a3, __args...) \
__emit_syscall2(__a1, __a2, "r" (__x2), ##__args)
#define __emit_syscall4(__a1, __a2, __a3, __a4, __args...) \
__emit_syscall3(__a1, __a2, __a3, "r" (__x3), ##__args)
#define __emit_syscall5(__a1, __a2, __a3, __a4, __a5, __args...) \
__emit_syscall4(__a1, __a2, __a3, __a4, "r" (__x4), ##__args)
#define __emit_syscall2(__args...) \
register unsigned long __x1 __asm__("x1") = __a2; \
__emit_syscall1("r" (__x1), ##__args)
#define __emit_syscall3(__args...) \
register unsigned long __x2 __asm__("x2") = __a3; \
__emit_syscall2("r" (__x2), ##__args)
#define __emit_syscall4(__args...) \
register unsigned long __x3 __asm__("x3") = __a4; \
__emit_syscall3("r" (__x3), ##__args)
#define __emit_syscall5(__args...) \
register unsigned long __x4 __asm__("x4") = __a5; \
__emit_syscall4("r" (__x4), ##__args)
#define DEFINE_XENOMAI_SYSCALL(__argnr) \
static inline long __attribute__((always_inline)) \
__xenomai_do_syscall##__argnr(unsigned int __op \
__xn_syscall_args##__argnr) \
{ \
__emit_syscall##__argnr(); \
}
#define XENOMAI_DO_SYSCALL(__argnr, __op, __args...) \
({ \
__emit_asmdecl##__argnr; \
__load_asminput##__argnr(__op, ##__args); \
__emit_syscall##__argnr(__args); \
})
DEFINE_XENOMAI_SYSCALL(0)
DEFINE_XENOMAI_SYSCALL(1)
DEFINE_XENOMAI_SYSCALL(2)
DEFINE_XENOMAI_SYSCALL(3)
DEFINE_XENOMAI_SYSCALL(4)
DEFINE_XENOMAI_SYSCALL(5)
#define XENOMAI_SYSCALL0(__op) \
XENOMAI_DO_SYSCALL(0, __op)
__xenomai_do_syscall0(__op)
#define XENOMAI_SYSCALL1(__op, __a1) \
XENOMAI_DO_SYSCALL(1, __op, __a1)
__xenomai_do_syscall1(__op, \
(unsigned long)__a1)
#define XENOMAI_SYSCALL2(__op, __a1, __a2) \
XENOMAI_DO_SYSCALL(2, __op, __a1, __a2)
__xenomai_do_syscall2(__op, \
(unsigned long)__a1, \
(unsigned long)__a2)
#define XENOMAI_SYSCALL3(__op, __a1, __a2, __a3) \
XENOMAI_DO_SYSCALL(3, __op, __a1, __a2, __a3)
__xenomai_do_syscall3(__op, \
(unsigned long)__a1, \
(unsigned long)__a2, \
(unsigned long)__a3)
#define XENOMAI_SYSCALL4(__op, __a1, __a2, __a3, __a4) \
XENOMAI_DO_SYSCALL(4, __op, __a1, __a2, __a3, __a4)
__xenomai_do_syscall4(__op, \
(unsigned long)__a1, \
(unsigned long)__a2, \
(unsigned long)__a3, \
(unsigned long)__a4)
#define XENOMAI_SYSCALL5(__op, __a1, __a2, __a3, __a4, __a5) \
XENOMAI_DO_SYSCALL(5, __op, __a1, __a2, __a3, __a4, __a5)
__xenomai_do_syscall5(__op, \
(unsigned long)__a1, \
(unsigned long)__a2, \
(unsigned long)__a3, \
(unsigned long)__a4, \
(unsigned long)__a5)
#define XENOMAI_SYSBIND(__breq) \
XENOMAI_DO_SYSCALL(1, sc_cobalt_bind, __breq)
__xenomai_do_syscall1(sc_cobalt_bind, \
(unsigned long)__breq)
#endif /* !_LIB_COBALT_ARM64_SYSCALL_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment