aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoffer Dall <cdall@linaro.org>2017-05-08 06:23:51 -0400
committerChristoffer Dall <cdall@linaro.org>2017-05-09 06:19:31 -0400
commit9a746d75c06e2a68f27886d041c6e46df0aa86d8 (patch)
tree97b26c33ec844d4f68ace82e6338f85316e94fcc
parent7fadcd3a859b218fa27c399db0aa8d6d62ad84a9 (diff)
KVM: arm/arm64: Make vgic_v3_check_base more broadly usable
As we are about to fiddle with the IO device registration mechanism, let's be a little more careful when setting base addresses as early as possible. When setting a base address, we can check that there's address space enough for its scope and when the last of the two base addresses (dist and redist) get set, we can also check if the regions overlap at that time. This allows us to provide error messages to the user at time when trying to set the base address, as opposed to later when trying to run the VM. To do this, we make vgic_v3_check_base available in the core vgic-v3 code as well as in the other parts of the GICv3 code, namely the MMIO config code. We also return true for undefined base addresses so that the function can be used before all base addresses are set; all callers already check for uninitialized addresses before calling this function. Signed-off-by: Christoffer Dall <cdall@linaro.org> Reviewed-by: Eric Auger <eric.auger@redhat.com>
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c19
-rw-r--r--virt/kvm/arm/vgic/vgic.h1
2 files changed, 16 insertions, 4 deletions
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 12e52a06e146..2d53d7a24bda 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -329,19 +329,30 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
329 return 0; 329 return 0;
330} 330}
331 331
332/* check for overlapping regions and for regions crossing the end of memory */ 332/*
333static bool vgic_v3_check_base(struct kvm *kvm) 333 * Check for overlapping regions and for regions crossing the end of memory
334 * for base addresses which have already been set.
335 */
336bool vgic_v3_check_base(struct kvm *kvm)
334{ 337{
335 struct vgic_dist *d = &kvm->arch.vgic; 338 struct vgic_dist *d = &kvm->arch.vgic;
336 gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE; 339 gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
337 340
338 redist_size *= atomic_read(&kvm->online_vcpus); 341 redist_size *= atomic_read(&kvm->online_vcpus);
339 342
340 if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base) 343 if (!IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) &&
344 d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
341 return false; 345 return false;
342 if (d->vgic_redist_base + redist_size < d->vgic_redist_base) 346
347 if (!IS_VGIC_ADDR_UNDEF(d->vgic_redist_base) &&
348 d->vgic_redist_base + redist_size < d->vgic_redist_base)
343 return false; 349 return false;
344 350
351 /* Both base addresses must be set to check if they overlap */
352 if (IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) ||
353 IS_VGIC_ADDR_UNDEF(d->vgic_redist_base))
354 return true;
355
345 if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base) 356 if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
346 return true; 357 return true;
347 if (d->vgic_redist_base + redist_size <= d->vgic_dist_base) 358 if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index a2aeaa866b18..89eb935c05be 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -175,6 +175,7 @@ int vgic_v3_map_resources(struct kvm *kvm);
175int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq); 175int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq);
176int vgic_v3_save_pending_tables(struct kvm *kvm); 176int vgic_v3_save_pending_tables(struct kvm *kvm);
177int vgic_register_redist_iodevs(struct kvm *kvm); 177int vgic_register_redist_iodevs(struct kvm *kvm);
178bool vgic_v3_check_base(struct kvm *kvm);
178 179
179void vgic_v3_load(struct kvm_vcpu *vcpu); 180void vgic_v3_load(struct kvm_vcpu *vcpu);
180void vgic_v3_put(struct kvm_vcpu *vcpu); 181void vgic_v3_put(struct kvm_vcpu *vcpu);