diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index b614aab77c59..27fb2fbeae8d 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -157,12 +157,12 @@ endif
 
 # ARM
 OBJS_ARM_COMMON		:= arm/fdt.o arm/gic.o arm/ioport.o arm/irq.o \
-			   arm/kvm.o arm/kvm-cpu.o
+			   arm/kvm.o arm/kvm-cpu.o arm/timer.o
 HDRS_ARM_COMMON		:= arm/include
 ifeq ($(ARCH), arm)
 	DEFINES		+= -DCONFIG_ARM
 	OBJS		+= $(OBJS_ARM_COMMON)
-	OBJS		+= arm/aarch32/cortex-a15.o
+	OBJS		+= arm/aarch32/arm-cpu.o
 	OBJS		+= arm/aarch32/kvm-cpu.o
 	ARCH_INCLUDE	:= $(HDRS_ARM_COMMON)
 	ARCH_INCLUDE	+= -Iarm/aarch32/include
@@ -175,7 +175,7 @@ endif
 ifeq ($(ARCH), arm64)
 	DEFINES		+= -DCONFIG_ARM64
 	OBJS		+= $(OBJS_ARM_COMMON)
-	OBJS		+= arm/aarch64/cortex-a57.o
+	OBJS		+= arm/aarch64/arm-cpu.o
 	OBJS		+= arm/aarch64/kvm-cpu.o
 	ARCH_INCLUDE	:= $(HDRS_ARM_COMMON)
 	ARCH_INCLUDE	+= -Iarm/aarch64/include
