]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/unix/sysv/linux/powerpc/sysdep.h
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / powerpc / sysdep.h
index aab490161afd6a0b7a6657124afb1e664e8f7f1d..d3605d562d2747a83bf25979573feef6149c9ca7 100644 (file)
@@ -1,5 +1,5 @@
 /* Syscall definitions, Linux PowerPC generic version.
-   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+   Copyright (C) 2019-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -38,7 +38,7 @@
    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.  */
 
-#define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, type, nr, args...)    \
+#define INTERNAL_VSYSCALL_CALL_TYPE(funcptr, type, nr, args...)         \
   ({                                                                   \
     register void *r0  __asm__ ("r0");                                 \
     register long int r3  __asm__ ("r3");                              \
     (long int) r0 & (1 << 28) ? -rval : rval;                          \
   })
 
-#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)              \
-  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, err, long int, nr, args)
+#define INTERNAL_VSYSCALL_CALL(funcptr, nr, args...)                   \
+  INTERNAL_VSYSCALL_CALL_TYPE(funcptr, long int, nr, args)
 
-/* This version is for kernels that implement system calls that
-   behave like function calls as far as register saving.  */
-#undef INLINE_SYSCALL
-#define INLINE_SYSCALL(name, nr, args...)                              \
-  ({                                                                   \
-    INTERNAL_SYSCALL_DECL (sc_err);                                    \
-    long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args);       \
-    if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))                     \
-      {                                                                        \
-        __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));         \
-        sc_ret = -1L;                                                  \
-      }                                                                        \
-    sc_ret;                                                            \
-  })
-
-/* Define a macro which expands inline into the wrapper code for a system
-   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.  */
+#define DECLARE_REGS                           \
+  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");
 
-#undef INTERNAL_SYSCALL
-#define 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");                                      \
-    r0 & (1 << 28) ? -r3 : r3;                                         \
+#define SYSCALL_SCV(nr)                                \
+  ({                                           \
+    __asm__ __volatile__                       \
+      ("scv 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",            \
+        "lr", "ctr", "memory");                \
+    r3;                                        \
   })
-#define INTERNAL_SYSCALL(name, err, nr, args...)                       \
-  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, args)
-
-#undef INTERNAL_SYSCALL_DECL
-#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
 
-#undef INTERNAL_SYSCALL_ERROR_P
-#define INTERNAL_SYSCALL_ERROR_P(val, err) \
-  ((unsigned long int) (val) > -4096UL)
+#define SYSCALL_SC(nr)                         \
+  ({                                           \
+    __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");               \
+    r0 & (1 << 28) ? -r3 : r3;                 \
+  })
 
-#undef INTERNAL_SYSCALL_ERRNO
-#define INTERNAL_SYSCALL_ERRNO(val, err)     (-(val))
+/* This will only be non-empty for 64-bit systems, see below.  */
+#define TRY_SYSCALL_SCV(nr)
 
 #if defined(__PPC64__) || defined(__powerpc64__)
 # define SYSCALL_ARG_SIZE 8
+
+/* For the static case, unlike the dynamic loader, there is no compile-time way
+   to check if we are inside startup code.  So we need to check if the thread
+   pointer has already been setup before trying to access the TLS.  */
+# ifndef SHARED
+#  define CHECK_THREAD_POINTER (__thread_register != 0)
+# else
+#  define CHECK_THREAD_POINTER (1)
+# endif
+
+/* When inside the dynamic loader, the thread pointer may not have been
+   initialized yet, so don't check for scv support in that case.  */
+# if !IS_IN(rtld)
+#  undef TRY_SYSCALL_SCV
+#  define TRY_SYSCALL_SCV(nr)                                          \
+  CHECK_THREAD_POINTER && THREAD_GET_HWCAP() & PPC_FEATURE2_SCV ?      \
+      SYSCALL_SCV(nr) :
+# endif
+
 #else
 # define SYSCALL_ARG_SIZE 4
 #endif
 
+# define INTERNAL_SYSCALL_NCS(name, nr, args...)       \
+  ({                                                   \
+    DECLARE_REGS;                                      \
+    LOADARGS_##nr (name, ##args);                      \
+    TRY_SYSCALL_SCV(nr)                                        \
+    SYSCALL_SC(nr);                                    \
+  })
+
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, nr, args...)                            \
+  INTERNAL_SYSCALL_NCS (__NR_##name, nr, args)
+
 #define LOADARGS_0(name, dummy) \
        r0 = name
 #define LOADARGS_1(name, __arg1) \
-       long int arg1 = (long int) (__arg1); \
+       long int _arg1 = (long int) (__arg1); \
        LOADARGS_0(name, 0); \
        extern void __illegally_sized_syscall_arg1 (void); \
        if (__builtin_classify_type (__arg1) != 5 \
            && sizeof (__arg1) > SYSCALL_ARG_SIZE) \
          __illegally_sized_syscall_arg1 (); \
-       r3 = arg1
+       r3 = _arg1
 #define LOADARGS_2(name, __arg1, __arg2) \
-       long int arg2 = (long int) (__arg2); \
+       long int _arg2 = (long int) (__arg2); \
        LOADARGS_1(name, __arg1); \
        extern void __illegally_sized_syscall_arg2 (void); \
        if (__builtin_classify_type (__arg2) != 5 \
            && sizeof (__arg2) > SYSCALL_ARG_SIZE) \
          __illegally_sized_syscall_arg2 (); \
-       r4 = arg2
+       r4 = _arg2
 #define LOADARGS_3(name, __arg1, __arg2, __arg3) \
-       long int arg3 = (long int) (__arg3); \
+       long int _arg3 = (long int) (__arg3); \
        LOADARGS_2(name, __arg1, __arg2); \
        extern void __illegally_sized_syscall_arg3 (void); \
        if (__builtin_classify_type (__arg3) != 5 \
            && sizeof (__arg3) > SYSCALL_ARG_SIZE) \
          __illegally_sized_syscall_arg3 (); \
-       r5 = arg3
+       r5 = _arg3
 #define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
-       long int arg4 = (long int) (__arg4); \
+       long int _arg4 = (long int) (__arg4); \
        LOADARGS_3(name, __arg1, __arg2, __arg3); \
        extern void __illegally_sized_syscall_arg4 (void); \
        if (__builtin_classify_type (__arg4) != 5 \
            && sizeof (__arg4) > SYSCALL_ARG_SIZE) \
          __illegally_sized_syscall_arg4 (); \
-       r6 = arg4
+       r6 = _arg4
 #define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
-       long int arg5 = (long int) (__arg5); \
+       long int _arg5 = (long int) (__arg5); \
        LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
        extern void __illegally_sized_syscall_arg5 (void); \
        if (__builtin_classify_type (__arg5) != 5 \
            && sizeof (__arg5) > SYSCALL_ARG_SIZE) \
          __illegally_sized_syscall_arg5 (); \
-       r7 = arg5
+       r7 = _arg5
 #define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
-       long int arg6 = (long int) (__arg6); \
+       long int _arg6 = (long int) (__arg6); \
        LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
        extern void __illegally_sized_syscall_arg6 (void); \
        if (__builtin_classify_type (__arg6) != 5 \
            && sizeof (__arg6) > SYSCALL_ARG_SIZE) \
          __illegally_sized_syscall_arg6 (); \
-       r8 = arg6
+       r8 = _arg6
 
 #define ASM_INPUT_0 "0" (r0)
 #define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)