x86: Handle _SC_LEVEL1_ICACHE_LINESIZE [BZ #27444]

Message ID 20210306191111.1760885-1-hjl.tools@gmail.com
State Committed
Commit f53ffc9b90cbd92fa5518686daf4091bdd1d4889
Delegated to: Carlos O'Donell
Headers
Series x86: Handle _SC_LEVEL1_ICACHE_LINESIZE [BZ #27444] |

Commit Message

H.J. Lu March 6, 2021, 7:11 p.m. UTC
  commit 2d651eb9265d1366d7b9e881bfddd46db9c1ecc4
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Sep 18 07:55:14 2020 -0700

    x86: Move x86 processor cache info to cpu_features

missed _SC_LEVEL1_ICACHE_LINESIZE.

1. Add level1_icache_linesize to struct cpu_features.
2. Initialize level1_icache_linesize by calling handle_intel,
handle_zhaoxin and handle_amd with _SC_LEVEL1_ICACHE_LINESIZE.
3. Return level1_icache_linesize for _SC_LEVEL1_ICACHE_LINESIZE.
---
 sysdeps/x86/Makefile                          |  8 +++
 sysdeps/x86/cacheinfo.c                       |  3 +
 sysdeps/x86/dl-cacheinfo.h                    |  6 ++
 sysdeps/x86/dl-diagnostics-cpu.c              |  2 +
 sysdeps/x86/include/cpu-features.h            |  2 +
 .../x86/tst-sysconf-cache-linesize-static.c   |  1 +
 sysdeps/x86/tst-sysconf-cache-linesize.c      | 57 +++++++++++++++++++
 7 files changed, 79 insertions(+)
 create mode 100644 sysdeps/x86/tst-sysconf-cache-linesize-static.c
 create mode 100644 sysdeps/x86/tst-sysconf-cache-linesize.c
  

Comments

Carlos O'Donell March 15, 2021, 12:32 p.m. UTC | #1
On 3/6/21 2:11 PM, H.J. Lu via Libc-alpha wrote:
> commit 2d651eb9265d1366d7b9e881bfddd46db9c1ecc4
> Author: H.J. Lu <hjl.tools@gmail.com>
> Date:   Fri Sep 18 07:55:14 2020 -0700
> 
>     x86: Move x86 processor cache info to cpu_features
> 
> missed _SC_LEVEL1_ICACHE_LINESIZE.

LGTM.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> 
> 1. Add level1_icache_linesize to struct cpu_features.
> 2. Initialize level1_icache_linesize by calling handle_intel,
> handle_zhaoxin and handle_amd with _SC_LEVEL1_ICACHE_LINESIZE.
> 3. Return level1_icache_linesize for _SC_LEVEL1_ICACHE_LINESIZE.
> ---
>  sysdeps/x86/Makefile                          |  8 +++
>  sysdeps/x86/cacheinfo.c                       |  3 +
>  sysdeps/x86/dl-cacheinfo.h                    |  6 ++
>  sysdeps/x86/dl-diagnostics-cpu.c              |  2 +
>  sysdeps/x86/include/cpu-features.h            |  2 +
>  .../x86/tst-sysconf-cache-linesize-static.c   |  1 +
>  sysdeps/x86/tst-sysconf-cache-linesize.c      | 57 +++++++++++++++++++
>  7 files changed, 79 insertions(+)
>  create mode 100644 sysdeps/x86/tst-sysconf-cache-linesize-static.c
>  create mode 100644 sysdeps/x86/tst-sysconf-cache-linesize.c
> 
> diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
> index e1f9379fd8..06c9f84f51 100644
> --- a/sysdeps/x86/Makefile
> +++ b/sysdeps/x86/Makefile
> @@ -211,3 +211,11 @@ $(objpfx)check-cet.out: $(..)sysdeps/x86/check-cet.awk \
>  generated += check-cet.out
>  endif
>  endif
> +
> +ifeq ($(subdir),posix)
> +tests += \
> +  tst-sysconf-cache-linesize \
> +  tst-sysconf-cache-linesize-static
> +tests-static += \
> +  tst-sysconf-cache-linesize-static
> +endif

OK. Add new test for static binary access of line size.

> diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c
> index 7b8df45e3b..5ea4723ca6 100644
> --- a/sysdeps/x86/cacheinfo.c
> +++ b/sysdeps/x86/cacheinfo.c
> @@ -32,6 +32,9 @@ __cache_sysconf (int name)
>      case _SC_LEVEL1_ICACHE_SIZE:
>        return cpu_features->level1_icache_size;
>  
> +    case _SC_LEVEL1_ICACHE_LINESIZE:
> +      return cpu_features->level1_icache_linesize;

OK. Return new struct member.

> +
>      case _SC_LEVEL1_DCACHE_SIZE:
>        return cpu_features->level1_dcache_size;
>  
> diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
> index f3de206dc1..d9944250fc 100644
> --- a/sysdeps/x86/dl-cacheinfo.h
> +++ b/sysdeps/x86/dl-cacheinfo.h
> @@ -707,6 +707,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
>    long int core = -1;
>    unsigned int threads = 0;
>    unsigned long int level1_icache_size = -1;
> +  unsigned long int level1_icache_linesize = -1;

OK. Struct member matches.

>    unsigned long int level1_dcache_size = -1;
>    unsigned long int level1_dcache_assoc = -1;
>    unsigned long int level1_dcache_linesize = -1;
> @@ -726,6 +727,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
>  
>        level1_icache_size
>  	= handle_intel (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
> +      level1_icache_linesize
> +	= handle_intel (_SC_LEVEL1_ICACHE_LINESIZE, cpu_features);

OK. Set member.

>        level1_dcache_size = data;
>        level1_dcache_assoc
>  	= handle_intel (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
> @@ -753,6 +756,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
>        shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
>  
>        level1_icache_size = handle_zhaoxin (_SC_LEVEL1_ICACHE_SIZE);
> +      level1_icache_linesize = handle_zhaoxin (_SC_LEVEL1_ICACHE_LINESIZE);

OK. Handle alternatives.

>        level1_dcache_size = data;
>        level1_dcache_assoc = handle_zhaoxin (_SC_LEVEL1_DCACHE_ASSOC);
>        level1_dcache_linesize = handle_zhaoxin (_SC_LEVEL1_DCACHE_LINESIZE);
> @@ -772,6 +776,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
>        shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
>  
>        level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
> +      level1_icache_linesize = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE);

OK. Likewise.

>        level1_dcache_size = data;
>        level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
>        level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
> @@ -833,6 +838,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
>      }
>  
>    cpu_features->level1_icache_size = level1_icache_size;
> +  cpu_features->level1_icache_linesize = level1_icache_linesize;

OK. Set actual cpu_features.

>    cpu_features->level1_dcache_size = level1_dcache_size;
>    cpu_features->level1_dcache_assoc = level1_dcache_assoc;
>    cpu_features->level1_dcache_linesize = level1_dcache_linesize;
> diff --git a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
> index 5d9713f8d9..5d04527ad1 100644
> --- a/sysdeps/x86/dl-diagnostics-cpu.c
> +++ b/sysdeps/x86/dl-diagnostics-cpu.c
> @@ -91,6 +91,8 @@ _dl_diagnostics_cpu (void)
>                              cpu_features->rep_stosb_threshold);
>    print_cpu_features_value ("level1_icache_size",
>                              cpu_features->level1_icache_size);
> +  print_cpu_features_value ("level1_icache_linesize",
> +                            cpu_features->level1_icache_linesize);

OK. Add it to diag printing.

>    print_cpu_features_value ("level1_dcache_size",
>                              cpu_features->level1_dcache_size);
>    print_cpu_features_value ("level1_dcache_assoc",
> diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
> index c5a779ba32..d042a2ebef 100644
> --- a/sysdeps/x86/include/cpu-features.h
> +++ b/sysdeps/x86/include/cpu-features.h
> @@ -876,6 +876,8 @@ struct cpu_features
>    unsigned long int rep_stosb_threshold;
>    /* _SC_LEVEL1_ICACHE_SIZE.  */
>    unsigned long int level1_icache_size;
> +  /* _SC_LEVEL1_ICACHE_LINESIZE.  */
> +  unsigned long int level1_icache_linesize;

OK.

>    /* _SC_LEVEL1_DCACHE_SIZE.  */
>    unsigned long int level1_dcache_size;
>    /* _SC_LEVEL1_DCACHE_ASSOC.  */
> diff --git a/sysdeps/x86/tst-sysconf-cache-linesize-static.c b/sysdeps/x86/tst-sysconf-cache-linesize-static.c
> new file mode 100644
> index 0000000000..152ae68821
> --- /dev/null
> +++ b/sysdeps/x86/tst-sysconf-cache-linesize-static.c
> @@ -0,0 +1 @@
> +#include "tst-sysconf-cache-linesize.c"
> diff --git a/sysdeps/x86/tst-sysconf-cache-linesize.c b/sysdeps/x86/tst-sysconf-cache-linesize.c
> new file mode 100644
> index 0000000000..642dbde5d2
> --- /dev/null
> +++ b/sysdeps/x86/tst-sysconf-cache-linesize.c
> @@ -0,0 +1,57 @@
> +/* Test system cache line sizes.
> +   Copyright (C) 2021 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 <stdlib.h>
> +#include <unistd.h>
> +#include <array_length.h>
> +
> +static struct
> +{
> +  const char *name;
> +  int _SC_val;
> +} sc_options[] =
> +  {
> +#define N(name) { "_SC_"#name, _SC_##name }
> +    N (LEVEL1_ICACHE_LINESIZE),
> +    N (LEVEL1_DCACHE_LINESIZE),
> +    N (LEVEL2_CACHE_LINESIZE)
> +  };
> +
> +static int
> +do_test (void)
> +{
> +  int result = EXIT_SUCCESS;
> +
> +  for (int i = 0; i < array_length (sc_options); ++i)
> +    {
> +      long int scret = sysconf (sc_options[i]._SC_val);
> +      if (scret < 0)
> +	{
> +	  printf ("sysconf (%s) returned < 0 (%ld)\n",
> +		  sc_options[i].name, scret);
> +	  result = EXIT_FAILURE;

OK. Expect that sysconf knows the value and returns a non-error return.

> +	}
> +      else
> +	printf ("sysconf (%s): %ld\n", sc_options[i].name, scret);
> +    }
> +
> +  return result;
> +}
> +
> +#include <support/test-driver.c>
>
  
H.J. Lu March 15, 2021, 12:52 p.m. UTC | #2
On Mon, Mar 15, 2021 at 5:32 AM Carlos O'Donell <carlos@redhat.com> wrote:
>
> On 3/6/21 2:11 PM, H.J. Lu via Libc-alpha wrote:
> > commit 2d651eb9265d1366d7b9e881bfddd46db9c1ecc4
> > Author: H.J. Lu <hjl.tools@gmail.com>
> > Date:   Fri Sep 18 07:55:14 2020 -0700
> >
> >     x86: Move x86 processor cache info to cpu_features
> >
> > missed _SC_LEVEL1_ICACHE_LINESIZE.
>
> LGTM.
>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
>
> >
> > 1. Add level1_icache_linesize to struct cpu_features.
> > 2. Initialize level1_icache_linesize by calling handle_intel,
> > handle_zhaoxin and handle_amd with _SC_LEVEL1_ICACHE_LINESIZE.
> > 3. Return level1_icache_linesize for _SC_LEVEL1_ICACHE_LINESIZE.
> > ---
> >  sysdeps/x86/Makefile                          |  8 +++
> >  sysdeps/x86/cacheinfo.c                       |  3 +
> >  sysdeps/x86/dl-cacheinfo.h                    |  6 ++
> >  sysdeps/x86/dl-diagnostics-cpu.c              |  2 +
> >  sysdeps/x86/include/cpu-features.h            |  2 +
> >  .../x86/tst-sysconf-cache-linesize-static.c   |  1 +
> >  sysdeps/x86/tst-sysconf-cache-linesize.c      | 57 +++++++++++++++++++
> >  7 files changed, 79 insertions(+)
> >  create mode 100644 sysdeps/x86/tst-sysconf-cache-linesize-static.c
> >  create mode 100644 sysdeps/x86/tst-sysconf-cache-linesize.c
> >
> > diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
> > index e1f9379fd8..06c9f84f51 100644
> > --- a/sysdeps/x86/Makefile
> > +++ b/sysdeps/x86/Makefile
> > @@ -211,3 +211,11 @@ $(objpfx)check-cet.out: $(..)sysdeps/x86/check-cet.awk \
> >  generated += check-cet.out
> >  endif
> >  endif
> > +
> > +ifeq ($(subdir),posix)
> > +tests += \
> > +  tst-sysconf-cache-linesize \
> > +  tst-sysconf-cache-linesize-static
> > +tests-static += \
> > +  tst-sysconf-cache-linesize-static
> > +endif
>
> OK. Add new test for static binary access of line size.
>
> > diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c
> > index 7b8df45e3b..5ea4723ca6 100644
> > --- a/sysdeps/x86/cacheinfo.c
> > +++ b/sysdeps/x86/cacheinfo.c
> > @@ -32,6 +32,9 @@ __cache_sysconf (int name)
> >      case _SC_LEVEL1_ICACHE_SIZE:
> >        return cpu_features->level1_icache_size;
> >
> > +    case _SC_LEVEL1_ICACHE_LINESIZE:
> > +      return cpu_features->level1_icache_linesize;
>
> OK. Return new struct member.
>
> > +
> >      case _SC_LEVEL1_DCACHE_SIZE:
> >        return cpu_features->level1_dcache_size;
> >
> > diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
> > index f3de206dc1..d9944250fc 100644
> > --- a/sysdeps/x86/dl-cacheinfo.h
> > +++ b/sysdeps/x86/dl-cacheinfo.h
> > @@ -707,6 +707,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
> >    long int core = -1;
> >    unsigned int threads = 0;
> >    unsigned long int level1_icache_size = -1;
> > +  unsigned long int level1_icache_linesize = -1;
>
> OK. Struct member matches.
>
> >    unsigned long int level1_dcache_size = -1;
> >    unsigned long int level1_dcache_assoc = -1;
> >    unsigned long int level1_dcache_linesize = -1;
> > @@ -726,6 +727,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
> >
> >        level1_icache_size
> >       = handle_intel (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
> > +      level1_icache_linesize
> > +     = handle_intel (_SC_LEVEL1_ICACHE_LINESIZE, cpu_features);
>
> OK. Set member.
>
> >        level1_dcache_size = data;
> >        level1_dcache_assoc
> >       = handle_intel (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
> > @@ -753,6 +756,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
> >        shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
> >
> >        level1_icache_size = handle_zhaoxin (_SC_LEVEL1_ICACHE_SIZE);
> > +      level1_icache_linesize = handle_zhaoxin (_SC_LEVEL1_ICACHE_LINESIZE);
>
> OK. Handle alternatives.
>
> >        level1_dcache_size = data;
> >        level1_dcache_assoc = handle_zhaoxin (_SC_LEVEL1_DCACHE_ASSOC);
> >        level1_dcache_linesize = handle_zhaoxin (_SC_LEVEL1_DCACHE_LINESIZE);
> > @@ -772,6 +776,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
> >        shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
> >
> >        level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
> > +      level1_icache_linesize = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE);
>
> OK. Likewise.
>
> >        level1_dcache_size = data;
> >        level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
> >        level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
> > @@ -833,6 +838,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
> >      }
> >
> >    cpu_features->level1_icache_size = level1_icache_size;
> > +  cpu_features->level1_icache_linesize = level1_icache_linesize;
>
> OK. Set actual cpu_features.
>
> >    cpu_features->level1_dcache_size = level1_dcache_size;
> >    cpu_features->level1_dcache_assoc = level1_dcache_assoc;
> >    cpu_features->level1_dcache_linesize = level1_dcache_linesize;
> > diff --git a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
> > index 5d9713f8d9..5d04527ad1 100644
> > --- a/sysdeps/x86/dl-diagnostics-cpu.c
> > +++ b/sysdeps/x86/dl-diagnostics-cpu.c
> > @@ -91,6 +91,8 @@ _dl_diagnostics_cpu (void)
> >                              cpu_features->rep_stosb_threshold);
> >    print_cpu_features_value ("level1_icache_size",
> >                              cpu_features->level1_icache_size);
> > +  print_cpu_features_value ("level1_icache_linesize",
> > +                            cpu_features->level1_icache_linesize);
>
> OK. Add it to diag printing.
>
> >    print_cpu_features_value ("level1_dcache_size",
> >                              cpu_features->level1_dcache_size);
> >    print_cpu_features_value ("level1_dcache_assoc",
> > diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
> > index c5a779ba32..d042a2ebef 100644
> > --- a/sysdeps/x86/include/cpu-features.h
> > +++ b/sysdeps/x86/include/cpu-features.h
> > @@ -876,6 +876,8 @@ struct cpu_features
> >    unsigned long int rep_stosb_threshold;
> >    /* _SC_LEVEL1_ICACHE_SIZE.  */
> >    unsigned long int level1_icache_size;
> > +  /* _SC_LEVEL1_ICACHE_LINESIZE.  */
> > +  unsigned long int level1_icache_linesize;
>
> OK.
>
> >    /* _SC_LEVEL1_DCACHE_SIZE.  */
> >    unsigned long int level1_dcache_size;
> >    /* _SC_LEVEL1_DCACHE_ASSOC.  */
> > diff --git a/sysdeps/x86/tst-sysconf-cache-linesize-static.c b/sysdeps/x86/tst-sysconf-cache-linesize-static.c
> > new file mode 100644
> > index 0000000000..152ae68821
> > --- /dev/null
> > +++ b/sysdeps/x86/tst-sysconf-cache-linesize-static.c
> > @@ -0,0 +1 @@
> > +#include "tst-sysconf-cache-linesize.c"
> > diff --git a/sysdeps/x86/tst-sysconf-cache-linesize.c b/sysdeps/x86/tst-sysconf-cache-linesize.c
> > new file mode 100644
> > index 0000000000..642dbde5d2
> > --- /dev/null
> > +++ b/sysdeps/x86/tst-sysconf-cache-linesize.c
> > @@ -0,0 +1,57 @@
> > +/* Test system cache line sizes.
> > +   Copyright (C) 2021 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 <stdlib.h>
> > +#include <unistd.h>
> > +#include <array_length.h>
> > +
> > +static struct
> > +{
> > +  const char *name;
> > +  int _SC_val;
> > +} sc_options[] =
> > +  {
> > +#define N(name) { "_SC_"#name, _SC_##name }
> > +    N (LEVEL1_ICACHE_LINESIZE),
> > +    N (LEVEL1_DCACHE_LINESIZE),
> > +    N (LEVEL2_CACHE_LINESIZE)
> > +  };
> > +
> > +static int
> > +do_test (void)
> > +{
> > +  int result = EXIT_SUCCESS;
> > +
> > +  for (int i = 0; i < array_length (sc_options); ++i)
> > +    {
> > +      long int scret = sysconf (sc_options[i]._SC_val);
> > +      if (scret < 0)
> > +     {
> > +       printf ("sysconf (%s) returned < 0 (%ld)\n",
> > +               sc_options[i].name, scret);
> > +       result = EXIT_FAILURE;
>
> OK. Expect that sysconf knows the value and returns a non-error return.
>
> > +     }
> > +      else
> > +     printf ("sysconf (%s): %ld\n", sc_options[i].name, scret);
> > +    }
> > +
> > +  return result;
> > +}
> > +
> > +#include <support/test-driver.c>
> >
>

I am backporting it to 2.33 branch.
  

Patch

diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index e1f9379fd8..06c9f84f51 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -211,3 +211,11 @@  $(objpfx)check-cet.out: $(..)sysdeps/x86/check-cet.awk \
 generated += check-cet.out
 endif
 endif
+
+ifeq ($(subdir),posix)
+tests += \
+  tst-sysconf-cache-linesize \
+  tst-sysconf-cache-linesize-static
+tests-static += \
+  tst-sysconf-cache-linesize-static
+endif
diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c
index 7b8df45e3b..5ea4723ca6 100644
--- a/sysdeps/x86/cacheinfo.c
+++ b/sysdeps/x86/cacheinfo.c
@@ -32,6 +32,9 @@  __cache_sysconf (int name)
     case _SC_LEVEL1_ICACHE_SIZE:
       return cpu_features->level1_icache_size;
 
+    case _SC_LEVEL1_ICACHE_LINESIZE:
+      return cpu_features->level1_icache_linesize;
+
     case _SC_LEVEL1_DCACHE_SIZE:
       return cpu_features->level1_dcache_size;
 
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
index f3de206dc1..d9944250fc 100644
--- a/sysdeps/x86/dl-cacheinfo.h
+++ b/sysdeps/x86/dl-cacheinfo.h
@@ -707,6 +707,7 @@  dl_init_cacheinfo (struct cpu_features *cpu_features)
   long int core = -1;
   unsigned int threads = 0;
   unsigned long int level1_icache_size = -1;
+  unsigned long int level1_icache_linesize = -1;
   unsigned long int level1_dcache_size = -1;
   unsigned long int level1_dcache_assoc = -1;
   unsigned long int level1_dcache_linesize = -1;
@@ -726,6 +727,8 @@  dl_init_cacheinfo (struct cpu_features *cpu_features)
 
       level1_icache_size
 	= handle_intel (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
+      level1_icache_linesize
+	= handle_intel (_SC_LEVEL1_ICACHE_LINESIZE, cpu_features);
       level1_dcache_size = data;
       level1_dcache_assoc
 	= handle_intel (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
@@ -753,6 +756,7 @@  dl_init_cacheinfo (struct cpu_features *cpu_features)
       shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
 
       level1_icache_size = handle_zhaoxin (_SC_LEVEL1_ICACHE_SIZE);
+      level1_icache_linesize = handle_zhaoxin (_SC_LEVEL1_ICACHE_LINESIZE);
       level1_dcache_size = data;
       level1_dcache_assoc = handle_zhaoxin (_SC_LEVEL1_DCACHE_ASSOC);
       level1_dcache_linesize = handle_zhaoxin (_SC_LEVEL1_DCACHE_LINESIZE);
@@ -772,6 +776,7 @@  dl_init_cacheinfo (struct cpu_features *cpu_features)
       shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
 
       level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
+      level1_icache_linesize = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE);
       level1_dcache_size = data;
       level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
       level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
@@ -833,6 +838,7 @@  dl_init_cacheinfo (struct cpu_features *cpu_features)
     }
 
   cpu_features->level1_icache_size = level1_icache_size;
+  cpu_features->level1_icache_linesize = level1_icache_linesize;
   cpu_features->level1_dcache_size = level1_dcache_size;
   cpu_features->level1_dcache_assoc = level1_dcache_assoc;
   cpu_features->level1_dcache_linesize = level1_dcache_linesize;
diff --git a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
index 5d9713f8d9..5d04527ad1 100644
--- a/sysdeps/x86/dl-diagnostics-cpu.c
+++ b/sysdeps/x86/dl-diagnostics-cpu.c
@@ -91,6 +91,8 @@  _dl_diagnostics_cpu (void)
                             cpu_features->rep_stosb_threshold);
   print_cpu_features_value ("level1_icache_size",
                             cpu_features->level1_icache_size);
+  print_cpu_features_value ("level1_icache_linesize",
+                            cpu_features->level1_icache_linesize);
   print_cpu_features_value ("level1_dcache_size",
                             cpu_features->level1_dcache_size);
   print_cpu_features_value ("level1_dcache_assoc",
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
index c5a779ba32..d042a2ebef 100644
--- a/sysdeps/x86/include/cpu-features.h
+++ b/sysdeps/x86/include/cpu-features.h
@@ -876,6 +876,8 @@  struct cpu_features
   unsigned long int rep_stosb_threshold;
   /* _SC_LEVEL1_ICACHE_SIZE.  */
   unsigned long int level1_icache_size;
+  /* _SC_LEVEL1_ICACHE_LINESIZE.  */
+  unsigned long int level1_icache_linesize;
   /* _SC_LEVEL1_DCACHE_SIZE.  */
   unsigned long int level1_dcache_size;
   /* _SC_LEVEL1_DCACHE_ASSOC.  */
diff --git a/sysdeps/x86/tst-sysconf-cache-linesize-static.c b/sysdeps/x86/tst-sysconf-cache-linesize-static.c
new file mode 100644
index 0000000000..152ae68821
--- /dev/null
+++ b/sysdeps/x86/tst-sysconf-cache-linesize-static.c
@@ -0,0 +1 @@ 
+#include "tst-sysconf-cache-linesize.c"
diff --git a/sysdeps/x86/tst-sysconf-cache-linesize.c b/sysdeps/x86/tst-sysconf-cache-linesize.c
new file mode 100644
index 0000000000..642dbde5d2
--- /dev/null
+++ b/sysdeps/x86/tst-sysconf-cache-linesize.c
@@ -0,0 +1,57 @@ 
+/* Test system cache line sizes.
+   Copyright (C) 2021 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 <stdlib.h>
+#include <unistd.h>
+#include <array_length.h>
+
+static struct
+{
+  const char *name;
+  int _SC_val;
+} sc_options[] =
+  {
+#define N(name) { "_SC_"#name, _SC_##name }
+    N (LEVEL1_ICACHE_LINESIZE),
+    N (LEVEL1_DCACHE_LINESIZE),
+    N (LEVEL2_CACHE_LINESIZE)
+  };
+
+static int
+do_test (void)
+{
+  int result = EXIT_SUCCESS;
+
+  for (int i = 0; i < array_length (sc_options); ++i)
+    {
+      long int scret = sysconf (sc_options[i]._SC_val);
+      if (scret < 0)
+	{
+	  printf ("sysconf (%s) returned < 0 (%ld)\n",
+		  sc_options[i].name, scret);
+	  result = EXIT_FAILURE;
+	}
+      else
+	printf ("sysconf (%s): %ld\n", sc_options[i].name, scret);
+    }
+
+  return result;
+}
+
+#include <support/test-driver.c>