(root)/
glibc-2.38/
sysdeps/
powerpc/
test-get_hwcap.c
       1  /* Check __ppc_get_hwcap() and __ppc_get_at_plaftorm() functionality.
       2     Copyright (C) 2015-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  /* Tests if the hwcap, hwcap2 and platform data are stored in the TCB.  */
      20  
      21  #include <inttypes.h>
      22  #include <stdio.h>
      23  #include <stdint.h>
      24  #include <pthread.h>
      25  
      26  #include <support/check.h>
      27  #include <support/xthread.h>
      28  
      29  #include <sys/auxv.h>
      30  
      31  #include <dl-procinfo.h>
      32  
      33  #ifndef STATIC_TST_HWCAP
      34  #undef PROCINFO_DECL
      35  #include <dl-procinfo.c>
      36  #endif
      37  
      38  /* Offsets copied from tcb-offsets.h.  */
      39  
      40  #ifdef __powerpc64__
      41  # define __TPREG     "r13"
      42  # define __HWCAPOFF -28776
      43  # define __ATPLATOFF -28764
      44  #else
      45  # define __TPREG     "r2"
      46  # define __HWCAPOFF -28736
      47  # define __HWCAP2OFF -28732
      48  # define __ATPLATOFF -28724
      49  #endif
      50  
      51  uint64_t check_tcbhwcap (long tid)
      52  {
      53  
      54    uint32_t tcb_at_platform, at_platform;
      55    uint64_t hwcap, hwcap2, tcb_hwcap;
      56    const char *at_platform_string;
      57  
      58    /* Testing if the hwcap/hwcap2 data is correctly initialized by
      59       TLS_TP_INIT.  */
      60  
      61    register unsigned long __tp __asm__ (__TPREG);
      62  
      63  #ifdef __powerpc64__
      64    __asm__  ("ld %0,%1(%2)\n"
      65  	    : "=r" (tcb_hwcap)
      66  	    : "n" (__HWCAPOFF), "b" (__tp));
      67  #else
      68    uint64_t h1, h2;
      69  
      70    __asm__ ("lwz %0,%1(%2)\n"
      71        : "=r" (h1)
      72        : "n" (__HWCAPOFF), "b" (__tp));
      73    __asm__ ("lwz %0,%1(%2)\n"
      74        : "=r" (h2)
      75        : "n" (__HWCAP2OFF), "b" (__tp));
      76    tcb_hwcap = (h1 >> 32) << 32 | (h2 >> 32);
      77  #endif
      78  
      79    hwcap = getauxval (AT_HWCAP);
      80    hwcap2 = getauxval (AT_HWCAP2);
      81  
      82    /* hwcap contains only the latest supported ISA, the code checks which is
      83       and fills the previous supported ones.  This is necessary because the
      84       same is done in hwcapinfo.c when setting the values that are copied to
      85       the TCB.  */
      86  
      87    if (hwcap2 & PPC_FEATURE2_ARCH_2_07)
      88      hwcap |= PPC_FEATURE_ARCH_2_06
      89  	  | PPC_FEATURE_ARCH_2_05
      90  	  | PPC_FEATURE_POWER5_PLUS
      91  	  | PPC_FEATURE_POWER5
      92  	  | PPC_FEATURE_POWER4;
      93    else if (hwcap & PPC_FEATURE_ARCH_2_06)
      94      hwcap |= PPC_FEATURE_ARCH_2_05
      95  	  | PPC_FEATURE_POWER5_PLUS
      96  	  | PPC_FEATURE_POWER5
      97  	  | PPC_FEATURE_POWER4;
      98    else if (hwcap & PPC_FEATURE_ARCH_2_05)
      99      hwcap |= PPC_FEATURE_POWER5_PLUS
     100  	  | PPC_FEATURE_POWER5
     101  	  | PPC_FEATURE_POWER4;
     102    else if (hwcap & PPC_FEATURE_POWER5_PLUS)
     103      hwcap |= PPC_FEATURE_POWER5
     104  	  | PPC_FEATURE_POWER4;
     105    else if (hwcap & PPC_FEATURE_POWER5)
     106      hwcap |= PPC_FEATURE_POWER4;
     107  
     108    hwcap = (hwcap << 32) + hwcap2;
     109  
     110    if ( tcb_hwcap != hwcap )
     111      {
     112        printf ("FAIL: __ppc_get_hwcap() - HWCAP is %" PRIx64 ". Should be %"
     113  	      PRIx64 " for thread %ld.\n", tcb_hwcap, hwcap, tid);
     114        return 1;
     115      }
     116  
     117    /* Same test for the platform number.  */
     118    __asm__  ("lwz %0,%1(%2)\n"
     119  	    : "=r" (tcb_at_platform)
     120  	    : "n" (__ATPLATOFF), "b" (__tp));
     121  
     122    at_platform_string = (const char *) getauxval (AT_PLATFORM);
     123    at_platform = _dl_string_platform (at_platform_string);
     124  
     125    if ( tcb_at_platform != at_platform )
     126      {
     127        printf ("FAIL: __ppc_get_at_platform() - AT_PLATFORM is %x. Should be %x"
     128  	     " for thread %ld\n", tcb_at_platform, at_platform, tid);
     129        return 1;
     130      }
     131  
     132    return 0;
     133  }
     134  
     135  void *t1 (void *tid)
     136  {
     137    if (check_tcbhwcap ((long) tid))
     138      {
     139        pthread_exit (tid);
     140      }
     141  
     142    pthread_exit (NULL);
     143  
     144  }
     145  
     146  static int
     147  do_test (void)
     148  {
     149  
     150    pthread_t threads[2];
     151    pthread_attr_t attr;
     152    pthread_attr_init (&attr);
     153    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
     154  
     155    long i = 0;
     156  
     157    /* Check for main.  */
     158    if (check_tcbhwcap (i))
     159      {
     160        return 1;
     161      }
     162  
     163    /* Check for other thread.  */
     164    i++;
     165    threads[i] = xpthread_create (&attr, t1, (void *)i);
     166  
     167    pthread_attr_destroy (&attr);
     168    TEST_VERIFY_EXIT (xpthread_join (threads[i]) == NULL);
     169  
     170    printf("PASS: HWCAP, HWCAP2 and AT_PLATFORM are correctly set in the TCB for"
     171  	 " all threads.\n");
     172  
     173    pthread_exit (NULL);
     174  
     175  }
     176  
     177  #include <support/test-driver.c>