diff options
author | Radim Krčmář <rkrcmar@redhat.com> | 2017-12-05 12:02:03 -0500 |
---|---|---|
committer | Radim Krčmář <rkrcmar@redhat.com> | 2017-12-05 12:02:03 -0500 |
commit | 609b7002705ae72a6ca45b633b7ff1a09a7a0d86 (patch) | |
tree | 515db242be433c34cd45c522dcf295580f864837 /virt | |
parent | ae64f9bd1d3621b5e60d7363bc20afb46aede215 (diff) | |
parent | fc396e066318c0a02208c1d3f0b62950a7714999 (diff) |
Merge tag 'kvm-arm-fixes-for-v4.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm
KVM/ARM Fixes for v4.15.
Fixes:
- A number of issues in the vgic discovered using SMATCH
- A bit one-off calculation in out stage base address mask (32-bit and
64-bit)
- Fixes to single-step debugging instructions that trap for other
reasons such as MMMIO aborts
- Printing unavailable hyp mode as error
- Potential spinlock deadlock in the vgic
- Avoid calling vgic vcpu free more than once
- Broken bit calculation for big endian systems
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 11 | ||||
-rw-r--r-- | virt/kvm/arm/arm.c | 7 | ||||
-rw-r--r-- | virt/kvm/arm/hyp/timer-sr.c | 48 | ||||
-rw-r--r-- | virt/kvm/arm/hyp/vgic-v2-sr.c | 4 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-irqfd.c | 3 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-its.c | 4 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-v3.c | 2 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-v4.c | 6 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic.c | 8 |
9 files changed, 43 insertions, 50 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 4151250ce8da..f9555b1e7f15 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
@@ -479,9 +479,6 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu) | |||
479 | 479 | ||
480 | vtimer_restore_state(vcpu); | 480 | vtimer_restore_state(vcpu); |
481 | 481 | ||
482 | if (has_vhe()) | ||
483 | disable_el1_phys_timer_access(); | ||
484 | |||
485 | /* Set the background timer for the physical timer emulation. */ | 482 | /* Set the background timer for the physical timer emulation. */ |
486 | phys_timer_emulate(vcpu); | 483 | phys_timer_emulate(vcpu); |
487 | } | 484 | } |
@@ -510,9 +507,6 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu) | |||
510 | if (unlikely(!timer->enabled)) | 507 | if (unlikely(!timer->enabled)) |
511 | return; | 508 | return; |
512 | 509 | ||
513 | if (has_vhe()) | ||
514 | enable_el1_phys_timer_access(); | ||
515 | |||
516 | vtimer_save_state(vcpu); | 510 | vtimer_save_state(vcpu); |
517 | 511 | ||
518 | /* | 512 | /* |
@@ -841,7 +835,10 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) | |||
841 | no_vgic: | 835 | no_vgic: |
842 | preempt_disable(); | 836 | preempt_disable(); |
843 | timer->enabled = 1; | 837 | timer->enabled = 1; |
844 | kvm_timer_vcpu_load_vgic(vcpu); | 838 | if (!irqchip_in_kernel(vcpu->kvm)) |
839 | kvm_timer_vcpu_load_user(vcpu); | ||
840 | else | ||
841 | kvm_timer_vcpu_load_vgic(vcpu); | ||
845 | preempt_enable(); | 842 | preempt_enable(); |
846 | 843 | ||
847 | return 0; | 844 | return 0; |
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index a67c106d73f5..6b60c98a6e22 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c | |||
@@ -188,6 +188,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm) | |||
188 | kvm->vcpus[i] = NULL; | 188 | kvm->vcpus[i] = NULL; |
189 | } | 189 | } |
190 | } | 190 | } |
191 | atomic_set(&kvm->online_vcpus, 0); | ||
191 | } | 192 | } |
192 | 193 | ||
193 | int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) | 194 | int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) |
@@ -296,7 +297,6 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) | |||
296 | { | 297 | { |
297 | kvm_mmu_free_memory_caches(vcpu); | 298 | kvm_mmu_free_memory_caches(vcpu); |
298 | kvm_timer_vcpu_terminate(vcpu); | 299 | kvm_timer_vcpu_terminate(vcpu); |
299 | kvm_vgic_vcpu_destroy(vcpu); | ||
300 | kvm_pmu_vcpu_destroy(vcpu); | 300 | kvm_pmu_vcpu_destroy(vcpu); |
301 | kvm_vcpu_uninit(vcpu); | 301 | kvm_vcpu_uninit(vcpu); |
302 | kmem_cache_free(kvm_vcpu_cache, vcpu); | 302 | kmem_cache_free(kvm_vcpu_cache, vcpu); |
@@ -627,6 +627,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
627 | ret = kvm_handle_mmio_return(vcpu, vcpu->run); | 627 | ret = kvm_handle_mmio_return(vcpu, vcpu->run); |
628 | if (ret) | 628 | if (ret) |
629 | return ret; | 629 | return ret; |
630 | if (kvm_arm_handle_step_debug(vcpu, vcpu->run)) | ||
631 | return 0; | ||
632 | |||
630 | } | 633 | } |
631 | 634 | ||
632 | if (run->immediate_exit) | 635 | if (run->immediate_exit) |
@@ -1502,7 +1505,7 @@ int kvm_arch_init(void *opaque) | |||
1502 | bool in_hyp_mode; | 1505 | bool in_hyp_mode; |
1503 | 1506 | ||
1504 | if (!is_hyp_mode_available()) { | 1507 | if (!is_hyp_mode_available()) { |
1505 | kvm_err("HYP mode not available\n"); | 1508 | kvm_info("HYP mode not available\n"); |
1506 | return -ENODEV; | 1509 | return -ENODEV; |
1507 | } | 1510 | } |
1508 | 1511 | ||
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c index f39861639f08..f24404b3c8df 100644 --- a/virt/kvm/arm/hyp/timer-sr.c +++ b/virt/kvm/arm/hyp/timer-sr.c | |||
@@ -27,42 +27,34 @@ void __hyp_text __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high) | |||
27 | write_sysreg(cntvoff, cntvoff_el2); | 27 | write_sysreg(cntvoff, cntvoff_el2); |
28 | } | 28 | } |
29 | 29 | ||
30 | void __hyp_text enable_el1_phys_timer_access(void) | ||
31 | { | ||
32 | u64 val; | ||
33 | |||
34 | /* Allow physical timer/counter access for the host */ | ||
35 | val = read_sysreg(cnthctl_el2); | ||
36 | val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; | ||
37 | write_sysreg(val, cnthctl_el2); | ||
38 | } | ||
39 | |||
40 | void __hyp_text disable_el1_phys_timer_access(void) | ||
41 | { | ||
42 | u64 val; | ||
43 | |||
44 | /* | ||
45 | * Disallow physical timer access for the guest | ||
46 | * Physical counter access is allowed | ||
47 | */ | ||
48 | val = read_sysreg(cnthctl_el2); | ||
49 | val &= ~CNTHCTL_EL1PCEN; | ||
50 | val |= CNTHCTL_EL1PCTEN; | ||
51 | write_sysreg(val, cnthctl_el2); | ||
52 | } | ||
53 | |||
54 | void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu) | 30 | void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu) |
55 | { | 31 | { |
56 | /* | 32 | /* |
57 | * We don't need to do this for VHE since the host kernel runs in EL2 | 33 | * We don't need to do this for VHE since the host kernel runs in EL2 |
58 | * with HCR_EL2.TGE ==1, which makes those bits have no impact. | 34 | * with HCR_EL2.TGE ==1, which makes those bits have no impact. |
59 | */ | 35 | */ |
60 | if (!has_vhe()) | 36 | if (!has_vhe()) { |
61 | enable_el1_phys_timer_access(); | 37 | u64 val; |
38 | |||
39 | /* Allow physical timer/counter access for the host */ | ||
40 | val = read_sysreg(cnthctl_el2); | ||
41 | val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; | ||
42 | write_sysreg(val, cnthctl_el2); | ||
43 | } | ||
62 | } | 44 | } |
63 | 45 | ||
64 | void __hyp_text __timer_enable_traps(struct kvm_vcpu *vcpu) | 46 | void __hyp_text __timer_enable_traps(struct kvm_vcpu *vcpu) |
65 | { | 47 | { |
66 | if (!has_vhe()) | 48 | if (!has_vhe()) { |
67 | disable_el1_phys_timer_access(); | 49 | u64 val; |
50 | |||
51 | /* | ||
52 | * Disallow physical timer access for the guest | ||
53 | * Physical counter access is allowed | ||
54 | */ | ||
55 | val = read_sysreg(cnthctl_el2); | ||
56 | val &= ~CNTHCTL_EL1PCEN; | ||
57 | val |= CNTHCTL_EL1PCTEN; | ||
58 | write_sysreg(val, cnthctl_el2); | ||
59 | } | ||
68 | } | 60 | } |
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c index a3f18d362366..d7fd46fe9efb 100644 --- a/virt/kvm/arm/hyp/vgic-v2-sr.c +++ b/virt/kvm/arm/hyp/vgic-v2-sr.c | |||
@@ -34,11 +34,7 @@ static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base) | |||
34 | else | 34 | else |
35 | elrsr1 = 0; | 35 | elrsr1 = 0; |
36 | 36 | ||
37 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
38 | cpu_if->vgic_elrsr = ((u64)elrsr0 << 32) | elrsr1; | ||
39 | #else | ||
40 | cpu_if->vgic_elrsr = ((u64)elrsr1 << 32) | elrsr0; | 37 | cpu_if->vgic_elrsr = ((u64)elrsr1 << 32) | elrsr0; |
41 | #endif | ||
42 | } | 38 | } |
43 | 39 | ||
44 | static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base) | 40 | static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base) |
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c index b7baf581611a..99e026d2dade 100644 --- a/virt/kvm/arm/vgic/vgic-irqfd.c +++ b/virt/kvm/arm/vgic/vgic-irqfd.c | |||
@@ -112,8 +112,7 @@ int kvm_vgic_setup_default_irq_routing(struct kvm *kvm) | |||
112 | u32 nr = dist->nr_spis; | 112 | u32 nr = dist->nr_spis; |
113 | int i, ret; | 113 | int i, ret; |
114 | 114 | ||
115 | entries = kcalloc(nr, sizeof(struct kvm_kernel_irq_routing_entry), | 115 | entries = kcalloc(nr, sizeof(*entries), GFP_KERNEL); |
116 | GFP_KERNEL); | ||
117 | if (!entries) | 116 | if (!entries) |
118 | return -ENOMEM; | 117 | return -ENOMEM; |
119 | 118 | ||
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 1f761a9991e7..8e633bd9cc1e 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c | |||
@@ -421,6 +421,7 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu) | |||
421 | u32 *intids; | 421 | u32 *intids; |
422 | int nr_irqs, i; | 422 | int nr_irqs, i; |
423 | unsigned long flags; | 423 | unsigned long flags; |
424 | u8 pendmask; | ||
424 | 425 | ||
425 | nr_irqs = vgic_copy_lpi_list(vcpu, &intids); | 426 | nr_irqs = vgic_copy_lpi_list(vcpu, &intids); |
426 | if (nr_irqs < 0) | 427 | if (nr_irqs < 0) |
@@ -428,7 +429,6 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu) | |||
428 | 429 | ||
429 | for (i = 0; i < nr_irqs; i++) { | 430 | for (i = 0; i < nr_irqs; i++) { |
430 | int byte_offset, bit_nr; | 431 | int byte_offset, bit_nr; |
431 | u8 pendmask; | ||
432 | 432 | ||
433 | byte_offset = intids[i] / BITS_PER_BYTE; | 433 | byte_offset = intids[i] / BITS_PER_BYTE; |
434 | bit_nr = intids[i] % BITS_PER_BYTE; | 434 | bit_nr = intids[i] % BITS_PER_BYTE; |
@@ -821,6 +821,8 @@ static int vgic_its_alloc_collection(struct vgic_its *its, | |||
821 | return E_ITS_MAPC_COLLECTION_OOR; | 821 | return E_ITS_MAPC_COLLECTION_OOR; |
822 | 822 | ||
823 | collection = kzalloc(sizeof(*collection), GFP_KERNEL); | 823 | collection = kzalloc(sizeof(*collection), GFP_KERNEL); |
824 | if (!collection) | ||
825 | return -ENOMEM; | ||
824 | 826 | ||
825 | collection->collection_id = coll_id; | 827 | collection->collection_id = coll_id; |
826 | collection->target_addr = COLLECTION_NOT_MAPPED; | 828 | collection->target_addr = COLLECTION_NOT_MAPPED; |
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c index 2f05f732d3fd..f47e8481fa45 100644 --- a/virt/kvm/arm/vgic/vgic-v3.c +++ b/virt/kvm/arm/vgic/vgic-v3.c | |||
@@ -327,13 +327,13 @@ int vgic_v3_save_pending_tables(struct kvm *kvm) | |||
327 | int last_byte_offset = -1; | 327 | int last_byte_offset = -1; |
328 | struct vgic_irq *irq; | 328 | struct vgic_irq *irq; |
329 | int ret; | 329 | int ret; |
330 | u8 val; | ||
330 | 331 | ||
331 | list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) { | 332 | list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) { |
332 | int byte_offset, bit_nr; | 333 | int byte_offset, bit_nr; |
333 | struct kvm_vcpu *vcpu; | 334 | struct kvm_vcpu *vcpu; |
334 | gpa_t pendbase, ptr; | 335 | gpa_t pendbase, ptr; |
335 | bool stored; | 336 | bool stored; |
336 | u8 val; | ||
337 | 337 | ||
338 | vcpu = irq->target_vcpu; | 338 | vcpu = irq->target_vcpu; |
339 | if (!vcpu) | 339 | if (!vcpu) |
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c index 53c324aa44ef..4a37292855bc 100644 --- a/virt/kvm/arm/vgic/vgic-v4.c +++ b/virt/kvm/arm/vgic/vgic-v4.c | |||
@@ -337,8 +337,10 @@ int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int virq, | |||
337 | goto out; | 337 | goto out; |
338 | 338 | ||
339 | WARN_ON(!(irq->hw && irq->host_irq == virq)); | 339 | WARN_ON(!(irq->hw && irq->host_irq == virq)); |
340 | irq->hw = false; | 340 | if (irq->hw) { |
341 | ret = its_unmap_vlpi(virq); | 341 | irq->hw = false; |
342 | ret = its_unmap_vlpi(virq); | ||
343 | } | ||
342 | 344 | ||
343 | out: | 345 | out: |
344 | mutex_unlock(&its->its_lock); | 346 | mutex_unlock(&its->its_lock); |
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index b168a328a9e0..ecb8e25f5fe5 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c | |||
@@ -492,6 +492,7 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid) | |||
492 | int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner) | 492 | int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner) |
493 | { | 493 | { |
494 | struct vgic_irq *irq; | 494 | struct vgic_irq *irq; |
495 | unsigned long flags; | ||
495 | int ret = 0; | 496 | int ret = 0; |
496 | 497 | ||
497 | if (!vgic_initialized(vcpu->kvm)) | 498 | if (!vgic_initialized(vcpu->kvm)) |
@@ -502,12 +503,12 @@ int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner) | |||
502 | return -EINVAL; | 503 | return -EINVAL; |
503 | 504 | ||
504 | irq = vgic_get_irq(vcpu->kvm, vcpu, intid); | 505 | irq = vgic_get_irq(vcpu->kvm, vcpu, intid); |
505 | spin_lock(&irq->irq_lock); | 506 | spin_lock_irqsave(&irq->irq_lock, flags); |
506 | if (irq->owner && irq->owner != owner) | 507 | if (irq->owner && irq->owner != owner) |
507 | ret = -EEXIST; | 508 | ret = -EEXIST; |
508 | else | 509 | else |
509 | irq->owner = owner; | 510 | irq->owner = owner; |
510 | spin_unlock(&irq->irq_lock); | 511 | spin_unlock_irqrestore(&irq->irq_lock, flags); |
511 | 512 | ||
512 | return ret; | 513 | return ret; |
513 | } | 514 | } |
@@ -823,13 +824,14 @@ void vgic_kick_vcpus(struct kvm *kvm) | |||
823 | 824 | ||
824 | bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid) | 825 | bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid) |
825 | { | 826 | { |
826 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid); | 827 | struct vgic_irq *irq; |
827 | bool map_is_active; | 828 | bool map_is_active; |
828 | unsigned long flags; | 829 | unsigned long flags; |
829 | 830 | ||
830 | if (!vgic_initialized(vcpu->kvm)) | 831 | if (!vgic_initialized(vcpu->kvm)) |
831 | return false; | 832 | return false; |
832 | 833 | ||
834 | irq = vgic_get_irq(vcpu->kvm, vcpu, vintid); | ||
833 | spin_lock_irqsave(&irq->irq_lock, flags); | 835 | spin_lock_irqsave(&irq->irq_lock, flags); |
834 | map_is_active = irq->hw && irq->active; | 836 | map_is_active = irq->hw && irq->active; |
835 | spin_unlock_irqrestore(&irq->irq_lock, flags); | 837 | spin_unlock_irqrestore(&irq->irq_lock, flags); |