Index: libgcc/libgcov.c
===================================================================
--- libgcc/libgcov.c	(revision 194562)
+++ libgcc/libgcov.c	(working copy)
@@ -46,11 +46,11 @@ see the files COPYING3 and COPYING.RUNTIME respect
 #include "tsystem.h"
 #include "coretypes.h"
 #include "tm.h"
-#endif /* __KERNEL__ */
 #include "libgcc_tm.h"
 #include "gthr.h"
+#endif /* __KERNEL__ */
 
-#if 1
+#ifndef __KERNEL__
 #define THREAD_PREFIX __thread
 #else
 #define THREAD_PREFIX
@@ -120,6 +120,7 @@ extern int gcov_dump_complete ATTRIBUTE_HIDDEN;
 #ifdef L_gcov
 #include "gcov-io.c"
 
+#ifndef __GCOV_KERNEL__
 /* Create a strong reference to these symbols so that they are
    unconditionally pulled into the instrumented binary, even when
    the only reference is a weak reference. This is necessary because
@@ -134,6 +135,7 @@ extern int gcov_dump_complete ATTRIBUTE_HIDDEN;
    these symbols will always need to be resolved.  */
 void (*__gcov_dummy_ref1)() = &__gcov_reset;
 void (*__gcov_dummy_ref2)() = &__gcov_dump;
+#endif /* __GCOV_KERNEL__ */
 
 /* Utility function for outputing errors.  */
 static int
@@ -151,6 +153,10 @@ gcov_error (const char *fmt, ...)
   return ret;
 }
 
+/* A program checksum allows us to distinguish program data for an
+   object file included in multiple programs.  */
+static gcov_unsigned_t gcov_crc32;
+
 #ifndef __GCOV_KERNEL__
 /* Emitted in coverage.c.  */
 extern char * __gcov_pmu_profile_filename;
@@ -183,10 +189,6 @@ THREAD_PREFIX gcov_unsigned_t __gcov_sample_counte
 /* Chain of per-object gcov structures.  */
 extern struct gcov_info *__gcov_list;
 
-/* A program checksum allows us to distinguish program data for an
-   object file included in multiple programs.  */
-static gcov_unsigned_t gcov_crc32;
-
 /* Size of the longest file name. */
 static size_t gcov_max_filename = 0;
 
@@ -323,8 +325,6 @@ gcov_counter_active (const struct gcov_info *info,
   return (info->merge[type] != 0);
 }
 
-#ifndef __GCOV_KERNEL__
-
 /* Add an unsigned value to the current crc */
 
 static gcov_unsigned_t
@@ -344,6 +344,8 @@ crc32_unsigned (gcov_unsigned_t crc32, gcov_unsign
   return crc32;
 }
 
+#ifndef __GCOV_KERNEL__
+
 /* Check if VERSION of the info block PTR matches libgcov one.
    Return 1 on success, or zero in case of versions mismatch.
    If FILENAME is not NULL, its value used for reporting purposes
@@ -464,6 +466,8 @@ gcov_alloc_filename (void)
   gi_filename_up = gi_filename + prefix_length;
 }
 
+#endif /* __GCOV_KERNEL__ */
+
 /* Sort N entries in VALUE_ARRAY in descending order.
    Each entry in VALUE_ARRAY has two values. The sorting
    is based on the second value.  */
@@ -509,6 +513,8 @@ gcov_sort_icall_topn_counter (const struct gcov_ct
     }
 }
 
+#ifndef __GCOV_KERNEL__
+
 /* Write imported files (auxiliary modules) for primary module GI_PTR
    into file GI_FILENAME.  */
 
@@ -586,6 +592,8 @@ gcov_dump_module_info (void)
   __gcov_finalize_dyn_callgraph ();
 }
 
+#endif /* __GCOV_KERNEL__ */
+
 /* Insert counter VALUE into HISTOGRAM.  */
 
 static void
@@ -656,6 +664,8 @@ gcov_compute_histogram (struct gcov_summary *sum)
     }
 }
 
