1  /* Copyright (C) 2013-2023 Free Software Foundation, Inc.
       2     Contributed by Andreas Krebbel <krebbel@linux.vnet.ibm.com>.
       3  
       4     This file is part of the GNU Transactional Memory Library (libitm).
       5  
       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.
      10  
      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
      14     more details.
      15  
      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.
      19  
      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/>.  */
      24  
      25  #ifdef HAVE_SYS_AUXV_H
      26  #include <sys/auxv.h>
      27  #endif
      28  
      29  namespace GTM HIDDEN {
      30  
      31  #define HW_CACHELINE_SIZE 256
      32  
      33  typedef struct gtm_jmpbuf
      34  {
      35    /* We save registers r6-r14.  */
      36    long int __gregs[9];
      37    /* r15 is stored into cfa field.  It needs to be named that way
      38       since tls.h is accessing the field by name.  Be aware that this
      39       is not actually what we consider the CFA on s390 (since there is
      40       a fix offset between sp and CFA).  It is merely the saved stack
      41       pointer.  */
      42    void *cfa;
      43  
      44  #ifdef __s390x__
      45    /* We save fpu registers f8 - f15.  */
      46    long __fpregs[8];
      47  #else
      48    /* We save fpu registers f4 and f6.  */
      49    long __fpregs[4];
      50  #endif
      51  } gtm_jmpbuf;
      52  
      53  static inline void
      54  cpu_relax (void)
      55  {
      56    __asm volatile ("" : : : "memory");
      57  }
      58  
      59  
      60  // Use HTM if it is supported by the system.
      61  // See gtm_thread::begin_transaction for how these functions are used.
      62  #if defined (__linux__) \
      63      && defined (HAVE_AS_HTM) \
      64      && defined (HAVE_GETAUXVAL) \
      65      && defined (HWCAP_S390_TE)
      66  
      67  #include <htmintrin.h>
      68  
      69  /* Number of retries for transient failures.  */
      70  #define _HTM_ITM_RETRIES 10
      71  #define USE_HTM_FASTPATH
      72  #define TARGET_BEGIN_TRANSACTION_ATTRIBUTE \
      73    __attribute__ ((target("soft-float")))
      74  
      75  
      76  static inline bool
      77  htm_available ()
      78  {
      79    return (getauxval (AT_HWCAP) & HWCAP_S390_TE) ? true : false;
      80  }
      81  
      82  static inline uint32_t
      83  htm_init ()
      84  {
      85    return htm_available () ? _HTM_ITM_RETRIES : 0;
      86  }
      87  
      88  static inline uint32_t
      89  htm_begin ()
      90  {
      91    __asm volatile (".machine \"all\"  \n\t");
      92    return __builtin_tbegin_nofloat (NULL);
      93  }
      94  
      95  static inline bool
      96  htm_begin_success (uint32_t begin_ret)
      97  {
      98    return begin_ret == _HTM_TBEGIN_STARTED;
      99  }
     100  
     101  static inline void
     102  htm_commit ()
     103  {
     104    __asm volatile (".machine \"all\"  \n\t");
     105    __builtin_tend ();
     106  }
     107  
     108  static inline void
     109  htm_abort ()
     110  {
     111    __asm volatile (".machine \"all\"  \n\t");
     112    __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
     113  }
     114  
     115  static inline bool
     116  htm_abort_should_retry (uint32_t begin_ret)
     117  {
     118    return begin_ret == _HTM_TBEGIN_TRANSIENT;
     119  }
     120  
     121  static inline bool
     122  htm_transaction_active ()
     123  {
     124    __asm volatile (".machine \"all\"  \n\t");
     125    return __builtin_tx_nesting_depth() != 0;
     126  }
     127  
     128  #endif
     129  
     130  } // namespace GTM