summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-07-12 18:26:36 +0000
committerJakub Jelinek <jakub@redhat.com>2007-07-12 18:26:36 +0000
commit75c50bbb58e47bf4a0519170539ea0bc83035290 (patch)
tree2ea1f8305970753e4a657acb2ccc15ca3eec8e2c
parentb898e8fb2edbd994cdaa9aca94228d13f4fb26de (diff)
-rw-r--r--fedora/glibc-rh234946.patch32
-rw-r--r--fedora/glibc-x86_64-memcpy.patch1439
-rw-r--r--fedora/glibc.spec.in7
3 files changed, 1477 insertions, 1 deletions
diff --git a/fedora/glibc-rh234946.patch b/fedora/glibc-rh234946.patch
new file mode 100644
index 0000000000..add3f8023f
--- /dev/null
+++ b/fedora/glibc-rh234946.patch
@@ -0,0 +1,32 @@
+2006-12-25 Sripathi Kodi <sripathik@in.ibm.com>
+
+ * include/link.h: Declare new flag l_fini_called in struct link_map.
+ * elf/dl-fini.c: In _dl_fini, set l_fini_called to 1 instead of
+ l_init_called to 0.
+
+--- libc/elf/dl-fini.c 2006-12-22 01:54:22.000000000 -0600
++++ libc/elf/dl-fini.c 2006-12-24 22:51:52.000000000 -0600
+@@ -215,10 +215,10 @@ _dl_fini (void)
+ {
+ l = maps[i];
+
+- if (l->l_init_called)
++ if (l->l_init_called && !l->l_fini_called)
+ {
+ /* Make sure nothing happens if we are called twice. */
+- l->l_init_called = 0;
++ l->l_fini_called = 1;
+
+ /* Is there a destructor function? */
+ if (l->l_info[DT_FINI_ARRAY] != NULL
+--- libc/include/link.h 2006-12-22 01:54:22.000000000 -0600
++++ libc/include/link.h 2006-12-24 22:53:29.000000000 -0600
+@@ -185,6 +185,8 @@ struct link_map
+ unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are
+ mprotected or if no holes are present at
+ all. */
++ unsigned int l_fini_called:1; /* Nonzero if _dl_fini has processed
++ this object */
+
+ /* Array with version names. */
+ unsigned int l_nversions;
diff --git a/fedora/glibc-x86_64-memcpy.patch b/fedora/glibc-x86_64-memcpy.patch
new file mode 100644
index 0000000000..3888134df8
--- /dev/null
+++ b/fedora/glibc-x86_64-memcpy.patch
@@ -0,0 +1,1439 @@
+2007-05-21 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/x86_64/cacheinfo.c (init_cacheinfo): Pass correct value
+ as second parameter to handle_intel.
+
+ * sysdeps/unix/sysv/linux/x86_64/sysconf.c: Move cache information
+ handling to ...
+ * sysdeps/x86_64/cacheinfo.c: ... here. New file.
+ * sysdeps/x86_64/Makefile [subdir=string] (sysdep_routines): Add
+ cacheinfo.
+ * sysdeps/x86_64/memcpy.S: Complete rewrite.
+ * sysdeps/x86_64/mempcpy.S: Adjust appropriately.
+ Patch by Evandro Menezes <evandro.menezes@amd.com>.
+
+--- libc/sysdeps/x86_64/Makefile 16 Aug 2004 06:46:14 -0000 1.4
++++ libc/sysdeps/x86_64/Makefile 21 May 2007 19:20:45 -0000 1.5
+@@ -9,3 +9,7 @@ endif
+ ifeq ($(subdir),gmon)
+ sysdep_routines += _mcount
+ endif
++
++ifeq ($(subdir),string)
++sysdep_routines += cacheinfo
++endif
+--- libc/sysdeps/x86_64/cacheinfo.c 1 Jan 1970 00:00:00 -0000
++++ libc/sysdeps/x86_64/cacheinfo.c 21 May 2007 22:37:45 -0000 1.2
+@@ -0,0 +1,451 @@
++/* x86_64 cache info.
++ Copyright (C) 2003, 2004, 2006, 2007 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, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA.
++*/
++
++#include <assert.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++static const struct intel_02_cache_info
++{
++ unsigned int idx;
++ int name;
++ long int size;
++ long int assoc;
++ long int linesize;
++} intel_02_known [] =
++ {
++ { 0x06, _SC_LEVEL1_ICACHE_SIZE, 8192, 4, 32 },
++ { 0x08, _SC_LEVEL1_ICACHE_SIZE, 16384, 4, 32 },
++ { 0x0a, _SC_LEVEL1_DCACHE_SIZE, 8192, 2, 32 },
++ { 0x0c, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 32 },
++ { 0x22, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 },
++ { 0x23, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 },
++ { 0x25, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 },
++ { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 },
++ { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 },
++ { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 },
++ { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 },
++ { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 },
++ { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 },
++ { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 },
++ { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 },
++ { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 },
++ { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 },
++ { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 },
++ { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 },
++ { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 },
++ { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 },
++ { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 },
++ { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 },
++ { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 },
++ { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 },
++ { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 },
++ { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 },
++ { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 },
++ { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 },
++ { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 },
++ { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 },
++ { 0x68, _SC_LEVEL1_DCACHE_SIZE, 32768, 4, 64 },
++ { 0x78, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
++ { 0x79, _SC_LEVEL2_CACHE_SIZE, 131072, 8, 64 },
++ { 0x7a, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 },
++ { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 },
++ { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
++ { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 },
++ { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 },
++ { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 },
++ { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 },
++ { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 },
++ { 0x85, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 32 },
++ { 0x86, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 },
++ { 0x87, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
++ };
++
++#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0]))
++
++static int
++intel_02_known_compare (const void *p1, const void *p2)
++{
++ const struct intel_02_cache_info *i1;
++ const struct intel_02_cache_info *i2;
++
++ i1 = (const struct intel_02_cache_info *) p1;
++ i2 = (const struct intel_02_cache_info *) p2;
++
++ if (i1->idx == i2->idx)
++ return 0;
++
++ return i1->idx < i2->idx ? -1 : 1;
++}
++
++
++static long int
++__attribute__ ((noinline))
++intel_check_word (int name, unsigned int value, bool *has_level_2,
++ bool *no_level_2_or_3)
++{
++ if ((value & 0x80000000) != 0)
++ /* The register value is reserved. */
++ return 0;
++
++ /* Fold the name. The _SC_ constants are always in the order SIZE,
++ ASSOC, LINESIZE. */
++ int folded_name = (_SC_LEVEL1_ICACHE_SIZE
++ + ((name - _SC_LEVEL1_ICACHE_SIZE) / 3) * 3);
++
++ while (value != 0)
++ {
++ unsigned int byte = value & 0xff;
++
++ if (byte == 0x40)
++ {
++ *no_level_2_or_3 = true;
++
++ if (folded_name == _SC_LEVEL3_CACHE_SIZE)
++ /* No need to look further. */
++ break;
++ }
++ else
++ {
++ if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE)
++ {
++ /* Intel reused this value. For family 15, model 6 it
++ specifies the 3rd level cache. Otherwise the 2nd
++ level cache. */
++ unsigned int eax;
++ unsigned int ebx;
++ unsigned int ecx;
++ unsigned int edx;
++ asm volatile ("cpuid"
++ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (1));
++
++ unsigned int family = ((eax >> 20) & 0xff) + ((eax >> 8) & 0xf);
++ unsigned int model = ((((eax >>16) & 0xf) << 4)
++ + ((eax >> 4) & 0xf));
++ if (family == 15 && model == 6)
++ {
++ /* The level 3 cache is encoded for this model like
++ the level 2 cache is for other models. Pretend
++ the caller asked for the level 2 cache. */
++ name = (_SC_LEVEL2_CACHE_SIZE
++ + (name - _SC_LEVEL3_CACHE_SIZE));
++ folded_name = _SC_LEVEL3_CACHE_SIZE;
++ }
++ }
++
++ struct intel_02_cache_info *found;
++ struct intel_02_cache_info search;
++
++ search.idx = byte;
++ found = bsearch (&search, intel_02_known, nintel_02_known,
++ sizeof (intel_02_known[0]), intel_02_known_compare);
++ if (found != NULL)
++ {
++ if (found->name == folded_name)
++ {
++ unsigned int offset = name - folded_name;
++
++ if (offset == 0)
++ /* Cache size. */
++ return found->size;
++ if (offset == 1)
++ return found->assoc;
++
++ assert (offset == 2);
++ return found->linesize;
++ }
++
++ if (found->name == _SC_LEVEL2_CACHE_SIZE)
++ *has_level_2 = true;
++ }
++ }
++
++ /* Next byte for the next round. */
++ value >>= 8;
++ }
++
++ /* Nothing found. */
++ return 0;
++}
++
++
++static long int __attribute__ ((noinline))
++handle_intel (int name, unsigned int maxidx)
++{
++ assert (maxidx >= 2);
++
++ /* OK, we can use the CPUID instruction to get all info about the
++ caches. */
++ unsigned int cnt = 0;
++ unsigned int max = 1;
++ long int result = 0;
++ bool no_level_2_or_3 = false;
++ bool has_level_2 = false;
++
++ while (cnt++ < max)
++ {
++ unsigned int eax;
++ unsigned int ebx;
++ unsigned int ecx;
++ unsigned int edx;
++ asm volatile ("cpuid"
++ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (2));
++
++ /* The low byte of EAX in the first round contain the number of
++ rounds we have to make. At least one, the one we are already
++ doing. */
++ if (cnt == 1)
++ {
++ max = eax & 0xff;
++ eax &= 0xffffff00;
++ }
++
++ /* Process the individual registers' value. */
++ result = intel_check_word (name, eax, &has_level_2, &no_level_2_or_3);
++ if (result != 0)
++ return result;
++
++ result = intel_check_word (name, ebx, &has_level_2, &no_level_2_or_3);
++ if (result != 0)
++ return result;
++
++ result = intel_check_word (name, ecx, &has_level_2, &no_level_2_or_3);
++ if (result != 0)
++ return result;
++
++ result = intel_check_word (name, edx, &has_level_2, &no_level_2_or_3);
++ if (result != 0)
++ return result;
++ }
++
++ if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE
++ && no_level_2_or_3)
++ return -1;
++
++ return 0;
++}
++
++
++static long int __attribute__ ((noinline))
++handle_amd (int name)
++{
++ unsigned int eax;
++ unsigned int ebx;
++ unsigned int ecx;
++ unsigned int edx;
++ asm volatile ("cpuid"
++ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (0x80000000));
++
++ if (name >= _SC_LEVEL3_CACHE_SIZE)
++ return 0;
++
++ unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
++ if (eax < fn)
++ return 0;
++
++ asm volatile ("cpuid"
++ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (fn));
++
++ if (name < _SC_LEVEL1_DCACHE_SIZE)
++ {
++ name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
++ ecx = edx;
++ }
++
++ switch (name)
++ {
++ case _SC_LEVEL1_DCACHE_SIZE:
++ return (ecx >> 14) & 0x3fc00;
++ case _SC_LEVEL1_DCACHE_ASSOC:
++ ecx >>= 16;
++ if ((ecx & 0xff) == 0xff)
++ /* Fully associative. */
++ return (ecx << 2) & 0x3fc00;
++ return ecx & 0xff;
++ case _SC_LEVEL1_DCACHE_LINESIZE:
++ return ecx & 0xff;
++ case _SC_LEVEL2_CACHE_SIZE:
++ return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
++ case _SC_LEVEL2_CACHE_ASSOC:
++ ecx >>= 12;
++ switch (ecx & 0xf)
++ {
++ case 0:
++ case 1:
++ case 2:
++ case 4:
++ return ecx & 0xf;
++ case 6:
++ return 8;
++ case 8:
++ return 16;
++ case 0xf:
++ return (ecx << 6) & 0x3fffc00;
++ default:
++ return 0;
++ }
++ case _SC_LEVEL2_CACHE_LINESIZE:
++ return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
++ default:
++ assert (! "cannot happen");
++ }
++ return -1;
++}
++
++
++/* Get the value of the system variable NAME. */
++long int
++attribute_hidden
++__cache_sysconf (int name)
++{
++ /* Find out what brand of processor. */
++ unsigned int eax;
++ unsigned int ebx;
++ unsigned int ecx;
++ unsigned int edx;
++ asm volatile ("cpuid"
++ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (0));
++
++ /* This spells out "GenuineIntel". */
++ if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
++ return handle_intel (name, eax);
++
++ /* This spells out "AuthenticAMD". */
++ if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
++ return handle_amd (name);
++
++ // XXX Fill in more vendors.
++
++ /* CPU not known, we have no information. */
++ return 0;
++}
++
++
++/* Half the core cache size for use in memory and string routines, typically
++ L1 size. */
++long int __x86_64_core_cache_size_half attribute_hidden = 32 * 1024 / 2;
++/* Shared cache size for use in memory and string routines, typically
++ L2 or L3 size. */
++long int __x86_64_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2;
++/* PREFETCHW support flag for use in memory and string routines. */
++int __x86_64_prefetchw attribute_hidden;
++
++
++static void
++__attribute__((constructor))
++init_cacheinfo (void)
++{
++ /* Find out what brand of processor. */
++ unsigned int eax;
++ unsigned int ebx;
++ unsigned int ecx;
++ unsigned int edx;
++ int max_cpuid;
++ int max_cpuid_ex;
++ long int core = -1;
++ long int shared = -1;
++ unsigned int level;
++ unsigned int threads = 0;
++
++ asm volatile ("cpuid"
++ : "=a" (max_cpuid), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (0));
++
++ /* This spells out "GenuineIntel". */
++ if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
++ {
++ core = handle_intel (_SC_LEVEL1_DCACHE_SIZE, max_cpuid);
++
++ /* Try L3 first. */
++ level = 3;
++ shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, max_cpuid);
++
++ if (shared <= 0)
++ {
++ /* Try L2 otherwise. */
++ level = 2;
++ shared = handle_intel (_SC_LEVEL2_CACHE_SIZE, max_cpuid);
++ }
++
++ /* Figure out the number of logical threads that share the
++ highest cache level. */
++ if (max_cpuid >= 4)
++ {
++ int i = 0;
++
++ /* Query until desired cache level is enumerated. */
++ do
++ {
++ asm volatile ("cpuid"
++ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (4), "2" (i++));
++ }
++ while (((eax >> 5) & 0x7) != level);
++
++ threads = ((eax >> 14) & 0x3ff) + 1;
++ }
++ else
++ {
++ /* Assume that all logical threads share the highest cache level. */
++ asm volatile ("cpuid"
++ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (1));
++
++ threads = (ebx >> 16) & 0xff;
++ }
++
++ /* Cap usage of highest cache level to the number of supported
++ threads. */
++ if (shared > 0 && threads > 0)
++ shared /= threads;
++ }
++ /* This spells out "AuthenticAMD". */
++ else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
++ {
++ core = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
++ shared = handle_amd (_SC_LEVEL2_CACHE_SIZE);
++
++ asm volatile ("cpuid"
++ : "=a" (max_cpuid_ex), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (0x80000000));
++
++ if (max_cpuid_ex >= 0x80000001)
++ {
++ asm volatile ("cpuid"
++ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++ : "0" (0x80000001));
++ /* PREFETCHW || 3DNow! */
++ if ((ecx & 0x100) || (edx & 0x80000000))
++ __x86_64_prefetchw = -1;
++ }
++ }
++
++ if (core > 0)
++ __x86_64_core_cache_size_half = core / 2;
++
++ if (shared > 0)
++ __x86_64_shared_cache_size_half = shared / 2;
++}
+--- libc/sysdeps/x86_64/memcpy.S 18 Oct 2004 04:17:08 -0000 1.5
++++ libc/sysdeps/x86_64/memcpy.S 21 May 2007 19:21:01 -0000 1.6
+@@ -1,7 +1,10 @@
+-/* Highly optimized version for x86-64.
+- Copyright (C) 1997, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
++/*
++ Optimized memcpy for x86-64.
++
++ Copyright (C) 2007 Free Software Foundation, Inc.
++ Contributed by Evandro Menezes <evandro.menezes@amd.com>, 2007.
++
+ This file is part of the GNU C Library.
+- Based on i586 version contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+@@ -16,86 +19,556 @@
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+- 02111-1307 USA. */
++ 02111-1307 USA.
++*/
+
+ #include <sysdep.h>
+ #include "asm-syntax.h"
+-#include "bp-sym.h"
+-#include "bp-asm.h"
+
+-/* BEWARE: `#ifdef memcpy' means that memcpy is redefined as `mempcpy',
+- and the return value is the byte after the last one copied in
+- the destination. */
+-#define MEMPCPY_P (defined memcpy)
++/* Stack slots in the red-zone. */
++
++#ifdef USE_AS_MEMPCPY
++# define RETVAL (0)
++#else
++# define RETVAL (-8)
++#endif
++#define SAVE0 (RETVAL - 8)
++#define SAVE1 (SAVE0 - 8)
++#define SAVE2 (SAVE1 - 8)
++#define SAVE3 (SAVE2 - 8)
+
+ .text
++
+ #if defined PIC && !defined NOT_IN_libc
+ ENTRY (__memcpy_chk)
++
+ cmpq %rdx, %rcx
+ jb HIDDEN_JUMPTARGET (__chk_fail)
++
+ END (__memcpy_chk)
+ #endif
+-ENTRY (BP_SYM (memcpy))
+- /* Cutoff for the big loop is a size of 32 bytes since otherwise
+- the loop will never be entered. */
++
++ENTRY(memcpy) /* (void *, const void*, size_t) */
++
++/* Handle tiny blocks. */
++
++L(1try): /* up to 32B */
+ cmpq $32, %rdx
+- movq %rdx, %rcx
+-#if !MEMPCPY_P
+- movq %rdi, %r10 /* Save value. */
++#ifndef USE_AS_MEMPCPY
++ movq %rdi, %rax /* save return value */
+ #endif
++ jae L(1after)
+
+- /* We need this in any case. */
+- cld
++L(1): /* 1-byte once */
++ testb $1, %dl
++ jz L(1a)
+
+- jbe 1f
++ movzbl (%rsi), %ecx
++ movb %cl, (%rdi)
+
+- /* Align destination. */
+- movq %rdi, %rax
+- negq %rax
+- andq $7, %rax
+- subq %rax, %rcx
+- xchgq %rax, %rcx
++ incq %rsi
++ incq %rdi
++
++ .p2align 4,, 4
++
++L(1a): /* 2-byte once */
++ testb $2, %dl
++ jz L(1b)
++
++ movzwl (%rsi), %ecx
++ movw %cx, (%rdi)
+
+- rep; movsb
++ addq $2, %rsi
++ addq $2, %rdi
+
+- movq %rax, %rcx
+- subq $32, %rcx
+- js 2f
++ .p2align 4,, 4
++
++L(1b): /* 4-byte once */
++ testb $4, %dl
++ jz L(1c)
++
++ movl (%rsi), %ecx
++ movl %ecx, (%rdi)
++
++ addq $4, %rsi
++ addq $4, %rdi
++
++ .p2align 4,, 4
++
++L(1c): /* 8-byte once */
++ testb $8, %dl
++ jz L(1d)
++
++ movq (%rsi), %rcx
++ movq %rcx, (%rdi)
++
++ addq $8, %rsi
++ addq $8, %rdi
++
++ .p2align 4,, 4
++
++L(1d): /* 16-byte loop */
++ andl $0xf0, %edx
++ jz L(exit)
+
+ .p2align 4
+-3:
+
+- /* Now correct the loop counter. Please note that in the following
+- code the flags are not changed anymore. */
+- subq $32, %rcx
++L(1loop):
++ movq (%rsi), %rcx
++ movq 8 (%rsi), %r8
++ movq %rcx, (%rdi)
++ movq %r8, 8 (%rdi)
++
++ subl $16, %edx
++
++ leaq 16 (%rsi), %rsi
++ leaq 16 (%rdi), %rdi
++
++ jnz L(1loop)
++
++ .p2align 4,, 4
++
++L(exit): /* exit */
++#ifdef USE_AS_MEMPCPY
++ movq %rdi, %rax /* return value */
++#else
++ rep
++#endif
++ retq
++
++ .p2align 4
++
++L(1after):
++#ifndef USE_AS_MEMPCPY
++ movq %rax, RETVAL (%rsp) /* save return value */
++#endif
++
++/* Align to the natural word size. */
++
++L(aligntry):
++ movl %esi, %ecx /* align by destination */
++
++ andl $7, %ecx
++ jz L(alignafter) /* already aligned */
++
++L(align): /* align */
++ leaq -8 (%rcx, %rdx), %rdx /* calculate remaining bytes */
++ subl $8, %ecx
++
++ .p2align 4
++
++L(alignloop): /* 1-byte alignment loop */
++ movzbl (%rsi), %eax
++ movb %al, (%rdi)
++
++ incl %ecx
++
++ leaq 1 (%rsi), %rsi
++ leaq 1 (%rdi), %rdi
++
++ jnz L(alignloop)
++
++ .p2align 4
++
++L(alignafter):
++
++/* Loop to handle mid-sized blocks. */
++
++L(32try): /* up to 1KB */
++ cmpq $1024, %rdx
++ ja L(32after)
++
++L(32): /* 32-byte loop */
++ movl %edx, %ecx
++ shrl $5, %ecx
++ jz L(32skip)
++
++ .p2align 4
++
++L(32loop):
++ decl %ecx
+
+ movq (%rsi), %rax
+- movq 8(%rsi), %rdx
+- movq 16(%rsi), %r8
+- movq 24(%rsi), %r9
++ movq 8 (%rsi), %r8
++ movq 16 (%rsi), %r9
++ movq 24 (%rsi), %r10
++
+ movq %rax, (%rdi)
+- movq %rdx, 8(%rdi)
+- movq %r8, 16(%rdi)
+- movq %r9, 24(%rdi)
++ movq %r8, 8 (%rdi)
++ movq %r9, 16 (%rdi)
++ movq %r10, 24 (%rdi)
+
+ leaq 32(%rsi), %rsi
+ leaq 32(%rdi), %rdi
+
+- jns 3b
++ jz L(32skip) /* help out smaller blocks */
++
++ decl %ecx
++
++ movq (%rsi), %rax
++ movq 8 (%rsi), %r8
++ movq 16 (%rsi), %r9
++ movq 24 (%rsi), %r10
++
++ movq %rax, (%rdi)
++ movq %r8, 8 (%rdi)
++ movq %r9, 16 (%rdi)
++ movq %r10, 24 (%rdi)
++
++ leaq 32 (%rsi), %rsi
++ leaq 32 (%rdi), %rdi
++
++ jnz L(32loop)
++
++ .p2align 4
+
+- /* Correct extra loop counter modification. */
+-2: addq $32, %rcx
+-1: rep; movsb
++L(32skip):
++ andl $31, %edx /* check for left overs */
++#ifdef USE_AS_MEMPCPY
++ jnz L(1)
+
+-#if MEMPCPY_P
+- movq %rdi, %rax /* Set return value. */
++ movq %rdi, %rax
+ #else
+- movq %r10, %rax /* Set return value. */
++ movq RETVAL (%rsp), %rax
++ jnz L(1)
+
++ rep
++#endif
++ retq /* exit */
++
++ .p2align 4
++
++L(32after):
++
++/*
++ In order to minimize code-size in RTLD, algorithms specific for
++ larger blocks are excluded when building for RTLD.
++*/
++
++/* Handle large blocks smaller than 1/2 L1. */
++
++L(fasttry): /* first 1/2 L1 */
++#ifndef NOT_IN_libc /* only up to this algorithm outside of libc.so */
++ movq __x86_64_core_cache_size_half (%rip), %r11
++ cmpq %rdx, %r11 /* calculate the smaller of */
++ cmovaq %rdx, %r11 /* remaining bytes and 1/2 L1 */
++#endif
++
++L(fast): /* good ol' MOVS */
++#ifndef NOT_IN_libc
++ movq %r11, %rcx
++ andq $-8, %r11
++#else
++ movq %rdx, %rcx
++#endif
++ shrq $3, %rcx
++ jz L(fastskip)
++
++ rep
++ movsq
++
++ .p2align 4,, 4
++
++L(fastskip):
++#ifndef NOT_IN_libc
++ subq %r11, %rdx /* check for more */
++ testq $-8, %rdx
++ jnz L(fastafter)
+ #endif
+- ret
+
+-END (BP_SYM (memcpy))
+-#if !MEMPCPY_P
++ andl $7, %edx /* check for left overs */
++#ifdef USE_AS_MEMPCPY
++ jnz L(1)
++
++ movq %rdi, %rax
++#else
++ movq RETVAL (%rsp), %rax
++ jnz L(1)
++
++ rep
++#endif
++ retq /* exit */
++
++#ifndef NOT_IN_libc /* none of the algorithms below for RTLD */
++
++ .p2align 4
++
++L(fastafter):
++
++/* Handle large blocks smaller than 1/2 L2. */
++
++L(pretry): /* first 1/2 L2 */
++ movq __x86_64_shared_cache_size_half (%rip), %r8
++ cmpq %rdx, %r8 /* calculate the lesser of */
++ cmovaq %rdx, %r8 /* remaining bytes and 1/2 L2 */
++
++L(pre): /* 64-byte with prefetching */
++ movq %r8, %rcx
++ andq $-64, %r8
++ shrq $6, %rcx
++ jz L(preskip)
++
++ movq %r14, SAVE0 (%rsp)
++ cfi_rel_offset (%r14, SAVE0)
++ movq %r13, SAVE1 (%rsp)
++ cfi_rel_offset (%r13, SAVE1)
++ movq %r12, SAVE2 (%rsp)
++ cfi_rel_offset (%r12, SAVE2)
++ movq %rbx, SAVE3 (%rsp)
++ cfi_rel_offset (%rbx, SAVE3)
++
++ cmpl $0, __x86_64_prefetchw (%rip)
++ jz L(preloop) /* check if PREFETCHW OK */
++
++ .p2align 4
++
++/* ... when PREFETCHW is available (less cache-probe traffic in MP systems). */
++
++L(prewloop): /* cache-line in state M */
++ decq %rcx
++
++ movq (%rsi), %rax
++ movq 8 (%rsi), %rbx
++ movq 16 (%rsi), %r9
++ movq 24 (%rsi), %r10
++ movq 32 (%rsi), %r11
++ movq 40 (%rsi), %r12
++ movq 48 (%rsi), %r13
++ movq 56 (%rsi), %r14
++
++ prefetcht0 0 + 896 (%rsi)
++ prefetcht0 64 + 896 (%rsi)
++
++ movq %rax, (%rdi)
++ movq %rbx, 8 (%rdi)
++ movq %r9, 16 (%rdi)
++ movq %r10, 24 (%rdi)
++ movq %r11, 32 (%rdi)
++ movq %r12, 40 (%rdi)
++ movq %r13, 48 (%rdi)
++ movq %r14, 56 (%rdi)
++
++ leaq 64 (%rsi), %rsi
++ leaq 64 (%rdi), %rdi
++
++ jz L(prebail)
++
++ decq %rcx
++
++ movq (%rsi), %rax
++ movq 8 (%rsi), %rbx
++ movq 16 (%rsi), %r9
++ movq 24 (%rsi), %r10
++ movq 32 (%rsi), %r11
++ movq 40 (%rsi), %r12
++ movq 48 (%rsi), %r13
++ movq 56 (%rsi), %r14
++
++ movq %rax, (%rdi)
++ movq %rbx, 8 (%rdi)
++ movq %r9, 16 (%rdi)
++ movq %r10, 24 (%rdi)
++ movq %r11, 32 (%rdi)
++ movq %r12, 40 (%rdi)
++ movq %r13, 48 (%rdi)
++ movq %r14, 56 (%rdi)
++
++ prefetchw 896 - 64 (%rdi)
++ prefetchw 896 - 0 (%rdi)
++
++ leaq 64 (%rsi), %rsi
++ leaq 64 (%rdi), %rdi
++
++ jnz L(prewloop)
++ jmp L(prebail)
++
++ .p2align 4
++
++/* ... when PREFETCHW is not available. */
++
++L(preloop): /* cache-line in state E */
++ decq %rcx
++
++ movq (%rsi), %rax
++ movq 8 (%rsi), %rbx
++ movq 16 (%rsi), %r9
++ movq 24 (%rsi), %r10
++ movq 32 (%rsi), %r11
++ movq 40 (%rsi), %r12
++ movq 48 (%rsi), %r13
++ movq 56 (%rsi), %r14
++
++ prefetcht0 896 + 0 (%rsi)
++ prefetcht0 896 + 64 (%rsi)
++
++ movq %rax, (%rdi)
++ movq %rbx, 8 (%rdi)
++ movq %r9, 16 (%rdi)
++ movq %r10, 24 (%rdi)
++ movq %r11, 32 (%rdi)
++ movq %r12, 40 (%rdi)
++ movq %r13, 48 (%rdi)
++ movq %r14, 56 (%rdi)
++
++ leaq 64 (%rsi), %rsi
++ leaq 64 (%rdi), %rdi
++
++ jz L(prebail)
++
++ decq %rcx
++
++ movq (%rsi), %rax
++ movq 8 (%rsi), %rbx
++ movq 16 (%rsi), %r9
++ movq 24 (%rsi), %r10
++ movq 32 (%rsi), %r11
++ movq 40 (%rsi), %r12
++ movq 48 (%rsi), %r13
++ movq 56 (%rsi), %r14
++
++ prefetcht0 896 - 64 (%rdi)
++ prefetcht0 896 - 0 (%rdi)
++
++ movq %rax, (%rdi)
++ movq %rbx, 8 (%rdi)
++ movq %r9, 16 (%rdi)
++ movq %r10, 24 (%rdi)
++ movq %r11, 32 (%rdi)
++ movq %r12, 40 (%rdi)
++ movq %r13, 48 (%rdi)
++ movq %r14, 56 (%rdi)
++
++ leaq 64 (%rsi), %rsi
++ leaq 64 (%rdi), %rdi
++
++ jnz L(preloop)
++
++L(prebail):
++ movq SAVE3 (%rsp), %rbx
++ cfi_restore (%rbx)
++ movq SAVE2 (%rsp), %r12
++ cfi_restore (%r12)
++ movq SAVE1 (%rsp), %r13
++ cfi_restore (%r13)
++ movq SAVE0 (%rsp), %r14
++ cfi_restore (%r14)
++
++/* .p2align 4 */
++
++L(preskip):
++ subq %r8, %rdx /* check for more */
++ testq $-64, %rdx
++ jnz L(preafter)
++
++ andl $63, %edx /* check for left overs */
++#ifdef USE_AS_MEMPCPY
++ jnz L(1)
++
++ movq %rdi, %rax
++#else
++ movq RETVAL (%rsp), %rax
++ jnz L(1)
++
++ rep
++#endif
++ retq /* exit */
++
++ .p2align 4
++
++L(preafter):
++
++/* Loop to handle huge blocks. */
++
++L(NTtry):
++
++L(NT): /* non-temporal 128-byte */
++ movq %rdx, %rcx
++ shrq $7, %rcx
++ jz L(NTskip)
++
++ movq %r14, SAVE0 (%rsp)
++ cfi_rel_offset (%r14, SAVE0)
++ movq %r13, SAVE1 (%rsp)
++ cfi_rel_offset (%r13, SAVE1)
++ movq %r12, SAVE2 (%rsp)
++ cfi_rel_offset (%r12, SAVE2)
++
++ .p2align 4
++
++L(NTloop):
++ prefetchnta 768 (%rsi)
++ prefetchnta 832 (%rsi)
++
++ decq %rcx
++
++ movq (%rsi), %rax
++ movq 8 (%rsi), %r8
++ movq 16 (%rsi), %r9
++ movq 24 (%rsi), %r10
++ movq 32 (%rsi), %r11
++ movq 40 (%rsi), %r12
++ movq 48 (%rsi), %r13
++ movq 56 (%rsi), %r14
++
++ movntiq %rax, (%rdi)
++ movntiq %r8, 8 (%rdi)
++ movntiq %r9, 16 (%rdi)
++ movntiq %r10, 24 (%rdi)
++ movntiq %r11, 32 (%rdi)
++ movntiq %r12, 40 (%rdi)
++ movntiq %r13, 48 (%rdi)
++ movntiq %r14, 56 (%rdi)
++
++ movq 64 (%rsi), %rax
++ movq 72 (%rsi), %r8
++ movq 80 (%rsi), %r9
++ movq 88 (%rsi), %r10
++ movq 96 (%rsi), %r11
++ movq 104 (%rsi), %r12
++ movq 112 (%rsi), %r13
++ movq 120 (%rsi), %r14
++
++ movntiq %rax, 64 (%rdi)
++ movntiq %r8, 72 (%rdi)
++ movntiq %r9, 80 (%rdi)
++ movntiq %r10, 88 (%rdi)
++ movntiq %r11, 96 (%rdi)
++ movntiq %r12, 104 (%rdi)
++ movntiq %r13, 112 (%rdi)
++ movntiq %r14, 120 (%rdi)
++
++ leaq 128 (%rsi), %rsi
++ leaq 128 (%rdi), %rdi
++
++ jnz L(NTloop)
++
++ sfence /* serialize memory stores */
++
++ movq SAVE2 (%rsp), %r12
++ cfi_restore (%r12)
++ movq SAVE1 (%rsp), %r13
++ cfi_restore (%r13)
++ movq SAVE0 (%rsp), %r14
++ cfi_restore (%r14)
++
++L(NTskip):
++ andl $127, %edx /* check for left overs */
++#ifdef USE_AS_MEMPCPY
++ jnz L(1)
++
++ movq %rdi, %rax
++#else
++ movq RETVAL (%rsp), %rax
++ jnz L(1)
++
++ rep
++#endif
++ retq /* exit */
++
++#endif /* !NOT_IN_libc */
++
++END(memcpy)
++
++#ifndef USE_AS_MEMPCPY
+ libc_hidden_builtin_def (memcpy)
+ #endif
+--- libc/sysdeps/x86_64/mempcpy.S 18 Oct 2004 04:17:08 -0000 1.3
++++ libc/sysdeps/x86_64/mempcpy.S 21 May 2007 19:21:16 -0000 1.4
+@@ -1,3 +1,4 @@
++#define USE_AS_MEMPCPY
+ #define memcpy __mempcpy
+ #define __memcpy_chk __mempcpy_chk
+ #include <sysdeps/x86_64/memcpy.S>
+--- libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c 10 Nov 2006 07:31:55 -0000 1.7
++++ libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c 21 May 2007 19:18:37 -0000 1.8
+@@ -24,328 +24,17 @@
+
+
+ static long int linux_sysconf (int name);
+-
+-
+-static const struct intel_02_cache_info
+-{
+- unsigned int idx;
+- int name;
+- long int size;
+- long int assoc;
+- long int linesize;
+-} intel_02_known[] =
+- {
+- { 0x06, _SC_LEVEL1_ICACHE_SIZE, 8192, 4, 32 },
+- { 0x08, _SC_LEVEL1_ICACHE_SIZE, 16384, 4, 32 },
+- { 0x0a, _SC_LEVEL1_DCACHE_SIZE, 8192, 2, 32 },
+- { 0x0c, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 32 },
+- { 0x22, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 },
+- { 0x23, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 },
+- { 0x25, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 },
+- { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 },
+- { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 },
+- { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 },
+- { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 },
+- { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 },
+- { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 },
+- { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 },
+- { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 },
+- { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 },
+- { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 },
+- { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 },
+- { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 },
+- { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 },
+- { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 },
+- { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 },
+- { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 },
+- { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 },
+- { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 },
+- { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 },
+- { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 },
+- { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 },
+- { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 },
+- { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 },
+- { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 },
+- { 0x68, _SC_LEVEL1_DCACHE_SIZE, 32768, 4, 64 },
+- { 0x78, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
+- { 0x79, _SC_LEVEL2_CACHE_SIZE, 131072, 8, 64 },
+- { 0x7a, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 },
+- { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 },
+- { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
+- { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 },
+- { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 },
+- { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 },
+- { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 },
+- { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 },
+- { 0x85, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 32 },
+- { 0x86, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 },
+- { 0x87, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 },
+- };
+-#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known[0]))
+-
+-
+-static int
+-intel_02_known_compare (const void *p1, const void *p2)
+-{
+- const struct intel_02_cache_info *i1;
+- const struct intel_02_cache_info *i2;
+-
+- i1 = (const struct intel_02_cache_info *) p1;
+- i2 = (const struct intel_02_cache_info *) p2;
+-
+- if (i1->idx == i2->idx)
+- return 0;
+-
+- return i1->idx < i2->idx ? -1 : 1;
+-}
+-
+-
+-static long int
+-__attribute__ ((noinline))
+-intel_check_word (int name, unsigned int value, bool *has_level_2,
+- bool *no_level_2_or_3)
+-{
+- if ((value & 0x80000000) != 0)
+- /* The register value is reserved. */
+- return 0;
+-
+- /* Fold the name. The _SC_ constants are always in the order SIZE,
+- ASSOC, LINESIZE. */
+- int folded_name = (_SC_LEVEL1_ICACHE_SIZE
+- + ((name - _SC_LEVEL1_ICACHE_SIZE) / 3) * 3);
+-
+- while (value != 0)
+- {
+- unsigned int byte = value & 0xff;
+-
+- if (byte == 0x40)
+- {
+- *no_level_2_or_3 = true;
+-
+- if (folded_name == _SC_LEVEL3_CACHE_SIZE)
+- /* No need to look further. */
+- break;
+- }
+- else
+- {
+- if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE)
+- {
+- /* Intel reused this value. For family 15, model 6 it
+- specifies the 3rd level cache. Otherwise the 2nd
+- level cache. */
+- unsigned int eax;
+- unsigned int ebx;
+- unsigned int ecx;
+- unsigned int edx;
+- asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+- : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+- : "0" (1));
+-
+- unsigned int family = ((eax >> 20) & 0xff) + ((eax >> 8) & 0xf);
+- unsigned int model = ((((eax >>16) & 0xf) << 4)
+- + ((eax >> 4) & 0xf));
+- if (family == 15 && model == 6)
+- {
+- /* The level 3 cache is encoded for this model like
+- the level 2 cache is for other models. Pretend
+- the caller asked for the level 2 cache. */
+- name = (_SC_LEVEL2_CACHE_SIZE
+- + (name - _SC_LEVEL3_CACHE_SIZE));
+- folded_name = _SC_LEVEL3_CACHE_SIZE;
+- }
+- }
+-
+- struct intel_02_cache_info *found;
+- struct intel_02_cache_info search;
+-
+- search.idx = byte;
+- found = bsearch (&search, intel_02_known, nintel_02_known,
+- sizeof (intel_02_known[0]), intel_02_known_compare);
+- if (found != NULL)
+- {
+- if (found->name == folded_name)
+- {
+- unsigned int offset = name - folded_name;
+-
+- if (offset == 0)
+- /* Cache size. */
+- return found->size;
+- if (offset == 1)
+- return found->assoc;
+-
+- assert (offset == 2);
+- return found->linesize;
+- }
+-
+- if (found->name == _SC_LEVEL2_CACHE_SIZE)
+- *has_level_2 = true;
+- }
+- }
+-
+- /* Next byte for the next round. */
+- value >>= 8;
+- }
+-
+- /* Nothing found. */
+- return 0;
+-}
+-
+-
+-static long int __attribute__ ((noinline))
+-handle_intel (int name, unsigned int maxidx)
+-{
+- assert (maxidx >= 2);
+-
+- /* OK, we can use the CPUID instruction to get all info about the
+- caches. */
+- unsigned int cnt = 0;
+- unsigned int max = 1;
+- long int result = 0;
+- bool no_level_2_or_3 = false;
+- bool has_level_2 = false;
+- while (cnt++ < max)
+- {
+- unsigned int eax;
+- unsigned int ebx;
+- unsigned int ecx;
+- unsigned int edx;
+- asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+- : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+- : "0" (2));
+-
+- /* The low byte of EAX in the first round contain the number of
+- rounds we have to make. At least one, the one we are already
+- doing. */
+- if (cnt == 1)
+- {
+- max = eax & 0xff;
+- eax &= 0xffffff00;
+- }
+-
+- /* Process the individual registers' value. */
+- result = intel_check_word (name, eax, &has_level_2, &no_level_2_or_3);
+- if (result != 0)
+- return result;
+-
+- result = intel_check_word (name, ebx, &has_level_2, &no_level_2_or_3);
+- if (result != 0)
+- return result;
+-
+- result = intel_check_word (name, ecx, &has_level_2, &no_level_2_or_3);
+- if (result != 0)
+- return result;
+-
+- result = intel_check_word (name, edx, &has_level_2, &no_level_2_or_3);
+- if (result != 0)
+- return result;
+- }
+-
+- if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE
+- && no_level_2_or_3)
+- return -1;
+-
+- return 0;
+-}
+-
+-
+-static long int __attribute__ ((noinline))
+-handle_amd (int name)
+-{
+- unsigned int eax;
+- unsigned int ebx;
+- unsigned int ecx;
+- unsigned int edx;
+- asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+- : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+- : "0" (0x80000000));
+-
+- if (name >= _SC_LEVEL3_CACHE_SIZE)
+- return 0;
+-
+- unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
+- if (eax < fn)
+- return 0;
+-
+- asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+- : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+- : "0" (fn));
+-
+- if (name < _SC_LEVEL1_DCACHE_SIZE)
+- {
+- name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
+- ecx = edx;
+- }
+-
+- switch (name)
+- {
+- case _SC_LEVEL1_DCACHE_SIZE:
+- return (ecx >> 14) & 0x3fc00;
+- case _SC_LEVEL1_DCACHE_ASSOC:
+- ecx >>= 16;
+- if ((ecx & 0xff) == 0xff)
+- /* Fully associative. */
+- return (ecx << 2) & 0x3fc00;
+- return ecx & 0xff;
+- case _SC_LEVEL1_DCACHE_LINESIZE:
+- return ecx & 0xff;
+- case _SC_LEVEL2_CACHE_SIZE:
+- return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
+- case _SC_LEVEL2_CACHE_ASSOC:
+- ecx >>= 12;
+- switch (ecx & 0xf)
+- {
+- case 0:
+- case 1:
+- case 2:
+- case 4:
+- return ecx & 0xf;
+- case 6:
+- return 8;
+- case 8:
+- return 16;
+- case 0xf:
+- return (ecx << 6) & 0x3fffc00;
+- default:
+- return 0;
+- }
+- case _SC_LEVEL2_CACHE_LINESIZE:
+- return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
+- default:
+- assert (! "cannot happen");
+- }
+- return -1;
+-}
++extern long int __cache_sysconf (int) attribute_hidden;
+
+
+ /* Get the value of the system variable NAME. */
+ long int
+ __sysconf (int name)
+ {
+- /* We only handle the cache information here (for now). */
+- if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_LINESIZE)
+- return linux_sysconf (name);
+-
+- /* Find out what brand of processor. */
+- unsigned int eax;
+- unsigned int ebx;
+- unsigned int ecx;
+- unsigned int edx;
+- asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+- : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+- : "0" (0));
+-
+- /* This spells out "GenuineIntel". */
+- if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
+- return handle_intel (name, eax);
+-
+- /* This spells out "AuthenticAMD". */
+- if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
+- return handle_amd (name);
+-
+- // XXX Fill in more vendors.
++ if (name >= _SC_LEVEL1_ICACHE_SIZE && name <= _SC_LEVEL4_CACHE_LINESIZE)
++ return __cache_sysconf (name);
+
+- /* CPU not known, we have no information. */
+- return 0;
++ return linux_sysconf (name);
+ }
+
+ /* Now the generic Linux version. */
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index 6710838ca5..5e13ea805a 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -1,4 +1,4 @@
-%define glibcrelease 19
+%define glibcrelease 18.1
%define auxarches i586 i686 athlon sparcv9 alphaev6
%define xenarches i686 athlon
%ifarch %{xenarches}
@@ -31,6 +31,8 @@ Source2: %(echo %{glibcsrcdir} | sed s/glibc-/glibc-libidn-/).tar.bz2
Source3: %{glibcname}-fedora-%{glibcdate}.tar.bz2
Patch0: %{glibcname}-fedora.patch
Patch1: %{name}-ia64-lib64.patch
+Patch2: glibc-rh234946.patch
+Patch3: glibc-x86_64-memcpy.patch
Buildroot: %{_tmppath}/glibc-%{PACKAGE_VERSION}-root
Obsoletes: zoneinfo, libc-static, libc-devel, libc-profile, libc-headers,
Obsoletes: gencat, locale, ldconfig, locale-ja, glibc-profile
@@ -242,6 +244,9 @@ package or when debugging this package.
%patch1 -p1
%endif
%endif
+%patch2 -p1
+# Postpone until this is enough tested in F7
+#%patch3 -p1
# Hack till glibc-kernheaders get updated, argh
mkdir -p override_headers/linux