#include <stackinfo.h>
#include <dl-vdso.h>
#include <dl-vdso-setup.h>
+#include <dl-auxv.h>
extern char *__progname;
char **_dl_argv = &__progname; /* This is checked for some error messages. */
case AT_RANDOM:
_dl_random = (void *) av->a_un.a_val;
break;
-# ifdef DL_PLATFORM_AUXV
DL_PLATFORM_AUXV
-# endif
}
if (seen == 0xf)
{
#include <tls.h>
#include <dl-tunables.h>
+#include <dl-auxv.h>
extern char **_environ attribute_hidden;
extern char _end[] attribute_hidden;
case AT_RANDOM:
_dl_random = (void *) av->a_un.a_val;
break;
-#ifdef DL_PLATFORM_AUXV
DL_PLATFORM_AUXV
-#endif
}
#ifndef HAVE_AUX_SECURE
--- /dev/null
+/* Auxiliary vector processing. Generic version.
+ Copyright (C) 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/>. */
+
+/* Define DL_PLATFORM_AUXV in order to process platform-specific AUXV entries
+ during the initialization of the loader or of a static libc. */
+#define DL_PLATFORM_AUXV
tests += tst-tlsopt-powerpc
$(objpfx)tst-tlsopt-powerpc: $(objpfx)mod-tlsopt-powerpc.so
+tests-static += tst-cache-ppc-static
+tests-internal += tst-cache-ppc-static
+
+ifeq (yes,$(build-shared))
+modules-names += mod-cache-ppc
+tests += tst-cache-ppc tst-cache-ppc-static-dlopen
+tests-static += tst-cache-ppc-static-dlopen
+test-internal-extras += mod-cache-ppc
+
+mod-cache-ppc.so-no-z-defs = yes
+tst-cache-ppc-static-dlopen-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+$(objpfx)tst-cache-ppc-static-dlopen: $(common-objpfx)dlfcn/libdl.a
+$(objpfx)tst-cache-ppc-static-dlopen.out: $(objpfx)mod-cache-ppc.so
+
+$(objpfx)tst-cache-ppc: $(objpfx)mod-cache-ppc.so
+endif
+
ifneq (no,$(multi-arch))
tests-static += tst-tlsifunc-static
tests-internal += tst-tlsifunc-static
,
#endif
+#if !IS_IN (ldconfig)
+# if !defined PROCINFO_DECL && defined SHARED
+ ._dl_cache_line_size
+# else
+PROCINFO_CLASS int _dl_cache_line_size
+# endif
+# ifndef PROCINFO_DECL
+ = 0
+# endif
+# if !defined SHARED || defined PROCINFO_DECL
+;
+# else
+,
+# endif
+#endif
+
+
#undef PROCINFO_DECL
#undef PROCINFO_CLASS
--- /dev/null
+/* Test if an executable can read from rtld_global_ro._dl_cache_line_size.
+ Copyright (C) 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/>. */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/auxv.h>
+#include <ldsodefs.h>
+#include <errno.h>
+
+/* errnop is required in order to work around BZ #20802. */
+int
+test_cache (int *errnop)
+{
+ int cls1 = GLRO (dl_cache_line_size);
+ errno = *errnop;
+ uint64_t cls2 = getauxval (AT_DCACHEBSIZE);
+ *errnop = errno;
+
+ printf ("AT_DCACHEBSIZE = %" PRIu64 " B\n", cls2);
+ printf ("_dl_cache_line_size = %d B\n", cls1);
+
+ if (cls1 != cls2)
+ {
+ printf ("error: _dl_cache_line_size != AT_DCACHEBSIZE\n");
+ return 1;
+ }
+
+ return 0;
+}
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
+#include <rtld-global-offsets.h>
#define PREFETCH_AHEAD 4 /* no cache lines SRC prefetching ahead */
#define ZERO_AHEAD 2 /* no cache lines DST zeroing ahead */
L(dst_aligned):
-#ifdef SHARED
+#ifdef PIC
mflr r0
-/* Establishes GOT addressability so we can load __cache_line_size
- from static. This value was set from the aux vector during startup. */
+/* Establishes GOT addressability so we can load the cache line size
+ from rtld_global_ro. This value was set from the aux vector during
+ startup. */
SETUP_GOT_ACCESS(r9,got_label)
- addis r9,r9,__cache_line_size-got_label@ha
- lwz r9,__cache_line_size-got_label@l(r9)
- mtlr r0
-#else
-/* Load __cache_line_size from static. This value was set from the
- aux vector during startup. */
- lis r9,__cache_line_size@ha
- lwz r9,__cache_line_size@l(r9)
+ addis r9,r9,_GLOBAL_OFFSET_TABLE_-got_label@ha
+ addi r9,r9,_GLOBAL_OFFSET_TABLE_-got_label@l
+ mtlr r0
#endif
+ __GLRO(r9, r9, _dl_cache_line_size,
+ RTLD_GLOBAL_RO_DL_CACHE_LINE_SIZE_OFFSET)
cmplwi cr5, r9, 0
bne+ cr5,L(cachelineset)
-/* __cache_line_size not set: generic byte copy without much optimization */
+/* Cache line size not set: generic byte copy without much optimization */
andi. r0,r5,1 /* If length is odd copy one byte. */
beq L(cachelinenotset_align)
lbz r7,0(r4) /* Read one byte from source. */
#include <dl-machine.h>
#include <_itoa.h>
-/* The value __cache_line_size is defined in dl-sysdep.c and is initialised
- by _dl_sysdep_start via DL_PLATFORM_INIT. */
-extern int __cache_line_size attribute_hidden;
-
-
/* Stuff for the PLT. */
#define PLT_INITIAL_ENTRY_WORDS 18
#define PLT_LONGBRANCH_ENTRY_WORDS 0
Assumes that dcbst and icbi apply to lines of 16 bytes or
more. Current known line sizes are 16, 32, and 128 bytes.
- The following gets the __cache_line_size, when available. */
+ The following gets the cache line size, when available. */
/* Default minimum 4 words per cache line. */
int line_size_words = 4;
- if (lazy && __cache_line_size != 0)
+ if (lazy && GLRO(dl_cache_line_size) != 0)
/* Convert bytes to words. */
- line_size_words = __cache_line_size / 4;
+ line_size_words = GLRO(dl_cache_line_size) / 4;
size_modified = lazy ? rel_offset_words : 6;
for (i = 0; i < size_modified; i += line_size_words)
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
+#include <rtld-global-offsets.h>
/* void * [r3] memset (void *s [r3], int c [r4], size_t n [r5]));
Returns 's'.
The memset is done in four sizes: byte (8 bits), word (32 bits),
- 32-byte blocks (256 bits) and __cache_line_size (128, 256, 1024 bits).
+ 32-byte blocks (256 bits) and cache line size (128, 256, 1024 bits).
There is a special case for setting whole cache lines to 0, which
takes advantage of the dcbz instruction. */
/* Check if we can use the special case for clearing memory using dcbz.
This requires that we know the correct cache line size for this
- processor. Getting the __cache_line_size may require establishing GOT
+ processor. Getting the cache line size may require establishing GOT
addressability, so branch out of line to set this up. */
beq cr1, L(checklinesize)
blr
L(checklinesize):
-#ifdef SHARED
- mflr rTMP
/* If the remaining length is less the 32 bytes then don't bother getting
the cache line size. */
beq L(medium)
-/* Establishes GOT addressability so we can load __cache_line_size
- from static. This value was set from the aux vector during startup. */
+#ifdef PIC
+ mflr rTMP
+/* Establishes GOT addressability so we can load the cache line size
+ from rtld_global_ro. This value was set from the aux vector during
+ startup. */
SETUP_GOT_ACCESS(rGOT,got_label)
- addis rGOT,rGOT,__cache_line_size-got_label@ha
- lwz rCLS,__cache_line_size-got_label@l(rGOT)
+ addis rGOT,rGOT,_GLOBAL_OFFSET_TABLE_-got_label@ha
+ addi rGOT,rGOT,_GLOBAL_OFFSET_TABLE_-got_label@l
mtlr rTMP
-#else
-/* Load __cache_line_size from static. This value was set from the
- aux vector during startup. */
- lis rCLS,__cache_line_size@ha
-/* If the remaining length is less the 32 bytes then don't bother getting
- the cache line size. */
- beq L(medium)
- lwz rCLS,__cache_line_size@l(rCLS)
#endif
+/* Load rtld_global_ro._dl_cache_line_size. */
+ __GLRO(rCLS, rGOT, _dl_cache_line_size,
+ RTLD_GLOBAL_RO_DL_CACHE_LINE_SIZE_OFFSET)
/* If the cache line size was not set then goto to L(nondcbz), which is
safe for any cache line size. */
/* Label in text section. */
#define C_TEXT(name) name
+/* Read the value of member from rtld_global_ro. */
+#ifdef PIC
+# ifdef SHARED
+# if IS_IN (rtld)
+/* Inside ld.so we use the local alias to avoid runtime GOT
+ relocations. */
+# define __GLRO(rOUT, rGOT, member, offset) \
+ lwz rOUT,_rtld_local_ro@got(rGOT); \
+ lwz rOUT,offset(rOUT)
+# else
+# define __GLRO(rOUT, rGOT, member, offset) \
+ lwz rOUT,_rtld_global_ro@got(rGOT); \
+ lwz rOUT,offset(rOUT)
+# endif
+# else
+# define __GLRO(rOUT, rGOT, member, offset) \
+ lwz rOUT,member@got(rGOT); \
+ lwz rOUT,0(rOUT)
+# endif
+#else
+/* Position-dependent code does not require access to the GOT. */
+# define __GLRO(rOUT, rGOT, member, offset) \
+ lis rOUT,(member+LOWORD)@ha \
+ lwz rOUT,(member+LOWORD)@l(rOUT)
+#endif /* PIC */
+
#endif /* __ASSEMBLER__ */
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
+#include <rtld-global-offsets.h>
#ifndef MEMCPY
# define MEMCPY memcpy
#define ZERO_AHEAD 2 /* no cache lines DST zeroing ahead */
.section ".toc","aw"
-.LC0:
- .tc __cache_line_size[TC],__cache_line_size
+__GLRO_DEF(dl_cache_line_size)
+
+
.section ".text"
.align 2
*/
neg r8,r3 /* LS 4 bits = # bytes to 8-byte dest bdry */
- ld r9,.LC0@toc(r2) /* Get cache line size (part 1) */
+ /* Get the cache line size. */
+ __GLRO (r9, dl_cache_line_size,
+ RTLD_GLOBAL_RO_DL_CACHE_LINE_SIZE_OFFSET)
clrldi r8,r8,64-4 /* align to 16byte boundary */
sub r7,r4,r3 /* compute offset to src from dest */
- lwz r9,0(r9) /* Get cache line size (part 2) */
cmpldi cr0,r8,0 /* Were we aligned on a 16 byte bdy? */
addi r10,r9,-1 /* Cache line mask */
beq+ L(dst_aligned)
cmpdi cr0,r9,0 /* Cache line size set? */
bne+ cr0,L(cachelineset)
-/* __cache_line_size not set: generic byte copy without much optimization */
+/* Cache line size not set: generic byte copy without much optimization */
clrldi. r0,r5,63 /* If length is odd copy one byte */
beq L(cachelinenotset_align)
lbz r7,0(r4) /* Read one byte from source */
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
+#include <rtld-global-offsets.h>
.section ".toc","aw"
-.LC0:
- .tc __cache_line_size[TC],__cache_line_size
+__GLRO_DEF(dl_cache_line_size)
+
.section ".text"
.align 2
/* If the remaining length is less the 32 bytes, don't bother getting
the cache line size. */
beq L(medium)
- ld rCLS,.LC0@toc(r2)
- lwz rCLS,0(rCLS)
+ /* Read the cache line size. */
+ __GLRO (rCLS, dl_cache_line_size,
+ RTLD_GLOBAL_RO_DL_CACHE_LINE_SIZE_OFFSET)
+
/* If the cache line size was not set just goto to L(nondcbz) which is
safe for any cache line size. */
cmpldi cr1,rCLS,0
#define PSEUDO_END_ERRVAL(name) \
END (name)
+#ifdef SHARED
+# if IS_IN (rtld)
+ /* Inside ld.so we use the local alias to avoid runtime GOT
+ relocations. */
+# define __GLRO_DEF(var) \
+.LC__ ## var: \
+ .tc _rtld_local_ro[TC],_rtld_local_ro
+# else
+# define __GLRO_DEF(var) \
+.LC__ ## var: \
+ .tc _rtld_global_ro[TC],_rtld_global_ro
+# endif
+# define __GLRO(rOUT, var, offset) \
+ ld rOUT,.LC__ ## var@toc(r2); \
+ lwz rOUT,offset(rOUT)
+#else
+# define __GLRO_DEF(var) \
+.LC__ ## var: \
+ .tc _ ## var[TC],_ ## var
+# define __GLRO(rOUT, var, offset) \
+ ld rOUT,.LC__ ## var@toc(r2); \
+ lwz rOUT,0(rOUT)
+#endif
+
#else /* !__ASSEMBLER__ */
#if _CALL_ELF != 2
RTLD_GLOBAL_RO_DL_HWCAP_OFFSET rtld_global_ro_offsetof (_dl_hwcap)
RTLD_GLOBAL_RO_DL_HWCAP2_OFFSET rtld_global_ro_offsetof (_dl_hwcap2)
+RTLD_GLOBAL_RO_DL_CACHE_LINE_SIZE_OFFSET rtld_global_ro_offsetof (_dl_cache_line_size)
--- /dev/null
+/* Test dl_cache_line_size from a dlopen'ed DSO from a static executable.
+ Copyright (C) 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/>. */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <errno.h>
+
+int test_cache(int *);
+
+static int
+do_test (void)
+{
+ int ret;
+ void *handle;
+ int (*test_cache) (int *);
+
+ handle = dlopen ("mod-cache-ppc.so", RTLD_LAZY | RTLD_LOCAL);
+ if (handle == NULL)
+ {
+ printf ("dlopen (mod-cache-ppc.so): %s\n", dlerror ());
+ return 1;
+ }
+
+ test_cache = dlsym (handle, "test_cache");
+ if (test_cache == NULL)
+ {
+ printf ("dlsym (test_cache): %s\n", dlerror ());
+ return 1;
+ }
+
+ ret = test_cache(&errno);
+
+ test_cache = NULL;
+ dlclose (handle);
+
+ return ret;
+}
+
+#include <support/test-driver.c>
--- /dev/null
+/* Test if an executable can read from _dl_cache_line_size.
+ Copyright (C) 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/>. */
+
+#include "tst-cache-ppc.c"
+#include "mod-cache-ppc.c"
--- /dev/null
+/* Test if an executable can read from rtld_global_ro._dl_cache_line_size.
+ Copyright (C) 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/>. */
+
+#include <errno.h>
+
+int test_cache(int *);
+
+static int
+do_test (void)
+{
+ return test_cache(&errno);
+}
+
+#include <support/test-driver.c>
-/* Operating system support for run-time dynamic linker. Linux/PPC version.
- Copyright (C) 1997-2020 Free Software Foundation, Inc.
+/* Auxiliary vector processing. Linux/PPC version.
+ Copyright (C) 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
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <config.h>
#include <ldsodefs.h>
-int __cache_line_size attribute_hidden;
+#if IS_IN (libc) && !defined SHARED
+int GLRO(dl_cache_line_size);
+#endif
-/* Scan the Aux Vector for the "Data Cache Block Size" entry. If found
- verify that the static extern __cache_line_size is defined by checking
- for not NULL. If it is defined then assign the cache block size
- value to __cache_line_size. */
+/* Scan the Aux Vector for the "Data Cache Block Size" entry and assign it
+ to dl_cache_line_size. */
#define DL_PLATFORM_AUXV \
case AT_DCACHEBSIZE: \
- __cache_line_size = av->a_un.a_val; \
+ GLRO(dl_cache_line_size) = av->a_un.a_val; \
break;
-
-#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
DL_AUXV = 1,
DL_HWCAP = 2,
DL_HWCAP2 = 3,
+ DL_CACHE_LINE_SIZE = 4
};
GLRO(dl_pagesize) = *((size_t *) array[DL_PAGESIZE]);
GLRO(dl_auxv) = (ElfW(auxv_t) *) *((size_t *) array[DL_AUXV]);
GLRO(dl_hwcap) = *((unsigned long int *) array[DL_HWCAP]);
GLRO(dl_hwcap2) = *((unsigned long int *) array[DL_HWCAP2]);
+ GLRO(dl_cache_line_size) = (int) *((int *) array[DL_CACHE_LINE_SIZE]);
}
#else
&GLRO(dl_auxv),
&GLRO(dl_hwcap),
&GLRO(dl_hwcap2),
+ &GLRO(dl_cache_line_size)
};
static void
#include <hwcapinfo.h>
#endif
-int __cache_line_size attribute_hidden;
/* The main work is done in the generic function. */
#define LIBC_START_MAIN generic_start_main
#define LIBC_START_DISABLE_INLINE
rtld_fini = NULL;
}
- /* 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;
+ /* 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 (). */
#ifndef SHARED
case AT_HWCAP:
_dl_hwcap = (unsigned long int) av->a_un.a_val;