Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 28 Aug 2019 17:37:21 +0000 (10:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 28 Aug 2019 17:37:21 +0000 (10:37 -0700)
Pull arm64 fixes from Will Deacon:
 "Hot on the heels of our last set of fixes are a few more for -rc7.

  Two of them are fixing issues with our virtual interrupt controller
  implementation in KVM/arm, while the other is a longstanding but
  straightforward kallsyms fix which was been acked by Masami and
  resolves an initialisation failure in kprobes observed on arm64.

   - Fix GICv2 emulation bug (KVM)

   - Fix deadlock in virtual GIC interrupt injection code (KVM)

   - Fix kprobes blacklist init failure due to broken kallsyms lookup"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  KVM: arm/arm64: vgic-v2: Handle SGI bits in GICD_I{S,C}PENDR0 as WI
  KVM: arm/arm64: vgic: Fix potential deadlock when ap_list is long
  kallsyms: Don't let kallsyms_lookup_size_offset() fail on retrieving the first symbol

kernel/kallsyms.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

index 95a260f9214b97e274ce4fdfe3ca1446b441ebbc..136ce049c4ad2f34f2b811c0e04c668ed511dba1 100644 (file)
@@ -263,8 +263,10 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
 {
        char namebuf[KSYM_NAME_LEN];
 
-       if (is_ksym_addr(addr))
-               return !!get_symbol_pos(addr, symbolsize, offset);
+       if (is_ksym_addr(addr)) {
+               get_symbol_pos(addr, symbolsize, offset);
+               return 1;
+       }
        return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) ||
               !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
 }
index 44efc2ff863f4b903075d55476e4374862c619dd..0d090482720d2f79ee0af937672f969de728a275 100644 (file)
@@ -211,6 +211,12 @@ static void vgic_hw_irq_spending(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        vgic_irq_set_phys_active(irq, true);
 }
 
+static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
+{
+       return (vgic_irq_is_sgi(irq->intid) &&
+               vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2);
+}
+
 void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
                              gpa_t addr, unsigned int len,
                              unsigned long val)
@@ -223,6 +229,12 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
+               /* GICD_ISPENDR0 SGI bits are WI */
+               if (is_vgic_v2_sgi(vcpu, irq)) {
+                       vgic_put_irq(vcpu->kvm, irq);
+                       continue;
+               }
+
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq->hw)
                        vgic_hw_irq_spending(vcpu, irq, is_uaccess);
@@ -270,6 +282,12 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
+               /* GICD_ICPENDR0 SGI bits are WI */
+               if (is_vgic_v2_sgi(vcpu, irq)) {
+                       vgic_put_irq(vcpu->kvm, irq);
+                       continue;
+               }
+
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                if (irq->hw)
index 96aab77d04718a00164abd251566aaa8e2167b48..b00aa304c260eb412210cf26aa2b011dc51dfa88 100644 (file)
@@ -184,7 +184,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                if (vgic_irq_is_sgi(irq->intid)) {
                        u32 src = ffs(irq->source);
 
-                       BUG_ON(!src);
+                       if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n",
+                                          irq->intid))
+                               return;
+
                        val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
                        irq->source &= ~(1 << (src - 1));
                        if (irq->source) {
index 0c653a1e5215280f4076db92fdb1db61b7b01386..a4ad431c92a912d2b3a9330db301059858ebc62b 100644 (file)
@@ -167,7 +167,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
                        u32 src = ffs(irq->source);
 
-                       BUG_ON(!src);
+                       if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n",
+                                          irq->intid))
+                               return;
+
                        val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
                        irq->source &= ~(1 << (src - 1));
                        if (irq->source) {
index 13d4b38a94ec4b81af13cd739497ae6db9640a55..e7bde65ba67c0802582883c195052b96cc427caf 100644 (file)
@@ -254,6 +254,13 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
        bool penda, pendb;
        int ret;
 
+       /*
+        * list_sort may call this function with the same element when
+        * the list is fairly long.
+        */
+       if (unlikely(irqa == irqb))
+               return 0;
+
        raw_spin_lock(&irqa->irq_lock);
        raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);