powerpc: Add hwcap/hwcap2/platform data to TCB.

This patch adds a new feature for powerpc.  In order to get faster access to
the HWCAP/HWCAP2 bits and platform number (i.e. for implementing
__builtin_cpu_is () / __builtin_cpu_supports () in GCC) without the overhead of
reading from the auxiliary vector, we now reserve space for them in the TCB.
This is an ABI change for GLIBC 2.23.

A new versioned symbol '__parse_hwcap_and_convert_at_platform' is available to
get the data from the auxiliary vector and parse it, and store it for later use
in the TLS initialization code.  This function is called very early
(in _dl_sysdep_start () via DL_PLATFORM_INFO for the dynamic linking case, and
in __libc_start_main () for the static linking case) to make sure the data is
available at the time of TLS initialization.

	* sysdeps/powerpc/Makefile (sysdep-dl-routines): Add hwcapinfo.
	(sysdep_routines): Likewise.
	(sysdep-rtld-routines): Likewise.
	[$(subdir) = nptl](tests): Add test-get_hwcap and test-get_hwcap-static
	[$(subdir) = nptl](tests-static): test-get_hwcap-static
	* sysdeps/powerpc/Versions: Added new
	__parse_hwcap_and_convert_at_platform symbol to GLIBC-2.23.
	* sysdeps/powerpc/hwcapinfo.c: New file.
	(__tcb_parse_hwcap_and_convert_at_platform): New function to initialize
	and parse hwcap, hwcap2 and platform number information.
	* sysdeps/powerpc/hwcapinfo.h: New file.  Creates global variables
	to store HWCAP+HWCAP2 and platform number.
	* sysdeps/powerpc/nptl/tcb-offsets.sym: Added new offsets
	for HWCAP+HWCAP2 and platform number in the TCB.
	* sysdeps/powerpc/nptl/tls.h: New functionality.  Stores
	the HWCAP, HWCAP2 and platform number in the TCB.
	(dtv): Added new fields for HWCAP+HWCAP2 and platform number.
	(TLS_INIT_TP): Included calls to add the hwcap and
	at_platform values in the TCB in TP initialization.
	(TLS_DEFINE_INIT_TP): Likewise.
	(THREAD_GET_HWCAP): New macro.
	(THREAD_SET_HWCAP): Likewise.
	(THREAD_GET_AT_PLATFORM): Likewise.
	(THREAD_SET_AT_PLATFORM): Likewise.
	* sysdeps/powerpc/powerpc32/dl-machine.h:
	(dl_platform_init): New function that calls
	__parse_hwcap_and_convert_at_platform for the dymanic linking case for
	powerpc32.
	* sysdeps/powerpc/powerpc64/dl-machine.h: Likewise, for powerpc64.
	* sysdeps/powerpc/test-get_hwcap-static.c: New file.  Testcase for
	this functionality, static linking case.
	* sysdeps/powerpc/test-get_hwcap.c: New file.  Likewise, dynamic
	linking case.
	* sysdeps/unix/sysv/linux/powerpc/libc-start.c: Added call to
	__parse_hwcap_and_convert_at_platform for the static linking case.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist:
	Included the new __parse_hwcap_and_convert_at_platform symbol in the
	ABI list for GLIBC 2.23.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist:
	Likewise.
This commit is contained in:
Carlos Eduardo Seo 2015-10-22 19:26:58 -05:00 committed by Tulio Magno Quites Machado Filho
parent db340c904d
commit 67385a01d2
15 changed files with 480 additions and 7 deletions

View File

