[PATCH v2 1/3] aarch64: Re-implement setcontext without rt_sigreturn syscall
Will Newton
will.newton@linaro.org
Thu Apr 17 08:35:00 GMT 2014
On 1 April 2014 12:32, Will Newton <will.newton@linaro.org> wrote:
> The current implementation of setcontext uses rt_sigreturn to restore
> the contents of registers. This contrasts with the way most other
> architectures implement setcontext:
>
> powerpc64, mips, tile:
>
> Call rt_sigreturn if context was created by a call to a signal handler,
> otherwise restore in user code.
>
> powerpc32:
>
> Call swapcontext system call and don't call sigreturn or rt_sigreturn.
>
> x86_64, sparc, hppa, sh, ia64, m68k, s390, arm:
>
> Only support restoring "synchronous" contexts, that is contexts
> created by getcontext, and restoring in user code and don't call
> sigreturn or rt_sigreturn.
>
> alpha:
>
> Call sigreturn (but not rt_sigreturn) in all cases to do the restore.
>
> The text of the setcontext manpage suggests that the requirement to be
> able to restore a signal handler created context has been dropped from
> SUSv2:
>
> If the context was obtained by a call to a signal handler, then old
> standard text says that "program execution continues with the program
> instruction following the instruction interrupted by the signal".
> However, this sentence was removed in SUSv2, and the present verdict
> is "the result is unspecified".
>
> Implementing setcontext by calling rt_sigreturn unconditionally causes
> problems when used with sigaltstack as in BZ #16629. On this basis it
> seems that aarch64 is broken and that new ports should only support
> restoring contexts created with getcontext and do not need to call
> rt_sigreturn at all.
>
> This patch re-implements the aarch64 setcontext function to restore
> the context in user code in a similar manner to x86_64 and other ports.
>
> ChangeLog:
>
> 2014-04-01 Will Newton <will.newton@linaro.org>
>
> [BZ #16629]
> * sysdeps/unix/sysv/linux/aarch64/setcontext.S (__setcontext):
> Re-implement to restore registers in user code and avoid
> rt_sigreturn system call.
> ---
> NEWS | 6 +-
> sysdeps/unix/sysv/linux/aarch64/setcontext.S | 147 +++++++++++++++++----------
> 2 files changed, 95 insertions(+), 58 deletions(-)
>
> Changes in v2:
> - Added NEWS entry
> - Fixed bug in handling sigmask value
> - Improved commit message
Ping?
> diff --git a/NEWS b/NEWS
> index 1574ab4..219198d 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -11,9 +11,9 @@ Version 2.20
>
> 6804, 15347, 15804, 15894, 16002, 16198, 16284, 16348, 16349, 16357,
> 16362, 16447, 16532, 16545, 16574, 16599, 16600, 16609, 16610, 16611,
> - 16613, 16623, 16632, 16634, 16639, 16642, 16648, 16649, 16670, 16674,
> - 16677, 16680, 16683, 16689, 16695, 16701, 16706, 16707, 16712, 16713,
> - 16714, 16731, 16743, 16758, 16759, 16760, 16770.
> + 16613, 16623, 16629, 16632, 16634, 16639, 16642, 16648, 16649, 16670,
> + 16674, 16677, 16680, 16683, 16689, 16695, 16701, 16706, 16707, 16712,
> + 16713, 16714, 16731, 16743, 16758, 16759, 16760, 16770.
>
> * Running the testsuite no longer terminates as soon as a test fails.
> Instead, a file tests.sum (xtests.sum from "make xcheck") is generated,
> diff --git a/sysdeps/unix/sysv/linux/aarch64/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/setcontext.S
> index d220c41..aef5149 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/setcontext.S
> +++ b/sysdeps/unix/sysv/linux/aarch64/setcontext.S
> @@ -22,68 +22,105 @@
> #include "ucontext_i.h"
> #include "ucontext-internal.h"
>
> -/* int setcontext (const ucontext_t *ucp) */
> +/* int __setcontext (const ucontext_t *ucp)
>
> - .text
> -
> -ENTRY(__setcontext)
> -
> - /* Create a signal frame on the stack:
> -
> - fp
> - lr
> - ...
> - sp-> rt_sigframe
> - */
> -
> - stp x29, x30, [sp, -16]!
> - cfi_adjust_cfa_offset (16)
> - cfi_rel_offset (x29, 0)
> - cfi_rel_offset (x30, 8)
> -
> - mov x29, sp
> - cfi_def_cfa_register (x29)
> -
> - /* Allocate space for the sigcontext. */
> - mov w3, #((RT_SIGFRAME_SIZE + SP_ALIGN_SIZE) & SP_ALIGN_MASK)
> - sub sp, sp, x3
> + Restores the machine context in UCP and thereby resumes execution
> + in that context.
>
> - /* Compute the base address of the ucontext structure. */
> - add x1, sp, #RT_SIGFRAME_UCONTEXT
> + This implementation is intended to be used for *synchronous* context
> + switches only. Therefore, it does not have to restore anything
> + other than the PRESERVED state. */
>
> - /* Only ucontext is required in the frame, *copy* it in. */
> -
> -#if UCONTEXT_SIZE % 16
> -#error The implementation of setcontext.S assumes sizeof(ucontext_t) % 16 == 0
> -#endif
> -
> - mov x2, #UCONTEXT_SIZE / 16
> -0:
> - ldp x3, x4, [x0], #16
> - stp x3, x4, [x1], #16
> - sub x2, x2, 1
> - cbnz x2, 0b
> + .text
>
> - /* rt_sigreturn () -- no arguments, sp points to struct rt_sigframe. */
> - mov x8, SYS_ify (rt_sigreturn)
> +ENTRY (__setcontext)
> + /* Save a copy of UCP. */
> + mov x9, x0
> +
> + /* Set the signal mask with
> + rt_sigprocmask (SIG_SETMASK, mask, NULL, _NSIG/8). */
> + mov x0, #SIG_SETMASK
> + add x1, x9, #UCONTEXT_SIGMASK
> + mov x2, #0
> + mov x3, #_NSIG8
> + mov x8, SYS_ify (rt_sigprocmask)
> svc 0
> -
> - /* Ooops we failed. Recover the stack */
> -
> - mov sp, x29
> - cfi_def_cfa_register (sp)
> -
> - ldp x29, x30, [sp], 16
> - cfi_adjust_cfa_offset (16)
> - cfi_restore (x29)
> - cfi_restore (x30)
> - b C_SYMBOL_NAME(__syscall_error)
> -
> + cbz x0, 1f
> + b C_SYMBOL_NAME (__syscall_error)
> +1:
> + /* Restore the general purpose registers. */
> + mov x0, x9
> + cfi_def_cfa (x0, 0)
> + cfi_offset (x18, oX0 + 18 * SZREG)
> + cfi_offset (x19, oX0 + 19 * SZREG)
> + cfi_offset (x20, oX0 + 20 * SZREG)
> + cfi_offset (x21, oX0 + 21 * SZREG)
> + cfi_offset (x22, oX0 + 22 * SZREG)
> + cfi_offset (x23, oX0 + 23 * SZREG)
> + cfi_offset (x24, oX0 + 24 * SZREG)
> + cfi_offset (x25, oX0 + 25 * SZREG)
> + cfi_offset (x26, oX0 + 26 * SZREG)
> + cfi_offset (x27, oX0 + 27 * SZREG)
> + cfi_offset (x28, oX0 + 28 * SZREG)
> + cfi_offset (x29, oX0 + 29 * SZREG)
> + cfi_offset (x30, oX0 + 30 * SZREG)
> +
> + cfi_offset ( d8, oV0 + 8 * SZVREG)
> + cfi_offset ( d9, oV0 + 9 * SZVREG)
> + cfi_offset (d10, oV0 + 10 * SZVREG)
> + cfi_offset (d11, oV0 + 11 * SZVREG)
> + cfi_offset (d12, oV0 + 12 * SZVREG)
> + cfi_offset (d13, oV0 + 13 * SZVREG)
> + cfi_offset (d14, oV0 + 14 * SZVREG)
> + cfi_offset (d15, oV0 + 15 * SZVREG)
> + ldp x18, x19, [x0, oX0 + 18 * SZREG]
> + ldp x20, x21, [x0, oX0 + 20 * SZREG]
> + ldp x22, x23, [x0, oX0 + 22 * SZREG]
> + ldp x24, x25, [x0, oX0 + 24 * SZREG]
> + ldp x26, x27, [x0, oX0 + 26 * SZREG]
> + ldp x28, x29, [x0, oX0 + 28 * SZREG]
> + ldr x30, [x0, oX0 + 30 * SZREG]
> + ldr x2, [x0, oSP]
> + mov sp, x2
> +
> + /* Check for FP SIMD context. */
> + add x2, x0, #oEXTENSION
> +
> + mov w3, #(FPSIMD_MAGIC & 0xffff)
> + movk w3, #(FPSIMD_MAGIC >> 16), lsl #16
> + ldr w1, [x2, #oHEAD + oMAGIC]
> + cmp w1, w3
> + b.ne 2f
> +
> + /* Restore the FP SIMD context. */
> + add x3, x2, #oV0 + 8 * SZVREG
> + ldp d8, d9, [x3], #2 * SZVREG
> + ldp d10, d11, [x3], #2 * SZVREG
> + ldp d12, d13, [x3], #2 * SZVREG
> + ldp d14, d15, [x3], #2 * SZVREG
> +
> + add x3, x2, oFPSR
> +
> + ldr w4, [x3]
> + msr fpsr, x4
> +
> + ldr w4, [x3, oFPCR - oFPSR]
> + msr fpcr, x4
> +
> +2:
> + ldr x16, [x0, oPC]
> + /* Restore arg registers. */
> + ldp x2, x3, [x0, oX0 + 2 * SZREG]
> + ldp x4, x5, [x0, oX0 + 4 * SZREG]
> + ldp x6, x7, [x0, oX0 + 6 * SZREG]
> + ldp x0, x1, [x0, oX0 + 0 * SZREG]
> + /* Jump to the new pc value. */
> + br x16
> PSEUDO_END (__setcontext)
> weak_alias (__setcontext, setcontext)
>
> -ENTRY(__startcontext)
> +ENTRY (__startcontext)
> mov x0, x19
> cbnz x0, __setcontext
> -1: b HIDDEN_JUMPTARGET(_exit)
> -END(__startcontext)
> +1: b HIDDEN_JUMPTARGET (_exit)
> +END (__startcontext)
> --
> 1.8.1.4
>
--
Will Newton
Toolchain Working Group, Linaro
More information about the Libc-alpha
mailing list