diff --git a/configure.ac b/configure.ac
index df0a0f61..5ff85d55 100644
--- a/configure.ac
+++ b/configure.ac
@@ -107,7 +107,7 @@ AS_CASE([$host],
   [i686*], [ARCH_DIR=x86],
   [mips64*], [ARCH_DIR=mips64],
   [powerpc*], [ARCH_DIR=powerpc],
-  [aarch64*], [ARCH_DIR=arm],
+  [aarch64*], [ARCH_DIR=aarch64],
   [arm*], [ARCH_DIR=arm],
   [ARCH_DIR=undefined]
 )
@@ -218,6 +218,7 @@ AM_CONDITIONAL([user_guide], [test "x${user_guides}" = "xyes" ])
 AM_CONDITIONAL([HAVE_MSCGEN], [test "x${MSCGEN}" = "xmscgen"])
 AM_CONDITIONAL([helper_linux], [test x$helper_linux = xyes ])
 AM_CONDITIONAL([ARCH_IS_ARM], [test "x${ARCH_DIR}" = "xarm"])
+AM_CONDITIONAL([ARCH_IS_AARCH64], [test "x${ARCH_DIR}" = "xaarch64"])
 AM_CONDITIONAL([ARCH_IS_MIPS64], [test "x${ARCH_DIR}" = "xmips64"])
 AM_CONDITIONAL([ARCH_IS_POWERPC], [test "x${ARCH_DIR}" = "xpowerpc"])
 AM_CONDITIONAL([ARCH_IS_X86], [test "x${ARCH_DIR}" = "xx86"])
diff --git a/platform/Makefile.inc b/platform/Makefile.inc
index 738f0f9a..bcd06c44 100644
--- a/platform/Makefile.inc
+++ b/platform/Makefile.inc
@@ -84,22 +84,3 @@ odpapiabiarchinclude_HEADERS = \
 	$(top_srcdir)/include/odp/arch/@ARCH_ABI@/odp/api/abi/pool.h \
 	$(top_srcdir)/include/odp/arch/@ARCH_ABI@/odp/api/abi/queue.h \
 	$(top_srcdir)/include/odp/arch/@ARCH_ABI@/odp/api/abi/shared_memory.h
-
-EXTRA_DIST = \
-	     arch/arm/odp/api/cpu_arch.h \
-	     arch/arm/odp_cpu_arch.c \
-	     arch/arm/odp_sysinfo_parse.c \
-	     arch/default/odp/api/cpu_arch.h \
-	     arch/default/odp_cpu_arch.c \
-	     arch/default/odp_sysinfo_parse.c \
-	     arch/mips64/odp/api/cpu_arch.h \
-	     arch/mips64/odp_cpu_arch.c \
-	     arch/mips64/odp_sysinfo_parse.c \
-	     arch/powerpc/odp/api/cpu_arch.h \
-	     arch/powerpc/odp_cpu_arch.c \
-	     arch/powerpc/odp_sysinfo_parse.c \
-	     arch/x86/odp/api/cpu_arch.h \
-	     arch/x86/odp_cpu_arch.c \
-	     arch/x86/odp_sysinfo_parse.c \
-	     arch/x86/cpu_flags.c \
-	     arch/x86/cpu_flags.h
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 8f0618f4..a0cb06a8 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -68,17 +68,16 @@ odpapiinclude_HEADERS = \
 		  $(srcdir)/include/odp/api/traffic_mngr.h \
 		  $(srcdir)/include/odp/api/version.h
 
+odpapiinclude_HEADERS += $(arch_odp_headers)
 if ARCH_IS_ARM
-odpapiinclude_HEADERS += $(srcdir)/arch/arm/odp/api/cpu_arch.h
+endif
+if ARCH_IS_AARCH64
 endif
 if ARCH_IS_MIPS64
-odpapiinclude_HEADERS += $(srcdir)/arch/mips64/odp/api/cpu_arch.h
 endif
 if ARCH_IS_POWERPC
-odpapiinclude_HEADERS += $(srcdir)/arch/powerpc/odp/api/cpu_arch.h
 endif
 if ARCH_IS_X86
-odpapiinclude_HEADERS += $(srcdir)/arch/x86/odp/api/cpu_arch.h
 endif
 
 odpapiplatincludedir= $(includedir)/odp/api/plat