@ -1,3 +1,48 @@
2015-12-03 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>
* sysdeps/powerpc/Makefile (sysdep-dl-routines): Add hwcapinfo.
(sysdep_routines): Likewise.
(sysdep-rtld-routines): Likewise.
[$(subdir) = nptl](tests): Add test-get_hwcap and test-get_hwcap-static
[$(subdir) = nptl](tests-static): test-get_hwcap-static
* sysdeps/powerpc/Versions: Added new
__parse_hwcap_and_convert_at_platform symbol to GLIBC-2.23.
* sysdeps/powerpc/hwcapinfo.c: New file.
(__tcb_parse_hwcap_and_convert_at_platform): New function to initialize
and parse hwcap, hwcap2 and platform number information.
* sysdeps/powerpc/hwcapinfo.h: New file. Creates global variables
to store HWCAP+HWCAP2 and platform number.
* sysdeps/powerpc/nptl/tcb-offsets.sym: Added new offsets
for HWCAP+HWCAP2 and platform number in the TCB.
* sysdeps/powerpc/nptl/tls.h: New functionality. Stores
the HWCAP, HWCAP2 and platform number in the TCB.
(dtv): Added new fields for HWCAP+HWCAP2 and platform number.
(TLS_INIT_TP): Included calls to add the hwcap and
at_platform values in the TCB in TP initialization.
(TLS_DEFINE_INIT_TP): Likewise.
(THREAD_GET_HWCAP): New macro.
(THREAD_SET_HWCAP): Likewise.
(THREAD_GET_AT_PLATFORM): Likewise.
(THREAD_SET_AT_PLATFORM): Likewise.
* sysdeps/powerpc/powerpc32/dl-machine.h:
(dl_platform_init): New function that calls
__parse_hwcap_and_convert_at_platform for the dymanic linking case for
powerpc32.
* sysdeps/powerpc/powerpc64/dl-machine.h: Likewise, for powerpc64.
* sysdeps/powerpc/test-get_hwcap-static.c: New file. Testcase for
this functionality, static linking case.
* sysdeps/powerpc/test-get_hwcap.c: New file. Likewise, dynamic
linking case.
* sysdeps/unix/sysv/linux/powerpc/libc-start.c: Added call to
__parse_hwcap_and_convert_at_platform for the static linking case.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist:
Included the new __parse_hwcap_and_convert_at_platform symbol in the
ABI list for GLIBC 2.23.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist:
Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist:
Likewise.
2015-12-02 Ludovic Courtès <ludo@gnu.org>
* configure.ac: Use 'pwd -P' instead of '/bin/pwd'.

View File

@ -4,10 +4,10 @@ endif
ifeq ($(subdir),elf)
# extra shared linker files to link into dl-allobjs.so and libc
sysdep-dl-routines += dl-machine
sysdep_routines += dl-machine
sysdep-dl-routines += dl-machine hwcapinfo
sysdep_routines += dl-machine hwcapinfo
# extra shared linker files to link only into dl-allobjs.so
sysdep-rtld-routines += dl-machine
sysdep-rtld-routines += dl-machine hwcapinfo
# Don't optimize GD tls sequence to LE.
LDFLAGS-tst-tlsopt-powerpc += -Wl,--no-tls-optimize
tests += tst-tlsopt-powerpc
@ -26,6 +26,11 @@ gen-as-const-headers += rtld-global-offsets.sym
gen-as-const-headers += locale-defines.sym
endif
ifeq ($(subdir),nptl)
tests += test-get_hwcap test-get_hwcap-static
tests-static += test-get_hwcap-static
endif
ifeq ($(subdir),misc)
sysdep_headers += sys/platform/ppc.h
tests += test-gettimebase

View File

@ -20,4 +20,9 @@ ld {
GLIBC_2.22 {
__tls_get_addr_opt;
}
GLIBC_2.23 {
# Symbol used to version control when the ABI started to specify that HWCAP
# and AT_PLATFORM data should be stored into the TCB.
__parse_hwcap_and_convert_at_platform;
}
}

View File

