summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--Documentation/virtual/kvm/api.txt2
-rw-r--r--arch/arm/include/uapi/asm/kvm.h2
-rw-r--r--arch/arm/kvm/Kconfig1
-rw-r--r--arch/arm/kvm/Makefile1
-rw-r--r--arch/arm/kvm/arm.c6
-rw-r--r--arch/arm64/kvm/Kconfig4
-rw-r--r--arch/arm64/kvm/hyp/switch.c8
-rw-r--r--arch/arm64/kvm/reset.c6
-rw-r--r--include/linux/irqchip/arm-gic-v3.h8
-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
15 files changed, 36 insertions, 63 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 8a5ebd118313..72a718c1176d 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2201,7 +2201,7 @@ after pausing the vcpu, but before it is resumed.
22014.71 KVM_SIGNAL_MSI 22014.71 KVM_SIGNAL_MSI
2202 2202
2203Capability: KVM_CAP_SIGNAL_MSI 2203Capability: KVM_CAP_SIGNAL_MSI
2204Architectures: x86 arm64 2204Architectures: x86 arm arm64
2205Type: vm ioctl 2205Type: vm ioctl
2206Parameters: struct kvm_msi (in) 2206Parameters: struct kvm_msi (in)
2207Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error 2207Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index b38c10c73579..af05f8e0903e 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -87,9 +87,11 @@ struct kvm_regs {
87/* Supported VGICv3 address types */ 87/* Supported VGICv3 address types */
88#define KVM_VGIC_V3_ADDR_TYPE_DIST 2 88#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
89#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3 89#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
90#define KVM_VGIC_ITS_ADDR_TYPE 4
90 91
91#define KVM_VGIC_V3_DIST_SIZE SZ_64K 92#define KVM_VGIC_V3_DIST_SIZE SZ_64K
92#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K) 93#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
94#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
93 95
94#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ 96#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
95#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */ 97#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 3e1cd0452d67..90d0176fb30d 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -34,6 +34,7 @@ config KVM
34 select HAVE_KVM_IRQFD 34 select HAVE_KVM_IRQFD
35 select HAVE_KVM_IRQCHIP 35 select HAVE_KVM_IRQCHIP
36 select HAVE_KVM_IRQ_ROUTING 36 select HAVE_KVM_IRQ_ROUTING
37 select HAVE_KVM_MSI
37 depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER 38 depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
38 ---help--- 39 ---help---
39 Support hosting virtualized guest machines. 40 Support hosting virtualized guest machines.
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index f19842ea5418..d571243ab4d1 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -32,5 +32,6 @@ obj-y += $(KVM)/arm/vgic/vgic-mmio.o
32obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o 32obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
33obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o 33obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
34obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o 34obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
35obj-y += $(KVM)/arm/vgic/vgic-its.o
35obj-y += $(KVM)/irqchip.o 36obj-y += $(KVM)/irqchip.o
36obj-y += $(KVM)/arm/arch_timer.o 37obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 19b5f5c1c0ff..8f92efa8460e 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -221,6 +221,12 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
221 case KVM_CAP_MAX_VCPUS: 221 case KVM_CAP_MAX_VCPUS:
222 r = KVM_MAX_VCPUS; 222 r = KVM_MAX_VCPUS;
223 break; 223 break;
224 case KVM_CAP_MSI_DEVID:
225 if (!kvm)
226 r = -EINVAL;
227 else
228 r = kvm->arch.vgic.msis_require_devid;
229 break;
224 default: 230 default:
225 r = kvm_arch_dev_ioctl_check_extension(kvm, ext); 231 r = kvm_arch_dev_ioctl_check_extension(kvm, ext);
226 break; 232 break;
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 6eaf12c1d627..52cb7ad9b2fd 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -16,9 +16,6 @@ menuconfig VIRTUALIZATION
16 16
17if VIRTUALIZATION 17if VIRTUALIZATION
18 18
19config KVM_ARM_VGIC_V3_ITS
20 bool
21
22config KVM 19config KVM
23 bool "Kernel-based Virtual Machine (KVM) support" 20 bool "Kernel-based Virtual Machine (KVM) support"
24 depends on OF 21 depends on OF
@@ -34,7 +31,6 @@ config KVM
34 select KVM_VFIO 31 select KVM_VFIO
35 select HAVE_KVM_EVENTFD 32 select HAVE_KVM_EVENTFD
36 select HAVE_KVM_IRQFD 33 select HAVE_KVM_IRQFD
37 select KVM_ARM_VGIC_V3_ITS
38 select KVM_ARM_PMU if HW_PERF_EVENTS 34 select KVM_ARM_PMU if HW_PERF_EVENTS
39 select HAVE_KVM_MSI 35 select HAVE_KVM_MSI
40 select HAVE_KVM_IRQCHIP 36 select HAVE_KVM_IRQCHIP
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 83037cd62d01..0c848c18ca44 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -85,7 +85,13 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
85 write_sysreg(val, hcr_el2); 85 write_sysreg(val, hcr_el2);
86 /* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */ 86 /* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */
87 write_sysreg(1 << 15, hstr_el2); 87 write_sysreg(1 << 15, hstr_el2);
88 /* Make sure we trap PMU access from EL0 to EL2 */ 88 /*
89 * Make sure we trap PMU access from EL0 to EL2. Also sanitize
90 * PMSELR_EL0 to make sure it never contains the cycle
91 * counter, which could make a PMXEVCNTR_EL0 access UNDEF at
92 * EL1 instead of being trapped to EL2.
93 */
94 write_sysreg(0, pmselr_el0);
89 write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0); 95 write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
90 write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); 96 write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
91 __activate_traps_arch()(); 97 __activate_traps_arch()();
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 5bc460884639..e95d4f68bf54 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -86,12 +86,6 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
86 case KVM_CAP_VCPU_ATTRIBUTES: 86 case KVM_CAP_VCPU_ATTRIBUTES:
87 r = 1; 87 r = 1;
88 break; 88 break;
89 case KVM_CAP_MSI_DEVID:
90 if (!kvm)
91 r = -EINVAL;
92 else
93 r = kvm->arch.vgic.msis_require_devid;
94 break;
95 default: 89 default:
96 r = 0; 90 r = 0;
97 } 91 }
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index b7e34313cdfe..0deea34494e7 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -295,10 +295,10 @@
295#define GITS_BASER_InnerShareable \ 295#define GITS_BASER_InnerShareable \
296 GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable) 296 GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)
297#define GITS_BASER_PAGE_SIZE_SHIFT (8) 297#define GITS_BASER_PAGE_SIZE_SHIFT (8)
298#define GITS_BASER_PAGE_SIZE_4K (0UL << GITS_BASER_PAGE_SIZE_SHIFT) 298#define GITS_BASER_PAGE_SIZE_4K (0ULL << GITS_BASER_PAGE_SIZE_SHIFT)
299#define GITS_BASER_PAGE_SIZE_16K (1UL << GITS_BASER_PAGE_SIZE_SHIFT) 299#define GITS_BASER_PAGE_SIZE_16K (1ULL << GITS_BASER_PAGE_SIZE_SHIFT)
300#define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT) 300#define GITS_BASER_PAGE_SIZE_64K (2ULL << GITS_BASER_PAGE_SIZE_SHIFT)
301#define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT) 301#define GITS_BASER_PAGE_SIZE_MASK (3ULL << GITS_BASER_PAGE_SIZE_SHIFT)
302#define GITS_BASER_PAGES_MAX 256 302#define GITS_BASER_PAGES_MAX 256
303#define GITS_BASER_PAGES_SHIFT (0) 303#define GITS_BASER_PAGES_SHIFT (0)
304#define GITS_BASER_NR_PAGES(r) (((r) & 0xff) + 1) 304#define GITS_BASER_NR_PAGES(r) (((r) & 0xff) + 1)
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);