@@ -236,21 +235,52 @@ __LIB__libodp_linux_la_SOURCES = \
 			   odp_weak.c
 
 if ARCH_IS_ARM
-__LIB__libodp_linux_la_SOURCES += arch/arm/odp_cpu_arch.c \
-				  arch/arm/odp_sysinfo_parse.c
-endif
+__LIB__libodp_linux_la_SOURCES += arch/default/odp_cpu_arch.c \
+				  arch/default/odp_cpu_cycles.c \
+				  arch/default/odp_global_time.c \
+				  arch/default/odp_sysinfo_parse.c
+arch_odp_headers = $(srcdir)/arch/arm/odp/api/cpu_arch.h
+else
+if ARCH_IS_AARCH64
+__LIB__libodp_linux_la_SOURCES += arch/default/odp_cpu_arch.c \
+				  arch/default/odp_cpu_cycles.c \
+				  arch/aarch64/odp_global_time.c \
+				  arch/default/odp_sysinfo_parse.c
+arch_odp_headers = $(srcdir)/arch/aarch64/odp/api/cpu_arch.h
+else
 if ARCH_IS_MIPS64
 __LIB__libodp_linux_la_SOURCES += arch/mips64/odp_cpu_arch.c \
+				  arch/default/odp_cpu_cycles.c \
+				  arch/default/odp_global_time.c \
 				  arch/mips64/odp_sysinfo_parse.c
-endif
+arch_odp_headers = $(srcdir)/arch/mips64/odp/api/cpu_arch.h
+else
 if ARCH_IS_POWERPC
-__LIB__libodp_linux_la_SOURCES += arch/powerpc/odp_cpu_arch.c \
+__LIB__libodp_linux_la_SOURCES += arch/default/odp_cpu_arch.c \
+				  arch/default/odp_cpu_cycles.c \
+				  arch/default/odp_global_time.c \
 				  arch/powerpc/odp_sysinfo_parse.c
-endif
+arch_odp_headers = $(srcdir)/arch/powerpc/odp/api/cpu_arch.h
+else
 if ARCH_IS_X86
 __LIB__libodp_linux_la_SOURCES += arch/x86/cpu_flags.c \
 				  arch/x86/odp_cpu_arch.c \
+				  arch/default/odp_cpu_cycles.c \
+				  arch/x86/odp_global_time.c \
 				  arch/x86/odp_sysinfo_parse.c
+arch_odp_headers = $(srcdir)/arch/x86/odp/api/cpu_arch.h \
+		   $(srcdir)/arch/x86/odp/api/cpu_flags.h
+
+else
+__LIB__libodp_linux_la_SOURCES += arch/default/odp_cpu_arch.c \
+				  arch/default/odp_cpu_cycles.c \
+				  arch/default/odp_global_time.c \
+				  arch/default/odp_sysinfo_parse.c
+arch_odp_headers = $(srcdir)/arch/default/odp/api/cpu_arch.h
+endif
+endif
+endif
+endif
 endif
 
 if HAVE_PCAP