@ -0,0 +1,76 @@
/* powerpc HWCAP/HWCAP2 and AT_PLATFORM data pre-processing.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <shlib-compat.h>
#include <dl-procinfo.h>
uint64_t __tcb_hwcap __attribute__ ((visibility ("hidden")));
uint32_t __tcb_platform __attribute__ ((visibility ("hidden")));
/* This function parses the HWCAP/HWCAP2 fields, adding the previous supported
ISA bits, as well as converting the AT_PLATFORM string to a number. This
data is stored in two global variables that can be used later by the
powerpc-specific code to store it into the TCB. */
void
__tcb_parse_hwcap_and_convert_at_platform (void)
{
uint64_t h1, h2;
/* Read AT_PLATFORM string from auxv and convert it to a number. */
__tcb_platform = _dl_string_platform (GLRO (dl_platform));
/* Read HWCAP and HWCAP2 from auxv. */
h1 = GLRO (dl_hwcap);
h2 = GLRO (dl_hwcap2);
/* hwcap contains only the latest supported ISA, the code checks which is
and fills the previous supported ones. */
if (h2 & PPC_FEATURE2_ARCH_2_07)
h1 |= PPC_FEATURE_ARCH_2_06
| PPC_FEATURE_ARCH_2_05
| PPC_FEATURE_POWER5_PLUS
| PPC_FEATURE_POWER5
| PPC_FEATURE_POWER4;
else if (h1 & PPC_FEATURE_ARCH_2_06)
h1 |= PPC_FEATURE_ARCH_2_05
| PPC_FEATURE_POWER5_PLUS
| PPC_FEATURE_POWER5
| PPC_FEATURE_POWER4;
else if (h1 & PPC_FEATURE_ARCH_2_05)
h1 |= PPC_FEATURE_POWER5_PLUS
| PPC_FEATURE_POWER5
| PPC_FEATURE_POWER4;
else if (h1 & PPC_FEATURE_POWER5_PLUS)
h1 |= PPC_FEATURE_POWER5
| PPC_FEATURE_POWER4;
else if (h1 & PPC_FEATURE_POWER5)
h1 |= PPC_FEATURE_POWER4;
/* Consolidate both HWCAP and HWCAP2 into a single doubleword so that
we can read both in a single load later. */
__tcb_hwcap = h2;
__tcb_hwcap = (h1 << 32) | __tcb_hwcap;
}
#if IS_IN (rtld)
versioned_symbol (ld, __tcb_parse_hwcap_and_convert_at_platform, \
__parse_hwcap_and_convert_at_platform, GLIBC_2_23);
#endif

View File

