Skip to content

Commit

Permalink
powerpc: Add hwcap/hwcap2/platform data to TCB.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Carlos Eduardo Seo authored and Tulio Magno Quites Machado Filho committed Dec 3, 2015
1 parent db340c9 commit 67385a0
Show file tree
Hide file tree
Showing 15 changed files with 480 additions and 7 deletions.
45 changes: 45 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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'.
Expand Down
11 changes: 8 additions & 3 deletions sysdeps/powerpc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions sysdeps/powerpc/Versions
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
76 changes: 76 additions & 0 deletions sysdeps/powerpc/hwcapinfo.c
Original file line number Diff line number Diff line change
@@ -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
29 changes: 29 additions & 0 deletions sysdeps/powerpc/hwcapinfo.h
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions sysdeps/powerpc/nptl/tcb-offsets.sym
Original file line number Diff line number Diff line change
Expand Up @@ -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
44 changes: 41 additions & 3 deletions sysdeps/powerpc/nptl/tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ typedef union dtv

#ifndef __ASSEMBLER__

# include <hwcapinfo.h>

/* Get system call information. */
# include <sysdep.h>

Expand All @@ -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;
Expand Down Expand Up @@ -134,15 +152,21 @@ 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; \
})

/* Value passed to 'clone' for initialization of the thread register. */
# 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() \
Expand Down Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions sysdeps/powerpc/powerpc32/dl-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions sysdeps/powerpc/powerpc64/dl-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions sysdeps/powerpc/test-get_hwcap-static.c
Original file line number Diff line number Diff line change
@@ -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"
Loading

0 comments on commit 67385a0

Please sign in to comment.