Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 6 May 2018 15:46:29 +0000 (05:46 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 6 May 2018 15:46:29 +0000 (05:46 -1000)
Pll KVM fixes from Radim Krčmář:
 "ARM:
   - Fix proxying of GICv2 CPU interface accesses
   - Fix crash when switching to BE
   - Track source vcpu git GICv2 SGIs
   - Fix an outdated bit of documentation

  x86:
   - Speed up injection of expired timers (for stable)"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: x86: remove APIC Timer periodic/oneshot spikes
  arm64: vgic-v2: Fix proxying of cpuif access
  KVM: arm/arm64: vgic_init: Cleanup reference to process_maintenance
  KVM: arm64: Fix order of vcpu_write_sys_reg() arguments
  KVM: arm/arm64: vgic: Fix source vcpu issues for GICv2 SGI

arch/arm64/include/asm/kvm_emulate.h
arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c
arch/x86/kvm/lapic.c
include/kvm/arm_vgic.h
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic.c
virt/kvm/arm/vgic/vgic.h

index 23b33e8..1dab3a9 100644 (file)
@@ -333,7 +333,7 @@ static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
        } else {
                u64 sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
                sctlr |= (1 << 25);
-               vcpu_write_sys_reg(vcpu, SCTLR_EL1, sctlr);
+               vcpu_write_sys_reg(vcpu, sctlr, SCTLR_EL1);
        }
 }
 
index 86801b6..39be799 100644 (file)
 #include <linux/compiler.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/kvm_host.h>
+#include <linux/swab.h>
 
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
 #include <asm/kvm_mmu.h>
 
+static bool __hyp_text __is_be(struct kvm_vcpu *vcpu)
+{
+       if (vcpu_mode_is_32bit(vcpu))
+               return !!(read_sysreg_el2(spsr) & COMPAT_PSR_E_BIT);
+
+       return !!(read_sysreg(SCTLR_EL1) & SCTLR_ELx_EE);
+}
+
 /*
  * __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
  *                                  guest.
@@ -64,14 +73,19 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
        addr += fault_ipa - vgic->vgic_cpu_base;
 
        if (kvm_vcpu_dabt_iswrite(vcpu)) {
-               u32 data = vcpu_data_guest_to_host(vcpu,
-                                                  vcpu_get_reg(vcpu, rd),
-                                                  sizeof(u32));
+               u32 data = vcpu_get_reg(vcpu, rd);
+               if (__is_be(vcpu)) {
+                       /* guest pre-swabbed data, undo this for writel() */
+                       data = swab32(data);
+               }
                writel_relaxed(data, addr);
        } else {
                u32 data = readl_relaxed(addr);
-               vcpu_set_reg(vcpu, rd, vcpu_data_host_to_guest(vcpu, data,
-                                                              sizeof(u32)));
+               if (__is_be(vcpu)) {
+                       /* guest expects swabbed data */
+                       data = swab32(data);
+               }
+               vcpu_set_reg(vcpu, rd, data);
        }
 
        return 1;
index 70dcb55..b74c9c1 100644 (file)
@@ -1463,23 +1463,6 @@ static void start_sw_tscdeadline(struct kvm_lapic *apic)
        local_irq_restore(flags);
 }
 
-static void start_sw_period(struct kvm_lapic *apic)
-{
-       if (!apic->lapic_timer.period)
-               return;
-
-       if (apic_lvtt_oneshot(apic) &&
-           ktime_after(ktime_get(),
-                       apic->lapic_timer.target_expiration)) {
-               apic_timer_expired(apic);
-               return;
-       }
-
-       hrtimer_start(&apic->lapic_timer.timer,
-               apic->lapic_timer.target_expiration,
-               HRTIMER_MODE_ABS_PINNED);
-}
-
 static void update_target_expiration(struct kvm_lapic *apic, uint32_t old_divisor)
 {
        ktime_t now, remaining;
@@ -1546,6 +1529,26 @@ static void advance_periodic_target_expiration(struct kvm_lapic *apic)
                                apic->lapic_timer.period);
 }
 
+static void start_sw_period(struct kvm_lapic *apic)
+{
+       if (!apic->lapic_timer.period)
+               return;
+
+       if (ktime_after(ktime_get(),
+                       apic->lapic_timer.target_expiration)) {
+               apic_timer_expired(apic);
+
+               if (apic_lvtt_oneshot(apic))
+                       return;
+
+               advance_periodic_target_expiration(apic);
+       }
+
+       hrtimer_start(&apic->lapic_timer.timer,
+               apic->lapic_timer.target_expiration,
+               HRTIMER_MODE_ABS_PINNED);
+}
+
 bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
 {
        if (!lapic_in_kernel(vcpu))
index 24f0394..e7efe12 100644 (file)
@@ -131,6 +131,7 @@ struct vgic_irq {
                u32 mpidr;                      /* GICv3 target VCPU */
        };
        u8 source;                      /* GICv2 SGIs only */
+       u8 active_source;               /* GICv2 SGIs only */
        u8 priority;
        enum vgic_irq_config config;    /* Level or edge */
 
index 68378fe..e07156c 100644 (file)
@@ -423,7 +423,7 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
         * We cannot rely on the vgic maintenance interrupt to be
         * delivered synchronously. This means we can only use it to
         * exit the VM, and we perform the handling of EOIed
-        * interrupts on the exit path (see vgic_process_maintenance).
+        * interrupts on the exit path (see vgic_fold_lr_state).
         */
        return IRQ_HANDLED;
 }
