@@ -57,6 +57,31 @@
#define INTERNAL_SYSCALL_CALL(...) \
__INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL, __VA_ARGS__)
+#define __EARLY_INTERNAL_SYSCALL0(name, err) \
+ EARLY_INTERNAL_SYSCALL (name, err, 0)
+#define __EARLY_INTERNAL_SYSCALL1(name, err, a1) \
+ EARLY_INTERNAL_SYSCALL (name, err, 1, a1)
+#define __EARLY_INTERNAL_SYSCALL2(name, err, a1, a2) \
+ EARLY_INTERNAL_SYSCALL (name, err, 2, a1, a2)
+#define __EARLY_INTERNAL_SYSCALL3(name, err, a1, a2, a3) \
+ EARLY_INTERNAL_SYSCALL (name, err, 3, a1, a2, a3)
+#define __EARLY_INTERNAL_SYSCALL4(name, err, a1, a2, a3, a4) \
+ EARLY_INTERNAL_SYSCALL (name, err, 4, a1, a2, a3, a4)
+#define __EARLY_INTERNAL_SYSCALL5(name, err, a1, a2, a3, a4, a5) \
+ EARLY_INTERNAL_SYSCALL (name, err, 5, a1, a2, a3, a4, a5)
+#define __EARLY_INTERNAL_SYSCALL6(name, err, a1, a2, a3, a4, a5, a6) \
+ EARLY_INTERNAL_SYSCALL (name, err, 6, a1, a2, a3, a4, a5, a6)
+#define __EARLY_INTERNAL_SYSCALL7(name, err, a1, a2, a3, a4, a5, a6, a7) \
+ EARLY_INTERNAL_SYSCALL (name, err, 7, a1, a2, a3, a4, a5, a6, a7)
+
+/* It is similar to INTERNAL_SYSCALL_CALL, but it is reserved to system calls
+ during process initialization, when internal structures may not be
+ available, e.g. TCB on powerpc. */
+#define EARLY_INTERNAL_SYSCALL_CALL(...) \
+ __INTERNAL_SYSCALL_DISP (__EARLY_INTERNAL_SYSCALL, __VA_ARGS__)
+#define EARLY_INTERNAL_SYSCALL(name, err, nr, args...) \
+ INTERNAL_SYSCALL (name, err, nr, args)
+
#define __INLINE_SYSCALL0(name) \
INLINE_SYSCALL (name, 0)
#define __INLINE_SYSCALL1(name, a1) \
@@ -25,9 +25,9 @@ __access_noerrno (const char *pathname, int mode)
int res;
INTERNAL_SYSCALL_DECL (err);
#ifdef __NR_access
- res = INTERNAL_SYSCALL_CALL (access, err, pathname, mode);
+ res = EARLY_INTERNAL_SYSCALL_CALL (access, err, pathname, mode);
#else
- res = INTERNAL_SYSCALL_CALL (faccessat, err, AT_FDCWD, pathname, mode);
+ res = EARLY_INTERNAL_SYSCALL_CALL (faccessat, err, AT_FDCWD, pathname, mode);
#endif
if (INTERNAL_SYSCALL_ERROR_P (res, err))
return INTERNAL_SYSCALL_ERRNO (res, err);
@@ -89,7 +89,10 @@
On powerpc a system call basically clobbers the same registers like a
function call, with the exception of LR (which is needed for the
"sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
- an error return status). */
+ an error return status).
+
+ Notice it requires the TCB to be allocated and completely set in order to
+ abort transactions before the syscall. */
# undef INTERNAL_SYSCALL_DECL
# define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused))
@@ -124,6 +127,37 @@
# define INTERNAL_SYSCALL(name, err, nr, args...) \
INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
+/* Similar to INTERNAL_SYSCALL, but reserved to early process initialization
+ without requiring the TCB to allocated and completely set. */
+# undef EARLY_INTERNAL_SYSCALL
+# define EARLY_INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+ ({ \
+ register long int r0 __asm__ ("r0"); \
+ register long int r3 __asm__ ("r3"); \
+ register long int r4 __asm__ ("r4"); \
+ register long int r5 __asm__ ("r5"); \
+ register long int r6 __asm__ ("r6"); \
+ register long int r7 __asm__ ("r7"); \
+ register long int r8 __asm__ ("r8"); \
+ register long int r9 __asm__ ("r9"); \
+ register long int r10 __asm__ ("r10"); \
+ register long int r11 __asm__ ("r11"); \
+ register long int r12 __asm__ ("r12"); \
+ LOADARGS_##nr(name, args); \
+ __asm__ __volatile__ \
+ ("sc \n\t" \
+ "mfcr %0" \
+ : "=&r" (r0), \
+ "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \
+ "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \
+ : ASM_INPUT_##nr \
+ : "cr0", "ctr", "memory"); \
+ err = r0; \
+ (int) r3; \
+ })
+# define EARLY_INTERNAL_SYSCALL(name, err, nr, args...) \
+ EARLY_INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
+
# undef INTERNAL_SYSCALL_ERROR_P
# define INTERNAL_SYSCALL_ERROR_P(val, err) \
((void) (val), __builtin_expect ((err) & (1 << 28), 0))
@@ -118,7 +118,10 @@
call. This use is for internal calls that do not need to handle errors
normally. It will never touch errno. This returns just what the kernel
gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
- the negation of the return value in the kernel gets reverted. */
+ the negation of the return value in the kernel gets reverted.
+
+ Notice it requires the TCB to be allocated and completely set in order to
+ abort transactions before the syscall. */
#undef INTERNAL_SYSCALL
#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
@@ -148,6 +151,35 @@
#define INTERNAL_SYSCALL(name, err, nr, args...) \
INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, args)
+/* Similar to INTERNAL_SYSCALL, but reserved to early process initialization
+ without requiring the TCB to allocated and completely set. */
+#undef EARLY_INTERNAL_SYSCALL
+#define EARLY_INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
+ ({ \
+ register long int r0 __asm__ ("r0"); \
+ register long int r3 __asm__ ("r3"); \
+ register long int r4 __asm__ ("r4"); \
+ register long int r5 __asm__ ("r5"); \
+ register long int r6 __asm__ ("r6"); \
+ register long int r7 __asm__ ("r7"); \
+ register long int r8 __asm__ ("r8"); \
+ LOADARGS_##nr (name, ##args); \
+ __asm__ __volatile__ \
+ ("sc\n\t" \
+ "mfcr %0\n\t" \
+ "0:" \
+ : "=&r" (r0), \
+ "=&r" (r3), "=&r" (r4), "=&r" (r5), \
+ "=&r" (r6), "=&r" (r7), "=&r" (r8) \
+ : ASM_INPUT_##nr \
+ : "r9", "r10", "r11", "r12", \
+ "cr0", "ctr", "memory"); \
+ err = r0; \
+ r3; \
+ })
+#define EARLY_INTERNAL_SYSCALL(name, err, nr, args...) \
+ EARLY_INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, args)
+
#undef INTERNAL_SYSCALL_DECL
#define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused))