Commit e1ba0207 authored by Christoffer Dall's avatar Christoffer Dall

ARM: KVM: Allow creating the VGIC after VCPUs

Rework the VGIC initialization slightly to allow initialization of the
vgic cpu-specific state even if the irqchip (the VGIC) hasn't been
created by user space yet.  This is safe, because the vgic data
structures are already allocated when the CPU is allocated if VGIC
support is compiled into the kernel.  Further, the init process does not
depend on any other information and the sacrifice is a slight
performance degradation for creating VMs in the no-VGIC case.

The reason is that the new device control API doesn't mandate creating
the VGIC before creating the VCPU and it is unreasonable to require user
space to create the VGIC before creating the VCPUs.

At the same time move the irqchip_in_kernel check out of
kvm_vcpu_first_run_init and into the init function to make the per-vcpu
and global init functions symmetric and add comments on the exported
functions making it a bit easier to understand the init flow by only
looking at vgic.c.
Acked-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
parent 39735a3a
...@@ -464,6 +464,8 @@ static void update_vttbr(struct kvm *kvm) ...@@ -464,6 +464,8 @@ static void update_vttbr(struct kvm *kvm)
static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
{ {
int ret;
if (likely(vcpu->arch.has_run_once)) if (likely(vcpu->arch.has_run_once))
return 0; return 0;
...@@ -473,9 +475,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) ...@@ -473,9 +475,8 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
* Initialize the VGIC before running a vcpu the first time on * Initialize the VGIC before running a vcpu the first time on
* this VM. * this VM.
*/ */
if (irqchip_in_kernel(vcpu->kvm) && if (unlikely(!vgic_initialized(vcpu->kvm))) {
unlikely(!vgic_initialized(vcpu->kvm))) { ret = kvm_vgic_init(vcpu->kvm);
int ret = kvm_vgic_init(vcpu->kvm);
if (ret) if (ret)
return ret; return ret;
} }
......
...@@ -1243,15 +1243,19 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data) ...@@ -1243,15 +1243,19 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/**
* kvm_vgic_vcpu_init - Initialize per-vcpu VGIC state
* @vcpu: pointer to the vcpu struct
*
* Initialize the vgic_cpu struct and vgic_dist struct fields pertaining to
* this vcpu and enable the VGIC for this VCPU
*/
int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
{ {
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_dist *dist = &vcpu->kvm->arch.vgic; struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
int i; int i;
if (!irqchip_in_kernel(vcpu->kvm))
return 0;
if (vcpu->vcpu_id >= VGIC_MAX_CPUS) if (vcpu->vcpu_id >= VGIC_MAX_CPUS)
return -EBUSY; return -EBUSY;
...@@ -1383,10 +1387,22 @@ int kvm_vgic_hyp_init(void) ...@@ -1383,10 +1387,22 @@ int kvm_vgic_hyp_init(void)
return ret; return ret;
} }
/**
* kvm_vgic_init - Initialize global VGIC state before running any VCPUs
* @kvm: pointer to the kvm struct
*
* Map the virtual CPU interface into the VM before running any VCPUs. We
* can't do this at creation time, because user space must first set the
* virtual CPU interface address in the guest physical address space. Also
* initialize the ITARGETSRn regs to 0 on the emulated distributor.
*/
int kvm_vgic_init(struct kvm *kvm) int kvm_vgic_init(struct kvm *kvm)
{ {
int ret = 0, i; int ret = 0, i;
if (!irqchip_in_kernel(kvm))
return 0;
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
if (vgic_initialized(kvm)) if (vgic_initialized(kvm))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment