aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Austin <Jonathan.Austin@arm.com>2014-01-06 17:38:33 +0000
committerWill Deacon <will.deacon@arm.com>2015-06-01 16:39:54 +0100
commit909d7f77617aeacb14579ced2e604b593ee78123 (patch)
tree5c7f0b90984b29368c2aca57431139813dec16f3
parent7800e6fa9bbe24a786c396ccb86e5389e7ca4096 (diff)
downloadkvmtool-909d7f77617aeacb14579ced2e604b593ee78123.tar.gz
kvm tools: arm: extract common timer support code for ARM cpus
The ARM V7 and V8 CPUs use the nearly identical support code for generating timer DT nodes as they both use ARM's architected timers. This code is currently duplicated for AArch32 and AArch64. This cleanup patch generalises timer DT node generation to follow the same pattern as for the GIC. The ability of a DT node to contain multiple compatible strings is exploited to allow an identical DT node to be used on V7 and V8 platforms. Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Jonathan Austin <jonathan.austin@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--Makefile6
-rw-r--r--arm/aarch32/arm-cpu.c35
-rw-r--r--arm/aarch32/cortex-a15.c61
-rw-r--r--arm/aarch64/arm-cpu.c50
-rw-r--r--arm/aarch64/cortex-a57.c80
-rw-r--r--arm/include/arm-common/timer.h6
-rw-r--r--arm/timer.c37
7 files changed, 131 insertions, 144 deletions
diff --git a/Makefile b/Makefile
index b614aab7..27fb2fbe 100644
--- a/Makefile
+++ b/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/arm/aarch32/arm-cpu.c b/arm/aarch32/arm-cpu.c
new file mode 100644
index 00000000..8817d2a8
--- /dev/null
+++ b/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/arm/aarch32/cortex-a15.c b/arm/aarch32/cortex-a15.c
deleted file mode 100644
index ca65af76..00000000
--- a/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/arm/aarch64/arm-cpu.c b/arm/aarch64/arm-cpu.c
new file mode 100644
index 00000000..ce5ea2fc
--- /dev/null
+++ b/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/arm/aarch64/cortex-a57.c b/arm/aarch64/cortex-a57.c
deleted file mode 100644
index 0c340fb7..00000000
--- a/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/arm/include/arm-common/timer.h b/arm/include/arm-common/timer.h
new file mode 100644
index 00000000..928e9ea7
--- /dev/null
+++ b/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/arm/timer.c b/arm/timer.c
new file mode 100644
index 00000000..e31faaec
--- /dev/null
+++ b/arm/timer.c
@@ -0,0 +1,37 @@
+#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));
+}