diff --git a/tools/kvm/arm/aarch32/arm-cpu.c b/tools/kvm/arm/aarch32/arm-cpu.c
new file mode 100644
index 000000000000..8817d2a8b772
--- /dev/null
+++ b/tools/kvm/arm/aarch32/arm-cpu.c
@@ -0,0 +1,35 @@
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/util.h"
+
+#include "arm-common/gic.h"
+#include "arm-common/timer.h"
+
+#include <linux/byteorder.h>
+#include <linux/types.h>
+
+static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 gic_phandle)
+{
+	int timer_interrupts[4] = {13, 14, 11, 10};
+
+	gic__generate_fdt_nodes(fdt, gic_phandle);
+	timer__generate_fdt_nodes(fdt, kvm, timer_interrupts);
+}
+
+static int arm_cpu__vcpu_init(struct kvm_cpu *vcpu)
+{
+	vcpu->generate_fdt_nodes = generate_fdt_nodes;
+	return 0;
+}
+
+static struct kvm_arm_target target_cortex_a15 = {
+	.id		= KVM_ARM_TARGET_CORTEX_A15,
+	.compatible	= "arm,cortex-a15",
+	.init		= arm_cpu__vcpu_init,
+};
+
+static int arm_cpu__core_init(struct kvm *kvm)
+{
+	return kvm_cpu__register_kvm_arm_target(&target_cortex_a15);
+}
+core_init(arm_cpu__core_init);
diff --git a/tools/kvm/arm/aarch32/cortex-a15.c b/tools/kvm/arm/aarch32/cortex-a15.c
deleted file mode 100644
index ca65af766921..000000000000
--- a/tools/kvm/arm/aarch32/cortex-a15.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "kvm/fdt.h"
-#include "kvm/kvm.h"
-#include "kvm/kvm-cpu.h"
-#include "kvm/util.h"
-
-#include "arm-common/gic.h"
-
-#include <linux/byteorder.h>
-#include <linux/types.h>
-
-static void generate_timer_nodes(void *fdt, struct kvm *kvm)
-{
-	u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
-		       & GIC_FDT_IRQ_PPI_CPU_MASK;
-	u32 irq_prop[] = {
-		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
-		cpu_to_fdt32(13),
-		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
-
-		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
-		cpu_to_fdt32(14),
-		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
-
-		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
-		cpu_to_fdt32(11),
-		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
-
-		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
-		cpu_to_fdt32(10),
-		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
-	};
-
-	_FDT(fdt_begin_node(fdt, "timer"));
-	_FDT(fdt_property_string(fdt, "compatible", "arm,armv7-timer"));
-	_FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
-	_FDT(fdt_end_node(fdt));
-}
-
-static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 gic_phandle)
-{
-	gic__generate_fdt_nodes(fdt, gic_phandle);
-	generate_timer_nodes(fdt, kvm);
-}
-
-static int cortex_a15__vcpu_init(struct kvm_cpu *vcpu)
-{
-	vcpu->generate_fdt_nodes = generate_fdt_nodes;
-	return 0;
-}
-
-static struct kvm_arm_target target_cortex_a15 = {
-	.id		= KVM_ARM_TARGET_CORTEX_A15,
-	.compatible	= "arm,cortex-a15",
-	.init		= cortex_a15__vcpu_init,
-};
-
-static int cortex_a15__core_init(struct kvm *kvm)
-{
-	return kvm_cpu__register_kvm_arm_target(&target_cortex_a15);
-}
-core_init(cortex_a15__core_init);
diff --git a/tools/kvm/arm/aarch64/arm-cpu.c b/tools/kvm/arm/aarch64/arm-cpu.c
new file mode 100644
index 000000000000..ce5ea2fc2cac
--- /dev/null
+++ b/tools/kvm/arm/aarch64/arm-cpu.c
@@ -0,0 +1,50 @@
+#include "kvm/fdt.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/util.h"
+
+#include "arm-common/gic.h"
+#include "arm-common/timer.h"
+
+#include <linux/byteorder.h>
+#include <linux/types.h>
+
+static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 gic_phandle)
+{
+	int timer_interrupts[4] = {13, 14, 11, 10};
+	gic__generate_fdt_nodes(fdt, gic_phandle);
+	timer__generate_fdt_nodes(fdt, kvm, timer_interrupts);
+}
+
+
+static int arm_cpu__vcpu_init(struct kvm_cpu *vcpu)
+{
+	vcpu->generate_fdt_nodes = generate_fdt_nodes;
+	return 0;
+}
+
+static struct kvm_arm_target target_aem_v8 = {
+	.id		= KVM_ARM_TARGET_AEM_V8,
+	.compatible	= "arm,arm-v8",
+	.init		= arm_cpu__vcpu_init,
+};
+
+static struct kvm_arm_target target_foundation_v8 = {
+	.id		= KVM_ARM_TARGET_FOUNDATION_V8,
+	.compatible	= "arm,arm-v8",
+	.init		= arm_cpu__vcpu_init,
+};
+
+static struct kvm_arm_target target_cortex_a57 = {
+	.id		= KVM_ARM_TARGET_CORTEX_A57,
+	.compatible	= "arm,cortex-a57",
+	.init		= arm_cpu__vcpu_init,
+};
+
+static int arm_cpu__core_init(struct kvm *kvm)
+{
+	return (kvm_cpu__register_kvm_arm_target(&target_aem_v8) ||
+		kvm_cpu__register_kvm_arm_target(&target_foundation_v8) ||
+		kvm_cpu__register_kvm_arm_target(&target_cortex_a57));
+}
+core_init(arm_cpu__core_init);
diff --git a/tools/kvm/arm/aarch64/cortex-a57.c b/tools/kvm/arm/aarch64/cortex-a57.c
deleted file mode 100644
index 0c340fb75087..000000000000
--- a/tools/kvm/arm/aarch64/cortex-a57.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "kvm/fdt.h"
-#include "kvm/kvm.h"
-#include "kvm/kvm-cpu.h"
-#include "kvm/util.h"
-
-#include "arm-common/gic.h"
-
-#include <linux/byteorder.h>
-#include <linux/types.h>
-
-static void generate_timer_nodes(void *fdt, struct kvm *kvm)
-{
-	u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
-		       & GIC_FDT_IRQ_PPI_CPU_MASK;
-	u32 irq_prop[] = {
-		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
-		cpu_to_fdt32(13),
-		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
-
-		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
-		cpu_to_fdt32(14),
-		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
-
-		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
-		cpu_to_fdt32(11),
-		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
-
-		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
-		cpu_to_fdt32(10),
-		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
-	};
-
-	_FDT(fdt_begin_node(fdt, "timer"));
-	_FDT(fdt_property_string(fdt, "compatible", "arm,armv8-timer"));
-	_FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
-	_FDT(fdt_end_node(fdt));
-}
-
-static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 gic_phandle)
-{
-	gic__generate_fdt_nodes(fdt, gic_phandle);
-	generate_timer_nodes(fdt, kvm);
-}
-
-
-static int cortex_a57__vcpu_init(struct kvm_cpu *vcpu)
-{
-	vcpu->generate_fdt_nodes = generate_fdt_nodes;
-	return 0;
-}
-
-/*
- * As far as userspace is concerned, both of these implementations are
- * extremely similar.
- */
-static struct kvm_arm_target target_aem_v8 = {
-	.id		= KVM_ARM_TARGET_AEM_V8,
-	.compatible	= "arm,arm-v8",
-	.init		= cortex_a57__vcpu_init,
-};
-
-static struct kvm_arm_target target_foundation_v8 = {
-	.id		= KVM_ARM_TARGET_FOUNDATION_V8,
-	.compatible	= "arm,arm-v8",
-	.init		= cortex_a57__vcpu_init,
-};
-
-static struct kvm_arm_target target_cortex_a57 = {
-	.id		= KVM_ARM_TARGET_CORTEX_A57,
-	.compatible	= "arm,cortex-a57",
-	.init		= cortex_a57__vcpu_init,
-};
-
-static int cortex_a57__core_init(struct kvm *kvm)
-{
-	return (kvm_cpu__register_kvm_arm_target(&target_aem_v8) ||
-		kvm_cpu__register_kvm_arm_target(&target_foundation_v8) ||
-		kvm_cpu__register_kvm_arm_target(&target_cortex_a57));
-}
-core_init(cortex_a57__core_init);
diff --git a/tools/kvm/arm/include/arm-common/timer.h b/tools/kvm/arm/include/arm-common/timer.h
new file mode 100644
index 000000000000..928e9ea7a9fc
--- /dev/null
+++ b/tools/kvm/arm/include/arm-common/timer.h
@@ -0,0 +1,6 @@
+#ifndef ARM_COMMON__TIMER_H
+#define ARM_COMMON__TIMER_H
+
+void timer__generate_fdt_nodes(void *fdt, struct kvm *kvm, int *irqs);
+
+#endif /* ARM_COMMON__TIMER_H */
diff --git a/tools/kvm/arm/timer.c b/tools/kvm/arm/timer.c
new file mode 100644
index 000000000000..bd6a0bb2c324
--- /dev/null
+++ b/tools/kvm/arm/timer.c
@@ -0,0 +1,38 @@
+#include "kvm/fdt.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/util.h"
+
+#include "arm-common/gic.h"
+#include "arm-common/timer.h"
+
+void timer__generate_fdt_nodes(void *fdt, struct kvm *kvm, int *irqs)
+{
+	const char compatible[] = "arm,armv8-timer\0arm,armv7-timer";
+
+	u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
+		       & GIC_FDT_IRQ_PPI_CPU_MASK;
+	u32 irq_prop[] = {
+		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
+		cpu_to_fdt32(irqs[0]),
+		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+
+		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
+		cpu_to_fdt32(irqs[1]),
+		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+
+		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
+		cpu_to_fdt32(irqs[2]),
+		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+
+		cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
+		cpu_to_fdt32(irqs[3]),
+		cpu_to_fdt32(cpu_mask | GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+	};
+
+	_FDT(fdt_begin_node(fdt, "timer"));
+	_FDT(fdt_property(fdt, "compatible", compatible, sizeof(compatible)));
+	_FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
+	_FDT(fdt_end_node(fdt));
+}
+
