aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatheus Castanho <msc@linux.ibm.com>2020-12-03 14:15:28 -0300
committerTulio Magno Quites Machado Filho <tuliom@linux.ibm.com>2020-12-30 18:26:33 -0300
commit41f013cef24884604c303435dd1915be2ea5c0e0 (patch)
treeecbca383796ba7121e14a33f91ec6a5060d5a34d
parent68ab82f56690ada86ac1e0c46bad06ba189a10ef (diff)
downloadglibc-41f013cef24884604c303435dd1915be2ea5c0e0.zip
glibc-41f013cef24884604c303435dd1915be2ea5c0e0.tar.gz
glibc-41f013cef24884604c303435dd1915be2ea5c0e0.tar.bz2
powerpc: Use scv instruction on clone when available
clone already uses r31 to temporarily save input arguments before doing the syscall, so we use a different register to read from the TCB. We can also avoid allocating another stack frame, which is not needed since we can simply extend the usage of the red zone. Tested-by: Lucas A. M. Magalhães <lamm@linux.ibm.com> Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S33
1 files changed, 30 insertions, 3 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
index fc496fa..247e0de 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
@@ -38,9 +38,11 @@ ENTRY (__clone)
beq- cr0,L(badargs)
/* Save some regs in the "red zone". */
+ std r28,-32(r1)
std r29,-24(r1)
std r30,-16(r1)
std r31,-8(r1)
+ cfi_offset(r28,-32)
cfi_offset(r29,-24)
cfi_offset(r30,-16)
cfi_offset(r31,-8)
@@ -69,11 +71,26 @@ ENTRY (__clone)
/* Do the call. */
li r0,SYS_ify(clone)
- DO_CALL_SC
+ CHECK_SCV_SUPPORT r28 0f
+ /* This is equivalent to DO_CALL_SCV, but we cannot use the macro here
+ because it uses CFI directives and we just called cfi_endproc. */
+ mflr r9
+ std r9,FRAME_LR_SAVE(r1)
+ scv 0
+ ld r9,FRAME_LR_SAVE(r1)
+ mtlr r9
+
+ /* Check for child process. */
+ /* When using scv, error is indicated by negative r3. */
+ cmpdi cr1,r3,0
+ b 1f
+0: DO_CALL_SC
/* Check for child process. */
+ /* With sc, error is indicated by cr0.SO. */
cmpdi cr1,r3,0
crandc cr1*4+eq,cr1*4+eq,cr0*4+so
+1:
bne- cr1,L(parent) /* The '-' is to minimise the race. */
std r2,FRAME_TOC_SAVE(r1)
@@ -95,19 +112,29 @@ L(badargs):
TAIL_CALL_SYSCALL_ERROR
L(parent):
+ /* Check if scv is available. */
+ cmpdi cr1,r28,0
+
/* Parent. Restore registers & return. */
+ cfi_offset(r28,-32)
cfi_offset(r29,-24)
cfi_offset(r30,-16)
cfi_offset(r31,-8)
+ ld r28,-32(r1)
ld r29,-24(r1)
ld r30,-16(r1)
ld r31,-8(r1)
+ cfi_restore(r28)
cfi_restore(r29)
cfi_restore(r30)
cfi_restore(r31)
- RET_SC
- TAIL_CALL_SYSCALL_ERROR
+ beq cr1,0f
+ RET_SCV
+ b 1f
+0: RET_SC
+1: TAIL_CALL_SYSCALL_ERROR
+
END (__clone)