From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by sourceware.org (Postfix) with ESMTP id 9EAB7383508C for ; Wed, 16 Dec 2020 19:40:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 9EAB7383508C Received: from microsoft-linux.home (unknown [47.187.219.45]) by linux.microsoft.com (Postfix) with ESMTPSA id 28C3020B718A; Wed, 16 Dec 2020 11:40:19 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 28C3020B718A From: madvenka@linux.microsoft.com To: libffi-discuss@sourceware.org Cc: green@moxielogic.com, fw@deneb.enyo.de, dj@redhat.com, madvenka@linux.microsoft.com Subject: [RFC PATCH v2 5/5] arm: Support for Static Trampolines Date: Wed, 16 Dec 2020 13:40:09 -0600 Message-Id: <20201216194009.8268-6-madvenka@linux.microsoft.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201216194009.8268-1-madvenka@linux.microsoft.com> References: <20201216194009.8268-1-madvenka@linux.microsoft.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-27.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, ENV_AND_HDR_SPF_MATCH, GIT_PATCH_0, SPF_HELO_PASS, SPF_PASS, TXREP, USER_IN_DEF_DKIM_WL, USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libffi-discuss@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libffi-discuss mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Dec 2020 19:40:22 -0000 From: "Madhavan T. Venkataraman" - Define the arch-specific initialization function ffi_tramp_arch () that returns trampoline size information to common code. - Define the trampoline code mapping and data mapping sizes. - Define the trampoline code table statically. - Introduce a tiny prolog for each ABI handling function. The ABI handlers addressed are: - ffi_closure_SYSV - ffi_closure_VFP Their prolog functions are called: - ffi_closure_SYSV_alt - ffi_closure_VFP_alt The legacy trampoline jumps to the ABI handler. The static trampoline jumps to the prolog function. The prolog function uses the information provided by the static trampoline, sets things up for the ABI handler and then jumps to the ABI handler. - Call ffi_closure_tramp_init () in ffi_prep_closure_loc () to initialize static trampoline parameters. Signed-off-by: Madhavan T. Venkataraman --- src/arm/ffi.c | 29 ++++++++++++++++++++++++++++- src/arm/internal.h | 10 ++++++++++ src/arm/sysv.S | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/arm/ffi.c b/src/arm/ffi.c index 0058390..7e3cf1a 100644 --- a/src/arm/ffi.c +++ b/src/arm/ffi.c @@ -570,7 +570,9 @@ ffi_closure_inner_VFP (ffi_cif *cif, } void ffi_closure_SYSV (void) FFI_HIDDEN; +void ffi_closure_SYSV_alt (void) FFI_HIDDEN; void ffi_closure_VFP (void) FFI_HIDDEN; +void ffi_closure_VFP_alt (void) FFI_HIDDEN; #ifdef FFI_GO_CLOSURES void ffi_go_closure_SYSV (void) FFI_HIDDEN; @@ -596,12 +598,16 @@ ffi_prep_closure_loc (ffi_closure * closure, void *user_data, void *codeloc) { void (*closure_func) (void) = ffi_closure_SYSV; + void (*closure_func_alt) (void) = ffi_closure_SYSV_alt; if (cif->abi == FFI_VFP) { /* We only need take the vfp path if there are vfp arguments. */ if (cif->vfp_used) - closure_func = ffi_closure_VFP; + { + closure_func = ffi_closure_VFP; + closure_func_alt = ffi_closure_VFP_alt; + } } else if (cif->abi != FFI_SYSV) return FFI_BAD_ABI; @@ -612,6 +618,14 @@ ffi_prep_closure_loc (ffi_closure * closure, config[1] = closure_func; #else + if (ffi_tramp_is_present(closure)) + { + /* Initialize the static trampoline's parameters. */ + ffi_tramp_set_parms (closure->ftramp, closure_func_alt, closure); + goto out; + } + + /* Initialize the dynamic trampoline. */ #ifndef _M_ARM memcpy(closure->tramp, ffi_arm_trampoline, 8); #else @@ -633,6 +647,7 @@ ffi_prep_closure_loc (ffi_closure * closure, #else *(void (**)(void))(closure->tramp + 8) = closure_func; #endif +out: #endif closure->cif = cif; @@ -873,4 +888,16 @@ layout_vfp_args (ffi_cif * cif) } } +#if defined(FFI_EXEC_STATIC_TRAMP) +void * +ffi_tramp_arch (size_t *tramp_size, size_t *map_size) +{ + extern void *trampoline_code_table; + + *tramp_size = ARM_TRAMP_SIZE; + *map_size = ARM_TRAMP_MAP_SIZE; + return &trampoline_code_table; +} +#endif + #endif /* __arm__ or _M_ARM */ diff --git a/src/arm/internal.h b/src/arm/internal.h index 6cf0b2a..fa8ab0b 100644 --- a/src/arm/internal.h +++ b/src/arm/internal.h @@ -5,3 +5,13 @@ #define ARM_TYPE_INT 4 #define ARM_TYPE_VOID 5 #define ARM_TYPE_STRUCT 6 + +#if defined(FFI_EXEC_STATIC_TRAMP) +/* + * For the trampoline table mapping, a mapping size of 4K (base page size) + * is chosen. + */ +#define ARM_TRAMP_MAP_SHIFT 12 +#define ARM_TRAMP_MAP_SIZE (1 << ARM_TRAMP_MAP_SHIFT) +#define ARM_TRAMP_SIZE 20 +#endif diff --git a/src/arm/sysv.S b/src/arm/sysv.S index 74bc53f..7617e57 100644 --- a/src/arm/sysv.S +++ b/src/arm/sysv.S @@ -260,6 +260,12 @@ ARM_FUNC_START(ffi_closure_SYSV) UNWIND(.fnend) ARM_FUNC_END(ffi_closure_SYSV) +ARM_FUNC_START(ffi_closure_SYSV_alt) + ldr ip, [sp, #4] + add sp, sp, 8 + b CNAME(ffi_closure_SYSV) +ARM_FUNC_END(ffi_closure_SYSV_alt) + ARM_FUNC_START(ffi_go_closure_VFP) cfi_startproc stmdb sp!, {r0-r3} @ save argument regs @@ -310,6 +316,12 @@ ARM_FUNC_START(ffi_closure_VFP) UNWIND(.fnend) ARM_FUNC_END(ffi_closure_VFP) +ARM_FUNC_START(ffi_closure_VFP_alt) + ldr ip, [sp, #4] + add sp, sp, 8 + b CNAME(ffi_closure_VFP) +ARM_FUNC_END(ffi_closure_VFP_alt) + /* Load values returned in registers for both closure entry points. Note that we use LDM with SP in the register set. This is deprecated by ARM, but not yet unpredictable. */ @@ -354,6 +366,35 @@ E(ARM_TYPE_STRUCT) cfi_endproc ARM_FUNC_END(ffi_closure_ret) +#if defined(FFI_EXEC_STATIC_TRAMP) +/* + * The trampoline uses register ip (r12). It saves the original value of ip + * on the stack. + * + * The trampoline has two parameters - target code to jump to and data for + * the target code. The trampoline extracts the parameters from its parameter + * block (see tramp_table_map()). The trampoline saves the data address on + * the stack. Finally, it jumps to the target code. + * + * The target code can choose to: + * + * - restore the value of ip + * - load the data address in a register + * - restore the stack pointer to what it was when the trampoline was invoked. + */ + .align ARM_TRAMP_MAP_SHIFT +ARM_FUNC_START(trampoline_code_table) + .rept ARM_TRAMP_MAP_SIZE / ARM_TRAMP_SIZE + sub sp, sp, #8 /* Make space on the stack */ + str ip, [sp] /* Save ip on stack */ + ldr ip, [pc, #4080] /* Copy data into ip */ + str ip, [sp, #4] /* Save data on stack */ + ldr pc, [pc, #4076] /* Copy code into PC */ + .endr +ARM_FUNC_END(trampoline_code_table) + .align ARM_TRAMP_MAP_SHIFT +#endif /* FFI_EXEC_STATIC_TRAMP */ + #if FFI_EXEC_TRAMPOLINE_TABLE #ifdef __MACH__ -- 2.27.0