index dbe99d6..ff9655c 100644 (file)
@@ -289,10 +289,16 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
               irq->vcpu->cpu != -1) /* VCPU thread is running */
                cond_resched_lock(&irq->irq_lock);
 
-       if (irq->hw)
+       if (irq->hw) {
                vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
-       else
+       } else {
+               u32 model = vcpu->kvm->arch.vgic.vgic_model;
+
                irq->active = active;
+               if (model == KVM_DEV_TYPE_ARM_VGIC_V2 &&
+                   active && vgic_irq_is_sgi(irq->intid))
+                       irq->active_source = requester_vcpu->vcpu_id;
+       }
 
        if (irq->active)
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
index 45aa433..a5f2e44 100644 (file)
@@ -37,13 +37,6 @@ void vgic_v2_init_lrs(void)
                vgic_v2_write_lr(i, 0);
 }
 
-void vgic_v2_set_npie(struct kvm_vcpu *vcpu)
-{
-       struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
-
-       cpuif->vgic_hcr |= GICH_HCR_NPIE;
-}
-
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
 {
        struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
@@ -71,13 +64,18 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
        int lr;
        unsigned long flags;
 
-       cpuif->vgic_hcr &= ~(GICH_HCR_UIE | GICH_HCR_NPIE);
+       cpuif->vgic_hcr &= ~GICH_HCR_UIE;
 
        for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
                u32 val = cpuif->vgic_lr[lr];
-               u32 intid = val & GICH_LR_VIRTUALID;
+               u32 cpuid, intid = val & GICH_LR_VIRTUALID;
                struct vgic_irq *irq;
 
+               /* Extract the source vCPU id from the LR */
+               cpuid = val & GICH_LR_PHYSID_CPUID;
+               cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+               cpuid &= 7;
+
                /* Notify fds when the guest EOI'ed a level-triggered SPI */
                if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
                        kvm_notify_acked_irq(vcpu->kvm, 0,
@@ -90,17 +88,16 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
                /* Always preserve the active bit */
                irq->active = !!(val & GICH_LR_ACTIVE_BIT);
 
+               if (irq->active && vgic_irq_is_sgi(intid))
+                       irq->active_source = cpuid;
+
                /* Edge is the only case where we preserve the pending bit */
                if (irq->config == VGIC_CONFIG_EDGE &&
                    (val & GICH_LR_PENDING_BIT)) {
                        irq->pending_latch = true;
 
-                       if (vgic_irq_is_sgi(intid)) {
-                               u32 cpuid = val & GICH_LR_PHYSID_CPUID;
-
-                               cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+                       if (vgic_irq_is_sgi(intid))
                                irq->source |= (1 << cpuid);
-                       }
                }
 
                /*
@@ -152,8 +149,15 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        u32 val = irq->intid;
        bool allow_pending = true;
 
-       if (irq->active)
+       if (irq->active) {
                val |= GICH_LR_ACTIVE_BIT;
+               if (vgic_irq_is_sgi(irq->intid))
+                       val |= irq->active_source << GICH_LR_PHYSID_CPUID_SHIFT;
+               if (vgic_irq_is_multi_sgi(irq)) {
+                       allow_pending = false;
+                       val |= GICH_LR_EOI;
+               }
+       }
 
        if (irq->hw) {
                val |= GICH_LR_HW;
@@ -190,8 +194,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                        BUG_ON(!src);
                        val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
                        irq->source &= ~(1 << (src - 1));
-                       if (irq->source)
+                       if (irq->source) {
                                irq->pending_latch = true;
+                               val |= GICH_LR_EOI;
+                       }
                }
        }
 
index 8195f52..c7423f3 100644 (file)
@@ -27,13 +27,6 @@ static bool group1_trap;
 static bool common_trap;
 static bool gicv4_enable;
 
-void vgic_v3_set_npie(struct kvm_vcpu *vcpu)
-{
-       struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
-
-       cpuif->vgic_hcr |= ICH_HCR_NPIE;
-}
-
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
        struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
@@ -55,17 +48,23 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
        int lr;
        unsigned long flags;
 
-       cpuif->vgic_hcr &= ~(ICH_HCR_UIE | ICH_HCR_NPIE);
+       cpuif->vgic_hcr &= ~ICH_HCR_UIE;
 
        for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
                u64 val = cpuif->vgic_lr[lr];
-               u32 intid;
+               u32 intid, cpuid;
                struct vgic_irq *irq;
+               bool is_v2_sgi = false;
 
-               if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+               cpuid = val & GICH_LR_PHYSID_CPUID;
+               cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+
+               if (model == KVM_DEV_TYPE_ARM_VGIC_V3) {
                        intid = val & ICH_LR_VIRTUAL_ID_MASK;
-               else
+               } else {
                        intid = val & GICH_LR_VIRTUALID;
+                       is_v2_sgi = vgic_irq_is_sgi(intid);
+               }
 
                /* Notify fds when the guest EOI'ed a level-triggered IRQ */
                if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
@@ -81,18 +80,16 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                /* Always preserve the active bit */
                irq->active = !!(val & ICH_LR_ACTIVE_BIT);
 
+               if (irq->active && is_v2_sgi)
+                       irq->active_source = cpuid;
+
                /* Edge is the only case where we preserve the pending bit */
                if (irq->config == VGIC_CONFIG_EDGE &&
                    (val & ICH_LR_PENDING_BIT)) {
                        irq->pending_latch = true;
 
-                       if (vgic_irq_is_sgi(intid) &&
-                           model == KVM_DEV_TYPE_ARM_VGIC_V2) {
-                               u32 cpuid = val & GICH_LR_PHYSID_CPUID;
-
-                               cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+                       if (is_v2_sgi)
                                irq->source |= (1 << cpuid);
-                       }
                }
 
                /*
@@ -133,10 +130,20 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
 {
        u32 model = vcpu->kvm->arch.vgic.vgic_model;
        u64 val = irq->intid;
-       bool allow_pending = true;
+       bool allow_pending = true, is_v2_sgi;
 
-       if (irq->active)
+       is_v2_sgi = (vgic_irq_is_sgi(irq->intid) &&
+                    model == KVM_DEV_TYPE_ARM_VGIC_V2);
+
+       if (irq->active) {
                val |= ICH_LR_ACTIVE_BIT;
+               if (is_v2_sgi)
+                       val |= irq->active_source << GICH_LR_PHYSID_CPUID_SHIFT;
+               if (vgic_irq_is_multi_sgi(irq)) {
+                       allow_pending = false;
+                       val |= ICH_LR_EOI;
+               }
+       }
 
        if (irq->hw) {
                val |= ICH_LR_HW;
@@ -174,8 +181,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                        BUG_ON(!src);
                        val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
                        irq->source &= ~(1 << (src - 1));
-                       if (irq->source)
+                       if (irq->source) {
                                irq->pending_latch = true;
+                               val |= ICH_LR_EOI;
+                       }
                }
        }
 
index 702936c..97bfba8 100644 (file)
@@ -725,14 +725,6 @@ static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
                vgic_v3_set_underflow(vcpu);
 }
 
-static inline void vgic_set_npie(struct kvm_vcpu *vcpu)
-{
-       if (kvm_vgic_global_state.type == VGIC_V2)
-               vgic_v2_set_npie(vcpu);
-       else
-               vgic_v3_set_npie(vcpu);
-}
-
 /* Requires the ap_list_lock to be held. */
 static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
                                 bool *multi_sgi)
@@ -746,17 +738,15 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
        DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
 
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+               int w;
+
                spin_lock(&irq->irq_lock);
                /* GICv2 SGIs can count for more than one... */
-               if (vgic_irq_is_sgi(irq->intid) && irq->source) {
-                       int w = hweight8(irq->source);
-
-                       count += w;
-                       *multi_sgi |= (w > 1);
-               } else {
-                       count++;
-               }
+               w = vgic_irq_get_lr_count(irq);
                spin_unlock(&irq->irq_lock);
+
+               count += w;
+               *multi_sgi |= (w > 1);
        }
        return count;
 }