diff --git a/platform/linux-generic/arch/aarch64/odp/api/cpu_arch.h b/platform/linux-generic/arch/aarch64/odp/api/cpu_arch.h
new file mode 100644
index 00000000..7c75a690
--- /dev/null
+++ b/platform/linux-generic/arch/aarch64/odp/api/cpu_arch.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_PLAT_CPU_ARCH_H_
+#define ODP_PLAT_CPU_ARCH_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _ODP_CACHE_LINE_SIZE 64
+
+static inline void odp_cpu_pause(void)
+{
+	/* YIELD hints the CPU to switch to another thread if possible
+	 * and executes as a NOP otherwise.
+	 * ISB flushes the pipeline, then restarts. This is guaranteed to
+	 * stall the CPU a number of cycles.
+	 */
+	__asm volatile("isb" ::: "memory");
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/arch/arm/odp_cpu_arch.c b/platform/linux-generic/arch/aarch64/odp_global_time.c
similarity index 65%
rename from platform/linux-generic/arch/arm/odp_cpu_arch.c
rename to platform/linux-generic/arch/aarch64/odp_global_time.c
index 6622e619..97444f7e 100644
--- a/platform/linux-generic/arch/arm/odp_cpu_arch.c
+++ b/platform/linux-generic/arch/aarch64/odp_global_time.c
@@ -8,48 +8,11 @@
 
 #include <odp_posix_extensions.h>
 
-#include <stdlib.h>
 #include <time.h>
 
-#include <odp/api/cpu.h>
-#include <odp/api/hints.h>
-#include <odp/api/system_info.h>
 #include <odp_debug_internal.h>
 #include <odp_time_internal.h>
 
-#define GIGA 1000000000
-
-uint64_t odp_cpu_cycles(void)
-{
-	struct timespec time;
-	uint64_t sec, ns, hz, cycles;
-	int ret;
-
-	ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time);
-
-	if (ret != 0)
-		ODP_ABORT("clock_gettime failed\n");
-
-	hz  = odp_cpu_hz_max();
-	sec = (uint64_t)time.tv_sec;
-	ns  = (uint64_t)time.tv_nsec;
-
-	cycles  = sec * hz;
-	cycles += (ns * hz) / GIGA;
-
-	return cycles;
-}
-
-uint64_t odp_cpu_cycles_max(void)
-{
-	return UINT64_MAX;
-}
-
-uint64_t odp_cpu_cycles_resolution(void)
-{
-	return 1;
-}
-
 int cpu_has_global_time(void)
 {
 	uint64_t hz = cpu_global_time_freq();
@@ -70,7 +33,6 @@ int cpu_has_global_time(void)
 
 uint64_t cpu_global_time(void)
 {
-#ifdef __aarch64__
 	uint64_t cntvct;
 
 	/*
@@ -83,20 +45,13 @@ uint64_t cpu_global_time(void)
 	__asm__ volatile("mrs %0, cntvct_el0" : "=r"(cntvct) : : "memory");
 
 	return cntvct;
-#else
-	return 0;
-#endif
 }
 
 uint64_t cpu_global_time_freq(void)
 {
-#ifdef __aarch64__
 	uint64_t cntfrq;
 
 	__asm__ volatile("mrs %0, cntfrq_el0" : "=r"(cntfrq) : : );
 
 	return cntfrq;
-#else
-	return 0;
-#endif
 }
diff --git a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c b/platform/linux-generic/arch/arm/odp_sysinfo_parse.c
deleted file mode 100644
index 1e9db418..00000000
--- a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright (c) 2016, Linaro Limited
- * All rights reserved.
- *
- * SPDX-License-Identifier:     BSD-3-Clause
- */
-
-#include "config.h"
-
-#include <odp_internal.h>
-#include <odp_debug_internal.h>
-#include <string.h>
-
-int cpuinfo_parser(FILE *file ODP_UNUSED, system_info_t *sysinfo)
-{
-	int i;
-
-	ODP_DBG("Warning: use dummy values for freq and model string\n");
-	for (i = 0; i < MAX_CPU_NUMBER; i++) {
-		sysinfo->cpu_hz_max[i] = 1400000000;
-		strcpy(sysinfo->model_str[i], "UNKNOWN");
-	}
-
-	return 0;
-}
-
-uint64_t odp_cpu_hz_current(int id ODP_UNUSED)
-{
-	return 0;
-}
-
-void sys_info_print_arch(void)
-{
-}
diff --git a/platform/linux-generic/arch/default/odp_cpu_arch.c b/platform/linux-generic/arch/default/odp_cpu_arch.c
index fab351fe..8a8da744 100644
--- a/platform/linux-generic/arch/default/odp_cpu_arch.c
+++ b/platform/linux-generic/arch/default/odp_cpu_arch.c
@@ -12,10 +12,7 @@
 #include <time.h>
 
 #include <odp/api/cpu.h>
-#include <odp/api/hints.h>
-#include <odp/api/system_info.h>
 #include <odp_debug_internal.h>
-#include <odp_time_internal.h>
 
 #define GIGA 1000000000
 
@@ -39,28 +36,3 @@ uint64_t odp_cpu_cycles(void)
 
 	return cycles;
 }
-
-uint64_t odp_cpu_cycles_max(void)
-{
-	return UINT64_MAX;
-}
-
-uint64_t odp_cpu_cycles_resolution(void)
-{
-	return 1;
-}
-
-int cpu_has_global_time(void)
-{
-	return 0;
-}
-
-uint64_t cpu_global_time(void)
-{
-	return 0;
-}
-
-uint64_t cpu_global_time_freq(void)
-{
-	return 0;
-}
diff --git a/platform/linux-generic/arch/default/odp_cpu_cycles.c b/platform/linux-generic/arch/default/odp_cpu_cycles.c
new file mode 100644
index 00000000..ccc58882
--- /dev/null
+++ b/platform/linux-generic/arch/default/odp_cpu_cycles.c
@@ -0,0 +1,19 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "config.h"
+
+#include <odp/api/cpu.h>
+
+uint64_t odp_cpu_cycles_max(void)
+{
+	return UINT64_MAX;
+}
+
+uint64_t odp_cpu_cycles_resolution(void)
+{
+	return 1;
+}
diff --git a/platform/linux-generic/arch/default/odp_global_time.c b/platform/linux-generic/arch/default/odp_global_time.c
new file mode 100644
index 00000000..89cce1cf
--- /dev/null
+++ b/platform/linux-generic/arch/default/odp_global_time.c
@@ -0,0 +1,33 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "config.h"
+
+#include <odp_posix_extensions.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+#include <odp/api/cpu.h>
+#include <odp/api/hints.h>
+#include <odp/api/system_info.h>
+#include <odp_debug_internal.h>
+#include <odp_time_internal.h>
+
+int cpu_has_global_time(void)
+{
+	return 0;
+}
+
+uint64_t cpu_global_time(void)
+{
+	return 0;
+}
+
+uint64_t cpu_global_time_freq(void)
+{
+	return 0;
+}
diff --git a/platform/linux-generic/arch/mips64/odp_cpu_arch.c b/platform/linux-generic/arch/mips64/odp_cpu_arch.c
index 143867ea..620a0104 100644
--- a/platform/linux-generic/arch/mips64/odp_cpu_arch.c
+++ b/platform/linux-generic/arch/mips64/odp_cpu_arch.c
@@ -22,28 +22,3 @@ uint64_t odp_cpu_cycles(void)
 
 	return cycle;
 }
