aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S9
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S6
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/syscall.S11
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/sysdep.h93
4 files changed, 88 insertions, 31 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
index b30641c805..fc496fa671 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
@@ -68,7 +68,8 @@ ENTRY (__clone)
cfi_endproc
/* Do the call. */
- DO_CALL(SYS_ify(clone))
+ li r0,SYS_ify(clone)
+ DO_CALL_SC
/* Check for child process. */
cmpdi cr1,r3,0
@@ -82,7 +83,8 @@ ENTRY (__clone)
bctrl
ld r2,FRAME_TOC_SAVE(r1)
- DO_CALL(SYS_ify(exit))
+ li r0,(SYS_ify(exit))
+ DO_CALL_SC
/* We won't ever get here but provide a nop so that the linker
will insert a toc adjusting stub if necessary. */
nop
@@ -104,7 +106,8 @@ L(parent):
cfi_restore(r30)
cfi_restore(r31)
- PSEUDO_RET
+ RET_SC
+ TAIL_CALL_SYSCALL_ERROR
END (__clone)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S
index 17199fb14a..a71f69e929 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S
@@ -28,9 +28,11 @@
ENTRY (__vfork)
CALL_MCOUNT 0
- DO_CALL (SYS_ify (vfork))
+ li r0,SYS_ify (vfork)
+ DO_CALL_SC
- PSEUDO_RET
+ RET_SC
+ TAIL_CALL_SYSCALL_ERROR
PSEUDO_END (__vfork)
libc_hidden_def (__vfork)
diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S
index 48dade4642..9fc4ddd3cb 100644
--- a/sysdeps/unix/sysv/linux/powerpc/syscall.S
+++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S
@@ -25,6 +25,13 @@ ENTRY (syscall)
mr r6,r7
mr r7,r8
mr r8,r9
- sc
- PSEUDO_RET
+#if !IS_IN(rtld) && (defined(__PPC64__) || defined(__powerpc64__))
+ CHECK_SCV_SUPPORT r9 0f
+ DO_CALL_SCV
+ RET_SCV
+ b 1f
+#endif
+0: DO_CALL_SC
+ RET_SC
+1: TAIL_CALL_SYSCALL_ERROR
PSEUDO_END (syscall)
diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h
index b2bca598b9..7f69804edc 100644
--- a/sysdeps/unix/sysv/linux/powerpc/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.h
@@ -64,39 +64,84 @@
#define INTERNAL_VSYSCALL_CALL(funcptr, nr, args...) \
INTERNAL_VSYSCALL_CALL_TYPE(funcptr, long int, nr, args)
+#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, 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, nr, args...) \
- INTERNAL_SYSCALL_NCS (__NR_##name, nr, args)
+
+#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; \
+ })
+
+/* 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) \