mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-10 15:20:10 +00:00
0f09154c64
X86 CPU features in ld.so are initialized by init_cpu_features, which is invoked by DL_PLATFORM_INIT from _dl_sysdep_start. But when ld.so is loaded by static executable, DL_PLATFORM_INIT is never called. Also x86 cache info in libc.o and libc.a is initialized by a constructor which may be called too late. Since some fields in _rtld_global_ro in ld.so are initialized by dynamic relocation, we can also initialize x86 CPU features in _rtld_global_ro in ld.so and cache info in libc.so by initializing dummy function pointers in ld.so and libc.so via IFUNC relocation. Key points: 1. IFUNC is always supported, independent of --enable-multi-arch or --disable-multi-arch. Linker generates IFUNC relocations from input IFUNC objects and ld.so performs IFUNC relocations. 2. There are no IFUNC dependencies in ld.so before dynamic relocation have been performed, 3. The x86 CPU features in ld.so is initialized by DL_PLATFORM_INIT in dynamic executable and by IFUNC relocation in dlopen in static executable. 4. The x86 cache info in libc.o is initialized by IFUNC relocation. 5. In libc.a, both x86 CPU features and cache info are initialized from ARCH_INIT_CPU_FEATURES, not by IFUNC relocation, before __libc_early_init is called. Note: _dl_x86_init_cpu_features can be called more than once from DL_PLATFORM_INIT and during relocation in ld.so.
64 lines
2.0 KiB
C
64 lines
2.0 KiB
C
/* x86 cache info.
|
|
Copyright (C) 2003-2020 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
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#if IS_IN (libc)
|
|
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#include <cpuid.h>
|
|
#include <ldsodefs.h>
|
|
#include <dl-cacheinfo.h>
|
|
|
|
/* Get the value of the system variable NAME. */
|
|
long int
|
|
attribute_hidden
|
|
__cache_sysconf (int name)
|
|
{
|
|
const struct cpu_features *cpu_features = __get_cpu_features ();
|
|
|
|
if (cpu_features->basic.kind == arch_kind_intel)
|
|
return handle_intel (name, cpu_features);
|
|
|
|
if (cpu_features->basic.kind == arch_kind_amd)
|
|
return handle_amd (name);
|
|
|
|
if (cpu_features->basic.kind == arch_kind_zhaoxin)
|
|
return handle_zhaoxin (name);
|
|
|
|
// XXX Fill in more vendors.
|
|
|
|
/* CPU not known, we have no information. */
|
|
return 0;
|
|
}
|
|
|
|
# ifdef SHARED
|
|
/* NB: In libc.a, cacheinfo.h is included in libc-start.c. In libc.so,
|
|
cacheinfo.h is included here and call init_cacheinfo by initializing
|
|
a dummy function pointer via IFUNC relocation after CPU features in
|
|
ld.so have been initialized by DL_PLATFORM_INIT or IFUNC relocation. */
|
|
# include <cacheinfo.h>
|
|
# include <ifunc-init.h>
|
|
|
|
extern void __x86_cacheinfo (void) attribute_hidden;
|
|
const void (*__x86_cacheinfo_p) (void) attribute_hidden
|
|
= __x86_cacheinfo;
|
|
|
|
__ifunc (__x86_cacheinfo, __x86_cacheinfo, NULL, void, init_cacheinfo);
|
|
# endif
|
|
#endif
|