diff --git a/ChangeLog b/ChangeLog
index dbdb85d..7626606 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2019-07-31  Feng Xue  <fxue@os.amperecomputing.com>
+
+       * manual/tunables.texi: Document glibc.cache.dc_zva_threshold.
+       * sysdeps/aarch64/dl-tunables.list (glibc):
+       Add cache.dc_zva_threshold.
+       * sysdeps/aarch64/multiarch/memset_emag.c: New file.
+       * sysdeps/aarch64/multiarch/memset_base64.S (__memset_base64) : Add
+       conditional compare over __dc_zva_threshold.
+       * sysdeps/aarch64/multiarch/memset_emag.S (DC_ZVA_THRESHOLD): Change
+       to a new value.
+       (HAVE_THRESHOLD_TUNABLE): New macro.
+
 2019-07-25  Florian Weimer  <fweimer@redhat.com>

        [BZ #24677]
diff --git a/manual/tunables.texi b/manual/tunables.texi
index ee0fdf2..fb304d0 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -411,3 +411,12 @@ instead.

 This tunable is specific to i386 and x86-64.
 @end deftp
+
+@deftp Tunable glibc.cache.dc_zva_threshold
+The @code{glibc.cache.dc_zva_threshold} tunable allows the user to set
+threshold to trigger DC ZVA in memset on emag processor. When memset size
+is less than this threshold, normal memory store instruction will be used,
+otherwise DC ZVA instruction will be used.
+
+This tunable is specific to emag aarch64.
+@end deftp
diff --git a/sysdeps/aarch64/dl-tunables.list b/sysdeps/aarch64/dl-tunables.list
index 5fac533..5d4bffe 100644
--- a/sysdeps/aarch64/dl-tunables.list
+++ b/sysdeps/aarch64/dl-tunables.list
@@ -22,4 +22,10 @@ glibc {
       type: STRING
     }
   }
+  cache {
+    dc_zva_threshold {
+      type: SIZE_T
+      default: 0
+    }
+  }
 }
diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c
index 4817587..792d7f6 100644
--- a/sysdeps/aarch64/multiarch/memset.c
+++ b/sysdeps/aarch64/multiarch/memset.c
@@ -41,4 +41,6 @@ libc_ifunc (__libc_memset,

 # undef memset
 strong_alias (__libc_memset, memset);
+
+# include "./memset_emag.c"
 #endif
diff --git a/sysdeps/aarch64/multiarch/memset_base64.S b/sysdeps/aarch64/multiarch/memset_base64.S
index 9a62325..748e321 100644
--- a/sysdeps/aarch64/multiarch/memset_base64.S
+++ b/sysdeps/aarch64/multiarch/memset_base64.S
@@ -91,7 +91,14 @@ L(set96):
        .p2align 4
 L(set_long):
        stp     val, val, [dstin]
+#ifdef HAVE_THRESHOLD_TUNABLE
+       adrp    tmp1, __dc_zva_threshold
+       add     tmp1, tmp1, :lo12:__dc_zva_threshold
+       ldr     tmp2, [tmp1]    /* Load DC ZVA tunable threshold value. */
+       cmp     count, tmp2
+#else
        cmp     count, DC_ZVA_THRESHOLD
+#endif
        ccmp    val, 0, 0, cs
        bic     dst, dstin, 15
        b.eq    L(zva_64)
diff --git a/sysdeps/aarch64/multiarch/memset_emag.S b/sysdeps/aarch64/multiarch/memset_emag.S
index 1c1fabc..a566e40 100644
--- a/sysdeps/aarch64/multiarch/memset_emag.S
+++ b/sysdeps/aarch64/multiarch/memset_emag.S
@@ -20,13 +20,18 @@
 #if IS_IN (libc)
 # define MEMSET __memset_emag

+# if HAVE_TUNABLES
+#  define HAVE_THRESHOLD_TUNABLE 1
+# endif
+
 /*
- * Using dc zva to zero memory does not produce better performance if
+ * Using DC ZVA to zero memory does not produce better performance if
  * memory size is not very large, especially when there are multiple
- * processes/threads contending memory/cache. Here we use a somewhat
- * large threshold to trigger usage of dc zva.
-*/
-# define DC_ZVA_THRESHOLD 1024
+ * processes/threads contending memory/cache. Here we use a very
+ * large threshold to trigger usage of DC ZVA, which is good for
+ * multi-process/thread workloads.
+ */
+# define DC_ZVA_THRESHOLD 8*1024*1024

 # include "./memset_base64.S"
 #endif
diff --git a/sysdeps/aarch64/multiarch/memset_emag.c b/sysdeps/aarch64/multiarch/memset_emag.c
new file mode 100644
index 0000000..8b83ab9
--- /dev/null
+++ b/sysdeps/aarch64/multiarch/memset_emag.c
@@ -0,0 +1,41 @@
+/* Setup threshold to trigger DC ZVA in memset for emag.
+   Copyright (C) 2019 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 HAVE_TUNABLES
+# include <elf/dl-tunables.h>
+
+/* We assume common workloads on server are likely to consist of multiple
+ * processes/threads, contending memory/cache. For this scenario, disabling
+ * DC ZVA in memset can archive better performance on emag processor.
+ * Therefore, by default, we use a very larget threshold, here is 8M,
+ * which has similar effect as disabling DC ZVA, kind of optimization
+ * for multi-process/thread workload.
+ */
+uint64_t __dc_zva_threshold = 8 * 1024 * 1024;
+
+static void
+__attribute__ ((constructor))
+init_dc_zva_threshold (void)
+{
+  uint64_t threshold
+    = TUNABLE_GET (glibc, cache, dc_zva_threshold, uint64_t, NULL);
+
+  if (threshold)
+    __dc_zva_threshold = threshold;
+}
+#endif
