aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@linaro.org>2014-10-06 12:15:16 +0100
committerWill Deacon <will.deacon@arm.com>2015-06-01 16:39:55 +0100
commit85bd726a06b6e6208e24f51cea464427bb9cfe42 (patch)
tree999720af4a5a823f5c09018cd5a1b71558c84289
parent91eaedaea9b067e98fd4e8dc81d0e12e71267e3a (diff)
downloadkvmtool-85bd726a06b6e6208e24f51cea464427bb9cfe42.tar.gz
kvmtool: ARM: Use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target cpu
Instead, of trying out each and every target type we should use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target type for KVM ARM/ARM64. If KVM_ARM_PREFERRED_TARGET vm ioctl fails then we fallback to old method of trying all known target types. If KVM_ARM_PREFERRED_TARGET vm ioctl succeeds but the returned target type is not known to KVMTOOL then we forcefully init VCPU with target type returned by KVM_ARM_PREFERRED_TARGET vm ioctl. Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org> Signed-off-by: Anup Patel <anup.patel@linaro.org> Reviewed-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arm/aarch32/arm-cpu.c8
-rw-r--r--arm/aarch64/arm-cpu.c9
-rw-r--r--arm/include/arm-common/kvm-cpu-arch.h2
-rw-r--r--arm/kvm-cpu.c56
4 files changed, 64 insertions, 11 deletions
diff --git a/arm/aarch32/arm-cpu.c b/arm/aarch32/arm-cpu.c
index 71b98fe3..946e4434 100644
--- a/arm/aarch32/arm-cpu.c
+++ b/arm/aarch32/arm-cpu.c
@@ -22,6 +22,12 @@ static int arm_cpu__vcpu_init(struct kvm_cpu *vcpu)
return 0;
}
+static struct kvm_arm_target target_generic_v7 = {
+ .id = UINT_MAX,
+ .compatible = "arm,arm-v7",
+ .init = arm_cpu__vcpu_init,
+};
+
static struct kvm_arm_target target_cortex_a15 = {
.id = KVM_ARM_TARGET_CORTEX_A15,
.compatible = "arm,cortex-a15",
@@ -36,6 +42,8 @@ static struct kvm_arm_target target_cortex_a7 = {
static int arm_cpu__core_init(struct kvm *kvm)
{
+ kvm_cpu__set_kvm_arm_generic_target(&target_generic_v7);
+
return (kvm_cpu__register_kvm_arm_target(&target_cortex_a15) ||
kvm_cpu__register_kvm_arm_target(&target_cortex_a7));
}
diff --git a/arm/aarch64/arm-cpu.c b/arm/aarch64/arm-cpu.c
index ce5ea2fc..88970de6 100644
--- a/arm/aarch64/arm-cpu.c
+++ b/arm/aarch64/arm-cpu.c
@@ -16,13 +16,18 @@ static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 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_generic_v8 = {
+ .id = UINT_MAX,
+ .compatible = "arm,arm-v8",
+ .init = arm_cpu__vcpu_init,
+};
+
static struct kvm_arm_target target_aem_v8 = {
.id = KVM_ARM_TARGET_AEM_V8,
.compatible = "arm,arm-v8",
@@ -43,6 +48,8 @@ static struct kvm_arm_target target_cortex_a57 = {
static int arm_cpu__core_init(struct kvm *kvm)
{
+ kvm_cpu__set_kvm_arm_generic_target(&target_generic_v8);
+
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));
diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h
index 83cd8b83..36c78725 100644
--- a/arm/include/arm-common/kvm-cpu-arch.h
+++ b/arm/include/arm-common/kvm-cpu-arch.h
@@ -34,6 +34,8 @@ struct kvm_arm_target {
int (*init)(struct kvm_cpu *vcpu);
};
+void kvm_cpu__set_kvm_arm_generic_target(struct kvm_arm_target *target);
+
int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target);
static inline bool kvm_cpu__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data,
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index aeaa4cfb..f1653733 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -13,7 +13,14 @@ int kvm_cpu__get_debug_fd(void)
return debug_fd;
}
+static struct kvm_arm_target *kvm_arm_generic_target;
static struct kvm_arm_target *kvm_arm_targets[KVM_ARM_NUM_TARGETS];
+
+void kvm_cpu__set_kvm_arm_generic_target(struct kvm_arm_target *target)
+{
+ kvm_arm_generic_target = target;
+}
+
int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target)
{
unsigned int i = 0;
@@ -34,6 +41,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
struct kvm_cpu *vcpu;
int coalesced_offset, mmap_size, err = -1;
unsigned int i;
+ struct kvm_vcpu_init preferred_init;
struct kvm_vcpu_init vcpu_init = {
.features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
};
@@ -55,19 +63,46 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
if (vcpu->kvm_run == MAP_FAILED)
die("unable to mmap vcpu fd");
- /* Find an appropriate target CPU type. */
- for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
- if (!kvm_arm_targets[i])
- continue;
- target = kvm_arm_targets[i];
- vcpu_init.target = target->id;
+ /*
+ * If the preferred target ioctl is successful then
+ * use preferred target else try each and every target type
+ */
+ err = ioctl(kvm->vm_fd, KVM_ARM_PREFERRED_TARGET, &preferred_init);
+ if (!err) {
+ /* Match preferred target CPU type. */
+ target = NULL;
+ for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
+ if (!kvm_arm_targets[i])
+ continue;
+ if (kvm_arm_targets[i]->id == preferred_init.target) {
+ target = kvm_arm_targets[i];
+ break;
+ }
+ }
+ if (!target) {
+ target = kvm_arm_generic_target;
+ vcpu_init.target = preferred_init.target;
+ } else {
+ vcpu_init.target = target->id;
+ }
err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
- if (!err)
- break;
+ } else {
+ /* Find an appropriate target CPU type. */
+ for (i = 0; i < ARRAY_SIZE(kvm_arm_targets); ++i) {
+ if (!kvm_arm_targets[i])
+ continue;
+ target = kvm_arm_targets[i];
+ vcpu_init.target = target->id;
+ err = ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu_init);
+ if (!err)
+ break;
+ }
+ if (err)
+ die("Unable to find matching target");
}
if (err || target->init(vcpu))
- die("Unable to initialise ARM vcpu");
+ die("Unable to initialise vcpu");
coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION,
KVM_CAP_COALESCED_MMIO);
@@ -78,9 +113,10 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
/* Populate the vcpu structure. */
vcpu->kvm = kvm;
vcpu->cpu_id = cpu_id;
- vcpu->cpu_type = target->id;
+ vcpu->cpu_type = vcpu_init.target;
vcpu->cpu_compatible = target->compatible;
vcpu->is_running = true;
+
return vcpu;
}