diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-08-28 13:37:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-08-28 13:37:21 -0400 |
commit | 9cf6b756cdf2cd38b8b0dac2567f7c6daf5e79d5 (patch) | |
tree | eb8af4cbe71eb8b6b8428a078abcbff8cc27a29e | |
parent | 9e8312f5e160ade069e131d54ab8652cf0e86e1a (diff) | |
parent | 82e40f558de566fdee214bec68096bbd5e64a6a4 (diff) |
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
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
-rw-r--r-- | kernel/kallsyms.c | 6 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio.c | 18 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-v2.c | 5 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-v3.c | 5 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic.c | 7 |
5 files changed, 37 insertions, 4 deletions
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 95a260f9214b..136ce049c4ad 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
@@ -263,8 +263,10 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, | |||
263 | { | 263 | { |
264 | char namebuf[KSYM_NAME_LEN]; | 264 | char namebuf[KSYM_NAME_LEN]; |
265 | 265 | ||
266 | if (is_ksym_addr(addr)) | 266 | if (is_ksym_addr(addr)) { |
267 | return !!get_symbol_pos(addr, symbolsize, offset); | 267 | get_symbol_pos(addr, symbolsize, offset); |
268 | return 1; | ||
269 | } | ||
268 | return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) || | 270 | return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) || |
269 | !!__bpf_address_lookup(addr, symbolsize, offset, namebuf); | 271 | !!__bpf_address_lookup(addr, symbolsize, offset, namebuf); |
270 | } | 272 | } |
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c index 44efc2ff863f..0d090482720d 100644 --- a/virt/kvm/arm/vgic/vgic-mmio.c +++ b/virt/kvm/arm/vgic/vgic-mmio.c | |||
@@ -211,6 +211,12 @@ static void vgic_hw_irq_spending(struct kvm_vcpu *vcpu, struct vgic_irq *irq, | |||
211 | vgic_irq_set_phys_active(irq, true); | 211 | vgic_irq_set_phys_active(irq, true); |
212 | } | 212 | } |
213 | 213 | ||
214 | static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq) | ||
215 | { | ||
216 | return (vgic_irq_is_sgi(irq->intid) && | ||
217 | vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2); | ||
218 | } | ||
219 | |||
214 | void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, | 220 | void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, |
215 | gpa_t addr, unsigned int len, | 221 | gpa_t addr, unsigned int len, |
216 | unsigned long val) | 222 | unsigned long val) |
@@ -223,6 +229,12 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, | |||
223 | for_each_set_bit(i, &val, len * 8) { | 229 | for_each_set_bit(i, &val, len * 8) { |
224 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | 230 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); |
225 | 231 | ||
232 | /* GICD_ISPENDR0 SGI bits are WI */ | ||
233 | if (is_vgic_v2_sgi(vcpu, irq)) { | ||
234 | vgic_put_irq(vcpu->kvm, irq); | ||
235 | continue; | ||
236 | } | ||
237 | |||
226 | raw_spin_lock_irqsave(&irq->irq_lock, flags); | 238 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
227 | if (irq->hw) | 239 | if (irq->hw) |
228 | vgic_hw_irq_spending(vcpu, irq, is_uaccess); | 240 | vgic_hw_irq_spending(vcpu, irq, is_uaccess); |
@@ -270,6 +282,12 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu, | |||
270 | for_each_set_bit(i, &val, len * 8) { | 282 | for_each_set_bit(i, &val, len * 8) { |
271 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | 283 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); |
272 | 284 | ||
285 | /* GICD_ICPENDR0 SGI bits are WI */ | ||
286 | if (is_vgic_v2_sgi(vcpu, irq)) { | ||
287 | vgic_put_irq(vcpu->kvm, irq); | ||
288 | continue; | ||
289 | } | ||
290 | |||
273 | raw_spin_lock_irqsave(&irq->irq_lock, flags); | 291 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
274 | 292 | ||
275 | if (irq->hw) | 293 | if (irq->hw) |
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c index 96aab77d0471..b00aa304c260 100644 --- a/virt/kvm/arm/vgic/vgic-v2.c +++ b/virt/kvm/arm/vgic/vgic-v2.c | |||
@@ -184,7 +184,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr) | |||
184 | if (vgic_irq_is_sgi(irq->intid)) { | 184 | if (vgic_irq_is_sgi(irq->intid)) { |
185 | u32 src = ffs(irq->source); | 185 | u32 src = ffs(irq->source); |
186 | 186 | ||
187 | BUG_ON(!src); | 187 | if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n", |
188 | irq->intid)) | ||
189 | return; | ||
190 | |||
188 | val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT; | 191 | val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT; |
189 | irq->source &= ~(1 << (src - 1)); | 192 | irq->source &= ~(1 << (src - 1)); |
190 | if (irq->source) { | 193 | if (irq->source) { |
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c index 0c653a1e5215..a4ad431c92a9 100644 --- a/virt/kvm/arm/vgic/vgic-v3.c +++ b/virt/kvm/arm/vgic/vgic-v3.c | |||
@@ -167,7 +167,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr) | |||
167 | model == KVM_DEV_TYPE_ARM_VGIC_V2) { | 167 | model == KVM_DEV_TYPE_ARM_VGIC_V2) { |
168 | u32 src = ffs(irq->source); | 168 | u32 src = ffs(irq->source); |
169 | 169 | ||
170 | BUG_ON(!src); | 170 | if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n", |
171 | irq->intid)) | ||
172 | return; | ||
173 | |||
171 | val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT; | 174 | val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT; |
172 | irq->source &= ~(1 << (src - 1)); | 175 | irq->source &= ~(1 << (src - 1)); |
173 | if (irq->source) { | 176 | if (irq->source) { |
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index 13d4b38a94ec..e7bde65ba67c 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c | |||
@@ -254,6 +254,13 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b) | |||
254 | bool penda, pendb; | 254 | bool penda, pendb; |
255 | int ret; | 255 | int ret; |
256 | 256 | ||
257 | /* | ||
258 | * list_sort may call this function with the same element when | ||
259 | * the list is fairly long. | ||
260 | */ | ||
261 | if (unlikely(irqa == irqb)) | ||
262 | return 0; | ||
263 | |||
257 | raw_spin_lock(&irqa->irq_lock); | 264 | raw_spin_lock(&irqa->irq_lock); |
258 | raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING); | 265 | raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING); |
259 | 266 | ||