+#ifndef __GCOV_KERNEL__
+
 /* Dump the coverage counts. We merge with existing counts when
    possible, to avoid growing the .da files ad infinitum. We use this
    program's checksum to make sure we only accumulate whole program
@@ -1013,12 +1023,7 @@ gcov_merge_gcda_file (struct gcov_info *gi_ptr)
              goto read_error;
        }
      if (tag && tag != GCOV_TAG_MODULE_INFO)
-       {
-         read_mismatch:;
-	 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
-	          gi_filename, f_ix + 1 ? "function" : "summaries");
-         goto read_fatal;
-	}
+       goto read_mismatch;
     }
   goto rewrite;
 
@@ -1031,6 +1036,11 @@ read_error:;
 
     goto rewrite;
 
+read_mismatch:;
+    gcov_error ("profiling:%s:Merge mismatch for %s\n",
+	     gi_filename, f_ix + 1 ? "function" : "summaries");
+    goto read_fatal;
+
 read_fatal:;
     gcov_close ();
     return 1;
@@ -1076,7 +1086,7 @@ rewrite:;
                               sizeof (*cs_all) - (sizeof (gcov_bucket_type)
                                                   * GCOV_HISTOGRAM_SIZE)))
           {
-            fprintf (stderr, "profiling:%s:Invocation mismatch - "
+            gcov_error ("profiling:%s:Invocation mismatch - "
                 "some data files may have been removed%s\n",
             gi_filename, GCOV_LOCKED
             ? "" : " or concurrent update without locking support");
@@ -1093,14 +1103,14 @@ rewrite:;
    the size is in units of gcov_type.  */
 
 GCOV_LINKAGE unsigned
