aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2016-07-15 07:43:38 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2016-07-18 13:14:38 -0400
commit0e4e82f154e387969ea7ecd2c8876689fb68f710 (patch)
tree684d959f3f33a71e91e5d53a868ba87d45d0e495
parent2891a7dfb6c4a273996f0047660a75e88e3b8690 (diff)
KVM: arm64: vgic-its: Enable ITS emulation as a virtual MSI controller
Now that all ITS emulation functionality is in place, we advertise MSI functionality to userland and also the ITS device to the guest - if userland has configured that. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Tested-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--Documentation/virtual/kvm/api.txt2
-rw-r--r--arch/arm64/kvm/Kconfig1
-rw-r--r--arch/arm64/kvm/Makefile1
-rw-r--r--arch/arm64/kvm/reset.c6
-rw-r--r--include/kvm/arm_vgic.h5
-rw-r--r--virt/kvm/arm/vgic/vgic-init.c3
-rw-r--r--virt/kvm/arm/vgic/vgic-kvm-device.c3
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio-v3.c14
-rw-r--r--virt/kvm/arm/vgic/vgic.c8
-rw-r--r--virt/kvm/arm/vgic/vgic.h6
10 files changed, 44 insertions, 5 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 65513119fee8..07049eadb124 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2162,7 +2162,7 @@ after pausing the vcpu, but before it is resumed.
21624.71 KVM_SIGNAL_MSI 21624.71 KVM_SIGNAL_MSI
2163 2163
2164Capability: KVM_CAP_SIGNAL_MSI 2164Capability: KVM_CAP_SIGNAL_MSI
2165Architectures: x86 2165Architectures: x86 arm64
2166Type: vm ioctl 2166Type: vm ioctl
2167Parameters: struct kvm_msi (in) 2167Parameters: struct kvm_msi (in)
2168Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error 2168Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index aa2e34e99582..9d2eff0b3ad3 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -36,6 +36,7 @@ config KVM
36 select HAVE_KVM_IRQFD 36 select HAVE_KVM_IRQFD
37 select KVM_ARM_VGIC_V3 37 select KVM_ARM_VGIC_V3
38 select KVM_ARM_PMU if HW_PERF_EVENTS 38 select KVM_ARM_PMU if HW_PERF_EVENTS
39 select HAVE_KVM_MSI
39 ---help--- 40 ---help---
40 Support hosting virtualized guest machines. 41 Support hosting virtualized guest machines.
41 We don't support KVM with 16K page tables yet, due to the multiple 42 We don't support KVM with 16K page tables yet, due to the multiple
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index f00b2cdd0d33..a5b96642a9cb 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -29,5 +29,6 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
29kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o 29kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
30kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o 30kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
31kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o 31kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
32kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
32kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o 33kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
33kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o 34kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index e95d4f68bf54..5bc460884639 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -86,6 +86,12 @@ 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;
89 default: 95 default:
90 r = 0; 96 r = 0;
91 } 97 }
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index a6ca326055cf..4e63a07b9001 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -163,6 +163,9 @@ struct vgic_dist {
163 /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */ 163 /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
164 u32 vgic_model; 164 u32 vgic_model;
165 165
166 /* Do injected MSIs require an additional device ID? */
167 bool msis_require_devid;
168
166 int nr_spis; 169 int nr_spis;
167 170
168 /* TODO: Consider moving to global state */ 171 /* TODO: Consider moving to global state */
@@ -308,4 +311,6 @@ static inline int kvm_vgic_get_max_vcpus(void)
308 return kvm_vgic_global_state.max_gic_vcpus; 311 return kvm_vgic_global_state.max_gic_vcpus;
309} 312}
310 313
314int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
315
311#endif /* __KVM_ARM_VGIC_H */ 316#endif /* __KVM_ARM_VGIC_H */
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 535e713704f0..01a60dcd05d6 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -258,6 +258,9 @@ int vgic_init(struct kvm *kvm)
258 if (ret) 258 if (ret)
259 goto out; 259 goto out;
260 260
261 if (vgic_has_its(kvm))
262 dist->msis_require_devid = true;
263
261 kvm_for_each_vcpu(i, vcpu, kvm) 264 kvm_for_each_vcpu(i, vcpu, kvm)
262 kvm_vgic_vcpu_init(vcpu); 265 kvm_vgic_vcpu_init(vcpu);
263 266
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 561d2ba96a4f..1813f93b5cde 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -223,6 +223,9 @@ int kvm_register_vgic_device(unsigned long type)
223 case KVM_DEV_TYPE_ARM_VGIC_V3: 223 case KVM_DEV_TYPE_ARM_VGIC_V3:
224 ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops, 224 ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
225 KVM_DEV_TYPE_ARM_VGIC_V3); 225 KVM_DEV_TYPE_ARM_VGIC_V3);
226 if (ret)
227 break;
228 ret = kvm_vgic_register_its_device();
226 break; 229 break;
227#endif 230#endif
228 } 231 }
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 84a301d789e0..ff668e0dd586 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -66,7 +66,12 @@ static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
66 case GICD_TYPER: 66 case GICD_TYPER:
67 value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS; 67 value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
68 value = (value >> 5) - 1; 68 value = (value >> 5) - 1;
69 value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19; 69 if (vgic_has_its(vcpu->kvm)) {
70 value |= (INTERRUPT_ID_BITS_ITS - 1) << 19;
71 value |= GICD_TYPER_LPIS;
72 } else {
73 value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
74 }
70 break; 75 break;
71 case GICD_IIDR: 76 case GICD_IIDR:
72 value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0); 77 value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
@@ -163,9 +168,8 @@ static void vgic_mmio_write_v3r_ctlr(struct kvm_vcpu *vcpu,
163 168
164 vgic_cpu->lpis_enabled = val & GICR_CTLR_ENABLE_LPIS; 169 vgic_cpu->lpis_enabled = val & GICR_CTLR_ENABLE_LPIS;
165 170
166 if (!was_enabled && vgic_cpu->lpis_enabled) { 171 if (!was_enabled && vgic_cpu->lpis_enabled)
167 /* Eventually do something */ 172 vgic_enable_lpis(vcpu);
168 }
169} 173}
170 174
171static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu, 175static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
@@ -179,6 +183,8 @@ static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
179 value |= ((target_vcpu_id & 0xffff) << 8); 183 value |= ((target_vcpu_id & 0xffff) << 8);
180 if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1) 184 if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
181 value |= GICR_TYPER_LAST; 185 value |= GICR_TYPER_LAST;
186 if (vgic_has_its(vcpu->kvm))
187 value |= GICR_TYPER_PLPIS;
182 188
183 return extract_bytes(value, addr & 7, len); 189 return extract_bytes(value, addr & 7, len);
184} 190}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 53299fc93c15..424cb9ceebd9 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -718,3 +718,11 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
718 718
719 return map_is_active; 719 return map_is_active;
720} 720}
721
722int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
723{
724 if (vgic_has_its(kvm))
725 return vgic_its_inject_msi(kvm, msi);
726 else
727 return -ENODEV;
728}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 9d557f25cbfc..9d40d7bb89f7 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -77,6 +77,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info);
77int vgic_v3_map_resources(struct kvm *kvm); 77int vgic_v3_map_resources(struct kvm *kvm);
78int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); 78int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
79bool vgic_has_its(struct kvm *kvm); 79bool vgic_has_its(struct kvm *kvm);
80int kvm_vgic_register_its_device(void);
80void vgic_enable_lpis(struct kvm_vcpu *vcpu); 81void vgic_enable_lpis(struct kvm_vcpu *vcpu);
81int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi); 82int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
82#else 83#else
@@ -136,6 +137,11 @@ static inline bool vgic_has_its(struct kvm *kvm)
136 return false; 137 return false;
137} 138}
138 139
140static inline int kvm_vgic_register_its_device(void)
141{
142 return -ENODEV;
143}
144
139static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu) 145static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu)
140{ 146{
141} 147}