aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2016-09-06 04:28:47 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2016-09-08 06:53:00 -0400
commita07d3b07a876d44827e62f3ef55837ebbf61c4e6 (patch)
tree58d07ebae9e09ac06c056d5a002a3840f96d8b60 /virt
parentbf8feb39642b4c71c644e2d534ce53029bd2219b (diff)
arm64: KVM: vgic-v2: Enable GICV access from HYP if access from guest is unsafe
So far, we've been disabling KVM on systems where the GICV region couldn't be safely given to a guest. Now that we're able to handle this access safely by emulating it in HYP, we can enable this feature when we detect an unsafe configuration. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic/vgic-v2.c69
1 files changed, 42 insertions, 27 deletions
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index b8da9011889d..0a063af40565 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -278,12 +278,14 @@ int vgic_v2_map_resources(struct kvm *kvm)
278 goto out; 278 goto out;
279 } 279 }
280 280
281 ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base, 281 if (!static_branch_unlikely(&vgic_v2_cpuif_trap)) {
282 kvm_vgic_global_state.vcpu_base, 282 ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
283 KVM_VGIC_V2_CPU_SIZE, true); 283 kvm_vgic_global_state.vcpu_base,
284 if (ret) { 284 KVM_VGIC_V2_CPU_SIZE, true);
285 kvm_err("Unable to remap VGIC CPU to VCPU\n"); 285 if (ret) {
286 goto out; 286 kvm_err("Unable to remap VGIC CPU to VCPU\n");
287 goto out;
288 }
287 } 289 }
288 290
289 dist->ready = true; 291 dist->ready = true;
@@ -312,45 +314,51 @@ int vgic_v2_probe(const struct gic_kvm_info *info)
312 return -ENXIO; 314 return -ENXIO;
313 } 315 }
314 316
315 if (!PAGE_ALIGNED(info->vcpu.start)) { 317 if (!PAGE_ALIGNED(info->vcpu.start) ||
316 kvm_err("GICV physical address 0x%llx not page aligned\n", 318 !PAGE_ALIGNED(resource_size(&info->vcpu))) {
317 (unsigned long long)info->vcpu.start); 319 kvm_info("GICV region size/alignment is unsafe, using trapping (reduced performance)\n");
318 return -ENXIO; 320 kvm_vgic_global_state.vcpu_base_va = ioremap(info->vcpu.start,
319 } 321 resource_size(&info->vcpu));
322 if (!kvm_vgic_global_state.vcpu_base_va) {
323 kvm_err("Cannot ioremap GICV\n");
324 return -ENOMEM;
325 }
320 326
321 if (!PAGE_ALIGNED(resource_size(&info->vcpu))) { 327 ret = create_hyp_io_mappings(kvm_vgic_global_state.vcpu_base_va,
322 kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n", 328 kvm_vgic_global_state.vcpu_base_va + resource_size(&info->vcpu),
323 (unsigned long long)resource_size(&info->vcpu), 329 info->vcpu.start);
324 PAGE_SIZE); 330 if (ret) {
325 return -ENXIO; 331 kvm_err("Cannot map GICV into hyp\n");
332 goto out;
333 }
334
335 static_branch_enable(&vgic_v2_cpuif_trap);
326 } 336 }
327 337
328 kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start, 338 kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
329 resource_size(&info->vctrl)); 339 resource_size(&info->vctrl));
330 if (!kvm_vgic_global_state.vctrl_base) { 340 if (!kvm_vgic_global_state.vctrl_base) {
331 kvm_err("Cannot ioremap GICH\n"); 341 kvm_err("Cannot ioremap GICH\n");
332 return -ENOMEM; 342 ret = -ENOMEM;
343 goto out;
333 } 344 }
334 345
335 vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR); 346 vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
336 kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1; 347 kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1;
337 348
338 ret = kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
339 if (ret) {
340 kvm_err("Cannot register GICv2 KVM device\n");
341 iounmap(kvm_vgic_global_state.vctrl_base);
342 return ret;
343 }
344
345 ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base, 349 ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
346 kvm_vgic_global_state.vctrl_base + 350 kvm_vgic_global_state.vctrl_base +
347 resource_size(&info->vctrl), 351 resource_size(&info->vctrl),
348 info->vctrl.start); 352 info->vctrl.start);
349 if (ret) { 353 if (ret) {
350 kvm_err("Cannot map VCTRL into hyp\n"); 354 kvm_err("Cannot map VCTRL into hyp\n");
351 kvm_unregister_device_ops(KVM_DEV_TYPE_ARM_VGIC_V2); 355 goto out;
352 iounmap(kvm_vgic_global_state.vctrl_base); 356 }
353 return ret; 357
358 ret = kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
359 if (ret) {
360 kvm_err("Cannot register GICv2 KVM device\n");
361 goto out;
354 } 362 }
355 363
356 kvm_vgic_global_state.can_emulate_gicv2 = true; 364 kvm_vgic_global_state.can_emulate_gicv2 = true;
@@ -361,4 +369,11 @@ int vgic_v2_probe(const struct gic_kvm_info *info)
361 kvm_info("vgic-v2@%llx\n", info->vctrl.start); 369 kvm_info("vgic-v2@%llx\n", info->vctrl.start);
362 370
363 return 0; 371 return 0;
372out:
373 if (kvm_vgic_global_state.vctrl_base)
374 iounmap(kvm_vgic_global_state.vctrl_base);
375 if (kvm_vgic_global_state.vcpu_base_va)
376 iounmap(kvm_vgic_global_state.vcpu_base_va);
377
378 return ret;
364} 379}