-
-uint64_t odp_cpu_cycles_max(void)
-{
-	return UINT64_MAX;
-}
-
-uint64_t odp_cpu_cycles_resolution(void)
-{
-	return 1;
-}
-
-int cpu_has_global_time(void)
-{
-	return 0;
-}
-
-uint64_t cpu_global_time(void)
-{
-	return 0;
-}
-
-uint64_t cpu_global_time_freq(void)
-{
-	return 0;
-}
diff --git a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
index fab351fe..6a16f13a 100644
--- a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
+++ b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c
@@ -39,28 +39,3 @@ uint64_t odp_cpu_cycles(void)
 
 	return cycles;
 }
-
-uint64_t odp_cpu_cycles_max(void)
-{
-	return UINT64_MAX;
-}
-
-uint64_t odp_cpu_cycles_resolution(void)
-{
-	return 1;
-}
-
-int cpu_has_global_time(void)
-{
-	return 0;
-}
-
-uint64_t cpu_global_time(void)
-{
-	return 0;
-}
-
-uint64_t cpu_global_time_freq(void)
-{
-	return 0;
-}
diff --git a/platform/linux-generic/arch/powerpc/odp_global_time.c b/platform/linux-generic/arch/powerpc/odp_global_time.c
new file mode 100644
index 00000000..d54ba6bc
--- /dev/null
+++ b/platform/linux-generic/arch/powerpc/odp_global_time.c
@@ -0,0 +1,15 @@
+
+int cpu_has_global_time(void)
+{
+	return 0;
+}
+
+uint64_t cpu_global_time(void)
+{
+	return 0;
+}
+
+uint64_t cpu_global_time_freq(void)
+{
+	return 0;
+}
diff --git a/platform/linux-generic/arch/x86/odp_cpu_arch.c b/platform/linux-generic/arch/x86/odp_cpu_arch.c
index 50fbbac6..a20d9173 100644
--- a/platform/linux-generic/arch/x86/odp_cpu_arch.c
+++ b/platform/linux-generic/arch/x86/odp_cpu_arch.c
@@ -9,7 +9,6 @@
 #include <odp_posix_extensions.h>
 
 #include <odp/api/cpu.h>
-#include <odp_time_internal.h>
 #include <odp_debug_internal.h>
 
 #include <time.h>
@@ -30,74 +29,3 @@ uint64_t odp_cpu_cycles(void)
 
 	return tsc.tsc_64;
 }
