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@xxxxxxxxxx> Signed-off-by: Anup Patel <anup.patel@xxxxxxxxxx> --- tools/kvm/arm/aarch32/arm-cpu.c | 8 ++++ tools/kvm/arm/aarch64/arm-cpu.c | 9 +++- tools/kvm/arm/include/arm-common/kvm-cpu-arch.h | 2 + tools/kvm/arm/kvm-cpu.c | 56 +++++++++++++++++++---- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/tools/kvm/arm/aarch32/arm-cpu.c b/tools/kvm/arm/aarch32/arm-cpu.c index 71b98fe..946e443 100644 --- a/tools/kvm/arm/aarch32/arm-cpu.c +++ b/tools/kvm/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/tools/kvm/arm/aarch64/arm-cpu.c b/tools/kvm/arm/aarch64/arm-cpu.c index ce5ea2f..88970de 100644 --- a/tools/kvm/arm/aarch64/arm-cpu.c +++ b/tools/kvm/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/tools/kvm/arm/include/arm-common/kvm-cpu-arch.h b/tools/kvm/arm/include/arm-common/kvm-cpu-arch.h index 83cd8b8..36c7872 100644 --- a/tools/kvm/arm/include/arm-common/kvm-cpu-arch.h +++ b/tools/kvm/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/tools/kvm/arm/kvm-cpu.c b/tools/kvm/arm/kvm-cpu.c index aeaa4cf..f165373 100644 --- a/tools/kvm/arm/kvm-cpu.c +++ b/tools/kvm/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; } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html