From 05538db4dc09764a7f1405a64a9005e45f12f602 Mon Sep 17 00:00:00 2001 From: Theo Schlossnagle Date: Wed, 29 Apr 2020 20:08:17 +0000 Subject: [PATCH] Add support for aarch64 --- aco.c | 23 +++++++++++++++++------ aco.h | 11 +++++++++++ acosw.S | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/aco.c b/aco.c index 812914c..f3c51c1 100644 --- a/aco.c +++ b/aco.c @@ -24,7 +24,7 @@ void aco_runtime_test(void){ #ifdef __i386__ _Static_assert(sizeof(void*) == 4, "require 'sizeof(void*) == 4'"); -#elif __x86_64__ +#elif defined(__x86_64__) || defined(__aarch64__) _Static_assert(sizeof(void*) == 8, "require 'sizeof(void*) == 8'"); _Static_assert(sizeof(__uint128_t) == 16, "require 'sizeof(__uint128_t) == 16'"); #else @@ -171,7 +171,7 @@ static __thread aco_cofuncp_t aco_gtls_last_word_fp = aco_default_protector_last #ifdef __i386__ static __thread void* aco_gtls_fpucw_mxcsr[2]; -#elif __x86_64__ +#elif defined(__x86_64__) || defined(__aarch64__) static __thread void* aco_gtls_fpucw_mxcsr[1]; #else #error "platform no support yet" @@ -273,11 +273,16 @@ aco_share_stack_t* aco_share_stack_new2(size_t sz, char guard_page_enabled){ p->ptr, (void*)((uintptr_t)p->ptr + p->sz) ); #endif -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) uintptr_t u_p = (uintptr_t)(p->sz - (sizeof(void*) << 1) + (uintptr_t)p->ptr); u_p = (u_p >> 4) << 4; p->align_highptr = (void*)u_p; +#ifdef __aarch64__ + // aarch64 hardware-enforces 16 byte stack alignment + p->align_retptr = (void*)(u_p - 16); +#else p->align_retptr = (void*)(u_p - sizeof(void*)); +#endif *((void**)(p->align_retptr)) = (void*)(aco_funcp_protector_asm); assert(p->sz > (16 + (sizeof(void*) << 1) + sizeof(void*))); p->align_limit = p->sz - 16 - (sizeof(void*) << 1); @@ -331,6 +336,12 @@ aco_t* aco_create( #ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV p->reg[ACO_REG_IDX_FPU] = aco_gtls_fpucw_mxcsr[0]; #endif +#elif __aarch64__ + p->reg[ACO_REG_IDX_RETADDR] = (void*)fp; + p->reg[ACO_REG_IDX_SP] = p->share_stack->align_retptr; + #ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + p->reg[ACO_REG_IDX_FPU] = aco_gtls_fpucw_mxcsr[0]; + #endif #else #error "platform no support yet" #endif @@ -343,7 +354,7 @@ aco_t* aco_create( p->save_stack.ptr = malloc(save_stack_sz); assertalloc_ptr(p->save_stack.ptr); p->save_stack.sz = save_stack_sz; -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) p->save_stack.valid_sz = 0; #else #error "platform no support yet" @@ -369,7 +380,7 @@ void aco_resume(aco_t* resume_co){ if(resume_co->share_stack->owner != NULL){ aco_t* owner_co = resume_co->share_stack->owner; assert(owner_co->share_stack == resume_co->share_stack); -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) assert( ( (uintptr_t)(owner_co->share_stack->align_retptr) @@ -430,7 +441,7 @@ void aco_resume(aco_t* resume_co){ #endif } assert(resume_co->share_stack->owner == NULL); -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) assert( resume_co->save_stack.valid_sz <= diff --git a/aco.h b/aco.h index 97ea2ec..d416542 100644 --- a/aco.h +++ b/aco.h @@ -46,6 +46,11 @@ extern "C" { #define ACO_REG_IDX_SP 5 #define ACO_REG_IDX_BP 7 #define ACO_REG_IDX_FPU 8 +#elif __aarch64__ + #define ACO_REG_IDX_RETADDR 13 + #define ACO_REG_IDX_SP 14 + #define ACO_REG_IDX_BP 12 + #define ACO_REG_IDX_FPU 15 #else #error "platform no support yet" #endif @@ -99,6 +104,12 @@ struct aco_s{ #else void* reg[9]; #endif +#elif __aarch64__ + #ifdef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + void* reg[15]; + #else + void* reg[16]; + #endif #else #error "platform no support yet" #endif diff --git a/acosw.S b/acosw.S index 6dbdae1..38aeb35 100644 --- a/acosw.S +++ b/acosw.S @@ -4,7 +4,9 @@ #else .type acosw, @function #endif +#ifndef __aarch64__ .intel_syntax noprefix +#endif acosw: /* extern void acosw(aco_t* from_co, aco_t* to_co); @@ -118,6 +120,43 @@ acosw: #endif mov rsp,rcx jmp rax +#elif __aarch64__ +/* + 0x00 --> 0xff + x16 x17 x19 ... x29 lr sp fpcr + 0 8 10 ... 60 68 70 78 +*/ + // r0 - from_co | r1 - to_co + mov x2, lr + stp x16, x17, [x0, 0x00] + stp x19, x20, [x0, 0x10] + stp x21, x22, [x0, 0x20] + stp x23, x24, [x0, 0x30] + stp x25, x26, [x0, 0x40] + stp x27, x28, [x0, 0x50] + stp x29, lr, [x0, 0x60] + mov x5, sp + str x5, [x0, 0x70] +#ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + mrs x5, fpcr + str x5, [x1, 0x78] +#endif + + ldp x16, x17, [x1, 0x00] + ldp x19, x20, [x1, 0x10] + ldp x21, x22, [x1, 0x20] + ldp x23, x24, [x1, 0x30] + ldp x25, x26, [x1, 0x40] + ldp x27, x28, [x1, 0x50] + ldp x29, x30, [x1, 0x60] + ldr x3, [x1, 0x70] + mov sp, x3 +#ifndef ACO_CONFIG_SHARE_FPU_MXCSR_ENV + ldr x3, [x1, 0x78] + msr fpcr,x3 +#endif + + br x30 #else #error "platform not support" #endif @@ -127,7 +166,9 @@ acosw: #else .type aco_save_fpucw_mxcsr, @function #endif +#ifndef __aarch64__ .intel_syntax noprefix +#endif aco_save_fpucw_mxcsr: #ifdef __i386__ mov eax,DWORD PTR [esp+0x4] // ptr @@ -138,6 +179,10 @@ aco_save_fpucw_mxcsr: fnstcw WORD PTR [rdi] stmxcsr DWORD PTR [rdi+0x4] ret +#elif __aarch64__ + mrs x1, fpcr + str x1, [x0] + ret #else #error "platform not support" #endif @@ -155,7 +200,9 @@ aco_save_fpucw_mxcsr: #else .type aco_funcp_protector_asm, @function #endif +#ifndef __aarch64__ .intel_syntax noprefix +#endif aco_funcp_protector_asm: #ifdef __i386__ and esp,0xfffffff0 @@ -187,6 +234,13 @@ aco_funcp_protector_asm: #endif #endif ret +#elif __aarch64__ + mov x9, sp + and x9, x9, #0xfffffffffffffff0 + mov sp, x9 + bl aco_funcp_protector + bl abort + ret #else #error "platform not support" #endif