-
-uint64_t odp_cpu_cycles_max(void)
-{
-	return UINT64_MAX;
-}
-
-uint64_t odp_cpu_cycles_resolution(void)
-{
-	return 1;
-}
-
-uint64_t cpu_global_time(void)
-{
-	return odp_cpu_cycles();
-}
-
-#define SEC_IN_NS 1000000000ULL
-
-/* Measure TSC frequency. Frequency information registers are defined for x86,
- * but those are often not enumerated. */
-uint64_t cpu_global_time_freq(void)
-{
-	struct timespec sleep, ts1, ts2;
-	uint64_t t1, t2, ts_nsec, cycles, hz;
-	int i;
-	uint64_t avg = 0;
-	int rounds = 3;
-	int warm_up = 1;
-
-	for (i = 0; i < rounds; i++) {
-		sleep.tv_sec = 0;
-
-		if (warm_up)
-			sleep.tv_nsec = SEC_IN_NS / 1000;
-		else
-			sleep.tv_nsec = SEC_IN_NS / 4;
-
-		if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts1)) {
-			ODP_DBG("clock_gettime failed\n");
-			return 0;
-		}
-
-		t1 = cpu_global_time();
-
-		if (nanosleep(&sleep, NULL) < 0) {
-			ODP_DBG("nanosleep failed\n");
-			return 0;
-		}
-
-		if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts2)) {
-			ODP_DBG("clock_gettime failed\n");
-			return 0;
-		}
-
-		t2 = cpu_global_time();
-
-		ts_nsec  = (ts2.tv_sec - ts1.tv_sec) * SEC_IN_NS;
-		ts_nsec += ts2.tv_nsec - ts1.tv_nsec;
-
-		cycles = t2 - t1;
-
-		hz = (cycles * SEC_IN_NS) / ts_nsec;
-
-		if (warm_up)
-			warm_up = 0;
-		else
-			avg += hz;
-	}
-
-	return avg / (rounds - 1);
-}
diff --git a/platform/linux-generic/arch/x86/odp_global_time.c b/platform/linux-generic/arch/x86/odp_global_time.c
new file mode 100644
index 00000000..3ed243cc
--- /dev/null
+++ b/platform/linux-generic/arch/x86/odp_global_time.c
@@ -0,0 +1,77 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include "config.h"
+
+#include <odp_posix_extensions.h>
+
+#include <time.h>
+
+#include <odp/api/cpu.h>
+#include <odp/api/hints.h>
+#include <odp_debug_internal.h>
+#include <odp_time_internal.h>
+
+uint64_t cpu_global_time(void)
+{
+	return odp_cpu_cycles();
+}
+
+#define SEC_IN_NS 1000000000ULL
+
+/* Measure TSC frequency. Frequency information registers are defined for x86,
+ * but those are often not enumerated. */
+uint64_t cpu_global_time_freq(void)
+{
+	struct timespec sleep, ts1, ts2;
+	uint64_t t1, t2, ts_nsec, cycles, hz;
+	int i;
+	uint64_t avg = 0;
+	int rounds = 3;
+	int warm_up = 1;
+
+	for (i = 0; i < rounds; i++) {
+		sleep.tv_sec = 0;
+
+		if (warm_up)
+			sleep.tv_nsec = SEC_IN_NS / 1000;
+		else
+			sleep.tv_nsec = SEC_IN_NS / 4;
+
+		if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts1)) {
+			ODP_DBG("clock_gettime failed\n");
+			return 0;
+		}
+
+		t1 = cpu_global_time();
+
+		if (nanosleep(&sleep, NULL) < 0) {
+			ODP_DBG("nanosleep failed\n");
+			return 0;
+		}
+
+		if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts2)) {
+			ODP_DBG("clock_gettime failed\n");
+			return 0;
+		}
+
+		t2 = cpu_global_time();
+
+		ts_nsec  = (ts2.tv_sec - ts1.tv_sec) * SEC_IN_NS;
+		ts_nsec += ts2.tv_nsec - ts1.tv_nsec;
+
+		cycles = t2 - t1;
+
+		hz = (cycles * SEC_IN_NS) / ts_nsec;
+
+		if (warm_up)
+			warm_up = 0;
+		else
+			avg += hz;
+	}
+
+	return avg / (rounds - 1);
+}
