coroutine/arm64: Skip saving/restoring x30 twice and use autiasp

We don't need to save/restore x30 twice, and we can just use `ret`,
which uses x30 as return address register instead of explicit `ret <reg>`
instruction. This also allows us to use `autiasp` instead of `autia1716`
and we can skip setting SP/LR to x16/x17.

Also the size of register save area is shrunk by 16 bytes due to the
removal of extra x30 save/restore.
This commit is contained in:
Yuta Saito 2023-12-22 08:52:20 +09:00
parent 2d004decde
commit fa0f7522c4
2 changed files with 8 additions and 15 deletions

View file

@ -36,7 +36,7 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
hint #34
#endif
# Make space on the stack for caller registers
sub sp, sp, 0xb0
sub sp, sp, 0xa0
# Save caller registers
stp d8, d9, [sp, 0x00]
@ -50,9 +50,6 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
stp x27, x28, [sp, 0x80]
stp x29, x30, [sp, 0x90]
# Save return address
str x30, [sp, 0xa0]
# Save stack pointer to x0 (first argument)
mov x2, sp
str x2, [x0, 0]
@ -73,20 +70,16 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
ldp x27, x28, [sp, 0x80]
ldp x29, x30, [sp, 0x90]
# Load return address into x17
ldr x17, [sp, 0xa0]
# Pop stack frame
add sp, sp, 0xb0
add sp, sp, 0xa0
#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
mov x16, sp
# autia1716
hint #12
# autiasp: Authenticate x30 (LR) with SP and key A
hint #29
#endif
# Jump to return address (in x17)
ret x17
# Jump to return address (in x30)
ret
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits

View file

@ -17,7 +17,7 @@
#define COROUTINE __attribute__((noreturn)) void
enum {COROUTINE_REGISTERS = 0xb0 / 8};
enum {COROUTINE_REGISTERS = 0xa0 / 8};
#if defined(__SANITIZE_ADDRESS__)
#define COROUTINE_SANITIZE_ADDRESS
@ -89,7 +89,7 @@ static inline void coroutine_initialize(
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
context->stack_pointer[0xa0 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top);
context->stack_pointer[0x98 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top);
}
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);