@ -0,0 +1,29 @@
/* powerpc HWCAP/HWCAP2 and AT_PLATFORM data pre-processing.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdint.h>
#ifndef HWCAPINFO_H
# define HWCAPINFO_H
extern uint64_t __tcb_hwcap attribute_hidden;
extern uint32_t __tcb_platform attribute_hidden;
extern void __tcb_parse_hwcap_and_convert_at_platform (void);
#endif

View File

@ -19,7 +19,15 @@ POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (
TAR_SAVE (offsetof (tcbhead_t, tar_save) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
DSO_SLOT1 (offsetof (tcbhead_t, dso_slot1) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
DSO_SLOT2 (offsetof (tcbhead_t, dso_slot2) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
#ifdef __powerpc64__
TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
#endif
TM_CAPABLE (offsetof (tcbhead_t, tm_capable) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
#ifndef __powerpc64__
TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
PADDING (offsetof (tcbhead_t, padding) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
#endif
TCB_HWCAP (offsetof (tcbhead_t, hwcap) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
#ifndef __ASSUME_PRIVATE_FUTEX
PRIVATE_FUTEX_OFFSET thread_offsetof (header.private_futex)
#endif

View File

@ -44,6 +44,8 @@ typedef union dtv
#ifndef __ASSEMBLER__
# include <hwcapinfo.h>
/* Get system call information. */
# include <sysdep.h>
@ -63,8 +65,24 @@ typedef union dtv
are private. */
typedef struct
{
/* Reservation for HWCAP data. To be accessed by GCC in
__builtin_cpu_supports(), so it is a part of public ABI. */
uint64_t hwcap;
/* Reservation for AT_PLATFORM data. To be accessed by GCC in
__builtin_cpu_is(), so it is a part of public ABI. Since there
are different ABIs for 32 and 64 bit, we put this field in a
previously empty padding space for powerpc64. */
#ifndef __powerpc64__
/* Padding to maintain alignment. */
uint32_t padding;
uint32_t at_platform;
#endif
/* Indicate if HTM capable (ISA 2.07). */
int tm_capable;
uint32_t tm_capable;
/* Reservation for AT_PLATFORM data - powerpc64. */
#ifdef __powerpc64__
uint32_t at_platform;
#endif
/* Reservation for Dynamic System Optimizer ABI. */
uintptr_t dso_slot2;
uintptr_t dso_slot1;
@ -134,7 +152,9 @@ register void *__thread_register __asm__ ("r13");
# define TLS_INIT_TP(tcbp) \
({ \
__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET; \
THREAD_SET_TM_CAPABLE (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM ? 1 : 0); \
THREAD_SET_TM_CAPABLE (__tcb_hwcap & PPC_FEATURE2_HAS_HTM ? 1 : 0); \
THREAD_SET_HWCAP (__tcb_hwcap); \
THREAD_SET_AT_PLATFORM (__tcb_platform); \
NULL; \
})
@ -142,7 +162,11 @@ register void *__thread_register __asm__ ("r13");
# define TLS_DEFINE_INIT_TP(tp, pd) \
void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE; \
(((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].tm_capable) = \
THREAD_GET_TM_CAPABLE ();
THREAD_GET_TM_CAPABLE (); \
(((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].hwcap) = \
THREAD_GET_HWCAP (); \
(((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].at_platform) = \
THREAD_GET_AT_PLATFORM ();
/* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \
@ -203,6 +227,20 @@ register void *__thread_register __asm__ ("r13");
# define THREAD_SET_TM_CAPABLE(value) \
(THREAD_GET_TM_CAPABLE () = (value))
/* hwcap field in TCB head. */
# define THREAD_GET_HWCAP() \
(((tcbhead_t *) ((char *) __thread_register \
- TLS_TCB_OFFSET))[-1].hwcap)
# define THREAD_SET_HWCAP(value) \
(THREAD_GET_HWCAP () = (value))
/* at_platform field in TCB head. */
# define THREAD_GET_AT_PLATFORM() \
(((tcbhead_t *) ((char *) __thread_register \
- TLS_TCB_OFFSET))[-1].at_platform)
# define THREAD_SET_AT_PLATFORM(value) \
(THREAD_GET_AT_PLATFORM () = (value))
/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some
different value to mean unset l_tls_offset. */
# define NO_TLS_OFFSET -1

View File

@ -24,6 +24,7 @@
#include <assert.h>
#include <dl-tls.h>
#include <dl-irel.h>
#include <hwcapinfo.h>
/* Translate a processor specific dynamic tag to the index
in l_info array. */
@ -150,6 +151,19 @@ __elf_preferred_address(struct link_map *loader, size_t maplength,
#define ELF_MACHINE_NO_REL 1
#define ELF_MACHINE_NO_RELA 0
/* We define an initialization function to initialize HWCAP/HWCAP2 and
platform data so it can be copied into the TCB later. This is called
very early in _dl_sysdep_start for dynamically linked binaries. */
#ifdef SHARED
# define DL_PLATFORM_INIT dl_platform_init ()
static inline void __attribute__ ((unused))
dl_platform_init (void)
{
__tcb_parse_hwcap_and_convert_at_platform ();
}
#endif
/* Set up the loaded object described by MAP so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c.
Also install a small trampoline to be used by entries that have

View File

@ -26,6 +26,7 @@
#include <sys/param.h>
#include <dl-tls.h>
#include <sysdep.h>
#include <hwcapinfo.h>
/* Translate a processor specific dynamic tag to the index
in l_info array. */
@ -296,6 +297,19 @@ BODY_PREFIX "_dl_start_user:\n" \
#define ELF_MACHINE_NO_REL 1
#define ELF_MACHINE_NO_RELA 0
/* We define an initialization function to initialize HWCAP/HWCAP2 and
platform data so it can be copied into the TCB later. This is called
very early in _dl_sysdep_start for dynamically linked binaries. */
#ifdef SHARED
# define DL_PLATFORM_INIT dl_platform_init ()
static inline void __attribute__ ((unused))
dl_platform_init (void)
{
__tcb_parse_hwcap_and_convert_at_platform ();
}
#endif
/* Stuff for the PLT. */
#if _CALL_ELF != 2
#define PLT_INITIAL_ENTRY_WORDS 3

View File

@ -0,0 +1,23 @@
/* Check __ppc_get_hwcap() and __ppc_get_at_plaftorm() functionality.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Tests if the hwcap, hwcap2 and platform data are stored in the TCB. */
#define STATIC_TST_HWCAP 1
#include "test-get_hwcap.c"

View File

@ -0,0 +1,188 @@
/* Check __ppc_get_hwcap() and __ppc_get_at_plaftorm() functionality.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Tests if the hwcap, hwcap2 and platform data are stored in the TCB. */
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/auxv.h>
#include <dl-procinfo.h>
#ifndef STATIC_TST_HWCAP
#undef PROCINFO_DECL
#include <dl-procinfo.c>
#endif
/* Offsets copied from tcb-offsets.h. */
#ifdef __powerpc64__
# define __TPREG "r13"
# define __HWCAPOFF -28776
# define __ATPLATOFF -28764
#else
# define __TPREG "r2"
# define __HWCAPOFF -28736
# define __HWCAP2OFF -28732
# define __ATPLATOFF -28724
#endif
uint64_t check_tcbhwcap (long tid)
{
uint32_t tcb_at_platform, at_platform;
uint64_t hwcap, hwcap2, tcb_hwcap;
const char *at_platform_string;
/* Testing if the hwcap/hwcap2 data is correctly initialized by
TLS_TP_INIT. */
register unsigned long __tp __asm__ (__TPREG);
#ifdef __powerpc64__
__asm__ ("ld %0,%1(%2)\n"
: "=r" (tcb_hwcap)
: "i" (__HWCAPOFF), "b" (__tp));
#else
uint64_t h1, h2;
__asm__ ("lwz %0,%1(%2)\n"
: "=r" (h1)
: "i" (__HWCAPOFF), "b" (__tp));
__asm__ ("lwz %0,%1(%2)\n"
: "=r" (h2)
: "i" (__HWCAP2OFF), "b" (__tp));
tcb_hwcap = (h1 >> 32) << 32 | (h2 >> 32);
#endif
hwcap = getauxval (AT_HWCAP);
hwcap2 = getauxval (AT_HWCAP2);
/* hwcap contains only the latest supported ISA, the code checks which is
and fills the previous supported ones. This is necessary because the
same is done in hwcapinfo.c when setting the values that are copied to
the TCB. */
if (hwcap2 & PPC_FEATURE2_ARCH_2_07)
hwcap |= PPC_FEATURE_ARCH_2_06
| PPC_FEATURE_ARCH_2_05
| PPC_FEATURE_POWER5_PLUS
| PPC_FEATURE_POWER5
| PPC_FEATURE_POWER4;
else if (hwcap & PPC_FEATURE_ARCH_2_06)
hwcap |= PPC_FEATURE_ARCH_2_05
| PPC_FEATURE_POWER5_PLUS
| PPC_FEATURE_POWER5
| PPC_FEATURE_POWER4;
else if (hwcap & PPC_FEATURE_ARCH_2_05)
hwcap |= PPC_FEATURE_POWER5_PLUS
| PPC_FEATURE_POWER5
| PPC_FEATURE_POWER4;
else if (hwcap & PPC_FEATURE_POWER5_PLUS)
hwcap |= PPC_FEATURE_POWER5
| PPC_FEATURE_POWER4;
else if (hwcap & PPC_FEATURE_POWER5)
hwcap |= PPC_FEATURE_POWER4;
hwcap = (hwcap << 32) + hwcap2;
if ( tcb_hwcap != hwcap )
{
printf ("FAIL: __ppc_get_hwcap() - HWCAP is %" PRIx64 ". Should be %"
PRIx64 " for thread %ld.\n", tcb_hwcap, hwcap, tid);
return 1;
}
/* Same test for the platform number. */
__asm__ ("lwz %0,%1(%2)\n"
: "=r" (tcb_at_platform)
: "i" (__ATPLATOFF), "b" (__tp));
at_platform_string = (const char *) getauxval (AT_PLATFORM);
at_platform = _dl_string_platform (at_platform_string);
if ( tcb_at_platform != at_platform )
{
printf ("FAIL: __ppc_get_at_platform() - AT_PLATFORM is %x. Should be %x"
" for thread %ld\n", tcb_at_platform, at_platform, tid);
return 1;
}
return 0;
}
void *t1 (void *tid)
{
if (check_tcbhwcap ((long) tid))
{
pthread_exit (tid);
}
pthread_exit (NULL);
}
static int
do_test (void)
{
pthread_t threads[2];
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
void *status;
long i = 0;
/* Check for main. */
if (check_tcbhwcap (i))
{
return 1;
}
/* Check for other thread. */
i++;
if (pthread_create (&threads[i], &attr, t1, (void *)i))
{
printf ("FAIL: error creating thread %ld.\n", i);
return 1;
}
pthread_attr_destroy (&attr);
if (pthread_join (threads[i], &status))
{
printf ("FAIL: error joining thread %ld.\n", i);
return 1;
}
if (status)
{
return 1;
}
printf("PASS: HWCAP, HWCAP2 and AT_PLATFORM are correctly set in the TCB for"
" all threads.\n");
pthread_exit (NULL);
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -20,6 +20,9 @@
#include <ldsodefs.h>
#include <sysdep.h>
#ifndef SHARED
#include <hwcapinfo.h>
#endif
int __cache_line_size attribute_hidden;
/* The main work is done in the generic function. */
@ -68,15 +71,34 @@ __libc_start_main (int argc, char **argv,
rtld_fini = NULL;
}
/* Initialize the __cache_line_size variable from the aux vector. */
/* Initialize the __cache_line_size variable from the aux vector. For the
static case, we also need _dl_hwcap, _dl_hwcap2 and _dl_platform, so we
can call __tcb_parse_hwcap_and_convert_at_platform (). */
for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av)
switch (av->a_type)
{
case AT_DCACHEBSIZE:
__cache_line_size = av->a_un.a_val;
break;
#ifndef SHARED
case AT_HWCAP:
_dl_hwcap = (unsigned long int) av->a_un.a_val;
break;
case AT_HWCAP2:
_dl_hwcap2 = (unsigned long int) av->a_un.a_val;
break;
case AT_PLATFORM:
_dl_platform = (void *) av->a_un.a_val;
break;
#endif
}
/* Initialize hwcap/hwcap2 and platform data so it can be copied to
the TCB later in __libc_setup_tls (). (static case only). */
#ifndef SHARED
__tcb_parse_hwcap_and_convert_at_platform ();
#endif
return generic_start_main (stinfo->main, argc, argv, auxvec,
stinfo->init, stinfo->fini, rtld_fini,
stack_on_entry);

View File

@ -10,6 +10,8 @@ GLIBC_2.1 __libc_stack_end D 0x4
GLIBC_2.1 _dl_mcount F
GLIBC_2.22 GLIBC_2.22 A
GLIBC_2.22 __tls_get_addr_opt F
GLIBC_2.23 GLIBC_2.23 A
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __tls_get_addr F
GLIBC_2.4 GLIBC_2.4 A

View File

@ -10,3 +10,5 @@ GLIBC_2.17 malloc F
GLIBC_2.17 realloc F
GLIBC_2.22 GLIBC_2.22 A
GLIBC_2.22 __tls_get_addr_opt F
GLIBC_2.23 GLIBC_2.23 A
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F

View File

@ -1,5 +1,7 @@
GLIBC_2.22 GLIBC_2.22 A
GLIBC_2.22 __tls_get_addr_opt F
GLIBC_2.23 GLIBC_2.23 A
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __libc_memalign F
GLIBC_2.3 __libc_stack_end D 0x8