@@ -767,7 +757,6 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
        struct vgic_irq *irq;
        int count;
-       bool npie = false;
        bool multi_sgi;
        u8 prio = 0xff;
 
@@ -797,10 +786,8 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                if (likely(vgic_target_oracle(irq) == vcpu)) {
                        vgic_populate_lr(vcpu, irq, count++);
 
-                       if (irq->source) {
-                               npie = true;
+                       if (irq->source)
                                prio = irq->priority;
-                       }
                }
 
                spin_unlock(&irq->irq_lock);
@@ -813,9 +800,6 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                }
        }
 
-       if (npie)
-               vgic_set_npie(vcpu);
-
        vcpu->arch.vgic_cpu.used_lrs = count;
 
        /* Nuke remaining LRs */
index 830e815..32c25d4 100644 (file)
@@ -110,6 +110,20 @@ static inline bool vgic_irq_is_mapped_level(struct vgic_irq *irq)
        return irq->config == VGIC_CONFIG_LEVEL && irq->hw;
 }
 
+static inline int vgic_irq_get_lr_count(struct vgic_irq *irq)
+{
+       /* Account for the active state as an interrupt */
+       if (vgic_irq_is_sgi(irq->intid) && irq->source)
+               return hweight8(irq->source) + irq->active;
+
+       return irq_is_pending(irq) || irq->active;
+}
+
+static inline bool vgic_irq_is_multi_sgi(struct vgic_irq *irq)
+{
+       return vgic_irq_get_lr_count(irq) > 1;
+}
+
 /*
  * This struct provides an intermediate representation of the fields contained
  * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC