diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2016-12-12 01:29:39 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-12-12 01:29:39 -0500 |
commit | f673b5b2a66332da5358def524dbfb3305c76d8c (patch) | |
tree | 9f55a133030bb236b7ecc48f776fefc688d243c3 /virt | |
parent | 36da91bdf568e804aac3ef02a5e3d867585f08fb (diff) | |
parent | 21cbe3cc8a48ff17059912e019fbde28ed54745a (diff) |
Merge tag 'kvm-arm-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/ARM updates for 4.10:
- Support for the GICv3 ITS on 32bit platforms
- A handful of timer and GIC emulation fixes
- A PMU architecture fix
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 17 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-its.c | 11 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-kvm-device.c | 2 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio-v2.c | 3 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio-v3.c | 2 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic.h | 26 |
6 files changed, 14 insertions, 47 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 27a1f6341d41..ae95fc0e3214 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
@@ -425,6 +425,11 @@ int kvm_timer_hyp_init(void) | |||
425 | info = arch_timer_get_kvm_info(); | 425 | info = arch_timer_get_kvm_info(); |
426 | timecounter = &info->timecounter; | 426 | timecounter = &info->timecounter; |
427 | 427 | ||
428 | if (!timecounter->cc) { | ||
429 | kvm_err("kvm_arch_timer: uninitialized timecounter\n"); | ||
430 | return -ENODEV; | ||
431 | } | ||
432 | |||
428 | if (info->virtual_irq <= 0) { | 433 | if (info->virtual_irq <= 0) { |
429 | kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n", | 434 | kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n", |
430 | info->virtual_irq); | 435 | info->virtual_irq); |
@@ -498,17 +503,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) | |||
498 | if (ret) | 503 | if (ret) |
499 | return ret; | 504 | return ret; |
500 | 505 | ||
501 | 506 | timer->enabled = 1; | |
502 | /* | ||
503 | * There is a potential race here between VCPUs starting for the first | ||
504 | * time, which may be enabling the timer multiple times. That doesn't | ||
505 | * hurt though, because we're just setting a variable to the same | ||
506 | * variable that it already was. The important thing is that all | ||
507 | * VCPUs have the enabled variable set, before entering the guest, if | ||
508 | * the arch timers are enabled. | ||
509 | */ | ||
510 | if (timecounter) | ||
511 | timer->enabled = 1; | ||
512 | 507 | ||
513 | return 0; | 508 | return 0; |
514 | } | 509 | } |
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 4660a7d04eea..8c2b3cdcb2c5 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c | |||
@@ -632,21 +632,22 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id) | |||
632 | int index; | 632 | int index; |
633 | u64 indirect_ptr; | 633 | u64 indirect_ptr; |
634 | gfn_t gfn; | 634 | gfn_t gfn; |
635 | int esz = GITS_BASER_ENTRY_SIZE(baser); | ||
635 | 636 | ||
636 | if (!(baser & GITS_BASER_INDIRECT)) { | 637 | if (!(baser & GITS_BASER_INDIRECT)) { |
637 | phys_addr_t addr; | 638 | phys_addr_t addr; |
638 | 639 | ||
639 | if (id >= (l1_tbl_size / GITS_BASER_ENTRY_SIZE(baser))) | 640 | if (id >= (l1_tbl_size / esz)) |
640 | return false; | 641 | return false; |
641 | 642 | ||
642 | addr = BASER_ADDRESS(baser) + id * GITS_BASER_ENTRY_SIZE(baser); | 643 | addr = BASER_ADDRESS(baser) + id * esz; |
643 | gfn = addr >> PAGE_SHIFT; | 644 | gfn = addr >> PAGE_SHIFT; |
644 | 645 | ||
645 | return kvm_is_visible_gfn(its->dev->kvm, gfn); | 646 | return kvm_is_visible_gfn(its->dev->kvm, gfn); |
646 | } | 647 | } |
647 | 648 | ||
648 | /* calculate and check the index into the 1st level */ | 649 | /* calculate and check the index into the 1st level */ |
649 | index = id / (SZ_64K / GITS_BASER_ENTRY_SIZE(baser)); | 650 | index = id / (SZ_64K / esz); |
650 | if (index >= (l1_tbl_size / sizeof(u64))) | 651 | if (index >= (l1_tbl_size / sizeof(u64))) |
651 | return false; | 652 | return false; |
652 | 653 | ||
@@ -670,8 +671,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id) | |||
670 | indirect_ptr &= GENMASK_ULL(51, 16); | 671 | indirect_ptr &= GENMASK_ULL(51, 16); |
671 | 672 | ||
672 | /* Find the address of the actual entry */ | 673 | /* Find the address of the actual entry */ |
673 | index = id % (SZ_64K / GITS_BASER_ENTRY_SIZE(baser)); | 674 | index = id % (SZ_64K / esz); |
674 | indirect_ptr += index * GITS_BASER_ENTRY_SIZE(baser); | 675 | indirect_ptr += index * esz; |
675 | gfn = indirect_ptr >> PAGE_SHIFT; | 676 | gfn = indirect_ptr >> PAGE_SHIFT; |
676 | 677 | ||
677 | return kvm_is_visible_gfn(its->dev->kvm, gfn); | 678 | return kvm_is_visible_gfn(its->dev->kvm, gfn); |
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c index ce1f4ed9daf4..fbe87a63d250 100644 --- a/virt/kvm/arm/vgic/vgic-kvm-device.c +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c | |||
@@ -221,11 +221,9 @@ int kvm_register_vgic_device(unsigned long type) | |||
221 | ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops, | 221 | ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops, |
222 | KVM_DEV_TYPE_ARM_VGIC_V3); | 222 | KVM_DEV_TYPE_ARM_VGIC_V3); |
223 | 223 | ||
224 | #ifdef CONFIG_KVM_ARM_VGIC_V3_ITS | ||
225 | if (ret) | 224 | if (ret) |
226 | break; | 225 | break; |
227 | ret = kvm_vgic_register_its_device(); | 226 | ret = kvm_vgic_register_its_device(); |
228 | #endif | ||
229 | break; | 227 | break; |
230 | } | 228 | } |
231 | 229 | ||
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index b44b359cbbad..78e34bc4d89b 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c | |||
@@ -129,6 +129,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu, | |||
129 | unsigned long val) | 129 | unsigned long val) |
130 | { | 130 | { |
131 | u32 intid = VGIC_ADDR_TO_INTID(addr, 8); | 131 | u32 intid = VGIC_ADDR_TO_INTID(addr, 8); |
132 | u8 cpu_mask = GENMASK(atomic_read(&vcpu->kvm->online_vcpus) - 1, 0); | ||
132 | int i; | 133 | int i; |
133 | 134 | ||
134 | /* GICD_ITARGETSR[0-7] are read-only */ | 135 | /* GICD_ITARGETSR[0-7] are read-only */ |
@@ -141,7 +142,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu, | |||
141 | 142 | ||
142 | spin_lock(&irq->irq_lock); | 143 | spin_lock(&irq->irq_lock); |
143 | 144 | ||
144 | irq->targets = (val >> (i * 8)) & 0xff; | 145 | irq->targets = (val >> (i * 8)) & cpu_mask; |
145 | target = irq->targets ? __ffs(irq->targets) : 0; | 146 | target = irq->targets ? __ffs(irq->targets) : 0; |
146 | irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); | 147 | irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); |
147 | 148 | ||
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c index 0d3c76a4208b..50f42f0f8c4f 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c | |||
@@ -42,7 +42,6 @@ u64 update_64bit_reg(u64 reg, unsigned int offset, unsigned int len, | |||
42 | return reg | ((u64)val << lower); | 42 | return reg | ((u64)val << lower); |
43 | } | 43 | } |
44 | 44 | ||
45 | #ifdef CONFIG_KVM_ARM_VGIC_V3_ITS | ||
46 | bool vgic_has_its(struct kvm *kvm) | 45 | bool vgic_has_its(struct kvm *kvm) |
47 | { | 46 | { |
48 | struct vgic_dist *dist = &kvm->arch.vgic; | 47 | struct vgic_dist *dist = &kvm->arch.vgic; |
@@ -52,7 +51,6 @@ bool vgic_has_its(struct kvm *kvm) | |||
52 | 51 | ||
53 | return dist->has_its; | 52 | return dist->has_its; |
54 | } | 53 | } |
55 | #endif | ||
56 | 54 | ||
57 | static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu, | 55 | static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu, |
58 | gpa_t addr, unsigned int len) | 56 | gpa_t addr, unsigned int len) |
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index 9d9e014765a2..859f65c6e056 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h | |||
@@ -84,37 +84,11 @@ int vgic_v3_probe(const struct gic_kvm_info *info); | |||
84 | int vgic_v3_map_resources(struct kvm *kvm); | 84 | int vgic_v3_map_resources(struct kvm *kvm); |
85 | int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); | 85 | int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); |
86 | 86 | ||
87 | #ifdef CONFIG_KVM_ARM_VGIC_V3_ITS | ||
88 | int vgic_register_its_iodevs(struct kvm *kvm); | 87 | int vgic_register_its_iodevs(struct kvm *kvm); |
89 | bool vgic_has_its(struct kvm *kvm); | 88 | bool vgic_has_its(struct kvm *kvm); |
90 | int kvm_vgic_register_its_device(void); | 89 | int kvm_vgic_register_its_device(void); |
91 | void vgic_enable_lpis(struct kvm_vcpu *vcpu); | 90 | void vgic_enable_lpis(struct kvm_vcpu *vcpu); |
92 | int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi); | 91 | int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi); |
93 | #else | ||
94 | static inline int vgic_register_its_iodevs(struct kvm *kvm) | ||
95 | { | ||
96 | return -ENODEV; | ||
97 | } | ||
98 | |||
99 | static inline bool vgic_has_its(struct kvm *kvm) | ||
100 | { | ||
101 | return false; | ||
102 | } | ||
103 | |||
104 | static inline int kvm_vgic_register_its_device(void) | ||
105 | { | ||
106 | return -ENODEV; | ||
107 | } | ||
108 | |||
109 | static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu) | ||
110 | { | ||
111 | } | ||
112 | |||
113 | static inline int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi) | ||
114 | { | ||
115 | return -ENODEV; | ||
116 | } | ||
117 | #endif | ||
118 | 92 | ||
119 | int kvm_register_vgic_device(unsigned long type); | 93 | int kvm_register_vgic_device(unsigned long type); |
120 | int vgic_lazy_init(struct kvm *kvm); | 94 | int vgic_lazy_init(struct kvm *kvm); |