-gcov_gcda_file_size (struct gcov_info *gi_ptr,
-                     struct gcov_summary *sum)
+gcov_gcda_file_size (struct gcov_info *gi_ptr)
 {
   unsigned size;
   const struct gcov_fn_info *fi_ptr;
   unsigned f_ix, t_ix, h_ix, h_cnt = 0;
   unsigned n_counts;
   const struct gcov_ctr_info *ci_ptr;
+  struct gcov_summary *sum = &this_program;
   const struct gcov_ctr_summary *csum;
 
   /* GCOV_DATA_MAGIC, GCOV_VERSION and time_stamp.  */
@@ -1181,13 +1191,14 @@ gcov_write_gcda_file (struct gcov_info *gi_ptr)
       ci_ptr = gfi_ptr->ctrs;
       for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
         {
+          gcov_type *c_ptr;
           if (!gi_ptr->merge[t_ix])
             continue;
 
           n_counts = ci_ptr->num;
           gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
                                  GCOV_TAG_COUNTER_LENGTH (n_counts));
-          gcov_type *c_ptr = ci_ptr->values;
+          c_ptr = ci_ptr->values;
           while (n_counts--)
             gcov_write_counter (*c_ptr++);
           ci_ptr++;
@@ -1692,7 +1703,7 @@ __gcov_topn_value_profiler_body (gcov_type *counte
      {
        unsigned i, j;
        gcov_type *p, minv;
-       gcov_type* tmp_cnts 
+       gcov_type* tmp_cnts
            = (gcov_type *)alloca (topn_val * sizeof(gcov_type));
 
        *num_eviction = 0;
@@ -2050,15 +2061,20 @@ gcov_set_vfile (gcov_kernel_vfile *file)
   gcov_current_file = file;
 }
 
+/* Init function before dumping the gcda file in kernel.  */
+
+void
+gcov_kernel_dump_gcov_init (void)
+{
+  gcov_exit_init ();
+}
+
 /* Dump one entry in the gcov_info list (for one object) in kernel.  */
 
 void
 gcov_kernel_dump_one_gcov (struct gcov_info *info)
 {
   gcc_assert (gcov_current_file);
-
-  gcov_exit_init ();
-
   gcov_dump_one_gcov (info);
 }
 
Index: gcc/gcov-io.c
===================================================================
--- gcc/gcov-io.c	(revision 194562)
+++ gcc/gcov-io.c	(working copy)
@@ -662,6 +662,30 @@ gcov_read_string (void)
   return (const char *) gcov_read_words (length);
 }
 
+#ifdef __GCOV_KERNEL__
+static const unsigned char __popcount_tab[256] =
+{
+    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+static int k_popcountll (long long x)
+{
+  int i, ret = 0;
+
+  for (i = 0; i < 8*sizeof(long long) ; i += 8)
+    ret += __popcount_tab[(x >> i) & 0xff];
+
+  return ret;
+}
+#endif
+
 GCOV_LINKAGE void
 gcov_read_summary (struct gcov_summary *summary)
 {
@@ -683,7 +707,11 @@ gcov_read_summary (struct gcov_summary *summary)
       for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
         {
           histo_bitvector[bv_ix] = gcov_read_unsigned ();
+#ifndef __GCOV_KERNEL__
           h_cnt += __builtin_popcountll (histo_bitvector[bv_ix]);
+#else
+          h_cnt += k_popcountll (histo_bitvector[bv_ix]);
+#endif
         }
       bv_ix = 0;
       h_ix = 0;
@@ -1137,7 +1165,6 @@ kernel_file_fclose (gcov_kernel_vfile *fp)
 long
 kernel_file_ftell (gcov_kernel_vfile *fp)
 {
-  gcc_assert (0);  /* should not reach here */
   return 0;
 }
 
@@ -1192,8 +1219,9 @@ kernel_file_fwrite (const void *ptr, size_t size,
   if (vsize <= vpos)
     {
       printk (KERN_ERR
-         "GCOV_KERNEL: something wrong: vbuf=%p vsize=%u vpos=%u\n",
-          vbuf, vsize, vpos);
+         "GCOV_KERNEL: something wrong in file %s: vbuf=%p vsize=%u"
+         " vpos=%u\n",
+          fp->info->filename, vbuf, vsize, vpos);
       return 0;
     }
   len = vsize - vpos;
@@ -1207,8 +1235,9 @@ kernel_file_fwrite (const void *ptr, size_t size,
 
   if (len != nitems)
     printk (KERN_ERR
-        "GCOV_KERNEL: something wrong: size=%lu nitems=%lu ret=%d\n",
-        size, nitems, len);
+        "GCOV_KERNEL: something wrong in file %s: size=%lu nitems=%lu"
+        " ret=%d, vsize=%u vpos=%u \n",
+        fp->info->filename, size, nitems, len, vsize, vpos);
   return len;
 }
 
Index: gcc/gcov-io.h
===================================================================
--- gcc/gcov-io.h	(revision 194562)
+++ gcc/gcov-io.h	(working copy)
@@ -300,6 +300,14 @@ typedef unsigned gcov_type_unsigned __attribute__
 
 #endif  /* BITS_PER_UNIT == 8  */
 
+#if LONG_LONG_TYPE_SIZE > 32
+#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_8
+#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_8
+#else
+#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_4
+#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_4
+#endif
+
 #undef EXTRACT_MODULE_ID_FROM_GLOBAL_ID
 #undef EXTRACT_FUNC_ID_FROM_GLOBAL_ID
 #undef GEN_FUNC_GLOBAL_ID
@@ -322,6 +330,18 @@ typedef unsigned gcov_type_unsigned __attribute__
 typedef unsigned gcov_unsigned_t;
 typedef unsigned gcov_position_t;
 
+#if LONG_LONG_TYPE_SIZE > 32
+#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_8
+#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_8
+#else
+#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_4
+#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_4
+#endif
+#define PROFILE_GEN_EDGE_ATOMIC (flag_profile_gen_atomic == 1 || \
+                                 flag_profile_gen_atomic == 3)
+#define PROFILE_GEN_VALUE_ATOMIC (flag_profile_gen_atomic == 2 || \
+                                  flag_profile_gen_atomic == 3)
+
 /* gcov_type is typedef'd elsewhere for the compiler */
 #if IN_GCOV
 #define GCOV_LINKAGE static
@@ -781,8 +801,8 @@ struct gcov_info
 					  unused) */
   
   unsigned n_functions;		/* number of functions */
-  const struct gcov_fn_info *const *functions; /* pointer to pointers
-					          to function information  */
+  const struct gcov_fn_info **functions; /* pointer to pointers
+					    to function information  */
 };
 
 /* Information about a single imported module.  */
@@ -988,8 +1008,7 @@ static void gcov_rewrite (void);
 GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN;
 GCOV_LINKAGE void gcov_truncate (void) ATTRIBUTE_HIDDEN;
 GCOV_LINKAGE gcov_unsigned_t gcov_string_length (const char *) ATTRIBUTE_HIDDEN;
-GCOV_LINKAGE unsigned gcov_gcda_file_size (struct gcov_info *,
-                                           struct gcov_summary *);
+GCOV_LINKAGE unsigned gcov_gcda_file_size (struct gcov_info *);
 #else
 /* Available outside libgcov */
 GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/,
