summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2016-12-12 01:29:39 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2016-12-12 01:29:39 -0500
commitf673b5b2a66332da5358def524dbfb3305c76d8c (patch)
tree9f55a133030bb236b7ecc48f776fefc688d243c3 /virt
parent36da91bdf568e804aac3ef02a5e3d867585f08fb (diff)
parent21cbe3cc8a48ff17059912e019fbde28ed54745a (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.c17
-rw-r--r--virt/kvm/arm/vgic/vgic-its.c11
-rw-r--r--virt/kvm/arm/vgic/vgic-kvm-device.c2
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio-v2.c3
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio-v3.c2
-rw-r--r--virt/kvm/arm/vgic/vgic.h26
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
46bool vgic_has_its(struct kvm *kvm) 45bool 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
57static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu, 55static 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);
84int vgic_v3_map_resources(struct kvm *kvm); 84int vgic_v3_map_resources(struct kvm *kvm);
85int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); 85int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
86 86
87#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS
88int vgic_register_its_iodevs(struct kvm *kvm); 87int vgic_register_its_iodevs(struct kvm *kvm);
89bool vgic_has_its(struct kvm *kvm); 88bool vgic_has_its(struct kvm *kvm);
90int kvm_vgic_register_its_device(void); 89int kvm_vgic_register_its_device(void);
91void vgic_enable_lpis(struct kvm_vcpu *vcpu); 90void vgic_enable_lpis(struct kvm_vcpu *vcpu);
92int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi); 91int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
93#else
94static inline int vgic_register_its_iodevs(struct kvm *kvm)
95{
96 return -ENODEV;
97}
98
99static inline bool vgic_has_its(struct kvm *kvm)
100{
101 return false;
102}
103
104static inline int kvm_vgic_register_its_device(void)
105{
106 return -ENODEV;
107}
108
109static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu)
110{
111}
112
113static inline int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
114{
115 return -ENODEV;
116}
117#endif
118 92
119int kvm_register_vgic_device(unsigned long type); 93int kvm_register_vgic_device(unsigned long type);
120int vgic_lazy_init(struct kvm *kvm); 94int vgic_lazy_init(struct kvm *kvm);