1 /* Copyright (C) 2008-2018 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU Transactional Memory Library (libitm).
6 Libitm is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
30 #define CONCAT1(a, b) CONCAT2(a, b)
31 #define CONCAT2(a, b) a ## b
33 #ifdef __USER_LABEL_PREFIX__
34 # define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
40 # define TYPE(x) .type SYM(x), @function
41 # define SIZE(x) .size SYM(x), . - SYM(x)
42 # ifdef HAVE_ATTRIBUTE_VISIBILITY
43 # define HIDDEN(x) .hidden SYM(x)
51 # define HIDDEN(x) .private_extern SYM(x)
57 /* These are duplicates of the canonical definitions in libitm.h. Note that
58 the code relies on pr_uninstrumentedCode == a_runUninstrumentedCode. */
59 #define pr_uninstrumentedCode 0x02
60 #define pr_hasNoAbort 0x08
61 #define pr_HTMRetryableAbort 0x800000
62 #define pr_HTMRetriedAfterAbort 0x1000000
63 #define a_runInstrumentedCode 0x01
64 #define a_runUninstrumentedCode 0x02
65 #define a_tryHTMFastPath 0x20
67 #define _XABORT_EXPLICIT (1 << 0)
68 #define _XABORT_RETRY (1 << 1)
73 .globl SYM(_ITM_beginTransaction)
75 SYM(_ITM_beginTransaction):
80 /* Custom HTM fast path. We start the HW transaction here and let
81 gtm_thread::begin_transaction (aka GTM_begin_transaction) decide
82 how to proceed on aborts: We either retry the fast path, or fall
83 back to another execution method. RTM restores all registers after
84 a HW transaction abort, so we can do the SW setjmp after aborts,
85 and we have to because we might choose a SW fall back. However,
86 we have to explicitly save/restore the first argument (edi).
87 The htm_fastpath field is the second int in gtm_rwlock. */
88 cmpl $0, (SYM(gtm_serial_lock)+4)(%rip)
90 testl $pr_hasNoAbort, %edi
94 /* Monitor the serial lock (specifically, the 32b writer/summary field
95 at its start), and only continue if there is no serial-mode
96 transaction. Note that we might be just a nested transaction and
97 our outermost transaction might be in serial mode; we check for
98 this case in the retry policy implementation. */
99 cmpl $0, SYM(gtm_serial_lock)(%rip)
101 /* Now also check that HW transactions are still allowed to run (see
102 gtm_thread::begin_transaction for why this is necessary). */
103 cmpl $0, (SYM(gtm_serial_lock)+4)(%rip)
105 /* Everything is good. Run the transaction, preferably using the
106 uninstrumented code path. Note that the following works because
107 pr_uninstrumentedCode == a_runUninstrumentedCode. */
108 andl $pr_uninstrumentedCode, %edi
109 mov $a_runInstrumentedCode, %eax
112 /* There is a serial-mode transaction or HW transactions are not
113 allowed anymore, so abort (see htm_abort() regarding the abort
117 /* If it might make sense to retry the HTM fast path, let the C++
119 testl $(_XABORT_RETRY|_XABORT_EXPLICIT), %eax
121 orl $pr_HTMRetryableAbort, %edi
122 /* Let the C++ code handle the retry policy. */
127 cfi_adjust_cfa_offset(72)
128 /* Store edi for future HTM fast path retries. We use a stack slot
129 lower than the jmpbuf so that the jmpbuf's rip field will overlap
130 with the proper return address on the stack. */
132 /* Save the jmpbuf for any non-HTM-fastpath execution method.
133 Because rsp-based addressing is 1 byte larger and we've got rax
143 /* Save zero or shadow stack pointer in the new field. */
144 #if defined __SHSTK__ && defined __CET__ && (__CET__ & 2) != 0
149 call SYM(GTM_begin_transaction)
152 cfi_adjust_cfa_offset(-72)
154 /* If a_tryHTMFastPath was returned, then we need to retry the
155 fast path. We also restore edi and set pr_HTMRetriedAfterAbort
156 to state that we have retried the fast path already (it's harmless
157 if this bit is set even if we don't retry the fast path because it
158 is checked iff pr_HTMRetryableAbort is set). We clear
159 pr_HTMRetryableAbort because it applies to a previous HW
160 transaction attempt. */
161 cmpl $a_tryHTMFastPath, %eax
163 andl $(0xffffffff-pr_HTMRetryableAbort), %edi
164 orl $pr_HTMRetriedAfterAbort, %edi
172 cfi_def_cfa_offset(32)
179 /* Save zero or shadow stack pointer in the new field. */
180 #if defined __SHSTK__ && defined __CET__ && (__CET__ & 2) != 0
185 #if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__
186 call SYM(GTM_begin_transaction)
187 #elif defined __ELF__
190 addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
191 call SYM(GTM_begin_transaction)@PLT
194 # error "Unsupported PIC sequence"
197 cfi_def_cfa_offset(4)
202 TYPE(_ITM_beginTransaction)
203 SIZE(_ITM_beginTransaction)
206 .globl SYM(GTM_longjmp)
222 cfi_register(%rsp, %rcx)
224 #if defined __SHSTK__ && defined __CET__ && (__CET__ & 2) != 0
225 /* Check if Shadow Stack is enabled. */
230 /* Calculate number of frames to skip. */
235 /* If # of frames is greater 255 then loop
260 cfi_register(%esp, %ecx)
262 #if defined __SHSTK__ && defined __CET__ && (__CET__ & 2) != 0
263 /* Check if Shadow Stack is enabled. */
268 /* Calculate # of frames to skip. */
273 /* If # of frames is greater 255 then loop
300 .section .note.GNU-stack, "", @progbits