Message ID | 1486509609.2866.59.camel@caviumnetworks.com |
---|---|
State | New |
Headers | show |
On Wednesday 08 February 2017 04:50 AM, Steve Ellcey wrote: > OK, here is the basic IFUNC enablement for aarch64 without the > memcpy/memmove changes that use it. I verified that it builds and > causes no regressions on aarch64. As mentioned in the original email > this code depends on the mrs instruction which is privileged, but the > 4.11 kernel will have emulation for it (https://lkml.org/lkml/2017/1/10 > /816). > > OK to checkin this part? Looks OK with a couple of nits below. > > Steve Ellcey > sellcey@cavium.com > > > 2017-02-07 Steve Ellcey <sellcey@caviumnetworks.com> > Adhemerval Zanella <adhemerval.zanella@linaro.org> > > * sysdeps/aarch64/dl-machine.h: Include cpu-features.c. > (DL_PLATFORM_INIT): New define. > (dl_platform_init): New function. > * sysdeps/aarch64/ldsodefs.h: Include cpu-features.h. > * sysdeps/unix/sysv/linux/aarch64/cpu-features.c: New file. > * sysdeps/unix/sysv/linux/aarch64/cpu-features.h: Ditto. > * sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c: Ditto. > * sysdeps/unix/sysv/linux/aarch64/libc-start.c: Ditto. I was told years ago that we prefer 'Likewise' to 'Ditto' :) > > > ifunc.patch > > > diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h > index 84b8aec..15d79a6 100644 > --- a/sysdeps/aarch64/dl-machine.h > +++ b/sysdeps/aarch64/dl-machine.h > @@ -25,6 +25,7 @@ > #include <tls.h> > #include <dl-tlsdesc.h> > #include <dl-irel.h> > +#include <cpu-features.c> > > /* Return nonzero iff ELF header is compatible with the running host. */ > static inline int __attribute__ ((unused)) > @@ -225,6 +226,23 @@ _dl_start_user: \n\ > #define ELF_MACHINE_NO_REL 1 > #define ELF_MACHINE_NO_RELA 0 > > +#define DL_PLATFORM_INIT dl_platform_init () > + > +static inline void __attribute__ ((unused)) > +dl_platform_init (void) > +{ > + if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') > + /* Avoid an empty string which would disturb us. */ > + GLRO(dl_platform) = NULL; > + > +#ifdef SHARED > + /* init_cpu_features has been called early from __libc_start_main in > + static executable. */ > + init_cpu_features (&GLRO(dl_aarch64_cpu_features)); > +#endif > +} > + > + > static inline ElfW(Addr) > elf_machine_fixup_plt (struct link_map *map, lookup_t t, > const ElfW(Rela) *reloc, > diff --git a/sysdeps/aarch64/ldsodefs.h b/sysdeps/aarch64/ldsodefs.h > index f277074..ba4ada3 100644 > --- a/sysdeps/aarch64/ldsodefs.h > +++ b/sysdeps/aarch64/ldsodefs.h > @@ -20,6 +20,7 @@ > #define _AARCH64_LDSODEFS_H 1 > > #include <elf.h> > +#include <cpu-features.h> > > struct La_aarch64_regs; > struct La_aarch64_retval; > diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c > index e69de29..8e4b514 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c > +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c > @@ -0,0 +1,38 @@ > +/* Initialize CPU feature data. AArch64 version. > + This file is part of the GNU C Library. > + Copyright (C) 2017 Free Software Foundation, Inc. > + > + 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 <cpu-features.h> > + > +#ifndef HWCAP_CPUID > +# define HWCAP_CPUID (1 << 11) > +#endif > + > +static inline void > +init_cpu_features (struct cpu_features *cpu_features) > +{ > + if (GLRO(dl_hwcap) & HWCAP_CPUID) > + { > + register uint64_t id = 0; > + asm volatile ("mrs %0, midr_el1" : "=r"(id)); > + cpu_features->midr_el1 = id; > + } > + else > + { > + cpu_features->midr_el1 = 0; > + } > +} > diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h > index e69de29..c92b650 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h > +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h > @@ -0,0 +1,49 @@ > +/* Initialize CPU feature data. AArch64 version. > + This file is part of the GNU C Library. > + Copyright (C) 2017 Free Software Foundation, Inc. > + > + 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/>. */ > + > +#ifndef _CPU_FEATURES_AARCH64_H > +#define _CPU_FEATURES_AARCH64_H > + > +#include <stdint.h> > + > +#define MIDR_PARTNUM_SHIFT 4 > +#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT) > +#define MIDR_PARTNUM(midr) \ > + (((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT) > +#define MIDR_ARCHITECTURE_SHIFT 16 > +#define MIDR_ARCHITECTURE_MASK (0xf << MIDR_ARCHITECTURE_SHIFT) > +#define MIDR_ARCHITECTURE(midr) \ > + (((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT) > +#define MIDR_VARIANT_SHIFT 20 > +#define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT) > +#define MIDR_VARIANT(midr) \ > + (((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT) > +#define MIDR_IMPLEMENTOR_SHIFT 24 > +#define MIDR_IMPLEMENTOR_MASK (0xff << MIDR_IMPLEMENTOR_SHIFT) > +#define MIDR_IMPLEMENTOR(midr) \ > + (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT) > + > +#define IS_THUNDERX(midr) (MIDR_IMPLEMENTOR(midr) == 'C' \ > + && MIDR_PARTNUM(midr) == 0x0a1) > + > +struct cpu_features > +{ > + uint64_t midr_el1; > +}; > + > +#endif /* _CPU_FEATURES_AARCH64_H */ > diff --git a/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c b/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c > index e69de29..438046a 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c > +++ b/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c > @@ -0,0 +1,60 @@ > +/* Data for AArch64 version of processor capability information. > + Linux version. > + Copyright (C) 2017 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/>. */ > + > +/* If anything should be added here check whether the size of each string > + is still ok with the given array size. > + > + All the #ifdefs in the definitions are quite irritating but > + necessary if we want to avoid duplicating the information. There > + are three different modes: > + > + - PROCINFO_DECL is defined. This means we are only interested in > + declarations. > + > + - PROCINFO_DECL is not defined: > + > + + if SHARED is defined the file is included in an array > + initializer. The .element = { ... } syntax is needed. > + > + + if SHARED is not defined a normal array initialization is > + needed. > + */ > + > +#ifndef PROCINFO_CLASS > +# define PROCINFO_CLASS > +#endif > + > +#if !IS_IN (ldconfig) > +# if !defined PROCINFO_DECL && defined SHARED > + ._dl_aarch64_cpu_features > +# else > +PROCINFO_CLASS struct cpu_features _dl_aarch64_cpu_features > +# endif > +# ifndef PROCINFO_DECL > += { } > +# endif > +# if !defined SHARED || defined PROCINFO_DECL > +; > +# else > +, > +# endif > +#endif > + > +#undef PROCINFO_DECL > +#undef PROCINFO_CLASS > diff --git a/sysdeps/unix/sysv/linux/aarch64/libc-start.c b/sysdeps/unix/sysv/linux/aarch64/libc-start.c > index e69de29..c98aff1 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/libc-start.c > +++ b/sysdeps/unix/sysv/linux/aarch64/libc-start.c > @@ -0,0 +1,40 @@ You've forgotten to add a one line description for this file. > +/* Copyright (C) 2017 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/>. */ > + > +#ifdef SHARED > +# include <csu/libc-start.c> > +# else > +/* The main work is done in the generic function. */ > +# define LIBC_START_DISABLE_INLINE > +# define LIBC_START_MAIN generic_start_main > +# include <csu/libc-start.c> > +# include <cpu-features.c> > + > +extern struct cpu_features _dl_aarch64_cpu_features; > + > +int > +__libc_start_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), > + int argc, char **argv, > + __typeof (main) init, > + void (*fini) (void), > + void (*rtld_fini) (void), void *stack_end) > +{ > + init_cpu_features (&_dl_aarch64_cpu_features); > + return generic_start_main (main, argc, argv, init, fini, rtld_fini, > + stack_end); > +} > +#endif >
On Wednesday 08 February 2017 11:15 AM, Siddhesh Poyarekar wrote:
> Looks OK with a couple of nits below.
Oh and I suppose you need an ack from the ARM maintainers as well before
you push.
Siddhesh
On 08/02/17 05:46, Siddhesh Poyarekar wrote: > On Wednesday 08 February 2017 11:15 AM, Siddhesh Poyarekar wrote: >> Looks OK with a couple of nits below. > > Oh and I suppose you need an ack from the ARM maintainers as well before > you push. > arm maintainer != aarch64 maintainer.
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h index 84b8aec..15d79a6 100644 --- a/sysdeps/aarch64/dl-machine.h +++ b/sysdeps/aarch64/dl-machine.h @@ -25,6 +25,7 @@ #include <tls.h> #include <dl-tlsdesc.h> #include <dl-irel.h> +#include <cpu-features.c> /* Return nonzero iff ELF header is compatible with the running host. */ static inline int __attribute__ ((unused)) @@ -225,6 +226,23 @@ _dl_start_user: \n\ #define ELF_MACHINE_NO_REL 1 #define ELF_MACHINE_NO_RELA 0 +#define DL_PLATFORM_INIT dl_platform_init () + +static inline void __attribute__ ((unused)) +dl_platform_init (void) +{ + if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') + /* Avoid an empty string which would disturb us. */ + GLRO(dl_platform) = NULL; + +#ifdef SHARED + /* init_cpu_features has been called early from __libc_start_main in + static executable. */ + init_cpu_features (&GLRO(dl_aarch64_cpu_features)); +#endif +} + + static inline ElfW(Addr) elf_machine_fixup_plt (struct link_map *map, lookup_t t, const ElfW(Rela) *reloc, diff --git a/sysdeps/aarch64/ldsodefs.h b/sysdeps/aarch64/ldsodefs.h index f277074..ba4ada3 100644 --- a/sysdeps/aarch64/ldsodefs.h +++ b/sysdeps/aarch64/ldsodefs.h @@ -20,6 +20,7 @@ #define _AARCH64_LDSODEFS_H 1 #include <elf.h> +#include <cpu-features.h> struct La_aarch64_regs; struct La_aarch64_retval; diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c index e69de29..8e4b514 100644 --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c @@ -0,0 +1,38 @@ +/* Initialize CPU feature data. AArch64 version. + This file is part of the GNU C Library. + Copyright (C) 2017 Free Software Foundation, Inc. + + 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 <cpu-features.h> + +#ifndef HWCAP_CPUID +# define HWCAP_CPUID (1 << 11) +#endif + +static inline void +init_cpu_features (struct cpu_features *cpu_features) +{ + if (GLRO(dl_hwcap) & HWCAP_CPUID) + { + register uint64_t id = 0; + asm volatile ("mrs %0, midr_el1" : "=r"(id)); + cpu_features->midr_el1 = id; + } + else + { + cpu_features->midr_el1 = 0; + } +} diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h index e69de29..c92b650 100644 --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h @@ -0,0 +1,49 @@ +/* Initialize CPU feature data. AArch64 version. + This file is part of the GNU C Library. + Copyright (C) 2017 Free Software Foundation, Inc. + + 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/>. */ + +#ifndef _CPU_FEATURES_AARCH64_H +#define _CPU_FEATURES_AARCH64_H + +#include <stdint.h> + +#define MIDR_PARTNUM_SHIFT 4 +#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT) +#define MIDR_PARTNUM(midr) \ + (((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT) +#define MIDR_ARCHITECTURE_SHIFT 16 +#define MIDR_ARCHITECTURE_MASK (0xf << MIDR_ARCHITECTURE_SHIFT) +#define MIDR_ARCHITECTURE(midr) \ + (((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT) +#define MIDR_VARIANT_SHIFT 20 +#define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT) +#define MIDR_VARIANT(midr) \ + (((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT) +#define MIDR_IMPLEMENTOR_SHIFT 24 +#define MIDR_IMPLEMENTOR_MASK (0xff << MIDR_IMPLEMENTOR_SHIFT) +#define MIDR_IMPLEMENTOR(midr) \ + (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT) + +#define IS_THUNDERX(midr) (MIDR_IMPLEMENTOR(midr) == 'C' \ + && MIDR_PARTNUM(midr) == 0x0a1) + +struct cpu_features +{ + uint64_t midr_el1; +}; + +#endif /* _CPU_FEATURES_AARCH64_H */ diff --git a/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c b/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c index e69de29..438046a 100644 --- a/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c +++ b/sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c @@ -0,0 +1,60 @@ +/* Data for AArch64 version of processor capability information. + Linux version. + Copyright (C) 2017 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/>. */ + +/* If anything should be added here check whether the size of each string + is still ok with the given array size. + + All the #ifdefs in the definitions are quite irritating but + necessary if we want to avoid duplicating the information. There + are three different modes: + + - PROCINFO_DECL is defined. This means we are only interested in + declarations. + + - PROCINFO_DECL is not defined: + + + if SHARED is defined the file is included in an array + initializer. The .element = { ... } syntax is needed. + + + if SHARED is not defined a normal array initialization is + needed. + */ + +#ifndef PROCINFO_CLASS +# define PROCINFO_CLASS +#endif + +#if !IS_IN (ldconfig) +# if !defined PROCINFO_DECL && defined SHARED + ._dl_aarch64_cpu_features +# else +PROCINFO_CLASS struct cpu_features _dl_aarch64_cpu_features +# endif +# ifndef PROCINFO_DECL += { } +# endif +# if !defined SHARED || defined PROCINFO_DECL +; +# else +, +# endif +#endif + +#undef PROCINFO_DECL +#undef PROCINFO_CLASS diff --git a/sysdeps/unix/sysv/linux/aarch64/libc-start.c b/sysdeps/unix/sysv/linux/aarch64/libc-start.c index e69de29..c98aff1 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc-start.c +++ b/sysdeps/unix/sysv/linux/aarch64/libc-start.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2017 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/>. */ + +#ifdef SHARED +# include <csu/libc-start.c> +# else +/* The main work is done in the generic function. */ +# define LIBC_START_DISABLE_INLINE +# define LIBC_START_MAIN generic_start_main +# include <csu/libc-start.c> +# include <cpu-features.c> + +extern struct cpu_features _dl_aarch64_cpu_features; + +int +__libc_start_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + int argc, char **argv, + __typeof (main) init, + void (*fini) (void), + void (*rtld_fini) (void), void *stack_end) +{ + init_cpu_features (&_dl_aarch64_cpu_features); + return generic_start_main (main, argc, argv, init, fini, rtld_fini, + stack_end); +} +#endif