We need this two factor initialization step to support a sane user space initialization of the emulated model. We simply follow the names of the ioctls for the internal vgic implementation steps and check if we have everything we need on the host side when we create the vgic and set up the rest on init. Signed-off-by: Christoffer Dall <c.dall@xxxxxxxxxxxxxxxxxxxxxx> --- arch/arm/include/asm/kvm_vgic.h | 6 ++++++ arch/arm/kvm/arm.c | 6 ++++++ arch/arm/kvm/vgic.c | 40 +++++++++++++++++++++++++++++++-------- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h index a688132..8bd1426 100644 --- a/arch/arm/include/asm/kvm_vgic.h +++ b/arch/arm/include/asm/kvm_vgic.h @@ -243,6 +243,7 @@ struct kvm_exit_mmio; #ifdef CONFIG_KVM_ARM_VGIC int kvm_vgic_hyp_init(void); int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr); +int kvm_vgic_create(struct kvm *kvm); int kvm_vgic_init(struct kvm *kvm); void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu); void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu); @@ -267,6 +268,11 @@ static inline int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 add return 0; } +static inline int kvm_vgic_create(struct kvm *kvm) +{ + return 0; +} + static inline int kvm_vgic_init(struct kvm *kvm) { return 0; diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 67c8cc2..c0af87e 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -890,6 +890,12 @@ long kvm_arch_vm_ioctl(struct file *filp, #ifdef CONFIG_KVM_ARM_VGIC case KVM_CREATE_IRQCHIP: { if (vgic_present) + return kvm_vgic_create(kvm); + else + return -EINVAL; + } + case KVM_INIT_IRQCHIP: { + if (vgic_present) return kvm_vgic_init(kvm); else return -EINVAL; diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c index 1e4be2d..78d590c 100644 --- a/arch/arm/kvm/vgic.c +++ b/arch/arm/kvm/vgic.c @@ -1084,12 +1084,12 @@ out_free_irq: int kvm_vgic_init(struct kvm *kvm) { int ret, i; - struct resource vcpu_res; mutex_lock(&kvm->lock); - if (of_address_to_resource(vgic_node, 3, &vcpu_res)) { - kvm_err("Cannot obtain VCPU resource\n"); + if (vgic_guest_dist_base == VGIC_ADDR_UNDEF || + vgic_guest_cpu_base == VGIC_ADDR_UNDEF) { + kvm_err("Need to set vgic cpu and dist addresses first\n"); ret = -ENXIO; goto out; } @@ -1101,11 +1101,12 @@ int kvm_vgic_init(struct kvm *kvm) spin_lock_init(&kvm->arch.vgic.lock); kvm->arch.vgic.vctrl_base = vgic_vctrl_base; - kvm->arch.vgic.vgic_dist_base = VGIC_DIST_BASE; + kvm->arch.vgic.vgic_dist_base = vgic_guest_dist_base; kvm->arch.vgic.vgic_dist_size = VGIC_DIST_SIZE; - ret = kvm_phys_addr_ioremap(kvm, VGIC_CPU_BASE, - vcpu_res.start, VGIC_CPU_SIZE); + ret = kvm_phys_addr_ioremap(kvm, vgic_guest_cpu_base, + vgic_vcpu_base, VGIC_CPU_SIZE); + if (ret) { kvm_err("Unable to remap VGIC CPU to VCPU\n"); goto out; @@ -1113,13 +1114,36 @@ int kvm_vgic_init(struct kvm *kvm) for (i = 32; i < VGIC_NR_IRQS; i += 4) vgic_set_target_reg(kvm, 0, i); - out: mutex_unlock(&kvm->lock); - if (!ret) kvm_timer_init(kvm); + return ret; +} + +int kvm_vgic_create(struct kvm *kvm) +{ + int ret; + struct resource vcpu_res; + + mutex_lock(&kvm->lock); + if (of_address_to_resource(vgic_node, 3, &vcpu_res)) { + kvm_err("Cannot obtain VCPU resource\n"); + ret = -ENXIO; + goto out; + } + + if (atomic_read(&kvm->online_vcpus) || kvm->arch.vgic.vctrl_base) { + ret = -EEXIST; + goto out; + } + + + vgic_vcpu_base = vcpu_res.start; + ret = 0; +out: + mutex_unlock(&kvm->lock); return ret; } -- 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