@@ -25,6 +25,7 @@ struct kvm_irqchip_flow {
void (*irqchip_vcpu_load)(struct kvm_vcpu *);
void (*irqchip_vcpu_put)(struct kvm_vcpu *);
int (*irqchip_vcpu_pending_irq)(struct kvm_vcpu *);
+ int (*irqchip_vcpu_first_run)(struct kvm_vcpu *);
};
/*
@@ -74,4 +75,7 @@ struct kvm_irqchip_flow {
#define kvm_irqchip_vcpu_pending_irq(v) \
__vcpu_irqchip_action_ret((v), vcpu_pending_irq, (v))
+#define kvm_irqchip_vcpu_first_run(v) \
+ __vcpu_irqchip_action_ret((v), vcpu_first_run, (v))
+
#endif
@@ -503,15 +503,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
vcpu->arch.has_run_once = true;
if (likely(irqchip_in_kernel(kvm))) {
- /*
- * Map the VGIC hardware resources before running a vcpu the
- * first time on this VM.
- */
- if (unlikely(!vgic_ready(kvm))) {
- ret = kvm_vgic_map_resources(kvm);
- if (ret)
- return ret;
- }
+ ret = kvm_irqchip_vcpu_first_run(vcpu);
+ if (ret)
+ return ret;
} else {
/*
* Tell the rest of the code that there are userspace irqchip
@@ -12,6 +12,7 @@
#include <asm/kvm_mmu.h>
#include "vgic.h"
+static int kvm_vgic_vcpu_first_run(struct kvm_vcpu *vcpu);
static int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu);
static void kvm_vgic_destroy(struct kvm *kvm);
@@ -23,6 +24,7 @@ static struct kvm_irqchip_flow vgic_irqchip_flow = {
.irqchip_vcpu_load = kvm_vgic_load,
.irqchip_vcpu_put = kvm_vgic_put,
.irqchip_vcpu_pending_irq = kvm_vgic_vcpu_pending_irq,
+ .irqchip_vcpu_first_run = kvm_vgic_vcpu_first_run,
};
/*
@@ -440,14 +442,17 @@ int vgic_lazy_init(struct kvm *kvm)
* Also map the virtual CPU interface into the VM.
* v2/v3 derivatives call vgic_init if not already done.
* vgic_ready() returns true if this function has succeeded.
- * @kvm: kvm struct pointer
+ * @vcpu: vcpu struct pointer
*/
-int kvm_vgic_map_resources(struct kvm *kvm)
+static int kvm_vgic_vcpu_first_run(struct kvm_vcpu *vcpu)
{
+ struct kvm *kvm = vcpu->kvm;
+ struct vgic_dist *dist = &kvm->arch.vgic;
int ret = 0;
mutex_lock(&kvm->lock);
- if (!irqchip_in_kernel(kvm))
+
+ if (vgic_ready(kvm))
goto out;
if (irqchip_is_gic_v2(kvm))
@@ -457,6 +462,8 @@ int kvm_vgic_map_resources(struct kvm *kvm)
if (ret)
__kvm_vgic_destroy(kvm);
+ else
+ dist->ready = true;
out:
mutex_unlock(&kvm->lock);
@@ -306,9 +306,6 @@ int vgic_v2_map_resources(struct kvm *kvm)
struct vgic_dist *dist = &kvm->arch.vgic;
int ret = 0;
- if (vgic_ready(kvm))
- goto out;
-
if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
kvm_err("Need to set vgic cpu and dist addresses first\n");
@@ -348,8 +345,6 @@ int vgic_v2_map_resources(struct kvm *kvm)
}
}
- dist->ready = true;
-
out:
return ret;
}
@@ -496,9 +496,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
int ret = 0;
int c;
- if (vgic_ready(kvm))
- goto out;
-
kvm_for_each_vcpu(c, vcpu, kvm) {
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
@@ -538,7 +535,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
if (kvm_vgic_global_state.has_gicv4_1)
vgic_v4_configure_vsgis(kvm);
- dist->ready = true;
out:
return ret;
@@ -98,6 +98,8 @@
#define DEBUG_SPINLOCK_BUG_ON(p)
#endif
+#define vgic_ready(k) ((k)->arch.vgic.ready)
+
/* Requires the irq_lock to be held by the caller. */
static inline bool irq_is_pending(struct vgic_irq *irq)
{
@@ -336,7 +336,6 @@ extern struct static_key_false vgic_v3_cpuif_trap;
int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
int kvm_vgic_create(struct kvm *kvm, u32 type);
-int kvm_vgic_map_resources(struct kvm *kvm);
int kvm_vgic_hyp_init(void);
void kvm_vgic_init_cpu_hardware(void);
@@ -348,7 +347,6 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid);
bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid);
#define vgic_initialized(k) ((k)->arch.vgic.initialized)
-#define vgic_ready(k) ((k)->arch.vgic.ready)
#define vgic_valid_spi(k, i) (((i) >= VGIC_NR_PRIVATE_IRQS) && \
((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
The "first run" part of the vgic init is pretty cumbersome, as it leaks all over the place. Reduce its footprint by moving it to an actual per-vcpu "first run" callback, and let it deal with the resource mapping. This allows the vgic_ready() macro to be made vgic-private, and placed in the common vgic code instead of the architecture backends. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/include/asm/kvm_irq.h | 4 ++++ arch/arm64/kvm/arm.c | 12 +++--------- arch/arm64/kvm/vgic/vgic-init.c | 13 ++++++++++--- arch/arm64/kvm/vgic/vgic-v2.c | 5 ----- arch/arm64/kvm/vgic/vgic-v3.c | 4 ---- arch/arm64/kvm/vgic/vgic.h | 2 ++ include/kvm/arm_vgic.h | 2 -- 7 files changed, 19 insertions(+), 23 deletions(-)